This commit is contained in:
pushuo 2022-07-28 16:48:33 +08:00
parent 94b7ec588a
commit 316085e4e2
9 changed files with 242 additions and 18 deletions

View File

@ -10,6 +10,7 @@ use Illuminate\Support\ServiceProvider;
use Beike\Admin\View\Components\Filter;
use Beike\Admin\View\Components\Header;
use Beike\Admin\View\Components\Sidebar;
use Beike\Admin\View\Components\Form\Image;
use Beike\Admin\View\Components\Form\Input;
use Beike\Console\Commands\MakeRootAdminUser;
use Beike\Admin\View\Components\Form\InputLocale;
@ -45,6 +46,7 @@ class AdminServiceProvider extends ServiceProvider
'form-input-locale' => InputLocale::class,
'form-switch' => SwitchRadio::class,
'form-input' => Input::class,
'form-image' => Image::class,
]);
$this->registerGuard();

View File

@ -0,0 +1,24 @@
<?php
namespace Beike\Admin\View\Components\Form;
use Illuminate\View\Component;
class Image extends Component
{
public string $name;
public string $image;
public string $value;
public function __construct(string $name, ?string $image, ?string $value)
{
$this->name = $name;
$this->image = $image ?? '';
$this->value = $value ?? '';
}
public function render()
{
return view('admin::components.form.image');
}
}

View File

