添加主题模块

This commit is contained in:
icssoa 2022-04-13 01:42:46 +08:00
parent c3b382f654
commit 112cb37802
13 changed files with 143 additions and 220 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "front-next", "name": "front-next",
"version": "5.0.3", "version": "5.1.0",
"scripts": { "scripts": {
"dev": "vite --host", "dev": "vite --host",
"build": "vite build", "build": "vite build",

View File

@ -1,57 +0,0 @@
<template>
<svg :class="svgClass" :style="style" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "vue";
import { isNumber } from "/@/cool/utils";
export default defineComponent({
name: "icon-svg",
cool: {
global: true
},
props: {
name: {
type: String
},
className: {
type: String
},
size: {
type: [String, Number]
}
},
setup(props) {
const style = ref<any>({
fontSize: isNumber(props.size) ? props.size + "px" : props.size
});
const iconName = computed<string>(() => `#icon-${props.name}`);
const svgClass = computed<Array<string>>(() => {
return ["icon-svg", `icon-svg__${props.name}`, String(props.className || "")];
});
return {
style,
iconName,
svgClass
};
}
});
</script>
<style scoped>
.icon-svg {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="app-process"> <div class="app-process">
<div class="app-process__left hidden-xs-only" @click="toScroll(true)"> <div class="app-process__back" @click="router.back">
<el-icon><arrow-left /></el-icon> <el-icon :size="15"><arrow-left /></el-icon>
</div> </div>
<div :ref="setRefs('scroller')" class="app-process__scroller"> <div :ref="setRefs('scroller')" class="app-process__scroller">
@ -16,19 +16,11 @@
@contextmenu.stop.prevent="openCM($event, item)" @contextmenu.stop.prevent="openCM($event, item)"
> >
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
<el-icon <el-icon v-if="index > 0" @mousedown.stop="onDel(Number(index))">
v-if="index > 0"
class="el-icon-close"
@mousedown.stop="onDel(Number(index))"
>
<close /> <close />
</el-icon> </el-icon>
</div> </div>
</div> </div>
<div class="app-process__right hidden-xs-only" @click="toScroll(false)">
<el-icon><arrow-right /></el-icon>
</div>
</div> </div>
</template> </template>
@ -36,11 +28,11 @@
import { watch } from "vue"; import { watch } from "vue";
import { last } from "/@/cool/utils"; import { last } from "/@/cool/utils";
import { useCool } from "/@/cool"; import { useCool } from "/@/cool";
import { ArrowLeft, ArrowRight, Close } from "@element-plus/icons-vue"; import { ArrowLeft, Close } from "@element-plus/icons-vue";
import { ContextMenu } from "@cool-vue/crud"; import { ContextMenu } from "@cool-vue/crud";
import { useBaseStore } from "/$/base"; import { useBaseStore } from "/$/base";
const { refs, setRefs, store, route, router }: any = useCool(); const { refs, setRefs, route, router } = useCool();
const { process } = useBaseStore(); const { process } = useBaseStore();
// //
@ -61,11 +53,6 @@ function scrollTo(left: number) {
}); });
} }
//
function toScroll(f: boolean) {
scrollTo(refs.value.scroller.scrollLeft + (f ? -100 : 100));
}
// //
function adScroll(index: number) { function adScroll(index: number) {
const el = refs.value[`item-${index}`]; const el = refs.value[`item-${index}`];
@ -103,8 +90,7 @@ function openCM(e: any, item: any) {
{ {
label: "关闭其他", label: "关闭其他",
callback(done) { callback(done) {
store.commit( process.set(
"SET_PROCESS",
process.list.filter((e: any) => e.value == item.value || e.value == "/") process.list.filter((e: any) => e.value == item.value || e.value == "/")
); );
done(); done();
@ -114,10 +100,7 @@ function openCM(e: any, item: any) {
{ {
label: "关闭所有", label: "关闭所有",
callback(done) { callback(done) {
store.commit( process.set(process.list.filter((e: any) => e.value == "/"));
"SET_PROCESS",
process.list.filter((e: any) => e.value == "/")
);
done(); done();
toPath(); toPath();
} }
@ -143,30 +126,22 @@ watch(
margin-bottom: 10px; margin-bottom: 10px;
padding: 0 10px; padding: 0 10px;
&__left, &__back {
&__right {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background-color: #fff; background-color: #fff;
height: 30px; height: 30px;
padding: 0 2px; padding: 0 10px;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
margin-right: 10px;
&:hover { &:hover {
background-color: #eee; background-color: #eee;
} }
} }
&__left {
margin-right: 10px;
}
&__right {
margin-left: 10px;
}
&__scroller { &__scroller {
width: 100%; width: 100%;
flex: 1; flex: 1;
@ -222,6 +197,8 @@ watch(
&.active { &.active {
span { span {
color: var(--color-primary); color: var(--color-primary);
font-weight: bold;
user-select: none;
} }
i { i {

View File

@ -155,7 +155,7 @@ export default defineComponent({
.app-slider { .app-slider {
height: 100%; height: 100%;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
background-color: var(--menu-bg-color); background-color: #2f3447;
&__logo { &__logo {
display: flex; display: flex;
@ -215,7 +215,6 @@ export default defineComponent({
.icon-svg, .icon-svg,
span { span {
// color: var(--menu-font-color);
color: #fff; color: #fff;
} }
} }
@ -224,7 +223,7 @@ export default defineComponent({
.el-sub-menu__title, .el-sub-menu__title,
&-item, &-item,
&__title { &__title {
color: var(--menu-font-color); color: #eee;
letter-spacing: 0.5px; letter-spacing: 0.5px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;

View File

@ -17,7 +17,9 @@
<!-- 工具栏 --> <!-- 工具栏 -->
<ul class="app-topbar__tools"> <ul class="app-topbar__tools">
<li>
<cl-theme /> <cl-theme />
</li>
</ul> </ul>
<!-- 用户信息 --> <!-- 用户信息 -->
@ -107,16 +109,12 @@ function onCommand(name: string) {
align-items: center; align-items: center;
list-style: none; list-style: none;
height: 45px; height: 45px;
padding: 0 10px; width: 45px;
margin-right: 10px; border-radius: 3px;
cursor: pointer; cursor: pointer;
i {
font-size: 18px;
&:hover { &:hover {
opacity: 0.8; background-color: rgba(0, 0, 0, 0.1);
}
} }
} }
} }

View File

@ -2,7 +2,9 @@
<div class="app-views" v-if="!app.loading"> <div class="app-views" v-if="!app.loading">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<keep-alive :include="caches"> <keep-alive :include="caches">
<transition name="el-fade-in-linear">
<component :is="Component" /> <component :is="Component" />
</transition>
</keep-alive> </keep-alive>
</router-view> </router-view>
</div> </div>

View File

@ -27,7 +27,7 @@ const { app } = useBaseStore();
<style lang="scss" scoped> <style lang="scss" scoped>
.page-layout { .page-layout {
display: flex; display: flex;
background-color: var(--view-bg-color); background-color: #f7f7f7;
height: 100%; height: 100%;
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;

View File

@ -59,42 +59,7 @@ import { useCrud, useUpsert, useTable, useForm, useAdvSearch } from "@cool-vue/c
const Crud = useCrud( const Crud = useCrud(
{ {
service: { service: "test"
page() {
return Promise.resolve({
list: [
{
id: 1,
name: "A"
},
{
id: 2,
name: "B"
},
{
id: 3,
name: "C"
}
],
pagination: {
total: 3,
size: 10,
page: 1
}
});
},
info() {
return Promise.resolve({
id: 1,
name: "A"
});
},
update() {
return Promise.reject({
message: "错误"
});
}
}
}, },
(app) => { (app) => {
app.refresh(); app.refresh();
@ -131,8 +96,6 @@ const Upsert = useUpsert({
}, },
{ {
label: "crud", label: "crud",
group: "2",
hidden: ":isEdit",
component: { component: {
name: "slot-crud" name: "slot-crud"
} }

View File

@ -1,35 +1,30 @@
<template> <template>
<div class="cl-theme" @click="open"> <div class="cl-theme" @click="open">
<el-badge type="primary" is-dot> <el-badge type="primary" is-dot>
<icon-svg name="icon-discover"></icon-svg> <icon-svg name="icon-discover" :size="15"></icon-svg>
</el-badge> </el-badge>
</div> </div>
<el-drawer v-model="visible" title="设置主题" size="350px"> <el-drawer v-model="visible" title="设置主题" size="350px" append-to-body>
<el-form label-position="top"> <el-form label-position="top">
<el-form-item label="推荐"> <el-form-item label="推荐">
<ul class="cl-theme__comd"> <ul class="cl-theme__comd">
<el-tooltip <li @click="setComd(item)" v-for="(item, name) in themes" :key="name">
v-for="(item, name) in themes" <div
:key="name" class="w"
:content="item.label"
placement="top"
>
<li
:style="{ :style="{
backgroundColor: item.color backgroundColor: item.color
}" }"
@click="setComd(item)"
> >
<check v-show="item.color == form.theme.color" /> <check v-show="item.color == form.theme.color" />
</div>
<span>{{ item.label }}</span>
</li> </li>
</el-tooltip>
</ul> </ul>
</el-form-item> </el-form-item>
<el-divider></el-divider> <el-form-item label="自定义主色">
<el-form-item label="主色">
<el-color-picker v-model="form.color" @change="setColor" /> <el-color-picker v-model="form.color" @change="setColor" />
<span class="ml-10px">{{ form.color }}</span> <span class="ml-10px">{{ form.color }}</span>
</el-form-item> </el-form-item>
@ -43,6 +38,7 @@ import { setTheme, themes } from "../utils";
import { module } from "/@/cool/utils"; import { module } from "/@/cool/utils";
import store from "store"; import store from "store";
import { Check } from "@element-plus/icons-vue"; import { Check } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
export default defineComponent({ export default defineComponent({
name: "cl-theme", name: "cl-theme",
@ -74,7 +70,9 @@ export default defineComponent({
function setComd(item: any) { function setComd(item: any) {
form.theme = item; form.theme = item;
form.color = item.color;
setTheme(item); setTheme(item);
ElMessage.success(`切换主题:${item.label}`);
} }
return { return {
@ -92,12 +90,24 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.cl-theme { .cl-theme {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
&__comd { &__comd {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
li { li {
display: inline-flex;
align-items: center;
list-style: none; list-style: none;
margin-right: 15px;
cursor: pointer;
.w {
height: 20px; height: 20px;
width: 20px; width: 20px;
border-radius: 3px; border-radius: 3px;
@ -105,19 +115,19 @@ export default defineComponent({
text-align: center; text-align: center;
color: #fff; color: #fff;
line-height: 20px; line-height: 20px;
cursor: pointer;
padding: 2px; padding: 2px;
box-sizing: border-box; box-sizing: border-box;
&:hover {
opacity: 0.7;
}
.el-icon { .el-icon {
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
} }
&:hover {
opacity: 0.7;
}
}
} }
} }
</style> </style>

View File

@ -1,11 +1,6 @@
export default { export default {
name: "blue" // 推荐主题:'jihei', 'guolv', 'jiangzi'
// color: "", name: "default"
// rules: { // 自定义主题色
// "--view-bg-color": "#f7f7f7", // color: "#4165d7"
// "--menu-bg-color": "#2f3447",
// "--menu-font-color": "#ffffff",
// "--topbar-bg-color": "#ffffff",
// "--topbar-font-color": "#000000"
// }
}; };

View File

@ -1,6 +1,7 @@
import store from "store"; import store from "store";
import { App } from "vue"; import { App } from "vue";
import { setTheme } from "./utils"; import { setTheme } from "./utils";
import "./static/css/index.scss";
export default { export default {
install(_: App, options: any) { install(_: App, options: any) {

View File

@ -0,0 +1,60 @@
.theme {
&-jihei {
.page-layout {
background-color: rgba(47, 52, 71, 0.9);
.app-topbar {
background-color: transparent;
color: #fff;
span {
color: #fff;
}
.el-breadcrumb {
span {
color: #ddd;
}
&__item {
&:last-child {
span {
color: #fff;
}
}
}
}
}
}
}
&-jiangzi {
.page-layout {
.app-slider__logo {
background-color: var(--color-primary);
}
.app-slider {
background-color: #fff;
.el-sub-menu__title,
.el-menu-item {
color: #000;
background-color: transparent !important;
&:hover,
&.is-active {
.icon-svg,
span {
color: var(--color-primary);
}
}
&.is-active {
border-right: 3px solid var(--color-primary);
}
}
}
}
}
}

View File

@ -20,42 +20,32 @@ function mix(color1: string, color2: string, weight: number) {
export const themes = [ export const themes = [
{ {
label: "钴蓝", label: "钴蓝",
name: "blue", name: "default",
color: "#4165d7", color: "#4165d7"
rules: {
"--menu-bg-color": "#2f3447",
"--menu-font-color": "#ffffff"
}
}, },
{ {
label: "极黑", label: "极黑",
name: "black", name: "jihei",
color: "#2f3447" color: "#222222"
}, },
{ {
label: "果绿", label: "果绿",
name: "green", name: "guolv",
color: "#51C21A" color: "#51C21A"
}, },
{ {
label: "酱紫", label: "酱紫",
name: "purple", name: "jiangzi",
color: "#d0378d", color: "#d0378d"
rules: {
"--view-bg-color": "#f7f7f7",
"--menu-bg-color": "#ffffff",
"--menu-font-color": "#000000"
}
} }
]; ];
declare interface Options { declare interface Options {
color?: string; color?: string;
name?: string; name?: string;
rules?: any;
} }
export function setTheme({ color, name, rules }: Options) { export function setTheme({ color, name }: Options) {
// 主题配置 // 主题配置
const theme = store.get("theme") || {}; const theme = store.get("theme") || {};
@ -76,16 +66,8 @@ export function setTheme({ color, name, rules }: Options) {
const item = themes.find((e) => e.name == name); const item = themes.find((e) => e.name == name);
if (item) { if (item) {
theme.name = name;
color = item.color; color = item.color;
rules = item.rules; document.querySelector("#app")?.setAttribute("class", `theme-${name}`);
switch (name) {
case "blue":
break;
case "black":
break;
}
} }
} }
@ -99,18 +81,11 @@ export function setTheme({ color, name, rules }: Options) {
el.style.setProperty(`${pre}-light-${i}`, mix(color, mixWhite, i * 0.1)); el.style.setProperty(`${pre}-light-${i}`, mix(color, mixWhite, i * 0.1));
el.style.setProperty(`${pre}-dark-${i}`, mix(color, mixBlack, i * 0.1)); el.style.setProperty(`${pre}-dark-${i}`, mix(color, mixBlack, i * 0.1));
} }
}
// 缓存 // 缓存
theme.name = name;
theme.color = color; theme.color = color;
}
if (rules) {
for (const i in rules) {
el.style.setProperty(i, rules[i]);
}
}
console.log(theme);
store.set("theme", theme); store.set("theme", theme);
} }