Browse Source

完善笔记

master
chenlong 1 year ago
parent
commit
e3e65775f4
  1. 4
      Controller/Admin/NotebookController.php
  2. 17
      Controller/Admin/NotebookUserController.php
  3. 34
      Controller/Admin/SharePreviewController.php
  4. 48
      Enums/NotebookUserEnumStatus.php
  5. 8
      Model/Notebook.php
  6. 8
      Model/NotebookUser.php
  7. 82
      Service/Admin/NotebookService.php
  8. 41
      Service/Admin/NotebookUserService.php
  9. 114
      View/Admin/Notebook/lists.blade.php
  10. 40
      View/Admin/Notebook/share.sc.php

4
Controller/Admin/NotebookController.php

@ -64,10 +64,12 @@ class NotebookController extends AbstractController
public function store(NotebookRequest $notebookRequest): ResponseInterface
{
$model = NotebookService::aop()->store($notebookRequest->post());
$data = $model->setVisible(['id', "title", "content", "create_time", 'update_time'])->toArray();
$data = $model->setVisible(['id', "title", "share_key", "content", 'mode', "create_time", 'update_time'])->toArray();
$data['create_name'] = $model->createAdmin->name;
$data['latest_name'] = $model->latestAdmin->name;
$data['user_mode'] = 'super';
$data['user'] = [];
return Response::json()->success($data);
}

17
Controller/Admin/NotebookUserController.php

@ -4,6 +4,7 @@ namespace Plugins\Notebook\Controller\Admin;
use App\Exception\ApiMessageException;
use App\Controller\AbstractController;
use Hyperf\Validation\Middleware\ValidationMiddleware;
use Plugins\Notebook\Service\Admin\NotebookUserService;
use App\Middleware\Admin\AuthenticateMiddleware;
use App\Middleware\Admin\PermissionsMiddleware;
@ -49,4 +50,20 @@ class NotebookUserController extends AbstractController
return Response::json()->success();
}
/**
* 删除数据
*
* @return ResponseInterface
* @throws ApiMessageException
*/
#[Scene('destroy')]
#[PostMapping(path: 'destroy')]
public function destroy(): ResponseInterface
{
NotebookUserService::aop()->destroy($this->request->post('ids'));
return Response::json()->success();
}
}

34
Controller/Admin/SharePreviewController.php

@ -0,0 +1,34 @@
<?php
namespace Plugins\Notebook\Controller\Admin;
use App\Util\Hy;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\View\Render;
use Plugins\Notebook\Model\Notebook;
use Psr\Http\Message\ResponseInterface;
use Sc\Util\HtmlStructure\Html\Html;
/**
* Class SharePreviewController
*/
#[Controller('plugins/notebook')]
class SharePreviewController
{
/**
* @param Render $render
*
* @return ResponseInterface
*/
#[GetMapping(path: 'index')]
public function index(Render $render): ResponseInterface
{
/** @var Notebook $notebook */
$notebook = Notebook::where('share_key', Hy::request()->query('key'))->first();
return $render->render('plugins.Notebook.Admin.Notebook.share', [
'notebook' => $notebook
]);
}
}

48
Enums/NotebookUserEnumStatus.php

@ -1,48 +0,0 @@
<?php
namespace Plugins\Notebook\Enums;
use App\Enums\EnumStatusTrait;
use Sc\Util\HtmlElement\ElementType\AbstractHtmlElement;
/**
* 笔记协作人员 : 状态
*/
enum NotebookUserEnumStatus :int
{
use EnumStatusTrait;
/**
* 正常
*/
case Normal = 1;
/**
* 剔除
*/
case Eliminate = 2;
/**
* 获取描述
*
* @return string
*/
public function getDes(): string
{
return match ($this) {
self::Normal => '正常',
self::Eliminate => '剔除',
};
}
/**
* 转标签
*/
public function toTag():AbstractHtmlElement
{
return match ($this){
self::Normal => $this->getTag('success', 'light'),
self::Eliminate => $this->getTag('warning', 'light'),
};
}
}

8
Model/Notebook.php

