mirror of
https://github.com/bs-community/blessing-skin-server.git
synced 2025-03-01 15:05:39 +08:00
Build "get-score-by-sharing" into core
This commit is contained in:
parent
9bed8d022d
commit
4b553c3c92
@ -141,7 +141,17 @@ class AdminController extends Controller
|
||||
'sign_score_to' => @explode(',', option('sign_score'))[1],
|
||||
])->handle();
|
||||
|
||||
return view('admin.score', ['forms' => compact('rate', 'sign')]);
|
||||
$sharing = Option::form('sharing', OptionForm::AUTO_DETECT, function ($form) {
|
||||
$form->group('score_award_per_texture')
|
||||
->text('score_award_per_texture')
|
||||
->addon(trans('general.user.score'));
|
||||
$form->checkbox('take_back_scores_after_deletion')->label();
|
||||
$form->group('score_award_per_like')
|
||||
->text('score_award_per_like')
|
||||
->addon(trans('general.user.score'));
|
||||
})->handle();
|
||||
|
||||
return view('admin.score', ['forms' => compact('rate', 'sign', 'sharing')]);
|
||||
}
|
||||
|
||||
public function options()
|
||||
@ -215,9 +225,9 @@ class AdminController extends Controller
|
||||
});
|
||||
|
||||
$meta = Option::form('meta', OptionForm::AUTO_DETECT, function ($form) {
|
||||
$form->text('meta_keywords')->hint(OptionForm::AUTO_DETECT);
|
||||
$form->text('meta_description')->hint(OptionForm::AUTO_DETECT);
|
||||
$form->textarea('meta_extras')->rows(6);
|
||||
$form->text('meta_keywords')->hint();
|
||||
$form->text('meta_description')->hint();
|
||||
$form->textarea('meta_extras')->rows(6);
|
||||
})->handle();
|
||||
|
||||
return view('admin.options')
|
||||
|
@ -71,7 +71,8 @@ class ClosetController extends Controller
|
||||
}
|
||||
|
||||
$tid = $request->tid;
|
||||
if (! Texture::find($tid)) {
|
||||
$texture = Texture::find($tid);
|
||||
if (! $texture) {
|
||||
return json(trans('user.closet.add.not-found'), 1);
|
||||
}
|
||||
|
||||
@ -82,6 +83,12 @@ class ClosetController extends Controller
|
||||
$user->closet()->attach($tid, ['item_name' => $request->name]);
|
||||
$user->setScore(option('score_per_closet_item'), 'minus');
|
||||
|
||||
$uploader = User::find($texture->uploader);
|
||||
if ($uploader && $uploader->uid != $user->uid) {
|
||||
$uploader->score += option('score_award_per_like', 0);
|
||||
$uploader->save();
|
||||
}
|
||||
|
||||
return json(trans('user.closet.add.success', ['name' => $request->input('name')]), 0);
|
||||
}
|
||||
|
||||
@ -108,19 +115,24 @@ class ClosetController extends Controller
|
||||
$this->validate($request, [
|
||||
'tid' => 'required|integer',
|
||||
]);
|
||||
$tid = $request->tid;
|
||||
|
||||
$user = auth()->user();
|
||||
|
||||
if ($user->closet()->where('tid', $request->tid)->count() == 0) {
|
||||
if ($user->closet()->where('tid', $tid)->count() == 0) {
|
||||
return json(trans('user.closet.remove.non-existent'), 1);
|
||||
}
|
||||
|
||||
$user->closet()->detach($request->tid);
|
||||
$user->closet()->detach($tid);
|
||||
|
||||
if (option('return_score')) {
|
||||
$user->setScore(option('score_per_closet_item'), 'plus');
|
||||
}
|
||||
|
||||
$uploader = User::find(Texture::find($tid)->uploader);
|
||||
$uploader->score -= option('score_award_per_like', 0);
|
||||
$uploader->save();
|
||||
|
||||
return json(trans('user.closet.remove.success'), 0);
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,7 @@ class SkinlibController extends Controller
|
||||
|
||||
$cost = $t->size * ($t->public ? Option::get('score_per_storage') : Option::get('private_score_per_storage'));
|
||||
$cost += option('score_per_closet_item');
|
||||
$cost -= option('score_award_per_texture', 0);
|
||||
|
||||
if ($user->getScore() < $cost) {
|
||||
return json(trans('skinlib.upload.lack-score'), 7);
|
||||
@ -243,18 +244,28 @@ class SkinlibController extends Controller
|
||||
Storage::disk('textures')->delete($result->hash);
|
||||
}
|
||||
|
||||
if (option('return_score')) {
|
||||
if ($u = $users->get($result->uploader)) {
|
||||
if ($result->public) {
|
||||
$u->setScore(
|
||||
$result->size * option('score_per_storage'), 'plus'
|
||||
);
|
||||
} else {
|
||||
$u->setScore(
|
||||
$result->size * option('private_score_per_storage'), 'plus'
|
||||
);
|
||||
}
|
||||
$result->likers()->get()->each(function ($user) use ($result) {
|
||||
$user->closet()->detach($result->tid);
|
||||
if (option('return_score')) {
|
||||
$user->setScore(option('score_per_closet_item'), 'plus');
|
||||
}
|
||||
});
|
||||
|
||||
if ($u = $users->get($result->uploader)) {
|
||||
$ret = 0;
|
||||
if (option('return_score')) {
|
||||
$ret += $result->size * (
|
||||
$result->public
|
||||
? option('score_per_storage')
|
||||
: option('private_score_per_storage')
|
||||
);
|
||||
}
|
||||
|
||||
if ($result->public && option('take_back_scores_after_deletion', true)) {
|
||||
$ret -= option('score_award_per_texture', 0);
|
||||
}
|
||||
|
||||
$u->setScore($ret, 'plus');
|
||||
}
|
||||
|
||||
if ($result->delete()) {
|
||||
@ -278,6 +289,9 @@ class SkinlibController extends Controller
|
||||
}
|
||||
|
||||
$score_diff = $t->size * (option('private_score_per_storage') - option('score_per_storage')) * ($t->public ? -1 : 1);
|
||||
if ($t->public && option('take_back_scores_after_deletion', true)) {
|
||||
$score_diff -= option('score_award_per_texture', 0);
|
||||
}
|
||||
if ($users->get($t->uploader)->getScore() + $score_diff < 0) {
|
||||
return json(trans('skinlib.upload.lack-score'), 1);
|
||||
}
|
||||
|
@ -42,4 +42,12 @@ return [
|
||||
'copyright_prefer' => '0',
|
||||
'score_per_closet_item' => '0',
|
||||
'favicon_url' => 'app/favicon.ico',
|
||||
'enable_redis' => 'false',
|
||||
'score_award_per_texture' => '0',
|
||||
'take_back_scores_after_deletion' => 'true',
|
||||
'score_award_per_like' => '0',
|
||||
'meta_keywords' => '',
|
||||
'meta_description' => '',
|
||||
'meta_extras' => '',
|
||||
'cdn_address' => '',
|
||||
];
|
||||
|
@ -75,6 +75,9 @@
|
||||
<div v-if="isPrivate" class="callout callout-info">
|
||||
<p>{{ privacyNotice }}</p>
|
||||
</div>
|
||||
<div v-if="!isPrivate && award" class="callout callout-success">
|
||||
<p>{{ $t('skinlib.upload.award', { score: award }) }}</p>
|
||||
</div>
|
||||
</div><!-- /.box-body -->
|
||||
|
||||
<div class="box-footer">
|
||||
@ -130,6 +133,7 @@ export default {
|
||||
privacyNotice: blessing.extra.privacyNotice,
|
||||
scorePublic: blessing.extra.scorePublic,
|
||||
scorePrivate: blessing.extra.scorePrivate,
|
||||
award: +blessing.extra.award,
|
||||
width2d: 64,
|
||||
}
|
||||
},
|
||||
|
@ -14,6 +14,7 @@ window.blessing.extra = {
|
||||
privacyNotice: 'privacyNotice',
|
||||
scorePrivate: 10,
|
||||
scorePublic: 1,
|
||||
award: 0,
|
||||
}
|
||||
|
||||
const csrf = document.createElement('meta')
|
||||
@ -163,3 +164,14 @@ test('upload file', async () => {
|
||||
expect(swal).toBeCalledWith({ type: 'success', text: '0' })
|
||||
expect(toastr.info).toBeCalledWith('skinlib.redirecting')
|
||||
})
|
||||
|
||||
test('show notice about awarding', () => {
|
||||
const wrapper = mount(Upload)
|
||||
expect(wrapper.find('.callout-success').exists()).toBeFalse()
|
||||
|
||||
wrapper.setData({ award: 5 })
|
||||
expect(wrapper.find('.callout-success').exists()).toBeTrue()
|
||||
|
||||
wrapper.find('[type=checkbox]').setChecked()
|
||||
expect(wrapper.find('.callout-success').exists()).toBeFalse()
|
||||
})
|
||||
|
@ -86,6 +86,7 @@ skinlib:
|
||||
dropZone: Drop a file here
|
||||
remove: Remove
|
||||
cost: (It cost you about :score score)
|
||||
award: You'll be awarded :score score(s) by uploading public texture.
|
||||
show:
|
||||
anonymous: You must login to use closets
|
||||
likes: People who like this
|
||||
|
@ -62,6 +62,17 @@ sign:
|
||||
label: Users can sign in after 0 everyday.
|
||||
hint: The above option will be ignored if this is checked.
|
||||
|
||||
sharing:
|
||||
title: Awarding Sharing
|
||||
|
||||
score_award_per_texture:
|
||||
title: Uploader will be rewarded for each uploading texture with
|
||||
take_back_scores_after_deletion:
|
||||
title: Return scores
|
||||
label: Return scores if uploader setting private or deleting texture.
|
||||
score_award_per_like:
|
||||
title: Each time the texture is collected, uploader will be rewarded with
|
||||
|
||||
general:
|
||||
title: General Options
|
||||
|
||||
|
@ -88,6 +88,7 @@ skinlib:
|
||||
dropZone: 拖拽文件到这里
|
||||
remove: 移除
|
||||
cost: (这会消耗您约 :score 积分)
|
||||
award: 上传公开材质至皮肤库可以获得 :score 积分奖励。
|
||||
show:
|
||||
anonymous: 登录后才能使用衣柜哦
|
||||
likes: 收藏人数
|
||||
|
@ -62,6 +62,17 @@ sign:
|
||||
label: 每天零点后可签到
|
||||
hint: 勾选后将无视上一条,每天零时后均可签到
|
||||
|
||||
sharing:
|
||||
title: 奖励分享
|
||||
|
||||
score_award_per_texture:
|
||||
title: 每上传一个材质奖励
|
||||
take_back_scores_after_deletion:
|
||||
title: 回收积分
|
||||
label: 改为私有或删除上传的材质后收回奖励积分
|
||||
score_award_per_like:
|
||||
title: 材质每被收藏一次奖励上传者
|
||||
|
||||
general:
|
||||
title: 常规选项
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
<div class="col-md-6">
|
||||
{!! $forms['sign']->render() !!}
|
||||
|
||||
{!! $forms['sharing']->render() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -23,7 +23,8 @@ blessing.extra = {
|
||||
rule: "{{ option('texture_name_regexp') ? trans('skinlib.upload.name-rule-regexp', compact('regexp')) : trans('skinlib.upload.name-rule') }}",
|
||||
privacyNotice: "@lang('skinlib.upload.private-score-notice', ['score' => option('private_score_per_storage')])",
|
||||
scorePublic: {{ option('score_per_storage') }},
|
||||
scorePrivate: {{ option('private_score_per_storage') }}
|
||||
scorePrivate: {{ option('private_score_per_storage') }},
|
||||
award: {{ option('score_award_per_texture') }},
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
@ -93,6 +93,15 @@ class AdminControllerTest extends BrowserKitTestCase
|
||||
$this->assertEquals('233,666', option('sign_score'));
|
||||
$this->assertEquals('7', option('sign_gap_time'));
|
||||
$this->assertTrue(option('sign_after_zero'));
|
||||
|
||||
$this->visit('/admin/score')
|
||||
->type('1', 'score_award_per_texture')
|
||||
->uncheck('take_back_scores_after_deletion')
|
||||
->type('1', 'score_award_per_like')
|
||||
->press('submit_sharing');
|
||||
$this->assertEquals('1', option('score_award_per_texture'));
|
||||
$this->assertFalse(option('take_back_scores_after_deletion'));
|
||||
$this->assertEquals('1', option('score_award_per_like'));
|
||||
}
|
||||
|
||||
public function testOptions()
|
||||
|
@ -80,7 +80,8 @@ class ClosetControllerTest extends TestCase
|
||||
|
||||
public function testAdd()
|
||||
{
|
||||
$texture = factory(Texture::class)->create();
|
||||
$uploader = factory(User::class)->create(['score' => 0]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$likes = $texture->likes;
|
||||
$name = 'my';
|
||||
option(['score_per_closet_item' => 10]);
|
||||
@ -140,6 +141,7 @@ class ClosetControllerTest extends TestCase
|
||||
]);
|
||||
|
||||
// Add a texture successfully
|
||||
option(['score_award_per_like' => 5]);
|
||||
$this->postJson(
|
||||
'/user/closet/add',
|
||||
['tid' => $texture->tid, 'name' => $name]
|
||||
@ -151,6 +153,8 @@ class ClosetControllerTest extends TestCase
|
||||
$this->user = User::find($this->user->uid);
|
||||
$this->assertEquals(90, $this->user->score);
|
||||
$this->assertEquals(1, $this->user->closet()->count());
|
||||
$uploader->refresh();
|
||||
$this->assertEquals(5, $uploader->score);
|
||||
|
||||
// If the texture is duplicated, should be warned
|
||||
$this->postJson(
|
||||
@ -224,7 +228,8 @@ class ClosetControllerTest extends TestCase
|
||||
|
||||
public function testRemove()
|
||||
{
|
||||
$texture = factory(Texture::class)->create();
|
||||
$uploader = factory(User::class)->create(['score' => 5]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$likes = $texture->likes;
|
||||
|
||||
// Missing `tid` field
|
||||
@ -253,6 +258,7 @@ class ClosetControllerTest extends TestCase
|
||||
]);
|
||||
|
||||
// Should return score if `return_score` is true
|
||||
option(['score_award_per_like' => 5]);
|
||||
$this->user->closet()->attach($texture->tid, ['item_name' => 'name']);
|
||||
$score = $this->user->score;
|
||||
$this->postJson(
|
||||
@ -265,6 +271,8 @@ class ClosetControllerTest extends TestCase
|
||||
$this->assertEquals($likes, Texture::find($texture->tid)->likes);
|
||||
$this->assertEquals($score + option('score_per_closet_item'), $this->user->score);
|
||||
$this->assertEquals(0, $this->user->closet()->count());
|
||||
$uploader->refresh();
|
||||
$this->assertEquals(0, $uploader->score);
|
||||
|
||||
$texture = Texture::find($texture->tid);
|
||||
$likes = $texture->likes;
|
||||
|
@ -554,6 +554,9 @@ class SkinlibControllerTest extends TestCase
|
||||
'errno' => 7,
|
||||
'msg' => trans('skinlib.upload.lack-score'),
|
||||
]);
|
||||
|
||||
// Success
|
||||
option(['score_award_per_texture' => 2]);
|
||||
$response = $this->postJson(
|
||||
'/skinlib/upload',
|
||||
[
|
||||
@ -571,7 +574,7 @@ class SkinlibControllerTest extends TestCase
|
||||
]);
|
||||
Storage::disk('textures')->assertExists($t->hash);
|
||||
$user = User::find($user->uid);
|
||||
$this->assertEquals(0, $user->score);
|
||||
$this->assertEquals(2, $user->score);
|
||||
$this->assertEquals('texture', $t->name);
|
||||
$this->assertEquals('steve', $t->type);
|
||||
$this->assertEquals(1, $t->likes);
|
||||
@ -683,6 +686,47 @@ class SkinlibControllerTest extends TestCase
|
||||
$uploader->score + $texture->size * option('private_score_per_storage'),
|
||||
User::find($uploader->uid)->score
|
||||
);
|
||||
|
||||
option(['return_score' => false]);
|
||||
|
||||
// Return the award
|
||||
option(['score_award_per_texture' => 5]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$uploader->refresh();
|
||||
$this->actAs($uploader)
|
||||
->postJson('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->assertJson(['errno' => 0]);
|
||||
$this->assertEquals($uploader->score - 5, User::find($uploader->uid)->score);
|
||||
// Option disabled
|
||||
option(['take_back_scores_after_deletion' => false]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$uploader->refresh();
|
||||
$this->actAs($uploader)
|
||||
->postJson('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->assertJson(['errno' => 0]);
|
||||
$this->assertEquals($uploader->score, User::find($uploader->uid)->score);
|
||||
// Private texture
|
||||
$texture = factory(Texture::class)->create([
|
||||
'uploader' => $uploader->uid,
|
||||
'public' => false
|
||||
]);
|
||||
$uploader->refresh();
|
||||
$this->actAs($uploader)
|
||||
->postJson('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->assertJson(['errno' => 0]);
|
||||
$this->assertEquals($uploader->score, User::find($uploader->uid)->score);
|
||||
|
||||
// Remove from closet
|
||||
option(['return_score' => true]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$other->closet()->attach($texture->tid, ['item_name' => 'a']);
|
||||
$other->score = 0;
|
||||
$other->save();
|
||||
$this->actAs($uploader)
|
||||
->postJson('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->assertJson(['errno' => 0]);
|
||||
$other->refresh();
|
||||
$this->assertEquals(option('score_per_closet_item'), $other->score);
|
||||
}
|
||||
|
||||
public function testPrivacy()
|
||||
@ -765,6 +809,18 @@ class SkinlibControllerTest extends TestCase
|
||||
User::find($other->uid)->score
|
||||
);
|
||||
|
||||
// Take back the score
|
||||
option(['score_award_per_texture' => 5]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$uploader->score = $texture->size * (
|
||||
option('private_score_per_storage') - option('score_per_storage')
|
||||
);
|
||||
$uploader->score += option('score_award_per_texture');
|
||||
$uploader->save();
|
||||
$this->postJson('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->assertJson(['errno' => 0]);
|
||||
$this->assertEquals(0, User::find($uploader->uid)->score);
|
||||
|
||||
// Without returning score
|
||||
option(['return_score' => false, 'private_score_per_storage' => 0]);
|
||||
$texture = factory(Texture::class)->create(['public' => 'false', 'uploader' => $uploader->uid]);
|
||||
|
Loading…
Reference in New Issue
Block a user