添加主题模块

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

View File

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

View File

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

View File

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

View File

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

View File

@ -59,42 +59,7 @@ import { useCrud, useUpsert, useTable, useForm, useAdvSearch } from "@cool-vue/c
const Crud = useCrud(
{
service: {
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: "错误"
});
}
}
service: "test"
},
(app) => {
app.refresh();
@ -131,8 +96,6 @@ const Upsert = useUpsert({
},
{
label: "crud",
group: "2",
hidden: ":isEdit",
component: {
name: "slot-crud"
}

View File

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

View File

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

View File

@ -1,6 +1,7 @@
import store from "store";
import { App } from "vue";
import { setTheme } from "./utils";
import "./static/css/index.scss";
export default {
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 = [
{
label: "钴蓝",
name: "blue",
color: "#4165d7",
rules: {
"--menu-bg-color": "#2f3447",
"--menu-font-color": "#ffffff"
}
name: "default",
color: "#4165d7"
},
{
label: "极黑",
name: "black",
color: "#2f3447"
name: "jihei",
color: "#222222"
},
{
label: "果绿",
name: "green",
name: "guolv",
color: "#51C21A"
},
{
label: "酱紫",
name: "purple",
color: "#d0378d",
rules: {
"--view-bg-color": "#f7f7f7",
"--menu-bg-color": "#ffffff",
"--menu-font-color": "#000000"
}
name: "jiangzi",
color: "#d0378d"
}
];
declare interface Options {
color?: string;
name?: string;
rules?: any;
}
export function setTheme({ color, name, rules }: Options) {
export function setTheme({ color, name }: Options) {
// 主题配置
const theme = store.get("theme") || {};
@ -76,16 +66,8 @@ export function setTheme({ color, name, rules }: Options) {
const item = themes.find((e) => e.name == name);
if (item) {
theme.name = name;
color = item.color;
rules = item.rules;
switch (name) {
case "blue":
break;
case "black":
break;
}
document.querySelector("#app")?.setAttribute("class", `theme-${name}`);
}
}
@ -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}-dark-${i}`, mix(color, mixBlack, i * 0.1));
}
// 缓存
theme.color = color;
}
if (rules) {
for (const i in rules) {
el.style.setProperty(i, rules[i]);
}
}
console.log(theme);
// 缓存
theme.name = name;
theme.color = color;
store.set("theme", theme);
}