This commit is contained in:
fthvgb1 2018-01-15 23:24:11 +08:00
parent f855bdbb2b
commit 46304b7935
23 changed files with 403 additions and 16 deletions

View File

@ -33,7 +33,8 @@ class TopicsController extends Controller
if (!empty($topic->slug) && $topic->slug != $request->slug) {
return redirect($topic->link(), 301);
}
return view('topics.show', compact('topic'));
$replies = $topic->replies;
return view('topics.show', compact('topic', 'replies'));
}
public function store(TopicRequest $request, Topic $topic)

19
app/Models/Reply.php Normal file
View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
class Reply extends Model
{
protected $fillable = ['content'];
public function topic()
{
return $this->belongsTo(Topic::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@ -41,6 +41,12 @@ class Topic extends Model
return $query->orderBy('created_at', 'desc');
}
public function replies()
{
return $this->hasMany(Reply::class);
}
public function user()
{
return $this->belongsTo(User::class);

View File

@ -37,6 +37,11 @@ class User extends Authenticatable
return $this->id == $model->user_id;
}
public function replies()
{
return $this->hasMany(Reply::class, 'user_id');
}
public function topics()
{
return $this->hasMany(Topic::class);

View File

@ -0,0 +1,21 @@
<?php
namespace App\Observers;
use App\Models\Reply;
// creating, created, updating, updated, saving,
// saved, deleting, deleted, restoring, restored
class ReplyObserver
{
public function creating(Reply $reply)
{
//
}
public function updating(Reply $reply)
{
//
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Policies;
use App\Models\Reply;
use App\Models\User;
class ReplyPolicy extends Policy
{
public function update(User $user, Reply $reply)
{
// return $reply->user_id == $user->id;
return true;
}
public function destroy(User $user, Reply $reply)
{
return true;
}
}

View File

@ -14,6 +14,7 @@ class AuthServiceProvider extends ServiceProvider
* @var array
*/
protected $policies = [
\App\Models\Reply::class => \App\Policies\ReplyPolicy::class,
\App\Models\Topic::class => \App\Policies\TopicPolicy::class,
'App\Model' => 'App\Policies\ModelPolicy',
User::class => UserPolicy::class,

View File

@ -0,0 +1,13 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\Reply::class, function (Faker $faker) {
$time = $faker->dateTimeThisMonth();
return [
'content' => $faker->sentence(),
'created_at' => $time,
'updated_at' => $time,
];
});

View File

@ -9,7 +9,7 @@ class CreateTopicsTable extends Migration
{
Schema::create('topics', function (Blueprint $table) {
$table->increments('id');
$table->string('"title')->index();
$table->string('title')->index();
$table->text('body');
$table->integer('user_id')->unsigned()->index();
$table->integer('category_id')->unsigned()->index();

View File

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateRepliesTable extends Migration
{
public function up()
{
Schema::create('replies', function (Blueprint $table) {
$table->increments('id');
$table->integer('topic_id')->unsigned()->default(0)->index();
$table->integer('user_id')->unsigned()->default(0)->index();
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::drop('replies');
}
}

View File

@ -13,5 +13,6 @@ class DatabaseSeeder extends Seeder
{
$this->call(UsersTableSeeder::class);
$this->call(TopicsTableSeeder::class);
$this->call(ReplysTableSeeder::class);
}
}

View File

@ -0,0 +1,36 @@
<?php
use App\Models\Reply;
use Illuminate\Database\Seeder;
class ReplysTableSeeder extends Seeder
{
public function run()
{
// 所有用户 ID 数组,如:[1,2,3,4]
$user_ids = \App\Models\User::all()->pluck('id')->toArray();
// 所有话题 ID 数组,如:[1,2,3,4]
$topic_ids = \App\Models\Topic::all()->pluck('id')->toArray();
// 获取 Faker 实例
$faker = app(Faker\Generator::class);
$replys = factory(Reply::class)
->times(1000)
->make()
->each(function ($reply, $index)
use ($user_ids, $topic_ids, $faker) {
// 从用户 ID 数组中随机取出一个并赋值
$reply->user_id = $faker->randomElement($user_ids);
// 话题 ID同上
$reply->topic_id = $faker->randomElement($topic_ids);
});
// 将数据集合转换为数组,并插入到数据库中
Reply::insert($replys->toArray());
}
}

View File

@ -27,7 +27,6 @@ class TopicsTableSeeder extends Seeder
// 话题分类,同上
$topic->category_id = $faker->randomElement($category_ids);
});
// 将数据集合转换为数组,并插入到数据库中
Topic::insert($topics->toArray());
}

View File

@ -39,7 +39,7 @@ class UsersTableSeeder extends Seeder
$user = \App\Models\User::find(1);
$user->name = 'fthvgb1';
$user->email = 'fthvgb1@163.com';
$user->avatar = '';
$user->password = bcrypt('123456');
$user->save();
}

29
public/css/app.css vendored
View File

@ -8442,16 +8442,21 @@ body {
margin: 12px 0;
}
.users-show-page .meta {
font-size: .9em;
color: #b3b3b3;
}
.users-show-page .reply-content {
margin: 6px 0;
}
.users-show-page .list-group .list-group-item {
border: none;
margin-bottom: 0px;
border-bottom: 1px solid #efefef;
}
.users-show-page .list-group .list-group-item .meta {
color: #b3b3b3;
}
/* Topic Index Page */
.topics-index-page .topic-list .nav > li > a,
@ -8956,3 +8961,19 @@ body {
line-height: 38px;
}
.topic-reply hr {
margin-top: 16px;
margin-bottom: 16px;
}
.topic-reply a {
color: inherit;
}
.topic-reply .meta {
font-size: .9em;
color: #b3b3b3;
}
/* Topic Index Page */

View File

@ -4,6 +4,7 @@
font-weight: normal;
font-style: normal;
}
.simditor-icon {
display: inline-block;
font: normal normal normal 14px/1 'Simditor';
@ -142,10 +143,12 @@
position: relative;
border: 1px solid #c9d8db;
}
.simditor .simditor-wrapper {
position: relative;
background: #ffffff;
}
.simditor .simditor-wrapper > textarea {
display: none !important;
width: 100%;
@ -160,6 +163,7 @@
background: transparent;
resize: none;
}
.simditor .simditor-wrapper .simditor-placeholder {
display: none;
position: absolute;
@ -172,12 +176,14 @@
color: #999999;
background: transparent;
}
.simditor .simditor-wrapper.toolbar-floating .simditor-toolbar {
position: fixed;
top: 0;
z-index: 10;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
}
.simditor .simditor-wrapper .simditor-image-loading {
width: 100%;
height: 100%;
@ -186,6 +192,7 @@
left: 0;
z-index: 2;
}
.simditor .simditor-wrapper .simditor-image-loading .progress {
width: 100%;
height: 100%;
@ -194,6 +201,7 @@
bottom: 0;
left: 0;
}
.simditor .simditor-body {
padding: 22px 15px 40px;
min-height: 300px;
@ -203,18 +211,23 @@
z-index: 1;
background: transparent;
}
.simditor .simditor-body a.selected {
background: #b3d4fd;
}
.simditor .simditor-body a.simditor-mention {
cursor: pointer;
}
.simditor .simditor-body .simditor-table {
position: relative;
}
.simditor .simditor-body .simditor-table.resizing {
cursor: col-resize;
}
.simditor .simditor-body .simditor-table .simditor-resize-handle {
position: absolute;
left: 0;
@ -223,6 +236,7 @@
height: 100%;
cursor: col-resize;
}
.simditor .simditor-body pre {
/*min-height: 28px;*/
box-sizing: border-box;
@ -230,12 +244,15 @@
word-wrap: break-word !important;
white-space: pre-wrap !important;
}
.simditor .simditor-body img {
cursor: pointer;
}
.simditor .simditor-body img.selected {
box-shadow: 0 0 0 4px #cccccc;
}
.simditor .simditor-paste-bin {
position: fixed;
bottom: 10px;
@ -250,21 +267,25 @@
opacity: 0;
-webkit-user-select: text;
}
.simditor .simditor-toolbar {
border-bottom: 1px solid #eeeeee;
background: #ffffff;
width: 100%;
}
.simditor .simditor-toolbar > ul {
margin: 0;
padding: 0 0 0 6px;
list-style: none;
}
.simditor .simditor-toolbar > ul > li {
position: relative;
display: inline-block;
font-size: 0;
}
.simditor .simditor-toolbar > ul > li > span.separator {
display: inline-block;
background: #cfcfcf;
@ -273,6 +294,7 @@
margin: 11px 15px;
vertical-align: middle;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item {
display: inline-block;
width: 46px;
@ -285,50 +307,63 @@
text-align: center;
text-decoration: none;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item span {
opacity: 0.6;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item span.simditor-icon {
display: inline;
line-height: normal;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item:hover span {
opacity: 1;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.active {
background: #eeeeee;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.active span {
opacity: 1;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled {
cursor: default;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.disabled span {
opacity: 0.3;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title span:before {
content: "H";
font-size: 19px;
font-weight: bold;
font-family: 'Times New Roman';
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h1 span:before {
content: 'H1';
font-size: 18px;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h2 span:before {
content: 'H2';
font-size: 18px;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-title.active-h3 span:before {
content: 'H3';
font-size: 18px;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image {
position: relative;
overflow: hidden;
}
.simditor .simditor-toolbar > ul > li > .toolbar-item.toolbar-item-image > input[type=file] {
position: absolute;
right: 0px;
@ -337,18 +372,22 @@
font-size: 100px;
cursor: pointer;
}
.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item {
position: relative;
z-index: 20;
background: #ffffff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.simditor .simditor-toolbar > ul > li.menu-on .toolbar-item span {
opacity: 1;
}
.simditor .simditor-toolbar > ul > li.menu-on .toolbar-menu {
display: block;
}
.simditor .simditor-toolbar .toolbar-menu {
display: none;
position: absolute;
@ -359,6 +398,7 @@
text-align: left;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
}
.simditor .simditor-toolbar .toolbar-menu:before {
content: '';
display: block;
@ -369,12 +409,14 @@
top: -3px;
left: 0;
}
.simditor .simditor-toolbar .toolbar-menu ul {
min-width: 160px;
list-style: none;
margin: 0;
padding: 10px 1px;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item {
display: block;
font-size: 16px;
@ -383,29 +425,36 @@
text-decoration: none;
color: #666666;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item:hover {
background: #f6f6f6;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h1 {
font-size: 24px;
color: #333333;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h2 {
font-size: 22px;
color: #333333;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h3 {
font-size: 20px;
color: #333333;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h4 {
font-size: 18px;
color: #333333;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .menu-item.menu-item-h5 {
font-size: 16px;
color: #333333;
}
.simditor .simditor-toolbar .toolbar-menu ul > li .separator {
display: block;
border-top: 1px solid #cccccc;
@ -414,19 +463,23 @@
font-size: 0;
margin: 6px 0;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color {
width: 96px;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list {
height: 40px;
margin: 10px 6px 6px 10px;
padding: 0;
min-width: 0;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li {
float: left;
margin: 0 4px 4px 0;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color {
display: block;
width: 16px;
@ -434,47 +487,60 @@
background: #dfdfdf;
border-radius: 2px;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color:hover {
opacity: 0.8;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color.font-color-default {
background: #333333;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-1 {
background: #E33737;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-2 {
background: #e28b41;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-3 {
background: #c8a732;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-4 {
background: #209361;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-5 {
background: #418caf;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-6 {
background: #aa8773;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-color .color-list li .font-color-7 {
background: #999999;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table {
background: #ffffff;
padding: 1px;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table {
border: none;
border-collapse: collapse;
border-spacing: 0;
table-layout: fixed;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td {
padding: 0;
cursor: pointer;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td:before {
width: 16px;
height: 16px;
@ -483,19 +549,24 @@
display: block;
content: "";
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-create-table table td.selected:before {
background: #cfcfcf;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table {
display: none;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-table .menu-edit-table ul li {
white-space: nowrap;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image {
position: relative;
overflow: hidden;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-image .menu-item-upload-image input[type=file] {
position: absolute;
right: 0px;
@ -504,15 +575,19 @@
font-size: 100px;
cursor: pointer;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment {
width: 100%;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment ul {
min-width: 100%;
}
.simditor .simditor-toolbar .toolbar-menu.toolbar-menu-alignment .menu-item {
text-align: center;
}
.simditor .simditor-popover {
display: none;
padding: 5px 8px 0;
@ -522,31 +597,37 @@
position: absolute;
z-index: 2;
}
.simditor .simditor-popover .settings-field {
margin: 0 0 5px 0;
font-size: 12px;
height: 25px;
line-height: 25px;
}
.simditor .simditor-popover .settings-field label {
display: inline-block;
margin: 0 5px 0 0;
}
.simditor .simditor-popover .settings-field input[type=text] {
display: inline-block;
width: 200px;
box-sizing: border-box;
font-size: 12px;
}
.simditor .simditor-popover .settings-field input[type=text].image-size {
width: 83px;
}
.simditor .simditor-popover .settings-field .times {
display: inline-block;
width: 26px;
font-size: 12px;
text-align: center;
}
.simditor .simditor-popover.link-popover .btn-unlink, .simditor .simditor-popover.image-popover .btn-upload, .simditor .simditor-popover.image-popover .btn-restore {
display: inline-block;
margin: 0 0 0 5px;
@ -554,18 +635,22 @@
font-size: 14px;
outline: 0;
}
.simditor .simditor-popover.link-popover .btn-unlink span, .simditor .simditor-popover.image-popover .btn-upload span, .simditor .simditor-popover.image-popover .btn-restore span {
opacity: 0.6;
}
.simditor .simditor-popover.link-popover .btn-unlink:hover span, .simditor .simditor-popover.image-popover .btn-upload:hover span, .simditor .simditor-popover.image-popover .btn-restore:hover span {
opacity: 1;
}
.simditor .simditor-popover.image-popover .btn-upload {
position: relative;
display: inline-block;
overflow: hidden;
vertical-align: middle;
}
.simditor .simditor-popover.image-popover .btn-upload input[type=file] {
position: absolute;
right: 0px;
@ -574,6 +659,7 @@
height: 100%;
width: 28px;
}
.simditor.simditor-mobile .simditor-wrapper.toolbar-floating .simditor-toolbar {
position: absolute;
top: 0;
@ -589,96 +675,123 @@
outline: none;
word-wrap: break-word;
}
.simditor .simditor-body > :first-child, .editor-style > :first-child {
margin-top: 0 !important;
}
.simditor .simditor-body a, .editor-style a {
color: #4298BA;
text-decoration: none;
word-break: break-all;
}
.simditor .simditor-body a:visited, .editor-style a:visited {
color: #4298BA;
}
.simditor .simditor-body a:hover, .editor-style a:hover {
color: #0F769F;
}
.simditor .simditor-body a:active, .editor-style a:active {
color: #9E792E;
}
.simditor .simditor-body a:hover, .simditor .simditor-body a:active, .editor-style a:hover, .editor-style a:active {
outline: 0;
}
.simditor .simditor-body h1, .simditor .simditor-body h2, .simditor .simditor-body h3, .simditor .simditor-body h4, .simditor .simditor-body h5, .simditor .simditor-body h6, .editor-style h1, .editor-style h2, .editor-style h3, .editor-style h4, .editor-style h5, .editor-style h6 {
font-weight: normal;
margin: 40px 0 20px;
color: #000000;
}
.simditor .simditor-body h1, .editor-style h1 {
font-size: 24px;
}
.simditor .simditor-body h2, .editor-style h2 {
font-size: 22px;
}
.simditor .simditor-body h3, .editor-style h3 {
font-size: 20px;
}
.simditor .simditor-body h4, .editor-style h4 {
font-size: 18px;
}
.simditor .simditor-body h5, .editor-style h5 {
font-size: 16px;
}
.simditor .simditor-body h6, .editor-style h6 {
font-size: 16px;
}
.simditor .simditor-body p, .simditor .simditor-body div, .editor-style p, .editor-style div {
word-wrap: break-word;
margin: 0 0 15px 0;
color: #333;
word-wrap: break-word;
}
.simditor .simditor-body b, .simditor .simditor-body strong, .editor-style b, .editor-style strong {
font-weight: bold;
}
.simditor .simditor-body i, .simditor .simditor-body em, .editor-style i, .editor-style em {
font-style: italic;
}
.simditor .simditor-body u, .editor-style u {
text-decoration: underline;
}
.simditor .simditor-body strike, .simditor .simditor-body del, .editor-style strike, .editor-style del {
text-decoration: line-through;
}
.simditor .simditor-body ul, .simditor .simditor-body ol, .editor-style ul, .editor-style ol {
list-style: disc outside none;
margin: 15px 0;
padding: 0 0 0 40px;
line-height: 1.6;
}
.simditor .simditor-body ul li, .simditor .simditor-body ol li, .editor-style ul li, .editor-style ol li {
list-style-type: inherit;
}
.simditor .simditor-body ul ul, .simditor .simditor-body ul ol, .simditor .simditor-body ol ul, .simditor .simditor-body ol ol, .editor-style ul ul, .editor-style ul ol, .editor-style ol ul, .editor-style ol ol {
padding-left: 30px;
}
.simditor .simditor-body ul ul, .simditor .simditor-body ol ul, .editor-style ul ul, .editor-style ol ul {
list-style: circle outside none;
}
.simditor .simditor-body ul ul ul, .simditor .simditor-body ol ul ul, .editor-style ul ul ul, .editor-style ol ul ul {
list-style: square outside none;
}
.simditor .simditor-body ol, .editor-style ol {
list-style: decimal;
}
.simditor .simditor-body blockquote, .editor-style blockquote {
border-left: 6px solid #ddd;
padding: 5px 0 5px 10px;
margin: 15px 0 15px 15px;
}
.simditor .simditor-body blockquote > :first-child, .editor-style blockquote > :first-child {
margin-top: 0;
}
.simditor .simditor-body code, .editor-style code {
display: inline-block;
padding: 0 4px;
@ -688,6 +801,7 @@
font-size: 13px;
font-family: 'monaco', 'Consolas', "Liberation Mono", Courier, monospace;
}
.simditor .simditor-body pre, .editor-style pre {
padding: 10px 5px 10px 10px;
margin: 15px 0;
@ -701,6 +815,7 @@
word-wrap: normal;
overflow-x: auto;
}
.simditor .simditor-body pre code, .editor-style pre code {
display: block;
padding: 0;
@ -708,6 +823,7 @@
background: none;
border-radius: 0;
}
.simditor .simditor-body hr, .editor-style hr {
display: block;
height: 0px;
@ -716,6 +832,7 @@
margin: 15px 0;
padding: 0;
}
.simditor .simditor-body table, .editor-style table {
width: 100%;
table-layout: fixed;
@ -723,9 +840,11 @@
border-spacing: 0;
margin: 15px 0;
}
.simditor .simditor-body table thead, .editor-style table thead {
background-color: #f9f9f9;
}
.simditor .simditor-body table td, .simditor .simditor-body table th, .editor-style table td, .editor-style table th {
min-width: 40px;
height: 30px;
@ -735,9 +854,11 @@
text-align: left;
box-sizing: border-box;
}
.simditor .simditor-body table td.active, .simditor .simditor-body table th.active, .editor-style table td.active, .editor-style table th.active {
background-color: #ffffee;
}
.simditor .simditor-body img, .editor-style img {
margin: 0 5px;
vertical-align: middle;

View File

@ -94,16 +94,19 @@ body {
.pagination {
margin: 12px 0;
}
.meta {
font-size: .9em;
color: #b3b3b3;
}
.reply-content {
margin: 6px 0;
}
.list-group {
.list-group-item {
border: none;
margin-bottom: 0px;
border-bottom: 1px solid #efefef;
.meta {
color: #b3b3b3;
}
}
}
@ -154,3 +157,21 @@ body {
}
}
}
.topic-reply {
hr {
margin-top: 16px;
margin-bottom: 16px;
}
a {
color: inherit;
}
.meta {
font-size: .9em;
color: #b3b3b3;
}
}
/* Topic Index Page */

View File

@ -0,0 +1,33 @@
<div class="reply-list">
@foreach ($replies as $index => $reply)
<div class=" media" name="reply{{ $reply->id }}" id="reply{{ $reply->id }}">
<div class="avatar pull-left">
<a href="{{ route('users.show', [$reply->user_id]) }}">
<img class="media-object img-thumbnail" alt="{{ $reply->user->name }}"
src="{{ $reply->user->avatar }}" style="width:48px;height:48px;"/>
</a>
</div>
<div class="infos">
<div class="media-heading">
<a href="{{ route('users.show', [$reply->user_id]) }}" title="{{ $reply->user->name }}">
{{ $reply->user->name }}
</a>
<span> </span>
<span class="meta" title="{{ $reply->created_at }}">{{ $reply->created_at->diffForHumans() }}</span>
{{-- 回复删除按钮 --}}
<span class="meta pull-right">
<a title="删除回复">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</a>
</span>
</div>
<div class="reply-content">
{!! $reply->content !!}
</div>
</div>
</div>
<hr>
@endforeach
</div>

View File

@ -63,6 +63,14 @@
</div>
</div>
{{-- 用户回复列表 --}}
<div class="panel panel-default topic-reply">
<div class="panel-body">
@include('topics._reply_box', ['topic' => $topic])
@include('topics._reply_list', ['replies' => $topic->replies()->with('user')->get()])
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,27 @@
@if (count($replies))
<ul class="list-group">
@foreach ($replies as $reply)
<li class="list-group-item">
<a href="{{ $reply->topic->link(['#reply' . $reply->id]) }}">
{{ $reply->topic->title }}
</a>
<div class="reply-content" style="margin: 6px 0;">
{!! $reply->content !!}
</div>
<div class="meta">
<span class="glyphicon glyphicon-time" aria-hidden="true"></span>
回复于 {{ $reply->created_at->diffForHumans() }}
</div>
</li>
@endforeach
</ul>
@else
<div class="empty-block">暂无数据 ~_~</div>
@endif
{{-- 分页 --}}
{!! $replies->appends(Request::except('page'))->render() !!}

View File

@ -39,10 +39,19 @@
<div class="panel panel-default">
<div class="panel-body">
<ul class="nav nav-tabs">
<li class="active"><a href="#">Ta 的话题</a></li>
<li><a href="#">Ta 的回复</a></li>
<li class="{{ active_class(if_query('tab', null)) }}">
<a href="{{ route('users.show', $user->id) }}">Ta 的话题</a>
</li>
<li class="{{ active_class(if_query('tab', 'replies')) }}">
<a href="{{ route('users.show', [$user->id, 'tab' => 'replies']) }}">Ta 的回复</a>
</li>
</ul>
@include('users._topics', ['topics' => $user->topics()->recent()->paginate(5)])
@if(if_query('tab','replies'))
@include('users._replies', ['replies' => $user->replies()->recent()->paginate(5)])
@else
@include('users._topics', ['topics' => $user->topics()->recent()->paginate(5)])
@endif
</div>
</div>

View File

@ -37,3 +37,5 @@ Route::get('topics/{topic}/{slug?}', 'TopicsController@show')->name('topics.show
Route::resource('categories', 'CategoriesController', ['only' => ['show']]);
Route::post('upload_image', 'TopicsController@uploadImage')->name('topics.upload_image');
Route::resource('replies', 'RepliesController', ['only' => ['index', 'show', 'create', 'store', 'update', 'edit', 'destroy']]);