optimize feature plugin form

wip
This commit is contained in:
pushuo 2023-03-09 11:28:22 +08:00 committed by Edward Yang
parent 1527721142
commit fc9b71e052
7 changed files with 265 additions and 254 deletions

View File

@ -123,7 +123,7 @@ class SettingsSeeder extends Seeder
*/
private function getFooterSetting(): bool|string
{
$json = '{"services":{"enable":true,"items":[{"image":"catalog\/demo\/services-icon\/4.png","title":{"en":"Material world","zh_cn":"\u7269\u884c\u5929\u4e0b"},"sub_title":{"en":"Multi - warehouse fast delivery","zh_cn":"\u591a\u4ed3\u76f4\u53d1 \u6781\u901f\u914d\u9001\u591a\u4ed3\u76f4\u53d1 \u6781\u901f\u914d\u9001"},"show":false},{"image":"catalog\/demo\/services-icon\/3.png","title":{"en":"Return all","zh_cn":"\u9000\u6362\u65e0\u5fe7"},"sub_title":{"en":"Rest assured shopping return worry","zh_cn":"\u653e\u5fc3\u8d2d\u7269 \u9000\u8fd8\u65e0\u5fe7\u653e\u5fc3\u8d2d\u7269 \u9000\u8fd8\u65e0\u5fe7"},"show":false},{"image":"catalog\/demo\/services-icon\/1.png","title":{"en":"Delicate service","zh_cn":"\u7cbe\u81f4\u670d\u52a1"},"sub_title":{"en":"Exquisite service and after-sales guarantee","zh_cn":"\u7cbe\u81f4\u670d\u52a1 \u552e\u540e\u4fdd\u969c\u7cbe\u81f4\u670d\u52a1 \u552e\u540e\u4fdd\u969c"},"show":false},{"image":"catalog\/demo\/services-icon\/2.png","title":{"en":"With reduced activity","zh_cn":"\u6ee1\u51cf\u6d3b\u52a8"},"sub_title":{"en":"If 500 yuan is exceeded, a reduction of 90 yuan will be given","zh_cn":"\u6ee1500\u5143\u7acb\u51cf90\uff0c\u65b0\u7528\u6237\u7acb\u51cf200"},"show":true}]},"content":{"intro":{"logo":"catalog\/logo.png","text":{"en":"<p>Chengdu Guangda Network Technology Co., Ltd. is a high-tech enterprise mainly engaged in Internet development. The company was established in August 2014.<\/p>","zh_cn":"<p style=\"line-height: 1.4;\"><strong>\u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280\u6709\u9650\u516c\u53f8<\/strong><\/p>\n<p style=\"line-height: 1.4;\">\u662f\u4e00\u5bb6\u4e13\u4e1a\u4e92\u8054\u7f51\u5f00\u53d1\u7684\u9ad8\u79d1\u6280\u4f01\u4e1a\uff0c\u516c\u53f8\u6210\u7acb\u4e8e2014\u5e748\u6708\u3002<\/p>\n<p style=\"line-height: 1.4;\">\u516c\u53f8\u4ee5\u4e3a\u5ba2\u6237\u521b\u9020\u4ef7\u503c\u4e3a\u6838\u5fc3\u4ef7\u503c\u89c2\uff0c\u5e2e\u52a9\u4e2d\u5c0f\u4f01\u4e1a\u5229\u7528\u4e92\u8054\u7f51\u5de5\u5177\u63d0\u5347\u4ea7\u54c1\u9500\u552e\u3002<\/p>"},"social_network":[]},"link1":{"title":{"en":"About us","zh_cn":"\u5173\u4e8e\u6211\u4eec"},"links":[{"link":"","type":"page","value":21,"text":{"en":"about us","zh_cn":"\u5173\u4e8e\u6211\u4eec"}},{"type":"page","value":18,"text":[],"link":""},{"type":"page","value":12,"text":[],"link":""},{"type":"static","value":"account.order.index","text":{"en":"","zh_cn":""},"link":""}]},"link2":{"title":{"en":"Account","zh_cn":"\u4f1a\u5458\u4e2d\u5fc3"},"links":[{"type":"static","value":"account.index","text":[],"link":""},{"type":"static","value":"account.order.index","text":[],"link":""},{"type":"static","value":"account.wishlist.index","text":[],"link":""},{"type":"static","value":"brands.index","text":{"en":"","zh_cn":""},"link":""}]},"link3":{"title":{"en":"Other","zh_cn":"\u5176\u4ed6"},"links":[{"type":"static","value":"brands.index","text":[],"link":""},{"type":"static","value":"account.index","text":{"en":"","zh_cn":""},"link":""},{"type":"page","value":20,"text":{"en":"","zh_cn":""},"link":""},{"type":"page","value":21,"text":{"en":"","zh_cn":""},"link":""}]},"contact":{"telephone":"028-87966209","address":{"en":"G8 Tianfu Software Park Chengdu China, Guangda Network Technology Co., Ltd.","zh_cn":"\u6210\u90fd\u5e02\u9ad8\u65b0\u533a\u76ca\u5dde\u5927\u9053\u4e2d\u6bb51858\u53f7\u5929\u5e9c\u8f6f\u4ef6\u56edG8 \u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280\u6709\u9650\u516c\u53f8"},"email":"marketing@guangda.work"}},"bottom":{"copyright":{"en":"<div>Technical Support <a href=\"https:\/\/beikeshop.com\/\" target=\"_blank\" rel=\"noopener\">beikeshop.com<\/a>&nbsp; - Chengdu Guangda Network Technology &copy; 2022<\/div>","zh_cn":"<div class=\"\">\u6280\u672f\u652f\u6301 <a href=\"https:\/\/beikeshop.com\/\" target=\"_blank\" rel=\"noopener\">beikeshop.com<\/a>&nbsp; - \u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280 &copy; 2022<\/div>"},"image":"catalog\/demo\/banner\/pay_icons.png"}}';
$json = '{"services":{"enable":true,"items":[{"image":"catalog\/demo\/services-icon\/4.png","title":{"en":"Material world","zh_cn":"\u7269\u884c\u5929\u4e0b"},"sub_title":{"en":"Multi - warehouse fast delivery","zh_cn":"\u591a\u4ed3\u76f4\u53d1 \u6781\u901f\u914d\u9001\u591a\u4ed3\u76f4\u53d1 \u6781\u901f\u914d\u9001"},"show":false},{"image":"catalog\/demo\/services-icon\/3.png","title":{"en":"Return all","zh_cn":"\u9000\u6362\u65e0\u5fe7"},"sub_title":{"en":"Rest assured shopping return worry","zh_cn":"\u653e\u5fc3\u8d2d\u7269 \u9000\u8fd8\u65e0\u5fe7\u653e\u5fc3\u8d2d\u7269 \u9000\u8fd8\u65e0\u5fe7"},"show":false},{"image":"catalog\/demo\/services-icon\/1.png","title":{"en":"Delicate service","zh_cn":"\u7cbe\u81f4\u670d\u52a1"},"sub_title":{"en":"Exquisite service and after-sales guarantee","zh_cn":"\u7cbe\u81f4\u670d\u52a1 \u552e\u540e\u4fdd\u969c\u7cbe\u81f4\u670d\u52a1 \u552e\u540e\u4fdd\u969c"},"show":false},{"image":"catalog\/demo\/services-icon\/2.png","title":{"en":"With reduced activity","zh_cn":"\u6ee1\u51cf\u6d3b\u52a8"},"sub_title":{"en":"If 500 yuan is exceeded, a reduction of 90 yuan will be given","zh_cn":"\u6ee1500\u5143\u7acb\u51cf90\uff0c\u65b0\u7528\u6237\u7acb\u51cf200"},"show":true}]},"content":{"intro":{"logo":"catalog\/logo.png","text":{"en":"<p>Chengdu Guangda Network Technology Co., Ltd. is a high-tech enterprise mainly engaged in Internet development. The company was established in August 2014.<\/p>","zh_cn":"<p style=\"line-height: 1.4;\"><strong>\u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280\u6709\u9650\u516c\u53f8<\/strong><\/p>\n<p style=\"line-height: 1.4;\">\u662f\u4e00\u5bb6\u4e13\u4e1a\u4e92\u8054\u7f51\u5f00\u53d1\u7684\u9ad8\u79d1\u6280\u4f01\u4e1a\uff0c\u516c\u53f8\u6210\u7acb\u4e8e2014\u5e748\u6708\u3002<\/p>\n<p style=\"line-height: 1.4;\">\u516c\u53f8\u4ee5\u4e3a\u5ba2\u6237\u521b\u9020\u4ef7\u503c\u4e3a\u6838\u5fc3\u4ef7\u503c\u89c2\uff0c\u5e2e\u52a9\u4e2d\u5c0f\u4f01\u4e1a\u5229\u7528\u4e92\u8054\u7f51\u5de5\u5177\u63d0\u5347\u4ea7\u54c1\u9500\u552e\u3002<\/p>"},"social_network":[]},"link1":{"title":{"en":"About us","zh_cn":"\u5173\u4e8e\u6211\u4eec"},"links":[{"link":"","type":"page","value":21,"text":{"en":"about us","zh_cn":"\u5173\u4e8e\u6211\u4eec"}},{"type":"page","value":18,"text":[],"link":""},{"type":"page","value":12,"text":[],"link":""},{"type":"static","value":"account.order.index","text":{"en":"","zh_cn":""},"link":""}]},"link2":{"title":{"en":"Account","zh_cn":"\u4f1a\u5458\u4e2d\u5fc3"},"links":[{"type":"static","value":"account.index","text":[],"link":""},{"type":"static","value":"account.order.index","text":[],"link":""},{"type":"static","value":"account.wishlist.index","text":[],"link":""},{"type":"static","value":"brands.index","text":{"en":"","zh_cn":""},"link":""}]},"link3":{"title":{"en":"Other","zh_cn":"\u5176\u4ed6"},"links":[{"type":"static","value":"brands.index","text":[],"link":""},{"type":"static","value":"account.index","text":{"en":"","zh_cn":""},"link":""},{"type":"page","value":20,"text":{"en":"","zh_cn":""},"link":""},{"type":"page","value":21,"text":{"en":"","zh_cn":""},"link":""}]},"contact":{"telephone":"028-87966209","address":{"en":"G8 Tianfu Software Park Chengdu China, Guangda Network Technology Co., Ltd.","zh_cn":"\u6210\u90fd\u5e02\u9ad8\u65b0\u533a\u76ca\u5dde\u5927\u9053\u4e2d\u6bb51858\u53f7\u5929\u5e9c\u8f6f\u4ef6\u56edG8 \u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280\u6709\u9650\u516c\u53f8"},"email":"marketing@guangda.work"}},"bottom":{"copyright":{"en":"<div>&nbsp; - Chengdu Guangda Network Technology &copy; 2023<\/div>","zh_cn":"<div class=\"\">&nbsp; - \u6210\u90fd\u5149\u5927\u7f51\u7edc\u79d1\u6280 &copy; 2023<\/div>"},"image":"catalog\/demo\/banner\/pay_icons.png"}}';
$setting = json_decode($json, true);
if (empty($setting)) {
throw new \Exception("无效的底部配置数据");

View File

@ -16,6 +16,18 @@ class Bootstrap
public function boot()
{
$this->addSocialData();
add_hook_blade('admin.plugin.form', function ($callback, $output, $data) {
$code = $data['plugin']->code;
if ($code == 'social') {
$view = view('Social::admin.config_form', $data)->render();
return $view;
}
return $output;
});
}
/**

View File

@ -1,192 +0,0 @@
@extends('admin::layouts.master')
@section('title', __('admin/plugin.plugins_show'))
@section('page-title-right')
<button type="button" class="btn btn-primary save-btn" onclick="app.submit('form')">{{ __('common.save') }}</button>
@endsection
@section('content')
<div class="card mb-4" id="app">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center border-bottom pb-3 mb-4">
<h6 class="mb-0">{{ $plugin->name }}</h6>
<button type="button" @click="addRow()" class="btn btn-sm btn-outline-primary">{{ __('common.add') }}</button>
</div>
@if (session('success'))
<x-admin-alert type="success" msg="{{ session('success') }}" class="mt-4"/>
@endif
<el-form ref="form" :model="form" class="form-wrap" :inline-message="true">
<table class="table table-bordered">
<thead>
<tr>
<th style="width: 150px">{{ __('Social::setting.entry_provider') }}</th>
<th>{{ __('Social::setting.entry_status') }}</th>
<th>{{ __('Social::setting.entry_key') }}</th>
<th>{{ __('Social::setting.entry_secret') }}</th>
<th>{{ __('Social::setting.entry_callback') }}</th>
<th style="width: 100px">{{ __('Social::setting.entry_sort_order') }}</th>
<th class="text-end"></th>
</tr>
</thead>
<tbody v-if="form.social.length">
<tr v-for="(item, index) in form.social" :key="index">
<td>
<el-form-item prop="provider" class="mb-0">
<el-select size="small" v-model="item.provider" @change="(e) => {providerChange(e, index)}" placeholder="{{ __('Social::setting.provider') }}">
<el-option
v-for="item in providers"
:key="item.code"
:label="item.label"
:disabled="item.disabled"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</td>
<td>
<el-form-item label="" prop="entry_status" class="mb-0">
<el-switch v-model="item.status" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</td>
<td>
<el-form-item
label="" :prop="`social[${index}].key`" class="mb-0"
:rules="[
{ required: true, message: '{{ __('common.error_required', ['name' => __('Social::setting.entry_key')]) }}', trigger: ['blur', 'change'] },]"
>
<el-input size="small" v-model="item.key" placeholder="{{ __('Social::setting.entry_key') }}"></el-input>
</el-form-item>
</td>
<td>
<el-form-item
label="" :prop="`social[${index}].secret`" class="mb-0"
:rules="[
{ required: true, message: '{{ __('common.error_required', ['name' => __('Social::setting.entry_secret')]) }}', trigger: ['blur', 'change'] },]"
>
<el-input size="small" v-model="item.secret" placeholder="{{ __('Social::setting.entry_secret') }}"></el-input>
</el-form-item>
</td>
<td>
<el-form-item label="" class="mb-0">
<div class="input-group">
<input size="small" class="form-control" :value="item.callback" placeholder="{{ __('Social::setting.entry_callback') }}"></input>
<a href="javascript:void(0)" class="btn btn-outline-secondary opacity-75 copy-code" :data-clipboard-text="item.callback" @click="copyCode"><i class="bi bi-front"></i></a>
</div>
</el-form-item>
</td>
<td>
<el-form-item label="" prop="sort_order" class="mb-0">
<el-input size="small" v-model="item.sort_order" placeholder="{{ __('Social::setting.entry_sort_order') }}"></el-input>
</el-form-item>
</td>
<td class="text-end">
<button type="button" @click="form.social.splice(index, 1)" class="btn btn-outline-danger btn-sm ml-1"><i class="bi bi-x-lg"></i></button>
</td>
</tr>
</tbody>
<tbody v-else><td colspan="7"><x-admin-no-data /></td></tbody>
</table>
</el-form>
</div>
</div>
<div class="card">
<div class="card-body">
<h6 class="border-bottom pb-3 mb-4">{{ __('Social::setting.text_help_msg') }}</h6>
<ol class="list-group list-group-numbered lh-lg text-secondary">
<li>{{ __('Social::setting.text_omni_explain') }}</li>
<li>{{ __('Social::setting.text_omni_explain_2') }}</li>
<li>{{ __('Social::setting.text_facebook_title') }}
<a target="_blank" href="https://developers.facebook.com/">Facebook</a>
</li>
<li>{{ __('Social::setting.text_twitter_title') }}
<a target="_blank" href="https://developer.twitter.com/">Twitter</a>
</li>
<li>{{ __('Social::setting.text_google_title') }}
<a target="_blank" href="https://console.developers.google.com/">Google</a>
</li>
.......
</ol>
</div>
</div>
<style>
.el-form-item__error--inline {
margin-left: 0;
}
.el-form-item__content {
line-height: 1;
}
</style>
<script src="{{ asset('vendor/clipboard/clipboard.min.js') }}"></script>
<script>
new ClipboardJS('.copy-code')
let app = new Vue({
el: '#app',
data: {
form: {
social: @json($plugin->getSetting('setting') ?? []),
},
source: {
providers: @json(Plugin\Social\Repositories\CustomerRepo::allProviders())
},
rules: {
}
},
computed: {
providers() {
let providers = @json(Plugin\Social\Repositories\CustomerRepo::allProviders());
providers.forEach(e => {
if (this.form.social.some(s => s.provider == e.code)) {
e.disabled = true;
}
})
return providers;
}
},
methods: {
submit(form) {
this.$refs[form].validate((valid) => {
if (!valid) {
this.$message.error('{{ __('common.error_form') }}');
return;
}
$http.post("{{ admin_route('plugin.social.setting') }}", this.form.social).then((res) => {
layer.msg(res.message)
})
});
},
providerChange(e, index) {
this.form.social[index].callback = `{{ shop_route('home.index') }}/social/callbacks/${e}`
},
addRow() {
let providers = this.source.providers.filter(e => !this.form.social.some(s => s.provider == e.code))
if (providers.length) {
this.form.social.push({provider: providers[0].code, status: 1, key: '', secret: '', callback: `{{ shop_route('home.index') }}/social/callbacks/${this.source.providers[0].code}`, sort_order: this.form.social.length})
}
},
copyCode() {
layer.msg('Ok');
}
}
})
</script>
@endsection

View File

@ -0,0 +1,187 @@
@section('page-title-right')
<button type="button" class="btn btn-primary save-btn" onclick="app.submit('form')">{{ __('common.save') }}</button>
@endsection
<div class="mb-5" id="app">
{{-- <div class="d-flex justify-content-between align-items-center border-bottom pb-3 mb-4">
<h6 class="mb-0">{{ $plugin->name }}</h6>
<button type="button" @click="addRow()" class="btn btn-sm btn-outline-primary">{{ __('common.add') }}</button>
</div> --}}
{{-- <button type="button" @click="addRow()" class="btn btn-sm btn-outline-primary">{{ __('common.add') }}</button> --}}
<el-form ref="form" :model="form" class="form-wrap" :inline-message="true">
<table class="table table-bordered">
<thead>
<tr>
<th style="width: 150px">{{ __('Social::setting.entry_provider') }}</th>
<th>{{ __('Social::setting.entry_status') }}</th>
<th>{{ __('Social::setting.entry_key') }}</th>
<th>{{ __('Social::setting.entry_secret') }}</th>
<th>{{ __('Social::setting.entry_callback') }}</th>
<th style="width: 100px">{{ __('Social::setting.entry_sort_order') }}</th>
<th class="text-end"></th>
</tr>
</thead>
<tbody v-if="form.social.length">
<tr v-for="(item, index) in form.social" :key="index">
<td>
<el-form-item prop="provider" class="mb-0">
<el-select size="small" v-model="item.provider" @change="(e) => {providerChange(e, index)}" placeholder="{{ __('Social::setting.provider') }}">
<el-option
v-for="item in providers"
:key="item.code"
:label="item.label"
:disabled="item.disabled"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</td>
<td>
<el-form-item label="" prop="entry_status" class="mb-0">
<el-switch v-model="item.status" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</td>
<td>
<el-form-item
label="" :prop="`social[${index}].key`" class="mb-0"
:rules="[
{ required: true, message: '{{ __('common.error_required', ['name' => __('Social::setting.entry_key')]) }}', trigger: ['blur', 'change'] },]"
>
<el-input size="small" v-model="item.key" placeholder="{{ __('Social::setting.entry_key') }}"></el-input>
</el-form-item>
</td>
<td>
<el-form-item
label="" :prop="`social[${index}].secret`" class="mb-0"
:rules="[
{ required: true, message: '{{ __('common.error_required', ['name' => __('Social::setting.entry_secret')]) }}', trigger: ['blur', 'change'] },]"
>
<el-input size="small" v-model="item.secret" placeholder="{{ __('Social::setting.entry_secret') }}"></el-input>
</el-form-item>
</td>
<td>
<el-form-item label="" class="mb-0">
<div class="input-group">
<input size="small" class="form-control" :value="item.callback" placeholder="{{ __('Social::setting.entry_callback') }}"></input>
<a href="javascript:void(0)" class="btn btn-outline-secondary opacity-75 copy-code" :data-clipboard-text="item.callback" @click="copyCode"><i class="bi bi-front"></i></a>
</div>
</el-form-item>
</td>
<td>
<el-form-item label="" prop="sort_order" class="mb-0">
<el-input size="small" v-model="item.sort_order" placeholder="{{ __('Social::setting.entry_sort_order') }}"></el-input>
</el-form-item>
</td>
<td class="text-end">
<button type="button" @click="form.social.splice(index, 1)" class="btn btn-outline-danger btn-sm ml-1"><i class="bi bi-x-lg"></i></button>
</td>
</tr>
<tr>
<td colspan="6"></td>
<td class="text-end"><button type="button" @click="addRow()" class="btn btn-sm btn-outline-primary">{{ __('common.add') }}</button></td>
</tr>
</tbody>
<tbody v-else>
<td colspan="7">
<div class="d-flex align-items-center justify-content-center p-4">
<div class="text-secondary fs-5 me-2">{{ __('common.no_data') }}</div>
<button type="button" @click="addRow()" class="btn btn-sm btn-outline-primary">{{ __('common.add') }}</button>
</div>
</td>
</tbody>
</table>
</el-form>
</div>
<h6 class="border-bottom pb-3 mb-4">{{ __('Social::setting.text_help_msg') }}</h6>
<ol class="list-group list-group-numbered lh-lg text-secondary">
<li>{{ __('Social::setting.text_omni_explain') }}</li>
<li>{{ __('Social::setting.text_omni_explain_2') }}</li>
<li>{{ __('Social::setting.text_facebook_title') }}
<a target="_blank" href="https://developers.facebook.com/">Facebook</a>
</li>
<li>{{ __('Social::setting.text_twitter_title') }}
<a target="_blank" href="https://developer.twitter.com/">Twitter</a>
</li>
<li>{{ __('Social::setting.text_google_title') }}
<a target="_blank" href="https://console.developers.google.com/">Google</a>
</li>
.......
</ol>
<style>
.el-form-item__error--inline {
margin-left: 0;
}
.el-form-item__content {
line-height: 1;
}
</style>
<script src="{{ asset('vendor/clipboard/clipboard.min.js') }}"></script>
<script>
new ClipboardJS('.copy-code')
let app = new Vue({
el: '#app',
data: {
form: {
social: @json($plugin->getSetting('setting') ?? []),
},
source: {
providers: @json(Plugin\Social\Repositories\CustomerRepo::allProviders())
},
rules: {
}
},
computed: {
providers() {
let providers = @json(Plugin\Social\Repositories\CustomerRepo::allProviders());
providers.forEach(e => {
if (this.form.social.some(s => s.provider == e.code)) {
e.disabled = true;
}
})
return providers;
}
},
methods: {
submit(form) {
this.$refs[form].validate((valid) => {
if (!valid) {
this.$message.error('{{ __('common.error_form') }}');
return;
}
$http.post("{{ admin_route('plugin.social.setting') }}", this.form.social).then((res) => {
layer.msg(res.message)
})
});
},
providerChange(e, index) {
this.form.social[index].callback = `{{ shop_route('home.index') }}/social/callbacks/${e}`
},
addRow() {
let providers = this.source.providers.filter(e => !this.form.social.some(s => s.provider == e.code))
if (providers.length) {
this.form.social.push({provider: providers[0].code, status: 1, key: '', secret: '', callback: `{{ shop_route('home.index') }}/social/callbacks/${this.source.providers[0].code}`, sort_order: this.form.social.length})
}
},
copyCode() {
layer.msg('Ok');
}
}
})
</script>

View File

@ -3,82 +3,87 @@
@section('title', __('admin/plugin.plugins_show'))
@section('content')
<div class="card">
<div class="card h-min-600">
<div class="card-body">
<h6 class="border-bottom pb-3 mb-4">{{ $plugin->getLocaleName() }}</h6>
@if (session('success'))
<x-admin-alert type="success" msg="{{ session('success') }}" class="mt-4"/>
@endif
<form class="needs-validation" novalidate action="{{ admin_route('plugins.update', [$plugin->code]) }}" method="POST">
@csrf
{{ method_field('put') }}
@foreach ($plugin->getColumns() as $column)
@if ($column['type'] == 'string')
<x-admin-form-input
:name="$column['name']"
:title="$column['label']"
:error="$errors->first($column['name'])"
:required="$column['required'] ? true : false"
:value="old($column['name'], $column['value'] ?? '')" />
@endif
@hookwrapper('admin.plugin.form')
<form class="needs-validation" novalidate action="{{ admin_route('plugins.update', [$plugin->code]) }}" method="POST">
@csrf
{{ method_field('put') }}
@if ($column['type'] == 'select')
<x-admin-form-select
@foreach ($plugin->getColumns() as $column)
@if ($column['type'] == 'string')
<x-admin-form-input
:name="$column['name']"
:title="$column['label']"
:error="$errors->first($column['name'])"
:required="$column['required'] ? true : false"
:value="old($column['name'], $column['value'] ?? '')" />
@endif
@if ($column['type'] == 'select')
<x-admin-form-select
:name="$column['name']"
:title="$column['label']"
:value="old($column['name'], $column['value'] ?? '')"
:options="$column['options']">
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-select>
@endif
@if ($column['type'] == 'bool')
<x-admin-form-switch
:name="$column['name']"
:title="$column['label']"
:value="old($column['name'], $column['value'] ?? '')">
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-switch>
@endif
@if ($column['type'] == 'textarea')
<x-admin-form-textarea
:name="$column['name']"
:title="$column['label']"
:required="$column['required'] ? true : false"
:value="old($column['name'], $column['value'] ?? '')">
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-textarea>
@endif
@if ($column['type'] == 'rich-text')
<x-admin-form-rich-text
:name="$column['name']"
:title="$column['label']"
:value="old($column['name'], $column['value'] ?? '')"
:options="$column['options']">
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-select>
@endif
@if ($column['type'] == 'bool')
<x-admin-form-switch
:name="$column['name']"
:title="$column['label']"
:value="old($column['name'], $column['value'] ?? '')">
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-switch>
@endif
@if ($column['type'] == 'textarea')
<x-admin-form-textarea
:name="$column['name']"
:title="$column['label']"
:required="$column['required'] ? true : false"
:value="old($column['name'], $column['value'] ?? '')">
:multiple="$column['multiple']"
>
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-textarea>
</x-admin-form-rich-text>
@endif
@if ($column['type'] == 'rich-text')
<x-admin-form-rich-text
:name="$column['name']"
:title="$column['label']"
:value="old($column['name'], $column['value'] ?? '')"
:required="$column['required'] ? true : false"
:multiple="$column['multiple']"
>
@if (isset($column['description']))
<div class="help-text font-size-12 lh-base">{{ $column['description'] }}</div>
@endif
</x-admin-form-rich-text>
@endif
@endforeach
@endforeach
<x-admin::form.row title="">
<button type="submit" class="btn btn-primary btn-lg mt-4">{{ __('common.submit') }}</button>
</x-admin::form.row>
</form>
<x-admin::form.row title="">
<button type="submit" class="btn btn-primary btn-lg mt-4">{{ __('common.submit') }}</button>
</x-admin::form.row>
</form>
@endhookwrapper
</div>
</div>
<img src="https://beikeshop.com/install/plugin.jpg?version={{ config('beike.version') }}&build_date={{ config('beike.build') }}&plugin={{ $plugin->code }}" class="d-none">
@endsection

View File

@ -75,7 +75,6 @@
</div>
@endhookwrapper
@hook('footer.contact.after')
</div>
</div>
</div>
@ -85,7 +84,7 @@
<div class="container">
<div class="row align-items-center">
<div class="col">
{!! $footer_content['bottom']['copyright'][$locale] ?? '' !!}
<div class="d-flex">Powered By &nbsp;<a href="https://beikeshop.com/" target="_blank" rel="noopener">BeikeShop</a> {!! $footer_content['bottom']['copyright'][$locale] ?? '' !!}</div>
</div>
@if (isset($footer_content['bottom']['image']) && $footer_content['bottom']['image'])
<div class="col-auto right-img">

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', system_setting('base.meta_title', 'BeikeShop开源好用的跨境电商系统 - BeikeShop官网'))</title>
<title>@yield('title', system_setting('base.meta_title', 'BeikeShop开源好用的跨境电商系统 - BeikeShop官网') . ' Powered By BeikeShop')</title>
<meta name="keywords" content="@yield('keywords', system_setting('base.meta_keywords'))">
<meta name="description" content="@yield('description', system_setting('base.meta_description'))">
<base href="{{ $shop_base_url }}">