mirror of
https://github.com/mashirozx/sakura.git
synced 2024-11-22 23:08:14 +08:00
Add vue admin panel
This commit is contained in:
parent
64bc72864b
commit
4efaa8413a
@ -5,10 +5,24 @@ namespace Sakura\Controllers;
|
|||||||
use WP_REST_Server;
|
use WP_REST_Server;
|
||||||
use WP_REST_Request;
|
use WP_REST_Request;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
use Sakura\Lib\Exception;
|
||||||
use Sakura\Models\OptionModel;
|
use Sakura\Models\OptionModel;
|
||||||
|
|
||||||
class ConfigurationController extends BaseController
|
class ConfigurationController extends BaseController
|
||||||
{
|
{
|
||||||
|
public function public_options()
|
||||||
|
{
|
||||||
|
$keys = [
|
||||||
|
// key => default value
|
||||||
|
'title' => 'Theme Sakura',
|
||||||
|
];
|
||||||
|
$res = [];
|
||||||
|
foreach ($keys as $key => $default) {
|
||||||
|
$res[$key] = $this->sakura_options($key, $default);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
@ -23,7 +37,7 @@ class ConfigurationController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* Registers the routes for comments.
|
* Registers the routes for comments.
|
||||||
*
|
*
|
||||||
* @since 4.7.0
|
* @since 5.0.0
|
||||||
*
|
*
|
||||||
* @see register_rest_route()
|
* @see register_rest_route()
|
||||||
*/
|
*/
|
||||||
@ -39,12 +53,6 @@ class ConfigurationController extends BaseController
|
|||||||
'permission_callback' => array($this, 'get_config_permissions_check'),
|
'permission_callback' => array($this, 'get_config_permissions_check'),
|
||||||
// 'args' => $this->get_collection_params(),
|
// 'args' => $this->get_collection_params(),
|
||||||
),
|
),
|
||||||
array(
|
|
||||||
'methods' => WP_REST_Server::CREATABLE,
|
|
||||||
'callback' => array($this, 'create_config'),
|
|
||||||
'permission_callback' => array($this, 'create_config_permissions_check'),
|
|
||||||
// 'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
|
|
||||||
),
|
|
||||||
array(
|
array(
|
||||||
'methods' => WP_REST_Server::EDITABLE,
|
'methods' => WP_REST_Server::EDITABLE,
|
||||||
'callback' => array($this, 'update_config'),
|
'callback' => array($this, 'update_config'),
|
||||||
@ -75,7 +83,7 @@ class ConfigurationController extends BaseController
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create_config(WP_REST_Request $request)
|
public function update_config(WP_REST_Request $request)
|
||||||
{
|
{
|
||||||
$original = (array) $this->get_config($request);
|
$original = (array) $this->get_config($request);
|
||||||
$json = (array) self::json_validate($request->get_body());
|
$json = (array) self::json_validate($request->get_body());
|
||||||
@ -83,8 +91,7 @@ class ConfigurationController extends BaseController
|
|||||||
return $original;
|
return $original;
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = OptionModel::create($this->rest_base, $json);
|
$config = OptionModel::update($this->rest_base, $json);
|
||||||
$config = $config ? $config : OptionModel::update($this->rest_base, $json);
|
|
||||||
if (!$config) {
|
if (!$config) {
|
||||||
return new WP_Error(
|
return new WP_Error(
|
||||||
'save_config_failure',
|
'save_config_failure',
|
||||||
@ -96,25 +103,51 @@ class ConfigurationController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create_config_permissions_check(WP_REST_Request $request)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update_config(WP_REST_Request $request)
|
|
||||||
{
|
|
||||||
return $this->create_config($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update_config_permissions_check(WP_REST_Request $request)
|
public function update_config_permissions_check(WP_REST_Request $request)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function inite_theme()
|
||||||
|
{
|
||||||
|
$config = OptionModel::create($this->rest_base, (array)[]);
|
||||||
|
}
|
||||||
|
|
||||||
public static function json_validate(string $string)
|
public static function json_validate(string $string)
|
||||||
{
|
{
|
||||||
$json = json_decode($string);
|
$json = json_decode($string);
|
||||||
|
|
||||||
return $json;
|
return $json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function set_key_value(string $key, $value)
|
||||||
|
{
|
||||||
|
$json = (array) OptionModel::get($this->rest_base);
|
||||||
|
if (!$json) {
|
||||||
|
return new WP_Error(
|
||||||
|
'no_such_option',
|
||||||
|
__('Maybe you should save the configuration bufore using it.', self::$text_domain),
|
||||||
|
array('status' => 500)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$json[$key] = $value;
|
||||||
|
$config = OptionModel::update($this->rest_base, $json);
|
||||||
|
$config = $config ? $config : OptionModel::create($this->rest_base, $json);
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sakura_options(string $namespace, $default)
|
||||||
|
{
|
||||||
|
$config = (array) OptionModel::get($this->rest_base);
|
||||||
|
if (array_key_exists($namespace, $config)) {
|
||||||
|
return $config[$namespace];
|
||||||
|
} else {
|
||||||
|
$this->set_key_value($namespace, $default);
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
// translators: %s: $namespace */
|
||||||
|
// throw new Exception(
|
||||||
|
// sprintf(__("No existing database saving value or default value for option '%s'.", self::$text_domain), $namespace)
|
||||||
|
// );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ namespace Sakura\Controllers;
|
|||||||
use WP_REST_Response;
|
use WP_REST_Response;
|
||||||
use WP_REST_Request;
|
use WP_REST_Request;
|
||||||
use WP_Rewrite;
|
use WP_Rewrite;
|
||||||
use Sakura\Controllers\MenuController;
|
|
||||||
use Sakura\Controllers\CommentController;
|
|
||||||
|
|
||||||
class InitStateController extends BaseController
|
class InitStateController extends BaseController
|
||||||
{
|
{
|
||||||
@ -33,6 +31,7 @@ class InitStateController extends BaseController
|
|||||||
'menus' => (new MenuController)->get_menus(),
|
'menus' => (new MenuController)->get_menus(),
|
||||||
// 'rewrite_rules' => (new \WP_Rewrite())->rewrite_rules(),
|
// 'rewrite_rules' => (new \WP_Rewrite())->rewrite_rules(),
|
||||||
'index' => (new WP_Rewrite())->index,
|
'index' => (new WP_Rewrite())->index,
|
||||||
|
'config' => (new ConfigurationController)->public_options(),
|
||||||
'recaptcha_site_key' => '6LfHEoEbAAAAAI5p_XBlr1WxEvrsOSNQFCQNcT79', // v2 secret key: 6LfHEoEbAAAAAIh0w2I9PCcVoa0j71mO6t7fipsj
|
'recaptcha_site_key' => '6LfHEoEbAAAAAI5p_XBlr1WxEvrsOSNQFCQNcT79', // v2 secret key: 6LfHEoEbAAAAAIh0w2I9PCcVoa0j71mO6t7fipsj
|
||||||
// 'recaptcha_site_key' => '6LdKhX8bAAAAAF5HJprXtKvg3nfBJMfgd2o007PN' // v3 secret key: 6LdKhX8bAAAAAA010EXlQ32FWoYD1J2sLb8SaYLR
|
// 'recaptcha_site_key' => '6LdKhX8bAAAAAF5HJprXtKvg3nfBJMfgd2o007PN' // v3 secret key: 6LdKhX8bAAAAAA010EXlQ32FWoYD1J2sLb8SaYLR
|
||||||
);
|
);
|
||||||
|
@ -11,13 +11,19 @@ define('SAKURA_DEVEPLOMENT_HOST', 'http://127.0.0.1:9000');
|
|||||||
// PHP loaders
|
// PHP loaders
|
||||||
require_once(__DIR__ . '/loader.php');
|
require_once(__DIR__ . '/loader.php');
|
||||||
|
|
||||||
new \Sakura\Helpers\SetupHelper();
|
new Sakura\Helpers\SetupHelper();
|
||||||
new \Sakura\Helpers\WhoopsHelper();
|
new Sakura\Helpers\WhoopsHelper();
|
||||||
new \Sakura\Helpers\ViteHelper();
|
new Sakura\Helpers\ViteHelper();
|
||||||
new \Sakura\Helpers\AdminPageHelper();
|
new Sakura\Helpers\AdminPageHelper();
|
||||||
new \Sakura\Helpers\CustomMenuMetaFieldsHelper();
|
new Sakura\Helpers\CustomMenuMetaFieldsHelper();
|
||||||
new \Sakura\Helpers\CommentHelper();
|
new Sakura\Helpers\CommentHelper();
|
||||||
new \Sakura\Helpers\PostQueryHelper('post');
|
new Sakura\Helpers\PostQueryHelper('post');
|
||||||
|
|
||||||
new \Sakura\Routers\ApiRouter();
|
new Sakura\Routers\ApiRouter();
|
||||||
new \Sakura\Routers\PagesRouter();
|
new Sakura\Routers\PagesRouter();
|
||||||
|
|
||||||
|
function sakura_options(string $namespace, $default)
|
||||||
|
{
|
||||||
|
$CF = new Sakura\Controllers\ConfigurationController();
|
||||||
|
return $CF->sakura_options($namespace, $default);
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Sakura\Helpers;
|
namespace Sakura\Helpers;
|
||||||
|
|
||||||
|
use Sakura\Controllers\ConfigurationController;
|
||||||
|
|
||||||
class SetupHelper
|
class SetupHelper
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@ -19,6 +21,8 @@ class SetupHelper
|
|||||||
add_filter('excerpt_length', [$this, 'changes_post_excerpt_length'], 10);
|
add_filter('excerpt_length', [$this, 'changes_post_excerpt_length'], 10);
|
||||||
// count post views
|
// count post views
|
||||||
add_action('get_header', [$this, 'set_post_views']);
|
add_action('get_header', [$this, 'set_post_views']);
|
||||||
|
// Inite config options
|
||||||
|
add_action('after_switch_theme', [new ConfigurationController(), 'inite_theme'], 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setup()
|
public function setup()
|
||||||
|
@ -1 +1,3 @@
|
|||||||
Elevation & shadows: <https://material.io/archive/guidelines/material-design/elevation-shadows.html>
|
Elevation & shadows: <https://material.io/archive/guidelines/material-design/elevation-shadows.html>
|
||||||
|
|
||||||
|
Typegraphy: <https://material.io/design/typography/the-type-system.html#type-scale>
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"sass-loader": "^12.1.0",
|
"sass-loader": "^12.1.0",
|
||||||
"snakecase-keys": "^4.0.2",
|
"snakecase-keys": "^4.0.2",
|
||||||
|
"swiper": "^6.7.5",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.1.4",
|
"vue": "^3.1.4",
|
||||||
"vue-intl": "^6.0.6",
|
"vue-intl": "^6.0.6",
|
||||||
|
@ -1,23 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app__wrapper">
|
<div class="app__wrapper">
|
||||||
<Layout></Layout>
|
<Core></Core>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
import Layout from './Layout.vue'
|
import Core from './Core.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { Layout },
|
components: { Core },
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use './styles/index';
|
@use './index';
|
||||||
.sakura-options-page__app {
|
.sakura-options-page__app {
|
||||||
width: calc(100% - 20px);
|
width: calc(100% - 20px);
|
||||||
padding: 20px 20px 20px 0;
|
padding: 20px 20px 20px 0;
|
||||||
|
@media screen and (max-width: 782px) {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
padding: 10px 10px 10px 0;
|
||||||
|
}
|
||||||
> .app__wrapper {
|
> .app__wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
91
src/admin/Core.vue
Normal file
91
src/admin/Core.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout mdc-card mdc-card--outlined">
|
||||||
|
<div class="tab-bar__wrapper">
|
||||||
|
<TabBar v-model:current="currentTabIndex" :items="tabs"></TabBar>
|
||||||
|
</div>
|
||||||
|
<Swiper
|
||||||
|
class="tab-page__wrapper"
|
||||||
|
:slidesPerView="1"
|
||||||
|
:spaceBetween="50"
|
||||||
|
:allowTouchMove="false"
|
||||||
|
:autoHeight="true"
|
||||||
|
@swiper="handleSwiperEvent"
|
||||||
|
>
|
||||||
|
<SwiperSlide
|
||||||
|
class="tab-page__container"
|
||||||
|
v-for="(tabKey, tabKeyIndex) in tabKeys"
|
||||||
|
:key="tabKeyIndex"
|
||||||
|
>
|
||||||
|
<div class="tab-page__content mdc-typography">
|
||||||
|
<h1 class="mdc-typography--headline5">{{ options[tabKey].title }}</h1>
|
||||||
|
<div
|
||||||
|
class="row__wrapper--options"
|
||||||
|
v-for="(option, optionIndex) in options[tabKey].options"
|
||||||
|
:key="optionIndex"
|
||||||
|
>
|
||||||
|
{{ option.namespace }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, Ref, watch, nextTick } from 'vue'
|
||||||
|
import { Swiper, SwiperSlide } from 'swiper/vue'
|
||||||
|
import { Swiper as SwiperInterface } from 'swiper'
|
||||||
|
import { useInjector } from '@/hooks'
|
||||||
|
import store from './store'
|
||||||
|
import options from '@/admin/options'
|
||||||
|
import TabBar from '@/components/tabBar/TabBar.vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { TabBar, Swiper, SwiperSlide },
|
||||||
|
setup() {
|
||||||
|
// UI controllers
|
||||||
|
const currentTabIndex: Ref<number> = ref(0)
|
||||||
|
const swiperRef: Ref<SwiperInterface | null> = ref(null)
|
||||||
|
const tabKeys = Object.keys(options)
|
||||||
|
const tabs = tabKeys.map((key) => {
|
||||||
|
return { context: options[key].title, icon: options[key].icon }
|
||||||
|
})
|
||||||
|
const handleSwiperEvent = (swiper: SwiperInterface) => {
|
||||||
|
swiperRef.value = swiper
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(currentTabIndex, (current) => swiperRef.value?.slideTo(current))
|
||||||
|
nextTick(() => swiperRef.value?.updateAutoHeight(100))
|
||||||
|
|
||||||
|
// data controllers
|
||||||
|
const { config, setConfig } = useInjector(store)
|
||||||
|
|
||||||
|
return { currentTabIndex, tabKeys, tabs, options, handleSwiperEvent }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
::v-deep() {
|
||||||
|
@import 'swiper/swiper';
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
> .tab-bar__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
> .tab-page__wrapper {
|
||||||
|
width: 100%;
|
||||||
|
.tab-page__container {
|
||||||
|
width: 100%;
|
||||||
|
.tab-page__content {
|
||||||
|
width: calc(100% - 24px);
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="layout mdc-card mdc-card--outlined">
|
|
||||||
<div class="tab-bar__wrapper">
|
|
||||||
<TabBar></TabBar>
|
|
||||||
</div>
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
<br /><br /><br /><br /><br /><br /><br />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue'
|
|
||||||
import TabBar from '@/components/tabBar/TabBar.vue'
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
components: { TabBar },
|
|
||||||
setup() {},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.layout {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
> .tab-bar__wrapper {
|
|
||||||
width: 100%;
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
24
src/admin/OptionItem.vue
Normal file
24
src/admin/OptionItem.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
<div class="option__container">
|
||||||
|
<h1 class="mdc-typography--headline6">{{ $props.namespace }}</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { useInjector } from '@/hooks'
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
|
const defaultOption = {}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
options: { type: Object, default: () => defaultOption },
|
||||||
|
},
|
||||||
|
emits: [],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const { config, setConfig } = useInjector(store)
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
@ -1,11 +1,12 @@
|
|||||||
import request from '@/utils/http'
|
import request from '@/utils/http'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
postConfigJson(config: any): Promise<any> {
|
postConfigJson(data: any): Promise<any> {
|
||||||
return request({
|
return request({
|
||||||
url: '/sakura/v1/config',
|
url: '/sakura/v1/config',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: config,
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
data: data,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
@ -11,3 +11,4 @@
|
|||||||
@use "@material/tab-scroller/mdc-tab-scroller";
|
@use "@material/tab-scroller/mdc-tab-scroller";
|
||||||
@use "@material/tab-indicator/mdc-tab-indicator";
|
@use "@material/tab-indicator/mdc-tab-indicator";
|
||||||
@use "@material/tab/mdc-tab";
|
@use "@material/tab/mdc-tab";
|
||||||
|
@use '@material/typography/mdc-typography';
|
@ -3,13 +3,13 @@ import { VueSvgIconPlugin } from '@yzfe/vue3-svgicon'
|
|||||||
import '@yzfe/svgicon/lib/svgicon.css'
|
import '@yzfe/svgicon/lib/svgicon.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import { storeProviderPlugin } from '@/hooks/store'
|
import { storeProviderPlugin } from '@/hooks/store'
|
||||||
// import { auth, init, posts, comments } from './store'
|
import store from './store'
|
||||||
import { intlPlugin } from '../locales'
|
import { intlPlugin } from '../locales'
|
||||||
import UiIcon from '@/components/icon/UiIcon.vue'
|
import UiIcon from '@/components/icon/UiIcon.vue'
|
||||||
import Image from '@/components/image/Image.vue'
|
import Image from '@/components/image/Image.vue'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
// app.use(storeProviderPlugin, [auth, init, posts, comments])
|
app.use(storeProviderPlugin, [store])
|
||||||
app.use(intlPlugin)
|
app.use(intlPlugin)
|
||||||
app.use(VueSvgIconPlugin, { tagName: 'svg-icon' })
|
app.use(VueSvgIconPlugin, { tagName: 'svg-icon' })
|
||||||
app.component('UiIcon', UiIcon)
|
app.component('UiIcon', UiIcon)
|
||||||
|
51
src/admin/options.ts
Normal file
51
src/admin/options.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
export interface Options {
|
||||||
|
[tag: string]: {
|
||||||
|
title: string
|
||||||
|
icon: string
|
||||||
|
options: Array<{
|
||||||
|
namespace: string
|
||||||
|
type: string
|
||||||
|
default: any
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: Options = {
|
||||||
|
basic: {
|
||||||
|
title: 'Basic',
|
||||||
|
icon: 'fas fa-address-card',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
namespace: 'basic.siteTitle',
|
||||||
|
type: 'string',
|
||||||
|
default: 'Opps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: 'basic.userName',
|
||||||
|
type: 'string',
|
||||||
|
default: 'Mashiro',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
social: {
|
||||||
|
title: 'Social',
|
||||||
|
icon: 'fas fa-users',
|
||||||
|
options: [
|
||||||
|
{ namespace: 'social.github', type: 'string', default: 'mashirozx' },
|
||||||
|
{ namespace: 'social.weibo', type: 'string', default: 'mashirozx' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
other: {
|
||||||
|
title: 'Other',
|
||||||
|
icon: 'fas fa-umbrella',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
namespace: 'other.hello',
|
||||||
|
type: 'string',
|
||||||
|
default: 'world',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default options
|
39
src/admin/store.ts
Normal file
39
src/admin/store.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Ref } from 'vue'
|
||||||
|
import { useState } from '@/hooks'
|
||||||
|
import API from '@/api'
|
||||||
|
import camelcaseKeys from 'camelcase-keys'
|
||||||
|
import intl from '@/locales'
|
||||||
|
import options, { Options } from './options'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
|
export interface OptionStore {
|
||||||
|
[namespace: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function auth(): object {
|
||||||
|
const [config, setConfig]: [Ref<OptionStore>, (arg: OptionStore) => void] = useState({})
|
||||||
|
|
||||||
|
const updateOption = (configState: Ref<OptionStore>, key: string, value: any) => {
|
||||||
|
const config = cloneDeep(configState.value)
|
||||||
|
config[key] = value
|
||||||
|
setConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// const saveOption
|
||||||
|
// const resetOption
|
||||||
|
// const resetAllOption
|
||||||
|
|
||||||
|
// const mapOption = (configState: Ref<OptionStore>) => {
|
||||||
|
// const config = cloneDeep(configState.value)
|
||||||
|
// const data: OptionStore = {}
|
||||||
|
// Object.keys(options).forEach((tagKey) => {
|
||||||
|
// const tag = options[tagKey]
|
||||||
|
// Object.keys(tag.options).forEach((namespace) => {
|
||||||
|
// data[tagKey][namespace].payload = config[namespace]
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// return data
|
||||||
|
// }
|
||||||
|
|
||||||
|
return { config, setConfig }
|
||||||
|
}
|
@ -80,4 +80,9 @@ export default defineComponent({
|
|||||||
.tab-bar__container {
|
.tab-bar__container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.mdc-tab__icon {
|
||||||
|
font-size: 14px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
20
yarn.lock
20
yarn.lock
@ -2788,6 +2788,13 @@ dom-serializer@^1.0.1:
|
|||||||
domhandler "^4.2.0"
|
domhandler "^4.2.0"
|
||||||
entities "^2.0.0"
|
entities "^2.0.0"
|
||||||
|
|
||||||
|
dom7@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.npm.taobao.org/dom7/download/dom7-3.0.0.tgz#b861ce5d67a6becd7aaa3ad02942ff14b1240331"
|
||||||
|
integrity sha1-uGHOXWemvs16qjrQKUL/FLEkAzE=
|
||||||
|
dependencies:
|
||||||
|
ssr-window "^3.0.0-alpha.1"
|
||||||
|
|
||||||
domelementtype@1:
|
domelementtype@1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz?cache=0&sync_timestamp=1617298554829&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
resolved "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz?cache=0&sync_timestamp=1617298554829&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||||
@ -6235,6 +6242,11 @@ sprintf-js@~1.0.2:
|
|||||||
resolved "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz"
|
resolved "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
|
ssr-window@^3.0.0, ssr-window@^3.0.0-alpha.1:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.npm.taobao.org/ssr-window/download/ssr-window-3.0.0.tgz#fd5b82801638943e0cc704c4691801435af7ac37"
|
||||||
|
integrity sha1-/VuCgBY4lD4MxwTEaRgBQ1r3rDc=
|
||||||
|
|
||||||
stable@^0.1.8:
|
stable@^0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
resolved "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
resolved "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||||
@ -6438,6 +6450,14 @@ svgo@^1.3.2:
|
|||||||
unquote "~1.1.1"
|
unquote "~1.1.1"
|
||||||
util.promisify "~1.0.0"
|
util.promisify "~1.0.0"
|
||||||
|
|
||||||
|
swiper@^6.7.5:
|
||||||
|
version "6.7.5"
|
||||||
|
resolved "https://registry.nlark.com/swiper/download/swiper-6.7.5.tgz?cache=0&sync_timestamp=1625145077063&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fswiper%2Fdownload%2Fswiper-6.7.5.tgz#8f150c7281919b7d6bea00889e9dc16448e92986"
|
||||||
|
integrity sha1-jxUMcoGRm31r6gCInp3BZEjpKYY=
|
||||||
|
dependencies:
|
||||||
|
dom7 "^3.0.0"
|
||||||
|
ssr-window "^3.0.0"
|
||||||
|
|
||||||
symbol-tree@^3.2.4:
|
symbol-tree@^3.2.4:
|
||||||
version "3.2.4"
|
version "3.2.4"
|
||||||
resolved "https://registry.npm.taobao.org/symbol-tree/download/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
resolved "https://registry.npm.taobao.org/symbol-tree/download/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||||
|
Loading…
Reference in New Issue
Block a user