no message

This commit is contained in:
kuaifan 2021-06-29 22:44:29 +08:00
parent 27789b8eb9
commit 14bb9bb7b2
18 changed files with 472 additions and 6 deletions

View File

@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\File;
use App\Models\User;
use App\Module\Base;
use Request;
/**
* @apiDefine file
*
* 文件
*/
class FileController extends AbstractController
{
/**
* 添加项目
*
* @apiParam {String} name 项目名称
* @apiParam {String} type 文件类型
* @apiParam {Number} [pid] 父级ID
*/
public function add()
{
$user = User::auth();
// 文件名称
$name = trim(Request::input('name'));
$type = trim(Request::input('type'));
$pid = intval(Request::input('pid'));
if (mb_strlen($name) < 2) {
return Base::retError('文件名称不可以少于2个字');
} elseif (mb_strlen($name) > 32) {
return Base::retError('文件名称最多只能设置32个字');
}
//
if (!in_array($type, [
'folder',
'document',
'mind',
'sheet',
'flow',
])) {
return Base::retError('类型错误');
}
//
if ($pid > 0) {
if (!File::whereUserid($user->id)->whereId($pid)->exists()) {
return Base::retError('参数错误');
}
}
// 开始创建
$file = File::createInstance([
'pid' => $pid,
'name' => $name,
'type' => $type,
'userid' => $user->userid,
]);
$file->save();
//
$data = File::find($file->id);
return Base::retSuccess('添加成功', $data);
}
}

View File

@ -32,5 +32,8 @@ class VerifyCsrfToken extends Middleware
// 聊天发文件
'api/dialog/msg/sendfile/',
// 保存文件
'api/file/save/',
];
}

31
app/Models/File.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace App\Models;
/**
* Class File
*
* @package App\Models
* @property int $id
* @property int|null $pid 上级ID
* @property string|null $name 名称
* @property string|null $type 类型
* @property int|null $userid 拥有者ID
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|File newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|File newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|File query()
* @method static \Illuminate\Database\Eloquent\Builder|File whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|File wherePid($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|File whereUserid($value)
* @mixin \Eloquent
*/
class File extends AbstractModel
{
}

View File

@ -2,10 +2,10 @@
directory=/var/www
# 生产环境
command=php bin/laravels start -i
#command=php bin/laravels start -i
# 开发环境
#command=./bin/inotify ./app
command=./bin/inotify ./app
numprocs=1
autostart=true

View File

@ -39,6 +39,10 @@
<div class="menu-title">{{$L('消息')}}</div>
<Badge class="menu-badge" :count="msgAllUnread"></Badge>
</li>
<li @click="toggleRoute('file')" :class="classNameRoute('file')">
<i class="iconfont">&#xe6f3;</i>
<div class="menu-title">{{$L('文件')}}</div>
</li>
<li class="menu-project">
<ul>
<li

View File