@ -33,9 +33,10 @@ class Sidebar extends Component
$routeNameWithPrefix = request()->route()->getName();
$routeName = str_replace($adminName . '.', '', $routeNameWithPrefix);
if (Str::startsWith($routeName, ['products.', 'categories.'])) {
if (Str::startsWith($routeName, ['products.', 'categories.', 'brands.'])) {
$this->addLink('商品分类', admin_route('categories.index'), 'fa fa-tachometer-alt', $this->equalRoute('categories.index'));
$this->addLink('商品列表', admin_route('products.index'), 'fa fa-tachometer-alt', $this->equalRoute('products.index'));
$this->addLink('品牌管理', admin_route('brands.index'), 'fa fa-tachometer-alt', $this->equalRoute('brands.index'));
$this->addLink('回收站', admin_route('products.index', ['trashed' => 1]), 'fa fa-tachometer-alt', false);
}

View File

@ -272,6 +272,7 @@ body {
background-color: #f8f8f8;
border: 1px dashed #e2e2e2;
display: flex;
cursor: pointer;
align-items: center;
justify-content: center;
transition: all 0.2s ease;

View File

@ -93,6 +93,7 @@ body {
background-color: #f8f8f8;
border: 1px dashed #e2e2e2;
display: flex;
cursor: pointer;
align-items: center; // flex-start | center
justify-content: center; // flex-end | center | space-between
transition: all .2s ease;

View File

@ -0,0 +1,10 @@
<div class="open-file-manager variants-producr-img">
<div>
@if ($image)
<img src="{{ image_resize($image) }}" class="img-fluid">
@else
<i class="bi bi-plus fs-1 text-muted"></i>
@endif
</div>
</div>
<input type="hidden" value="{{ $value }}" name="{{ $name }}">

View File

@ -3,10 +3,10 @@
@section('title', '品牌管理')
@section('content')
<div id="brand-app" class="card">
<div id="customer-app" class="card" v-cloak>
<div class="card-body">
<div class="d-flex justify-content-between my-4">
<a href="{{ admin_route('currencies.create') }}" class="btn btn-primary">创建</a>
<div class="d-flex justify-content-between mb-4">
<button type="button" class="btn btn-primary" @click="checkedCreate('add', null)">创建品牌</button>
</div>
<table class="table">
<thead>
@ -20,21 +20,146 @@
</tr>
</thead>
<tbody>
@foreach ($brands as $brand)
<tr>
<td>{{ $brand['id'] }}</td>
<td>{{ $brand['name'] }}</td>
<td>{{ $brand['logo'] }}</td>
<td>{{ $brand['sort_order'] }}</td>
<td>{{ $brand['status'] }}</td>
<td>
<a class="btn btn-outline-secondary btn-sm"
href="{{ admin_route('brands.edit', [$brand['id']]) }}">编辑</a>
</td>
</tr>
@endforeach
<tr v-for="brand, index in brands" :key="index">
<td>@{{ brand.id }}</td>
<td>@{{ brand.name }}</td>
<td>@{{ brand.logo }}</td>
<td>@{{ brand.sort_order }}</td>
<td>@{{ brand.status }}</td>
<td>
<button class="btn btn-outline-secondary btn-sm" @click="checkedCreate('edit', index)">编辑</button>
<button class="btn btn-outline-danger btn-sm ml-1" type="button" @click="deleteItem(brand.id, index)">删除</button>
</td>
</tr>
</tbody>
</table>
{{-- {{ $brands->links('admin::vendor/pagination/bootstrap-4') }} --}}
</div>
<el-dialog title="创建用户组" :visible.sync="dialog.show" width="600px"
@close="closeDialog('form')" :close-on-click-modal="false">
<el-form ref="form" :rules="rules" :model="dialog.form" label-width="100px">
<el-form-item label="名称" prop="name">
<el-input class="mb-0" v-model="dialog.form.name" placeholder="名称"></el-input>
</el-form-item>
<el-form-item label="图标">
<vue-image v-model="dialog.form.logo"></vue-image>
</el-form-item>
<el-form-item label="排序">
<el-input class="mb-0" type="number" v-model="dialog.form.sort_order" placeholder="排序"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="dialog.form.status" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submit('form')">保存</el-button>
<el-button @click="closeDialog('form')">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
@endsection
@push('footer')
@include('admin::shared.vue-image')
<script>
new Vue({
el: '#customer-app',
data: {
brands: @json($brands->data ?? []),
source: {
// languages: ['zh-ck','en-gb']
languages: @json($languages ?? []),
},
dialog: {
show: false,
index: null,
type: 'add',
form: {
id: null,
name: '',
logo: '',
sort_order: '',
status: '',
},
},
rules: {
// password: [{required: true,message: '请输入密码',trigger: 'blur'}, ],
}
},
methods: {
checkedCreate(type, index) {
this.dialog.show = true
this.dialog.type = type
this.dialog.index = index
if (type == 'edit') {
let brand = this.brands[index];
this.dialog.form = {
id: brand.id,
name: brand.name,
logo: brand.logo,
sort_order: brand.sort_order,
status: brand.status,
}
}
},
submit(form) {
const self = this;
const type = this.dialog.type == 'add' ? 'post' : 'put';
const url = this.dialog.type == 'add' ? 'brands' : 'brands/' + this.dialog.form.id;
this.$refs[form].validate((valid) => {
if (!valid) {
this.$message.error('请检查表单是否填写正确');
return;
}
$http[type](url, this.dialog.form).then((res) => {
this.$message.success(res.message);
if (type == 'add') {
this.brands.push(res.data)
} else {
this.brands[this.dialog.index] = res.data
}
this.dialog.show = false
})
});
},
deleteItem(id, index) {
const self = this;
this.$confirm('确定要删除用户码?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
$http.delete('brands/' + id).then((res) => {
this.$message.success(res.message);
self.brands.splice(index, 1)
})
}).catch(()=>{})
},
closeDialog(form) {
Object.keys(this.dialog.form).forEach(key => this.dialog.form[key] = '')
this.dialog.show = false
}
}
})
</script>
@endpush

View File

@ -136,6 +136,7 @@
checkedCustomersCreate(type, index) {
this.dialog.show = true
this.dialog.type = type
this.dialog.index = index
if (type == 'edit') {
let group = this.customer_groups[index];
@ -174,7 +175,11 @@
$http[type](url, this.dialog.form).then((res) => {
this.$message.success(res.message);
this.customer_groups.push(res.data)
if (type == 'add') {
this.customer_groups.push(res.data)
} else {
this.customer_groups[this.dialog.index] = res.data
}
this.dialog.show = false
})
});

View File

@ -0,0 +1,55 @@
<template id="vue-image">
<div class="set-product-img wh-70" @click="updateImages">
<img v-if="value" :src="thumbnail(value)" class="img-fluid">
<i v-else class="bi bi-plus fs-1 text-muted"></i>
</div>
</template>
<script type="text/javascript">
Vue.component('vue-image', {
template: '#vue-image',
props: ['value'],
data: function () {
return {
//
}
},
methods: {
updateImages() {
const self = this;
layer.open({
type: 2,
title: '图片管理器',
shadeClose: false,
skin: 'file-manager-box',
scrollbar: false,
shade: 0.4,
area: ['1060px', '680px'],
content: `${document.querySelector('base').href}/file_manager`,
success: function(layerInstance, index) {
var iframeWindow = window[layerInstance.find("iframe")[0]["name"]];
iframeWindow.callback = (images) => {
if (images) {
self.$emit('input', images[0].path);
}
}
}
});
},
}
});
Vue.prototype.thumbnail = function thumbnail(image, width, height) {
// 判断 image 是否以 http 开头
if (image.indexOf('http') === 0) {
return image;
}
return '{{ asset('/') }}' + image;
};
</script>