feat: 优化登陆状态
parent
be45f03006
commit
c9d63cde28
|
|
@ -5,12 +5,13 @@
|
|||
<component v-else :is="Component"></component>
|
||||
</router-view>
|
||||
</a-config-provider>
|
||||
<!-- <div>
|
||||
<div v-if="false">
|
||||
<my-editor></my-editor>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MyEditor from "@/components/editor/index.vue";
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@ import { Font } from "./interface";
|
|||
export * from "./interface";
|
||||
|
||||
export const FontRender = Render;
|
||||
|
||||
export const FontOption = Option;
|
||||
|
||||
export const font: Font = {
|
||||
content: "请输入文字",
|
||||
family: "microsoft yahei",
|
||||
size: 14,
|
||||
size: 24,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<slot name="content">
|
||||
<slot>
|
||||
<a-form-item label="内容">
|
||||
<a-textarea v-model="data.content" placeholder="输入内容..."></a-textarea>
|
||||
</a-form-item>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<a-select v-model="data.family" :options="FontFamilyOptions" class="w-full overflow-hidden"> </a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="大小">
|
||||
<a-input-number v-model="data.size" :min="12"> </a-input-number>
|
||||
<a-input-number v-model="data.size" :min="12" :step="2"> </a-input-number>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import InputColor from "../../components/InputColor.vue";
|
||||
import InputColor from "../../../components/InputColor.vue";
|
||||
import { AlignOptions, Font, FontFamilyOptions } from "./interface";
|
||||
|
||||
defineProps({
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { defineBlocker } from "../../config";
|
||||
import { DateData } from "./interface";
|
||||
import { Date } from "./interface";
|
||||
import { font } from "../components/font";
|
||||
import Option from "./option.vue";
|
||||
import Render from "./render.vue";
|
||||
|
||||
export default defineBlocker<DateData>({
|
||||
export default defineBlocker<Date>({
|
||||
type: "date",
|
||||
icon: "icon-park-outline-calendar",
|
||||
title: "日期组件",
|
||||
|
|
@ -25,18 +26,9 @@ export default defineBlocker<DateData>({
|
|||
actived: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
data: {
|
||||
params: {
|
||||
format: "YYYY-MM-DD",
|
||||
fontCh: {
|
||||
content: "请输入文字",
|
||||
family: "微软雅黑",
|
||||
size: 14,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
align: 3,
|
||||
},
|
||||
fontCh: { ...font, content: "YYYY-MM-DD" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
import { Font } from "../font";
|
||||
import { Block } from "../../config";
|
||||
import { Font } from "../components/font";
|
||||
|
||||
export interface DateData {
|
||||
export interface DatePrams {
|
||||
/**
|
||||
* 日期格式
|
||||
*/
|
||||
format: 'YYYY-MM-DD' | 'YYYY年MM月DD日';
|
||||
fontCh: Font;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期组件
|
||||
*/
|
||||
export type Date = Block<DatePrams>;
|
||||
|
||||
/**
|
||||
* 日期格式建议
|
||||
*/
|
||||
export const FomatSuguestions = ['YYYY-MM-DD', 'YYYY年MM月DD日'];
|
||||
|
|
@ -1,18 +1,38 @@
|
|||
<template>
|
||||
<base-option :data="data"></base-option>
|
||||
<font-option :data="data.data.fontCh"></font-option>
|
||||
<a-divider></a-divider>
|
||||
<font-option :data="data.params.fontCh">
|
||||
<a-form-item label="日期格式">
|
||||
<a-auto-complete
|
||||
v-model="data.params.fontCh.content"
|
||||
:data="FomatSuguestions"
|
||||
:allow-clear="true"
|
||||
placeholder="例如 HH:mm:ss"
|
||||
>
|
||||
<template #suffix>
|
||||
<a-popover>
|
||||
<i class="icon-park-outline-info text-gray-400 cursor-pointer"></i>
|
||||
<template #content>
|
||||
<p>YYYY 4位数的年数, 例如: 2020</p>
|
||||
<p>MM 2位数的月份, 例如: 01</p>
|
||||
<p>DD 2位数的天数, 例如: 02</p>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</font-option>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import BaseOption from "../../components/BaseOption.vue";
|
||||
import { Block } from "../../config";
|
||||
import { FontOption } from "../font";
|
||||
import { DateData } from "./interface";
|
||||
import { FontOption } from "../components/font";
|
||||
import { Date, FomatSuguestions } from "./interface";
|
||||
|
||||
defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<DateData>>,
|
||||
type: Object as PropType<Date>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -25,3 +45,4 @@ defineProps({
|
|||
}
|
||||
}
|
||||
</style>
|
||||
../components/font
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<font-render :data="data.data.fontCh">
|
||||
{{ dayjs().format(data.data.format) }}
|
||||
<font-render :data="data.params.fontCh">
|
||||
{{ dayjs().format(data.params.fontCh.content) }}
|
||||
</font-render>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dayjs } from '@/libs/dayjs';
|
||||
import { dayjs } from "@/libs/dayjs";
|
||||
import { PropType } from "vue";
|
||||
import { Block } from "../../config";
|
||||
import { FontRender } from "../font";
|
||||
import { DateData } from "./interface";
|
||||
import { FontRender } from "../components/font";
|
||||
import { Date } from "./interface";
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<DateData>>,
|
||||
type: Object as PropType<Date>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
../components/font
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
import Date from './date';
|
||||
import Text from "./text";
|
||||
import Time from "./time";
|
||||
import { Blocker } from "../config";
|
||||
|
||||
export const BlockerMap = {
|
||||
[Text.type]: Text,
|
||||
[Date.type]: Date,
|
||||
[Time.type]: Time,
|
||||
};
|
||||
const blockers: Record<string, Blocker> = import.meta.glob("./*/index.ts", { eager: true, import: "default" });
|
||||
const BlockerMap: Record<string, Blocker> = {};
|
||||
|
||||
export const getBlockerRender = (type: string) => {
|
||||
for (const blocker of Object.values(blockers)) {
|
||||
BlockerMap[blocker.type] = blocker;
|
||||
}
|
||||
|
||||
const getBlockerRender = (type: string) => {
|
||||
return BlockerMap[type].render;
|
||||
};
|
||||
|
||||
export default BlockerMap;
|
||||
export { BlockerMap, getBlockerRender };
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { defineBlocker } from "../../config";
|
||||
import Render from "./render.vue";
|
||||
import Option from "./option.vue";
|
||||
import { TextData } from "./interface";
|
||||
import { Text } from "./interface";
|
||||
import { font } from "../components/font";
|
||||
|
||||
export default defineBlocker<TextData>({
|
||||
export default defineBlocker<Text>({
|
||||
type: "text",
|
||||
icon: "icon-park-outline-text",
|
||||
title: "文本组件",
|
||||
|
|
@ -25,19 +26,14 @@ export default defineBlocker<TextData>({
|
|||
actived: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
data: {
|
||||
params: {
|
||||
marquee: false,
|
||||
marqueeSpeed: 1,
|
||||
marqueeDirection: "left",
|
||||
speed: 100,
|
||||
direction: "left",
|
||||
fontCh: {
|
||||
content: "请输入文字",
|
||||
family: "微软雅黑",
|
||||
size: 14,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
align: 3,
|
||||
...font,
|
||||
content:
|
||||
"温馨提示:乘客您好,进站检票时,持票卡的乘客请在右侧闸机上方感应区内验票,扫码过闸的乘客请将乘车码对准闸机扫码口,扇门打开后依次进闸。乘车过程中请妥善保管好车票,以免丢失。",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Font } from "../font";
|
||||
import { Block } from "../../config";
|
||||
import { Font } from "../components/font";
|
||||
|
||||
export interface TextData {
|
||||
export interface TextPrams {
|
||||
/**
|
||||
* 是否滚动
|
||||
*/
|
||||
|
|
@ -8,17 +9,25 @@ export interface TextData {
|
|||
/**
|
||||
* 滚动速度
|
||||
*/
|
||||
marqueeSpeed?: number;
|
||||
speed?: number;
|
||||
/**
|
||||
* 滚动方向
|
||||
*/
|
||||
marqueeDirection?: "left" | "right" | "up" | "down";
|
||||
direction?: "left" | "right" | "up" | "down";
|
||||
/**
|
||||
* 内容(中文)
|
||||
*/
|
||||
fontCh: Font;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本组件
|
||||
*/
|
||||
export type Text = Block<TextPrams>;
|
||||
|
||||
/**
|
||||
* 滚动方向选项
|
||||
*/
|
||||
export const DirectionOptions = [
|
||||
{
|
||||
icon: "icon-park-outline-arrow-left",
|
||||
|
|
|
|||
|
|
@ -2,47 +2,42 @@
|
|||
<div>
|
||||
<base-option :data="data"></base-option>
|
||||
</div>
|
||||
<div>
|
||||
<a-divider></a-divider>
|
||||
<div>
|
||||
<div class="muti-form-item grid grid-cols-2 gap-x-4">
|
||||
<a-form-item label="是否滚动">
|
||||
<a-radio-group type="button" v-model="data.data.marquee" class="!w-full">
|
||||
<a-radio-group type="button" v-model="data.params.marquee" class="!w-full">
|
||||
<a-radio :value="false">否</a-radio>
|
||||
<a-radio :value="true">是</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="data.data.marquee" label="滚动速度">
|
||||
<a-input-number v-model="data.data.marqueeSpeed" :min="10" :step="10"></a-input-number>
|
||||
<a-form-item :disabled="!data.params.marquee" label="滚动速度">
|
||||
<a-input-number v-model="data.params.speed" :min="10" :step="10"></a-input-number>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item v-if="data.data.marquee" label="滚动方向">
|
||||
<a-radio-group type="button" v-model="data.data.marqueeDirection" class="!w-full">
|
||||
<a-form-item :disabled="!data.params.marquee" label="滚动方向">
|
||||
<a-radio-group type="button" v-model="data.params.direction" class="!w-full">
|
||||
<a-radio v-for="item in DirectionOptions" :key="item.value" :value="item.value" class="dir-radio">
|
||||
<i :class="item.icon"></i>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-divider :margin="0"></a-divider>
|
||||
<a-divider></a-divider>
|
||||
<div>
|
||||
<div class="my-4 leading-0">
|
||||
<i class="icon-park-outline-text-style"></i>
|
||||
内容(中文)
|
||||
</div>
|
||||
<font-option :data="data.data.fontCh"></font-option>
|
||||
<font-option :data="data.params.fontCh"></font-option>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import BaseOption from "../../components/BaseOption.vue";
|
||||
import { Block } from "../../config";
|
||||
import { FontOption } from "../font";
|
||||
import { DirectionOptions, TextData } from "./interface";
|
||||
import { FontOption } from "../components/font";
|
||||
import { DirectionOptions, Text } from "./interface";
|
||||
|
||||
defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<TextData>>,
|
||||
type: Object as PropType<Text>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -55,3 +50,4 @@ defineProps({
|
|||
}
|
||||
}
|
||||
</style>
|
||||
../components/font
|
||||
|
|
@ -1,32 +1,27 @@
|
|||
<template>
|
||||
<ani-marquee
|
||||
v-if="data.data.marquee"
|
||||
:style="style"
|
||||
:speed="data.data.marqueeSpeed"
|
||||
:direction="data.data.marqueeDirection"
|
||||
>
|
||||
{{ data.data.fontCh.content }}
|
||||
<ani-marquee v-if="data.params.marquee" :style="style" :speed="data.params.speed" :direction="data.params.direction">
|
||||
{{ data.params.fontCh.content }}
|
||||
</ani-marquee>
|
||||
<font-render v-else :data="data.data.fontCh"></font-render>
|
||||
<font-render v-else :data="data.params.fontCh"></font-render>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import { FontRender, getFontStyle } from "../font";
|
||||
import { Block } from "../../config";
|
||||
import { TextData } from "./interface";
|
||||
import { FontRender, getFontStyle } from "../components/font";
|
||||
import { Text } from "./interface";
|
||||
import AniMarquee from "./marquee.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<TextData>>,
|
||||
type: Object as PropType<Text>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const style = computed(() => {
|
||||
return getFontStyle(props.data.data.fontCh);
|
||||
return getFontStyle(props.data.params.fontCh);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
../components/font
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { defineBlocker } from "../../config";
|
||||
import { TimeData } from "./interface";
|
||||
import { Time } from "./interface";
|
||||
import Option from "./option.vue";
|
||||
import Render from "./render.vue";
|
||||
import { font } from "../components/font";
|
||||
|
||||
export default defineBlocker<TimeData>({
|
||||
export default defineBlocker<Time>({
|
||||
type: "time",
|
||||
icon: "icon-park-outline-time",
|
||||
title: "时间组件",
|
||||
|
|
@ -25,18 +26,8 @@ export default defineBlocker<TimeData>({
|
|||
actived: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
data: {
|
||||
format: "HH:mm:ss",
|
||||
fontCh: {
|
||||
content: "请输入文字",
|
||||
family: "微软雅黑",
|
||||
size: 14,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
align: 3,
|
||||
},
|
||||
params: {
|
||||
fontCh: { ...font, content: "HH:mm:ss" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
import { Font } from "../font";
|
||||
import { Block } from "../../config";
|
||||
import { Font } from "../components/font";
|
||||
|
||||
export interface TimeData {
|
||||
export interface TimeParams {
|
||||
/**
|
||||
* 日期格式
|
||||
*/
|
||||
format: string;
|
||||
fontCh: Font;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间组件
|
||||
*/
|
||||
export type Time = Block<TimeParams>;
|
||||
|
||||
/**
|
||||
* 时间格式建议
|
||||
*/
|
||||
export const FomatSuguestions = ["HH:mm:ss", "HH:mm", "HH时mm分ss秒", "HH时mm分"];
|
||||
|
|
|
|||
|
|
@ -1,25 +1,38 @@
|
|||
<template>
|
||||
<base-option :data="data"></base-option>
|
||||
<a-divider></a-divider>
|
||||
<font-option :data="data.data.fontCh">
|
||||
<template #content>
|
||||
<font-option :data="data.params.fontCh">
|
||||
<a-form-item label="时间格式">
|
||||
<a-input v-model="data.data.fontCh.content" placeholder="例如 HH:mm:ss"></a-input>
|
||||
</a-form-item>
|
||||
<a-auto-complete
|
||||
v-model="data.params.fontCh.content"
|
||||
:data="FomatSuguestions"
|
||||
:allow-clear="true"
|
||||
placeholder="例如 HH:mm:ss"
|
||||
>
|
||||
<template #suffix>
|
||||
<a-popover>
|
||||
<i class="icon-park-outline-info text-gray-400 cursor-pointer"></i>
|
||||
<template #content>
|
||||
<p>HH 两位数的小时, 01 到 24</p>
|
||||
<p>mm 两位数的分钟, 00 到 59</p>
|
||||
<p>ss 两位数的秒数, 00 到 59</p>
|
||||
</template>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-auto-complete>
|
||||
</a-form-item>
|
||||
</font-option>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import BaseOption from "../../components/BaseOption.vue";
|
||||
import { Block } from "../../config";
|
||||
import { FontOption } from "../font";
|
||||
import { TimeData } from "./interface";
|
||||
import { FontOption } from "../components/font";
|
||||
import { Time, FomatSuguestions } from "./interface";
|
||||
|
||||
defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<TimeData>>,
|
||||
type: Object as PropType<Time>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -32,3 +45,4 @@ defineProps({
|
|||
}
|
||||
}
|
||||
</style>
|
||||
../components/font
|
||||
|
|
@ -1,29 +1,29 @@
|
|||
<template>
|
||||
<font-render :data="data.data.fontCh">
|
||||
{{ currentTime }}
|
||||
<font-render :data="data.params.fontCh">
|
||||
{{ time }}
|
||||
</font-render>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dayjs } from "@/libs/dayjs";
|
||||
import { PropType, onMounted, onUnmounted, ref } from "vue";
|
||||
import { Block } from "../../config";
|
||||
import { FontRender } from "../font";
|
||||
import { TimeData } from "./interface";
|
||||
import { FontRender } from "../components/font";
|
||||
import { Time } from "./interface";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object as PropType<Block<TimeData>>,
|
||||
type: Object as PropType<Time>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const currentTime = ref("");
|
||||
const timer: any = null;
|
||||
const format = computed(() => props.data.params.fontCh.content || "HH:mm:ss");
|
||||
const time = ref(dayjs().format(format.value));
|
||||
let timer: any = null;
|
||||
|
||||
onMounted(() => {
|
||||
const timer = setInterval(() => {
|
||||
currentTime.value = dayjs().format(props.data.data.format);
|
||||
timer = setInterval(() => {
|
||||
time.value = dayjs().format(format.value);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
|
|
@ -33,3 +33,4 @@ onUnmounted(() => {
|
|||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
../components/font
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
transition: all 0.3s ease;
|
||||
box-sizing: content-box;
|
||||
z-index: 99999;
|
||||
right: 0;
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
></a-input-search>
|
||||
</div>
|
||||
</div>
|
||||
<a-spin :loading="loading" :dot="true" tip="正在加载中,请稍等..." class="h-[450px] w-full">
|
||||
<a-spin :loading="loading" :dot="true" tip="加载中..." class="h-[450px] w-full">
|
||||
<div class="h-[450px] grid grid-cols-5 grid-rows-2 items-start justify-between gap-4 mt-2">
|
||||
<div
|
||||
v-for="item in images"
|
||||
|
|
@ -40,10 +40,10 @@
|
|||
<img :src="item.url" class="w-full aspect-video object-cover rounded hover:opacity-80" />
|
||||
</div>
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<div class="flex-1 truncate">
|
||||
{{ item.title }}
|
||||
<div class="flex-1 truncate text-gray-600" :class="{ 'text-brand-500': selectedKeys.includes(item.id) }">
|
||||
{{ item.title }}(<span class="text-xs text-gray-400">1280 * 800</span>)
|
||||
</div>
|
||||
<div class="text-xs text-gray-400">1280 * 800</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-input v-model="model">
|
||||
<template #prefix>
|
||||
<a-input v-model="model" placeholder="例如:#0099ff">
|
||||
<template #suffix>
|
||||
<color-picker v-model="model"></color-picker>
|
||||
</template>
|
||||
</a-input>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-input v-model="model" class="group w-full" allow-clear placeholder="暂无">
|
||||
<template #prefix>
|
||||
<a-input v-model="model" class="group w-full" allow-clear placeholder="例如: a.com/b.png">
|
||||
<template #suffix>
|
||||
<a-link @click="visible = true">选择</a-link>
|
||||
</template>
|
||||
</a-input>
|
||||
|
|
|
|||
|
|
@ -9,27 +9,9 @@ export interface Block<T = any> {
|
|||
yFixed: boolean;
|
||||
bgImage?: string;
|
||||
bgColor?: string;
|
||||
data: T;
|
||||
actived: boolean;
|
||||
resizable: boolean;
|
||||
draggable: boolean;
|
||||
meta: Record<string, any>;
|
||||
actived: boolean,
|
||||
resizable: boolean,
|
||||
draggable: boolean,
|
||||
params: T;
|
||||
}
|
||||
|
||||
export const DefaultBlock: Block = {
|
||||
id: "",
|
||||
type: "",
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 50,
|
||||
h: 50,
|
||||
xFixed: false,
|
||||
yFixed: false,
|
||||
bgImage: "",
|
||||
bgColor: "",
|
||||
data: {},
|
||||
meta: {},
|
||||
actived: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Component } from "vue";
|
||||
import { Block } from "./block";
|
||||
|
||||
interface Blocker<T = any> {
|
||||
export interface Blocker<T = any> {
|
||||
/**
|
||||
* 组件名称
|
||||
*/
|
||||
|
|
@ -21,7 +21,7 @@ interface Blocker<T = any> {
|
|||
/**
|
||||
* 组件默认值
|
||||
*/
|
||||
initial: Block<T>;
|
||||
initial: T;
|
||||
/**
|
||||
* 编辑时的渲染组件
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,13 +1,42 @@
|
|||
|
||||
export interface Container {
|
||||
/**
|
||||
* 容器id
|
||||
*/
|
||||
id: number | string;
|
||||
/**
|
||||
* X轴偏移量
|
||||
*/
|
||||
x: number;
|
||||
/**
|
||||
* Y轴偏移量
|
||||
*/
|
||||
y: number;
|
||||
/**
|
||||
* 缩放比例
|
||||
*/
|
||||
zoom: number;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* 宽度
|
||||
*/
|
||||
width: number;
|
||||
/**
|
||||
* 高度
|
||||
*/
|
||||
height: number;
|
||||
/**
|
||||
* 背景图片
|
||||
*/
|
||||
bgImage: string;
|
||||
/**
|
||||
* 背景颜色
|
||||
*/
|
||||
bgColor: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,38 @@ import { Block } from "./block";
|
|||
import { Container } from "./container";
|
||||
|
||||
export interface Context {
|
||||
/**
|
||||
* 运行时数据
|
||||
*/
|
||||
current: Ref<{
|
||||
block: Block | null;
|
||||
rightPanelCollapsed: boolean;
|
||||
}>;
|
||||
/**
|
||||
* 组件列表
|
||||
*/
|
||||
blocks: Ref<Block[]>;
|
||||
/**
|
||||
* 画布配置
|
||||
*/
|
||||
container: Ref<Container>;
|
||||
/**
|
||||
* 设置当前组件
|
||||
* @param block 组件
|
||||
* @returns
|
||||
*/
|
||||
setCurrentBlock: (block: Block | null) => void;
|
||||
/**
|
||||
* 容器自适应
|
||||
*/
|
||||
setContainerOrigin: () => void;
|
||||
/**
|
||||
* 保存数据
|
||||
*/
|
||||
saveData: () => void;
|
||||
/**
|
||||
* 加载数据
|
||||
*/
|
||||
loadData: () => void;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
<panel-header></panel-header>
|
||||
</div>
|
||||
<div class="grid grid-cols-[auto_1fr_auto]">
|
||||
<div class="bg-white shadow-[2px_0_6px_rgba(0,0,0,.05)] z-10">
|
||||
<div class="h-full overflow-hidden bg-white shadow-[2px_0_6px_rgba(0,0,0,.05)] z-10">
|
||||
<panel-left></panel-left>
|
||||
</div>
|
||||
<div class="w-full h-full">
|
||||
<panel-main></panel-main>
|
||||
</div>
|
||||
<div class="bg-white shadow-[-2px_0_6px_rgba(0,0,0,.05)]">
|
||||
<div class="h-full overflow-hidden bg-white shadow-[-2px_0_6px_rgba(0,0,0,.05)]">
|
||||
<panel-right></panel-right>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -31,6 +31,7 @@ import PanelRight from "./panel-right/index.vue";
|
|||
*/
|
||||
const current = ref({
|
||||
block: null as Block | null,
|
||||
rightPanelCollapsed: false,
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="h-full flex items-center justify-between gap-4 px-4 bg-white">
|
||||
<div class="h-full flex items-center justify-between gap-4 pl-4 pr-2 bg-white">
|
||||
<div class="flex-1">
|
||||
<div class="group">
|
||||
<span class="text-gray-400">描述: </span>
|
||||
|
|
@ -58,6 +58,16 @@
|
|||
</a-form>
|
||||
</template>
|
||||
</a-popover>
|
||||
<a-tooltip :content="current.rightPanelCollapsed ? '展开' : '折叠'" position="bottom">
|
||||
<a-button type="text" @click="current.rightPanelCollapsed = !current.rightPanelCollapsed">
|
||||
<template #icon>
|
||||
<i
|
||||
class="text-base !text-gray-600"
|
||||
:class="current.rightPanelCollapsed ? 'icon-park-outline-expand-right' : 'icon-park-outline-expand-left'"
|
||||
></i>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -68,7 +78,7 @@ import InputImage from "../../components/InputImage.vue";
|
|||
import { ContextKey } from "../../config";
|
||||
import AniTexter from "./texter.vue";
|
||||
|
||||
const { container, blocks, setContainerOrigin } = inject(ContextKey)!;
|
||||
const { container, blocks, current, setContainerOrigin } = inject(ContextKey)!;
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlockerMap from "../blocks";
|
||||
import { BlockerMap } from "../blocks";
|
||||
import { ContextKey } from "../config";
|
||||
import AniBlock from "./components/block.vue";
|
||||
import AniHeader from "./components/header.vue";
|
||||
|
|
@ -35,7 +35,7 @@ const onClick = (e: Event) => {
|
|||
if (e.target === e.currentTarget) {
|
||||
setCurrentBlock(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const isStart = ref(false);
|
||||
const position = ref({
|
||||
|
|
|
|||
|
|
@ -1,57 +1,27 @@
|
|||
<template>
|
||||
<div class="w-[248px] overflow-hidden p-3">
|
||||
<a-radio-group type="button" class="w-full mb-2">
|
||||
<a-radio value="1">基本</a-radio>
|
||||
<div class="h-full w-[248px] overflow-hidden" :style="`display: ${current.rightPanelCollapsed ? 'none' : 'block'}`">
|
||||
<div v-if="current.block" class="p-3">
|
||||
<a-radio-group type="button" default-value="1" class="w-full mb-2">
|
||||
<a-radio value="1">属性</a-radio>
|
||||
<a-radio value="2">文本</a-radio>
|
||||
</a-radio-group>
|
||||
<a-form :model="block" layout="vertical">
|
||||
<div v-if="current.block" class="muti-form-item mt-2">
|
||||
<a-form :model="{}" layout="vertical">
|
||||
<div class="muti-form-item mt-2">
|
||||
<component :is="BlockerMap[current.block.type].option" :data="current.block" />
|
||||
</div>
|
||||
<a-empty v-else :description="'选择组件后显示'" class="mt-8"></a-empty>
|
||||
</a-form>
|
||||
</div>
|
||||
<div v-else class="w-full h-full flex justify-center items-center">
|
||||
<a-empty :description="'选择组件后显示'" class="mt-8"></a-empty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { BlockerMap } from "../blocks";
|
||||
import { ContextKey } from "../config";
|
||||
import TextAttr from "./text-attr.vue";
|
||||
|
||||
const { current } = inject(ContextKey)!;
|
||||
|
||||
const item = ref<any>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 200,
|
||||
h: 100,
|
||||
bgColor: "#0099ff",
|
||||
xFixed: false,
|
||||
yFixed: false,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
});
|
||||
|
||||
const block = ref({
|
||||
x: 10,
|
||||
y: 19,
|
||||
w: 20,
|
||||
h: 5,
|
||||
volume: 39,
|
||||
textStyle: {
|
||||
family: "simsun",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
size: 14,
|
||||
color: "#33cc99",
|
||||
align: 3,
|
||||
},
|
||||
meta: {
|
||||
vFixed: false,
|
||||
hFixed: false,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@
|
|||
<div class="text-2xl">欢迎登陆</div>
|
||||
<div class="text-base text-gray-500 mt-2">{{ meridiem }}好,欢迎登陆{{ appStore.title }}!</div>
|
||||
<a-form ref="formRef" :model="model" :rules="formRules" layout="vertical" class="mt-8">
|
||||
<a-form-item field="username" label="账号" hide-asterisk>
|
||||
<a-form-item field="username" label="账号" :disabled="loading" hide-asterisk>
|
||||
<a-input v-model="model.username" placeholder="请输入账号/手机号/邮箱" allow-clear>
|
||||
<template #prefix>
|
||||
<i class="icon-park-outline-user" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="password" label="密码" hide-asterisk>
|
||||
<a-form-item field="password" label="密码" :disabled="loading" hide-asterisk>
|
||||
<a-input-password v-model="model.password" placeholder="请输入密码" allow-clear>
|
||||
<template #prefix>
|
||||
<i class="icon-park-outline-lock" />
|
||||
|
|
@ -38,11 +38,11 @@
|
|||
</a-form-item>
|
||||
<a-space :size="16" direction="vertical">
|
||||
<div class="flex items-center justify-between">
|
||||
<a-checkbox checked="rememberPassword">记住我</a-checkbox>
|
||||
<a-checkbox checked="rememberPassword" :disabled="loading">记住我</a-checkbox>
|
||||
<a-link @click="onForgetPassword">忘记密码?</a-link>
|
||||
</div>
|
||||
<a-button type="primary" html-type="submit" long class="mt-2" :loading="loading" @click="onSubmitForm">
|
||||
立即登录
|
||||
{{ loading ? '登陆中' : '立即登录' }}
|
||||
</a-button>
|
||||
<p type="text" long class="text-gray-400 text-center m-0">暂不支持其他方式登录</p>
|
||||
</a-space>
|
||||
|
|
|
|||
|
|
@ -7,57 +7,34 @@ export {}
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
AAlert: typeof import('@arco-design/web-vue')['Alert']
|
||||
AAvatar: typeof import('@arco-design/web-vue')['Avatar']
|
||||
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem']
|
||||
AAutoComplete: typeof import('@arco-design/web-vue')['AutoComplete']
|
||||
AButton: typeof import('@arco-design/web-vue')['Button']
|
||||
ACard: typeof import('@arco-design/web-vue')['Card']
|
||||
ACheckbox: typeof import('@arco-design/web-vue')['Checkbox']
|
||||
ACheckboxGroup: typeof import('@arco-design/web-vue')['CheckboxGroup']
|
||||
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
|
||||
ADatePicker: typeof import('@arco-design/web-vue')['DatePicker']
|
||||
ADivider: typeof import('@arco-design/web-vue')['Divider']
|
||||
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
||||
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
||||
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
||||
ADropdownButton: typeof import('@arco-design/web-vue')['DropdownButton']
|
||||
AEmpty: typeof import('@arco-design/web-vue')['Empty']
|
||||
AForm: typeof import('@arco-design/web-vue')['Form']
|
||||
AFormItem: typeof import('@arco-design/web-vue')['FormItem']
|
||||
AImage: typeof import('@arco-design/web-vue')['Image']
|
||||
AInput: typeof import('@arco-design/web-vue')['Input']
|
||||
AInputNumber: typeof import('@arco-design/web-vue')['InputNumber']
|
||||
AInputPassword: typeof import('@arco-design/web-vue')['InputPassword']
|
||||
AInputSearch: typeof import('@arco-design/web-vue')['InputSearch']
|
||||
ALayout: typeof import('@arco-design/web-vue')['Layout']
|
||||
ALayoutContent: typeof import('@arco-design/web-vue')['LayoutContent']
|
||||
ALayoutHeader: typeof import('@arco-design/web-vue')['LayoutHeader']
|
||||
ALayoutSider: typeof import('@arco-design/web-vue')['LayoutSider']
|
||||
ALink: typeof import('@arco-design/web-vue')['Link']
|
||||
AList: typeof import('@arco-design/web-vue')['List']
|
||||
AListItem: typeof import('@arco-design/web-vue')['ListItem']
|
||||
AListItemMeta: typeof import('@arco-design/web-vue')['ListItemMeta']
|
||||
AMenu: typeof import('@arco-design/web-vue')['Menu']
|
||||
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
|
||||
AMenuItemGroup: typeof import('@arco-design/web-vue')['MenuItemGroup']
|
||||
AModal: typeof import('@arco-design/web-vue')['Modal']
|
||||
APagination: typeof import('@arco-design/web-vue')['Pagination']
|
||||
APopover: typeof import('@arco-design/web-vue')['Popover']
|
||||
ARadio: typeof import('@arco-design/web-vue')['Radio']
|
||||
ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup']
|
||||
AScrollbar: typeof import('@arco-design/web-vue')['Scrollbar']
|
||||
ASelect: typeof import('@arco-design/web-vue')['Select']
|
||||
ASpace: typeof import('@arco-design/web-vue')['Space']
|
||||
ASpin: typeof import('@arco-design/web-vue')['Spin']
|
||||
ASwitch: typeof import('@arco-design/web-vue')['Switch']
|
||||
ATabPane: typeof import('@arco-design/web-vue')['TabPane']
|
||||
ATabs: typeof import('@arco-design/web-vue')['Tabs']
|
||||
ATag: typeof import('@arco-design/web-vue')['Tag']
|
||||
ATextarea: typeof import('@arco-design/web-vue')['Textarea']
|
||||
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
|
||||
ATree: typeof import('@arco-design/web-vue')['Tree']
|
||||
AUpload: typeof import('@arco-design/web-vue')['Upload']
|
||||
BaseOption: typeof import('./../components/editor/components/BaseOption.vue')['default']
|
||||
Block: typeof import('./../components/editor/panel-main/components/block.vue')['default']
|
||||
BreadCrumb: typeof import('./../components/breadcrumb/bread-crumb.vue')['default']
|
||||
|
|
|
|||
Loading…
Reference in New Issue