@ -0,0 +1,162 @@
<template>
<div class="page-file">
<PageTitle :title="$L('文件')"/>
<div class="file-wrapper">
<div class="file-head">
<h1>{{$L('文件')}}</h1>
<div class="file-search">
<i class="iconfont">&#xe6f8;</i>
</div>
<div class="file-add">
<EDropdown
trigger="click"
placement="bottom"
@command="addFile">
<i class="iconfont">&#xe6f2;</i>
<EDropdownMenu slot="dropdown" class="page-file-dropdown-menu">
<EDropdownItem v-for="(type, key) in types" :key="key" :command="type.value">
<div :class="['file-item ' + type.value]">新建{{$L(type.name)}}</div>
</EDropdownItem>
</EDropdownMenu>
</EDropdown>
</div>
</div>
<div v-if="files.length + temps.length == 0" class="file-no">
<i class="iconfont">&#xe60b;</i>
<p>{{$L('没有任何文件')}}</p>
</div>
<div v-else class="file-list">
<ul class="clearfix">
<li v-for="item in folderList" :class="item.type">
<div class="file-icon"></div>
<div v-if="item._edit" class="file-input">
<Input
:ref="'input_' + item.id"
v-model="item.newname"
size="small"
:disabled="item._load"
@on-blur="onBlur(item)"
@on-enter="onEnter(item)"/>
<div v-if="item._load" class="file-load"><Loading/></div>
</div>
<div v-else class="file-name">{{item.name}}</div>
</li>
<li v-for="item in fileList" :class="item.type">
<div class="file-icon"></div>
<div v-if="item._edit" class="file-input">
<Input
:ref="'input_' + item.id"
v-model="item.newname"
size="small"
@on-blur="onBlur(item)"
@on-enter="onEnter(item)"/>
<div v-if="item._load" class="file-load"><Loading/></div>
</div>
<div v-else class="file-name">{{item.name}}</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
data() {
return {
types: [
{value: 'folder', name: "目录"},
{value: 'document', name: "文本"},
{value: 'mind', name: "脑图"},
{value: 'sheet', name: "表格"},
{value: 'flow', name: "流程图"},
],
files: [],
temps: [],
}
},
mounted() {
},
destroyed() {
},
computed: {
...mapState(['userInfo']),
folderList() {
const data = this.files.filter(({type}) => type == 'folder')
return Object.assign(data, this.temps.filter(({type}) => type == 'folder'))
},
fileList() {
const data = this.files.filter(({type}) => type != 'folder')
return Object.assign(data, this.temps.filter(({type}) => type != 'folder'))
}
},
watch: {
},
methods: {
addFile(command) {
let id = $A.randomString(8);
this.temps.push({
_edit: true,
id: id,
type: command,
newname: this.$L('未命名')
});
this.$nextTick(() => {
this.$refs['input_' + id][0].focus({
cursor: 'all'
})
})
},
onBlur(item) {
this.onEnter(item);
},
onEnter(item) {
if (item._load) {
return;
}
if (!item.newname) {
this.temps = this.temps.filter(({id}) => id != item.id);
} else {
this.$set(item, '_load', true);
this.$store.dispatch("call", {
url: 'file/add',
data: {
name: item.newname,
type: item.type,
},
}).then(({data, msg}) => {
$A.messageSuccess(msg)
this.$set(item, '_load', false);
this.$set(item, '_edit', false);
if (this.temps.find(({id}) => id == item.id)) {
this.temps = this.temps.filter(({id}) => id != item.id);
this.files.push(data);
} else {
Object.keys(data).forEach((key) => {
this.$set(item, key, data[key]);
})
}
}).catch(({msg}) => {
$A.modalError(msg)
this.$set(item, '_edit', false);
this.temps = this.temps.filter(({id}) => id != item.id);
})
}
}
}
}
</script>

View File