@ -25,7 +25,7 @@ CREATE TABLE `sd_notebook` (
`title` varchar(127) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '标题',
`content` text COLLATE utf8mb4_general_ci COMMENT '内容',
`administrators_id` int NOT NULL COMMENT '创建人',
`mode` tinyint(1) NOT NULL DEFAULT '1' COMMENT '模式:1=公开,2=私有',
`mode` tinyint(1) NOT NULL DEFAULT '2' COMMENT '模式:1=公开,2=私有',
`share_key` varchar(10) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '分享密钥',
`latest_administrators_id` int NOT NULL COMMENT '最后修改人',
`create_time` datetime NOT NULL COMMENT '创建时间',
@ -68,7 +68,11 @@ class Notebook extends Model
public function user()
{
return $this->hasMany(NotebookUser::class);
return $this->hasMany(NotebookUser::class)
->join('administrators', 'administrators.id', '=', "notebook_user.administrators_id")
->select([
"notebook_user.id","notebook_user.notebook_id","notebook_user.administrators_id","notebook_user.mode","notebook_user.status","notebook_user.create_time","administrators.name as user"
]);
}
}

8
Model/NotebookUser.php

@ -11,10 +11,10 @@ use App\Model\Model;
* @property int $notebook_id 笔记
* @property int $administrators_id 管理员
* @property int $mode 权限
* @property int $status 状态
* @property string $create_time
* @property string $update_time
* @property int $delete_time
* @property Notebook $notebook
*/
#[CreateSql(<<<SQL
CREATE TABLE `sd_notebook_user` (
@ -22,7 +22,6 @@ CREATE TABLE `sd_notebook_user` (
`notebook_id` int NOT NULL DEFAULT '0' COMMENT '笔记',
`administrators_id` int NOT NULL DEFAULT '0' COMMENT '管理员',
`mode` tinyint(1) NOT NULL DEFAULT '1' COMMENT '权限:1=只读,2=读写',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1=正常,2=剔除',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`delete_time` int DEFAULT NULL,
@ -50,5 +49,10 @@ class NotebookUser extends Model
{
return $this->attributes['administrators_id'] = (int)$value;
}
public function notebook()
{
return $this->belongsTo(Notebook::class);
}
}

82
Service/Admin/NotebookService.php

@ -10,6 +10,10 @@ use App\Service\Admin\Traits\StoreServiceTrait;
use App\Service\Admin\Traits\UpdateServiceTrait;
use App\Service\Admin\Traits\SwitchServiceTrait;
use App\Util\AdminAuth;
use App\Util\Hy;
use Hyperf\Database\Query\JoinClause;
use Plugins\Notebook\Enums\NotebookEnumMode;
use Plugins\Notebook\Enums\NotebookUserEnumMode;
use Plugins\Notebook\Model\Notebook;
use App\Util\EasySearch;
use Plugins\Notebook\Model\NotebookUser;
@ -34,27 +38,95 @@ class NotebookService extends AbstractAdminService
$query = $this->model
->leftJoin('administrators as a1', 'a1.id', '=', 'notebook.administrators_id')
->leftJoin('administrators as a2', 'a2.id', '=', 'notebook.latest_administrators_id')
->leftJoin('notebook_user', function (JoinClause $clause){
$clause->on('notebook_user.notebook_id', '=', 'notebook.id')
->where('notebook_user.administrators_id', AdminAuth::getInfo()->id)
->whereNull('notebook_user.delete_time');
})
->where(function ($builder){
$builder->orWhere('notebook.administrators_id', AdminAuth::getInfo()->id)
->orWhere('notebook_user.administrators_id', AdminAuth::getInfo()->id)
->orWhere('notebook.mode', NotebookEnumMode::Public->value);
})
->orderBy('notebook.id', 'desc')
->with(['user'])
->select(["notebook.id","notebook.title","notebook.content","notebook.mode","notebook.share_key","a1.name as create_name","a2.name as latest_name","notebook.create_time","notebook.update_time"]);
->select(["notebook.id","notebook.administrators_id","notebook.title","notebook_user.mode as user_mode","notebook.content","notebook.mode","notebook.share_key","a1.name as create_name","a2.name as latest_name","notebook.create_time","notebook.update_time"]);
return EasySearch::create($query)->getData();
$data = EasySearch::create($query)->getData();
$data['data']->each(function ($datum) {
if ($datum->administrators_id === AdminAuth::getInfo()->id) {
$datum->user_mode = "super";
} elseif ($datum->user_mode === NotebookUserEnumMode::ReadingAndWriting->value) {
$datum->user_mode = "write";
} else {
$datum->user_mode = "read";
}
});
return $data;
}
/**
* @param $data
*
* @return void
*/
public function beforeStore(&$data): void
{
$data['administrators_id'] = AdminAuth::getInfo()->id;
$data['mode'] = NotebookEnumMode::Private->value;
$data['share_key'] = substr(md5(time()), 0, 10);
}
/**
* @param $data
* @param $id
*
* @return void
*/
public function beforeWrite(&$data, $id = null): void
{
$data['latest_administrators_id'] = AdminAuth::getInfo()->id;
}
/**
* @param array $ids
*
* @return void
*/
public function beforeDestroy(array $ids)
{
$this->model->where('administrators_id', AdminAuth::getInfo()->id);
}
/**
* @param $data
* @param $id
*
* @return void
* @throws ApiMessageException
*/
public function beforeUpdate(&$data, $id): void
{
if (strtotime($data['update_time']) < strtotime($this->model->update_time)){
throw new ApiMessageException("文档内容不是最新版,请更新后编辑");
}
if ($this->model->administrators_id === AdminAuth::getInfo()->id) {
return;
}
if ($data['mode'] != $this->model->mode){
throw new ApiMessageException("对不起,你无修改权限");
}
$userMode = NotebookUser::where('notebook_id', $id)
->where('administrators_id', AdminAuth::getInfo()->id)
->value('mode');
if ($userMode !== NotebookUserEnumMode::ReadingAndWriting->value) {
throw new ApiMessageException("对不起,你暂无修改权限");
}
}
/**
@ -85,6 +157,12 @@ class NotebookService extends AbstractAdminService
*/
public function addUser(int $notebook_id, array $userIds): void
{
$notebook = $this->model->find($notebook_id);
if ($notebook?->administrators_id != AdminAuth::getInfo()->id) {
throw new ApiMessageException("对不起,未找到该操作");
}
$data = [];
foreach ($userIds as $user_id) {
$data[] = [

41
Service/Admin/NotebookUserService.php

@ -3,11 +3,15 @@
namespace Plugins\Notebook\Service\Admin;
use App\Exception\ApiMessageException;
use App\Service\Admin\AbstractAdminService;
use App\Service\Admin\Traits\DestroyServiceTrait;
use App\Service\Admin\Traits\StoreServiceTrait;
use App\Service\Admin\Traits\UpdateServiceTrait;
use App\Service\Admin\Traits\SwitchServiceTrait;
use App\Util\AdminAuth;
use App\Util\Hy;
use Plugins\Notebook\Model\Notebook;
use Plugins\Notebook\Model\NotebookUser;
use App\Util\EasySearch;
@ -30,7 +34,42 @@ class NotebookUserService extends AbstractAdminService
{
$query = $this->model->select(["notebook_user.id","notebook_user.notebook_id","notebook_user.administrators_id","notebook_user.mode","notebook_user.status","notebook_user.create_time"]);
return EasySearch::create($query)->getData();
if (Hy::request()->query('notebook_id')) {
$query->where("notebook_user.notebook_id", Hy::request()->query('notebook_id'));
}
return EasySearch::create($query)->totalCancellations()->getData()['data']->toArray();
}
/**
* @param $data
* @param $id
*
* @return void
* @throws ApiMessageException
*/
public function beforeUpdate(&$data, $id): void
{
if ($this->model->notebook->administrators_id != AdminAuth::getInfo()->id) {
throw new ApiMessageException('对不起,未找到该操作');
}
}
/**
* @param array $ids
*
* @return void
* @throws ApiMessageException
*/
public function beforeDestroy(array $ids): void
{
$data = NotebookUser::whereIn('id', $ids)->pluck('notebook_id');
$notAuth = Notebook::whereIn('id', $data->toArray())
->where('administrators_id', '<>', AdminAuth::getInfo()->id)
->value('id');
if ($notAuth) {
throw new ApiMessageException('对不起,未找到该操作');
}
}
}

114
View/Admin/Notebook/lists.blade.php

@ -136,6 +136,25 @@
width: 100%;
user-select: none;
}
.delete-user{
color: red;
}
.delete-user:hover{
cursor: pointer;
}
.readonly{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 110px;
z-index: 99;
background-color: #f8e3c535;
color: #f89898;
font-size: 30px;
line-height: 110px;
text-align: center;
}
</style>
@endsection
@section('main')
@ -160,10 +179,10 @@
<div class="time">创建时间:@{{item.create_time}}</div>
<div class="time"><div>创建人:@{{ item.create_name }}</div> <div>最后更新: @{{ item.latest_name }}</div></div>
<div class="list-tool">
<div class="list-tool-item delete" ><el-icon @click.stop="deleteaa(item, index)"><delete/></el-icon></div>
<div v-if="item.user_mode === 'super'" class="list-tool-item delete" ><el-icon @click.stop="deleteaa(item, index)"><delete/></el-icon></div>
<div class="list-tool-item share" ><el-icon @click.stop="share(item, index)"><Share/></el-icon></div>
<div class="list-tool-item allow-user" ><el-icon @click.stop="allowUser(item, index)"><Avatar/></el-icon></div>
<div class="list-tool-item mode" ><el-icon @click.stop="mode(item, index)"><Operation/></el-icon></div>
<div v-if="item.user_mode === 'super'" class="list-tool-item allow-user" ><el-icon @click.stop="allowUser(item, index)"><Avatar/></el-icon></div>
<div v-if="item.user_mode === 'super'" class="list-tool-item mode" ><el-icon @click.stop="mode(item, index)"><Operation/></el-icon></div>
</div>
</div>
<el-divider v-if="notNotebook">
@ -180,12 +199,14 @@
<div class="content-shade" v-if="!currentNotebook.title">
<div class="logo">notebook</div>
</div>
<div class="readonly" v-if="currentNotebook.title && currentNotebook.user_mode === 'read'"> 只读模式,任何修改都无效 </div>
</el-col>
</el-row>
{{-- 分享 --}}
<el-dialog v-model="shareVisible" title="分享地址">
<el-link :underline="false" type="primary">@{{ shareUrl }}</el-link>
<el-link :underline="false" target="_blank" :href="shareUrl" type="primary">@{{ shareUrl }}</el-link>
<a href="" target="_blank"></a>
</el-dialog>
{{-- 模式 --}}
@ -202,8 +223,8 @@
</span>
</template>
</el-dialog>
{{-- 允许查看 --}}
<el-dialog v-model="allowVisible" title="协作人员">
{{-- 协作用户 --}}
<el-dialog v-model="allowVisible" width="500px" title="协作人员">
<div>
<el-select v-model="waitAddAllowUser" filterable multiple clearable placeholder="请选择">
<el-option
@ -226,13 +247,18 @@
</el-table-column>
<el-table-column prop="mode" label="权限">
<template #default="scope">
<el-radio-group v-model="scope.row.mode" class="ml-4">
<el-radio-group v-model="scope.row.mode" class="ml-4" @change="modeChange(scope.row)">
@foreach(\Plugins\Notebook\Enums\NotebookUserEnumMode::mapping() as $mode)
<el-radio :label="{{ $mode['value'] }}" size="large">{{ $mode['label'] }}</el-radio>
@endforeach
</el-radio-group>
</template>
</el-table-column>
<el-table-column width="50">
<template #default="scope">
<el-icon class="delete-user" @click.stop="deleteUser(scope.row, scope.$index)"><delete/></el-icon>
</template>
</el-table-column>
</el-table>
</div>
</el-dialog>
@ -256,7 +282,7 @@
VueInit.data.allowVisible = false;
VueInit.data.modeData = {!! json_encode(\Plugins\Notebook\Enums\NotebookEnumMode::mapping()) !!};
VueInit.data.adminData = {!! json_encode(\App\Model\Base\Administrators::getSelectData('name')) !!};
VueInit.data.adminData.push({value:"*",label:'全部用户'})
VueInit.data.adminData.unshift({value:"*",label:'全部用户'})
VueInit.data.shareUrl = "";
VueInit.data.updateNotebook = "";
VueInit.data.allowUserData = [];
@ -282,17 +308,69 @@
this.updateNotebook = item;
};
VueInit.methods.deleteUser = function (row, index) {
axios({
url: "{{ \App\Util\Hy::route()->to([\Plugins\Notebook\Controller\Admin\NotebookUserController::class, 'destroy']) }}",
method: 'post',
data: {
ids: [row.id]
},
}).then(({ data }) => {
if (data.code !== 200) {
this.$message.error(data.msg);
}else{
this.$message.success('更新成功');
this.getNotebookUsers(this.updateNotebook.id, (data) => {
this.updateNotebook.user = data;
});
}
});
};
VueInit.methods.modeChange = function (row) {
axios({
url: "{{ \App\Util\Hy::route()->to([\Plugins\Notebook\Controller\Admin\NotebookUserController::class, 'update']) }}",
method: 'post',
data: row,
}).then(({ data }) => {
if (data.code !== 200) {
row.mode = row.mode === 1 ? 2 : 1;
this.$message.error(data.msg);
}else{
this.$message.success('更新成功');
}
});
};
VueInit.methods.getNotebookUsers = function (notebook_id, success){
axios({
url: "{{ \App\Util\Hy::route()->to([\Plugins\Notebook\Controller\Admin\NotebookUserController::class, 'listsData']) }}",
method: 'get',
params: {
notebook_id:notebook_id
},
}).then(({ data }) => {
if (data.code === 200) {
success && success(data.data)
}
});
}
VueInit.methods.addAllowUser = function () {
if (this.waitAddAllowUser.length > 0) {
let waitAddAllowUser = [];
if (this.waitAddAllowUser.includes('*')) {
this.waitAddAllowUser = this.adminData.map(v => v.value);
}
this.waitAddAllowUser.map(v =>{
if (!this.updateNotebook.map(v1 => v1.administrators_id).includes(v)) {
if (!this.updateNotebook.user.map(v1 => v1.administrators_id).includes(v) && v !== '*') {
waitAddAllowUser.push(v);
}
})
});
this.waitAddAllowUser = [];
if (waitAddAllowUser) {
if (waitAddAllowUser.length > 0) {
this.addAllowUserRequest(waitAddAllowUser);
}
}
@ -309,7 +387,9 @@
}).then(({data}) =>{
if (data.code === 200) {
this.$message.success("设置成功");
// todo getNewData
this.getNotebookUsers(this.updateNotebook.id, (data) => {
this.updateNotebook.user = data;
})
}else{
this.$message.error("设置失败");
}
@ -368,7 +448,9 @@
}
VueInit.methods.deleteaa = function (item, index){
this.$confirm("确认删除笔记吗?").then(() =>{
this.$confirm("确认删除笔记吗?", {
confirm:"确认"
}).then(() =>{
this.notebook.splice(index, 1);
if (index === this.active) {
this.currentNotebook = this.notebook[index] ? this.notebook[index] : {title: ''};
@ -420,6 +502,10 @@
}
data = data ? data : this.currentNotebook;
if (data.user_mode === 'read') {
return;
}
data.update_time = this.toTime();
axios({
url: "update",
@ -506,7 +592,7 @@
VueInit.methods.share = function (item,index){
this.shareVisible = true;
this.shareUrl = `http://www.baidu.com/${item.id}`;
this.shareUrl = `{{ \App\Util\Hy::route()->to([\Plugins\Notebook\Controller\Admin\SharePreviewController::class, 'index']) }}?key=${item.share_key}`;
}
</script>

40
View/Admin/Notebook/share.sc.php

@ -0,0 +1,40 @@
<?php
use Plugins\Notebook\Model\Notebook;
use Sc\Util\HtmlStructure\Html\Html;
/**
* @var Notebook $notebook
*/
Html::create($notebook?->title ?: '不存在的页面');
if (!$notebook) {
Html::loadThemeResource('ElementUI');
}
Html::css()->addCss(<<<CSS
#app {
width: 1100px;
margin: auto;
border-left: 1px #ddd solid;
border-right: 1px #ddd solid;
padding: 0 20px;
box-sizing: border-box;
background-color: white;
overflow: auto;
min-height: 100vh;
}
body{
background-color: #F2F3F5;
margin: 0 !important;
}
table,table tr th, table tr td {
border:1px solid #ddd;
}
table {
border-collapse: collapse;
padding:2px;
}
CSS);
return $notebook?->content ?: ' <el-empty description="Not Found" />';
Loading…
Cancel
Save