@ -63,6 +63,11 @@ export default [
path: 'project/:id',
component: () => import('./pages/manage/project.vue'),
},
{
name: 'manage-file',
path: 'file',
component: () => import('./pages/manage/file.vue'),
},
]
},
{

View File

@ -1,8 +1,8 @@
@font-face {
font-family: 'iconfont'; /* Project id 2583385 */
src: url('//at.alicdn.com/t/font_2583385_q96au6w9mi.woff2?t=1624526227684') format('woff2'),
url('//at.alicdn.com/t/font_2583385_q96au6w9mi.woff?t=1624526227684') format('woff'),
url('//at.alicdn.com/t/font_2583385_q96au6w9mi.ttf?t=1624526227684') format('truetype');
src: url('//at.alicdn.com/t/font_2583385_9cbmdxw5tl.woff2?t=1624963755686') format('woff2'),
url('//at.alicdn.com/t/font_2583385_9cbmdxw5tl.woff?t=1624963755686') format('woff'),
url('//at.alicdn.com/t/font_2583385_9cbmdxw5tl.ttf?t=1624963755686') format('truetype');
}
.iconfont {

View File

@ -1,6 +1,7 @@
@import "common";
@import "page-calendar";
@import "page-dashboard";
@import "page-file";
@import "page-login";
@import "page-manage";
@import "page-messenger";

View File

@ -269,6 +269,20 @@ body {
display: none !important;
}
.clearfix {
*zoom: 1;
&:after,
&:before {
display: table;
content: ""
}
&:after {
clear: both
}
}
.page-box {
text-align: center;
padding: 20px 0;

View File

@ -0,0 +1,172 @@
.page-file {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.file-wrapper {
flex: 1;
display: flex;
flex-direction: column;
.file-head {
display: flex;
align-items: center;
padding-bottom: 16px;
margin: 32px 32px 16px;
border-bottom: 1px solid #F4F4F5;
> h1 {
flex: 1;
color: #333333;
font-size: 28px;
font-weight: 600;
}
.file-search {
flex-shrink: 0;
margin-left: 24px;
cursor: pointer;
.iconfont {
font-size: 18px;
}
}
.file-add {
flex-shrink: 0;
margin-left: 24px;
cursor: pointer;
.iconfont {
font-size: 18px;
}
}
}
.file-no {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin-bottom: 5%;
opacity: 0.8;
> i {
font-size: 64px;
}
> p {
margin-top: 18px;
font-size: 14px;
font-weight: 500;
line-height: 1;
}
}
.file-list {
flex: 1;
padding: 0 20px 20px;
> ul {
> li {
list-style: none;
float: left;
margin: 12px;
width: 90px;
height: 95px;
text-align: center;
position: relative;
overflow: visible;
border: 1px dashed transparent;
border-radius: 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
.file-input {
margin: 0 2px 2px;
position: relative;
input {
margin: 0;
padding: 1px 5px;
font-size: 13px;
}
.file-load {
position: absolute;
top: 0;
right: 6px;
bottom: 0;
display: flex;
.common-loading {
width: 10px;
height: 10px;
}
}
}
.file-name {
display: block;
width: 100%;
height: 20px;
line-height: 20px;
color: #666;
font-size: 12px;
text-align: center;
margin-top: 5px;
margin-bottom: 3px;
padding: 0 6px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.file-icon {
display: inline-block;
width: 38px;
height: 38px;
background: no-repeat center center;
background-size: contain;
margin-top: 14px;
}
&.folder .file-icon {
background-image: url("../images/file/folder.svg");
}
&.document .file-icon {
background-image: url("../images/file/document.svg");
}
&.mind .file-icon {
background-image: url("../images/file/mind.svg");
}
&.sheet .file-icon {
background-image: url("../images/file/sheet.svg");
}
&.flow .file-icon {
background-image: url("../images/file/flow.svg");
}
&:hover {
background-color: #f4f5f7;
}
}
}
}
}
}
.page-file-dropdown-menu {
.file-item {
display: flex;
align-items: center;
position: relative;
&:before {
content: "";
width: 14px;
height: 14px;
background: no-repeat center center;
background-size: contain;
margin-right: 6px;
}
&.folder:before {
background-image: url("../images/file/folder.svg");
}
&.document:before {
background-image: url("../images/file/document.svg");
}
&.mind:before {
background-image: url("../images/file/mind.svg");
}
&.sheet:before {
background-image: url("../images/file/sheet.svg");
}
&.flow:before {
background-image: url("../images/file/flow.svg");
}
}
}

View File

@ -3,7 +3,7 @@
flex-direction: column;
.setting-head {
display: flex;
align-items: flex-start;
align-items: center;
margin: 32px 32px 16px;
border-bottom: 1px solid #F4F4F5;
.setting-titbox {

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1624964505724" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1059" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><defs><style type="text/css"></style></defs><path d="M594.944 0l335.12448 341.31968v563.2c0 65.9968-52.50048 119.48032-117.29408 119.48032H209.54624c-64.7936 0-117.2992-53.5296-117.2992-119.48032V119.48032C92.25216 53.48352 144.75776 0 209.55136 0H594.944z" fill="#5895FF" p-id="1060"></path><path d="M930.06848 341.31968h-211.9168c-64.74752 0-123.20768-59.48928-123.20768-125.4912V0l335.12448 341.31968z" fill="#FFFFFF" fill-opacity=".4" p-id="1061"></path><path d="M427.37664 725.31968V768H259.8144v-42.68032h167.56224zM594.944 640v42.68032H259.8144V640H594.944z m0-85.31968v42.63936H259.8144v-42.63936H594.944z m0-85.36064V512H259.8144v-42.68032H594.944z" fill="#FFFFFF" p-id="1062"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1624964747859" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1522" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><defs><style type="text/css"></style></defs><path d="M594.944 0l335.12448 341.31968v563.2c0 65.9968-52.50048 119.48032-117.29408 119.48032H209.54624c-64.7936 0-117.2992-53.5296-117.2992-119.48032V119.48032C92.25216 53.48352 144.75776 0 209.55136 0H594.944z" fill="#424242" p-id="1523"></path><path d="M930.06848 341.31968h-211.9168c-64.74752 0-123.20768-59.48928-123.20768-125.4912V0l335.12448 341.31968z" fill="#FFFFFF" fill-opacity=".4" p-id="1524"></path><path d="M504.45824 580.608c49.52576 0 90.3424 40.86784 90.3424 92.02176 0 50.45248-40.81664 92.06784-90.3424 92.06784a86.10816 86.10816 0 0 1-51.57376-16.384c-6.05184-4.096-7.35232-12.94336-3.34848-19.08736a13.5424 13.5424 0 0 1 18.75456-3.39456c10.70592 7.44448 23.41376 11.58656 36.16768 11.58656 34.816 0 63.58016-29.32224 63.58016-64.78848 0-35.47136-28.76416-64.7936-63.58016-64.7936-32.768 0-60.1856 25.97376-63.30368 58.6496l-0.32256 6.144c0 50.45248-40.82176 92.06784-90.34752 92.06784-49.52576 0-90.38848-41.61536-90.38848-92.06784 0-50.4576 40.86272-92.02176 90.38848-92.02176 17.408 0 34.11968 4.74624 48.87552 14.2848 6.04672 4.096 8.00256 12.288 3.99872 19.08736a13.5936 13.5936 0 0 1-18.75456 4.096 60.8768 60.8768 0 0 0-34.11968-10.24c-34.816 0-63.58016 29.32224-63.58016 64.7936 0 35.46624 28.76416 64.78848 63.58016 64.78848 34.816 0 63.58016-29.32224 63.58016-64.78848 0-50.4576 40.82176-92.02176 90.3936-92.02176z" fill="#FFFFFF" p-id="1525"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1624964488544" class="icon" viewBox="0 0 1208 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="907" xmlns:xlink="http://www.w3.org/1999/xlink" width="1208" height="1024"><defs><style type="text/css"></style></defs><path d="M132.51584 120.4736h879.4368c33.26976 0 60.2368 26.96704 60.2368 60.23168v409.6c0 33.26976-26.96704 60.2368-60.2368 60.2368H132.51584c-33.26464 0-60.23168-26.96704-60.23168-60.2368v-409.6c0-33.26464 26.96704-60.2368 60.23168-60.2368z" fill="#F9B552" p-id="908"></path><path d="M469.8368 0c73.18528 0 132.51584 59.33056 132.51584 132.51584v84.3264h469.8368c73.18528 0 132.51584 59.33568 132.51584 132.52096v542.12096c0 73.18528-59.33056 132.51584-132.51584 132.51584H132.51584A132.51584 132.51584 0 0 1 0 891.48416V349.3632c0-4.03456 0.1792-8.06912 0.54272-12.04736A134.25664 134.25664 0 0 1 0 325.2736V132.51584C0 59.33056 59.33056 0 132.51584 0h337.32096z" fill="#FFCF5C" p-id="909"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1624964573291" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1367" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><defs><style type="text/css"></style></defs><path d="M594.944 0l335.12448 341.31968v563.2c0 65.9968-52.50048 119.48032-117.29408 119.48032H209.54624c-64.7936 0-117.2992-53.5296-117.2992-119.48032V119.48032C92.25216 53.48352 144.75776 0 209.55136 0H594.944z" fill="#E94848" p-id="1368"></path><path d="M482.95424 375.48032a40.58624 40.58624 0 0 0-40.02816 40.77568c0 27.78624 15.17056 62.32576 31.1808 94.7712-12.56448 39.8336-26.71616 82.47296-44.82048 118.5024-37.0944 14.7968-70.1952 25.8304-90.0608 42.16832a41.70752 41.70752 0 0 0-12.3904 29.9264c0 22.34368 18.06336 40.77568 40.0384 40.77568a39.33184 39.33184 0 0 0 29.27104-12.47232c14.6176-17.82784 31.88736-50.12992 47.29344-79.6416 35.42016-14.19776 72.60672-28.672 108.44672-37.3248 26.1632 21.4528 64.0512 35.65056 95.18592 35.65056 21.96992 0 40.03328-18.38592 40.03328-40.77568a40.58624 40.58624 0 0 0-40.03328-40.72448c-24.99072 0-61.29664 9.07264-89.0368 18.61632a301.3376 301.3376 0 0 1-58.09152-76.98432c10.65984-33.3312 23.04-66.65728 23.04-92.48768a40.58624 40.58624 0 0 0-40.02816-40.77568z m0 24.43776c8.98048 0 16.01024 7.168 16.01024 16.29184 0 12.2368-6.42048 34.816-13.87008 59.01824C475.136 451.67616 466.944 429.056 466.944 416.256c0-9.1648 7.02464-16.29184 16.01024-16.29184v-0.04608z m6.8864 139.5456a323.57376 323.57376 0 0 0 41.5232 53.76c-23.74144 6.6048-46.91968 15.0784-69.82144 23.92064 11.07968-25.36448 19.9168-51.75808 28.29824-77.72672v0.04608z m157.2352 52.12672c8.98048 0 16.01024 7.12192 16.01024 16.29184 0 9.12384-7.02976 16.29184-16.01536 16.29184-18.05824 0-43.65824-8.28416-64.18432-19.87584 23.552-6.79424 49.2032-12.7488 64.18432-12.7488v0.04096zM408.15104 664.576c-11.264 20.48-22.43584 39.56224-30.2592 49.152a15.0784 15.0784 0 0 1-11.02848 4.18816 15.96416 15.96416 0 0 1-16.01024-16.29184c0.03072-4.16256 1.53088-8.18688 4.23424-11.35616 9.40032-7.3984 29.83424-16.29184 53.06368-25.69216z" fill="#FFFFFF" p-id="1369"></path><path d="M930.06848 341.31968h-211.9168c-64.74752 0-123.20768-59.48928-123.20768-125.4912V0l335.12448 341.31968z" fill="#FFFFFF" fill-opacity=".4" p-id="1370"></path></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1624964523472" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1212" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="1024"><defs><style type="text/css"></style></defs><path d="M594.944 0l335.12448 341.31968v563.2c0 65.9968-52.50048 119.48032-117.29408 119.48032H209.54624c-64.7936 0-117.2992-53.5296-117.2992-119.48032V119.48032C92.25216 53.48352 144.75776 0 209.55136 0H594.944z" fill="#1ABF74" p-id="1213"></path><path d="M930.06848 341.31968h-211.9168c-64.74752 0-123.20768-59.48928-123.20768-125.4912V0l335.12448 341.31968z" fill="#FFFFFF" fill-opacity=".4" p-id="1214"></path><path d="M594.61632 426.82368v0.2304h0.09216V768H566.8352v-0.0512h-83.968 0.04608H399.7696h0.0512-139.91936v-28.3904l0.0512-0.04608v-85.82656h-0.0512v-28.39552h0.0512v-85.82656h-0.09728v-28.39552l0.09216-0.04608V455.168h-0.09216v-28.3904h334.70976l0.04608 0.04608z m-222.62784 226.86208H287.88224v85.82656h84.10624v-85.82656z m83.08224 0h-55.2448v85.82656h55.19872v-85.82656h0.0512z m111.75936 0H482.90816v85.82656H566.784v-85.82656h0.04608z m-194.8416-114.2272H287.88224v85.83168h84.10624v-85.82656z m83.08224 0h-55.2448v85.83168h55.19872v-85.82656h0.0512z m111.75936 0H482.90816v85.83168H566.784v-85.82656h0.04608z m0-84.24448H287.88224v55.808H566.784V455.168l0.04608 0.0512z" fill="#FFFFFF" p-id="1215"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,6 +1,7 @@
<?php
use App\Http\Controllers\Api\DialogController;
use App\Http\Controllers\Api\FileController;
use App\Http\Controllers\Api\ProjectController;
use App\Http\Controllers\Api\SystemController;
use App\Http\Controllers\Api\UsersController;
@ -35,6 +36,9 @@ Route::prefix('api')->middleware(['webapi'])->group(function () {
// 对话
Route::any('dialog/{method}', DialogController::class);
Route::any('dialog/{method}/{action}', DialogController::class);
// 文件
Route::any('file/{method}', FileController::class);
Route::any('file/{method}/{action}', FileController::class);
});
/**