feat: 添加日期和时间组件

master
绝弹 2023-10-11 22:48:31 +08:00
parent 14d68f09fb
commit be45f03006
16 changed files with 275 additions and 28 deletions

View File

@ -1,17 +1,16 @@
<template> <template>
<!-- <a-config-provider> <a-config-provider>
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<page-403 v-if="Math.random() > 0.999"></page-403> <page-403 v-if="Math.random() > 0.999"></page-403>
<component v-else :is="Component"></component> <component v-else :is="Component"></component>
</router-view> </router-view>
</a-config-provider> --> </a-config-provider>
<div> <!-- <div>
<my-editor></my-editor> <my-editor></my-editor>
</div> </div> -->
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import MyEditor from './components/editor/index.vue';
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -0,0 +1,42 @@
import { defineBlocker } from "../../config";
import { DateData } from "./interface";
import Option from "./option.vue";
import Render from "./render.vue";
export default defineBlocker<DateData>({
type: "date",
icon: "icon-park-outline-calendar",
title: "日期组件",
description: "文字",
render: Render,
option: Option,
initial: {
id: "",
type: "date",
x: 0,
y: 0,
w: 300,
h: 100,
xFixed: false,
yFixed: false,
bgImage: "",
bgColor: "",
meta: {},
actived: false,
resizable: true,
draggable: true,
data: {
format: "YYYY-MM-DD",
fontCh: {
content: "请输入文字",
family: "微软雅黑",
size: 14,
color: "#000000",
bold: false,
italic: false,
underline: false,
align: 3,
},
},
},
});

View File

@ -0,0 +1,9 @@
import { Font } from "../font";
export interface DateData {
/**
*
*/
format: 'YYYY-MM-DD' | 'YYYY年MM月DD日';
fontCh: Font;
}

View File

@ -0,0 +1,27 @@
<template>
<base-option :data="data"></base-option>
<font-option :data="data.data.fontCh"></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";
defineProps({
data: {
type: Object as PropType<Block<DateData>>,
required: true,
},
});
</script>
<style lang="less" scoped>
.dir-radio {
.arco-radio-button-content {
padding: 0;
}
}
</style>

View File

@ -0,0 +1,22 @@
<template>
<font-render :data="data.data.fontCh">
{{ dayjs().format(data.data.format) }}
</font-render>
</template>
<script setup lang="ts">
import { dayjs } from '@/libs/dayjs';
import { PropType } from "vue";
import { Block } from "../../config";
import { FontRender } from "../font";
import { DateData } from "./interface";
const props = defineProps({
data: {
type: Object as PropType<Block<DateData>>,
required: true,
},
});
</script>
<style scoped></style>

View File

@ -1,8 +1,10 @@
<template> <template>
<div> <div>
<a-form-item label="内容"> <slot name="content">
<a-textarea v-model="data.content" placeholder="输入内容..."></a-textarea> <a-form-item label="内容">
</a-form-item> <a-textarea v-model="data.content" placeholder="输入内容..."></a-textarea>
</a-form-item>
</slot>
<a-form-item label="颜色"> <a-form-item label="颜色">
<input-color v-model="data.color"></input-color> <input-color v-model="data.color"></input-color>
@ -56,7 +58,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from "vue"; import { PropType } from "vue";
import InputColor from "../../components/InputColor.vue"; import InputColor from "../../components/InputColor.vue";
import { Font, AlignOptions, FontFamilyOptions } from "./interface"; import { AlignOptions, Font, FontFamilyOptions } from "./interface";
defineProps({ defineProps({
data: { data: {

View File

@ -1,7 +1,11 @@
import Date from './date';
import Text from "./text"; import Text from "./text";
import Time from "./time";
export const BlockerMap = { export const BlockerMap = {
[Text.type]: Text, [Text.type]: Text,
[Date.type]: Date,
[Time.type]: Time,
}; };
export const getBlockerRender = (type: string) => { export const getBlockerRender = (type: string) => {

View File

@ -4,18 +4,18 @@
</div> </div>
<div> <div>
<a-divider></a-divider> <a-divider></a-divider>
<div class="muti-form-item grid grid-cols-2 gap-4"> <div class="muti-form-item grid grid-cols-2 gap-x-4">
<a-form-item label="是否滚动"> <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.data.marquee" class="!w-full">
<a-radio :value="false"></a-radio> <a-radio :value="false"></a-radio>
<a-radio :value="true"></a-radio> <a-radio :value="true"></a-radio>
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<a-form-item v-show="data.data.marquee" label="滚动速度"> <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-input-number v-model="data.data.marqueeSpeed" :min="10" :step="10"></a-input-number>
</a-form-item> </a-form-item>
</div> </div>
<a-form-item v-show="data.data.marquee" label="滚动方向"> <a-form-item v-if="data.data.marquee" label="滚动方向">
<a-radio-group type="button" v-model="data.data.marqueeDirection" class="!w-full"> <a-radio-group type="button" v-model="data.data.marqueeDirection" class="!w-full">
<a-radio v-for="item in DirectionOptions" :key="item.value" :value="item.value" class="dir-radio"> <a-radio v-for="item in DirectionOptions" :key="item.value" :value="item.value" class="dir-radio">
<i :class="item.icon"></i> <i :class="item.icon"></i>
@ -23,9 +23,9 @@
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
</div> </div>
<a-divider :margin="0"></a-divider>
<div> <div>
<a-divider></a-divider> <div class="my-4 leading-0">
<div class="mb-4 leading-0">
<i class="icon-park-outline-text-style"></i> <i class="icon-park-outline-text-style"></i>
内容(中文) 内容(中文)
</div> </div>
@ -35,10 +35,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from "vue"; import { PropType } from "vue";
import { FontOption } from "../font";
import { Block } from "../../config";
import { TextData, DirectionOptions } from "./interface";
import BaseOption from "../../components/BaseOption.vue"; import BaseOption from "../../components/BaseOption.vue";
import { Block } from "../../config";
import { FontOption } from "../font";
import { DirectionOptions, TextData } from "./interface";
defineProps({ defineProps({
data: { data: {

View File

@ -0,0 +1,42 @@
import { defineBlocker } from "../../config";
import { TimeData } from "./interface";
import Option from "./option.vue";
import Render from "./render.vue";
export default defineBlocker<TimeData>({
type: "time",
icon: "icon-park-outline-time",
title: "时间组件",
description: "文字",
render: Render,
option: Option,
initial: {
id: "",
type: "time",
x: 0,
y: 0,
w: 300,
h: 100,
xFixed: false,
yFixed: false,
bgImage: "",
bgColor: "",
meta: {},
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,
},
},
},
});

View File

@ -0,0 +1,9 @@
import { Font } from "../font";
export interface TimeData {
/**
*
*/
format: string;
fontCh: Font;
}

View File

@ -0,0 +1,34 @@
<template>
<base-option :data="data"></base-option>
<a-divider></a-divider>
<font-option :data="data.data.fontCh">
<template #content>
<a-form-item label="时间格式">
<a-input v-model="data.data.fontCh.content" placeholder="例如 HH:mm:ss"></a-input>
</a-form-item>
</template>
</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";
defineProps({
data: {
type: Object as PropType<Block<TimeData>>,
required: true,
},
});
</script>
<style lang="less" scoped>
.dir-radio {
.arco-radio-button-content {
padding: 0;
}
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<font-render :data="data.data.fontCh">
{{ currentTime }}
</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";
const props = defineProps({
data: {
type: Object as PropType<Block<TimeData>>,
required: true,
},
});
const currentTime = ref("");
const timer: any = null;
onMounted(() => {
const timer = setInterval(() => {
currentTime.value = dayjs().format(props.data.data.format);
}, 1000);
});
onUnmounted(() => {
clearInterval(timer);
});
</script>
<style scoped></style>

View File

@ -41,7 +41,7 @@
v-for="item in blocks" v-for="item in blocks"
:key="item.type" :key="item.type"
:draggable="true" :draggable="true"
:data-type="'text'" :data-type="item.type"
class="flex items-center justify-between gap-2 bg-gray-100 text-gray-500 px-2 py-1 rounded cursor-move" class="flex items-center justify-between gap-2 bg-gray-100 text-gray-500 px-2 py-1 rounded cursor-move"
> >
<div class=""> <div class="">

View File

@ -19,11 +19,11 @@
<template #help> 支持 5MB 以内大小, png jpg 格式的图片 </template> <template #help> 支持 5MB 以内大小, png jpg 格式的图片 </template>
</a-form-item> </a-form-item>
<a-form-item label="用户昵称"> <a-form-item label="用户昵称">
<a-input v-model="user.nickname" placeholder="请输入" class="!w-[432px]"></a-input> <a-input v-model="user.nickname" placeholder="请输入" class="!w-[432px]" :max-length="24" :show-word-limit="true"></a-input>
<template #help> 用作系统内显示的名称可在后台修改 </template> <template #help> 用作系统内显示的名称可在后台修改 </template>
</a-form-item> </a-form-item>
<a-form-item label="个人描述"> <a-form-item label="个人描述">
<a-textarea v-model="user.description" placeholder="请输入" class="!w-[432px] h-24"></a-textarea> <a-textarea v-model="user.description" placeholder="请输入" class="!w-[432px] h-24" :max-length="140" :show-word-limit="true"></a-textarea>
</a-form-item> </a-form-item>
<a-form-item label="性别"> <a-form-item label="性别">
<a-radio-group v-model="user.gender" type="button"> <a-radio-group v-model="user.gender" type="button">

View File

@ -1,7 +1,7 @@
<template> <template>
<BreadPage> <BreadPage>
<div class="min-h-full grid grid-cols-[auto_auto_1fr]"> <div class="min-h-full grid grid-cols-[auto_auto_1fr]">
<div class="w-[220px]"> <div class="w-[200px]">
<!-- <div class="h-6 flex items-end justify-between gap-2"> <!-- <div class="h-6 flex items-end justify-between gap-2">
<div class="text-base"> <div class="text-base">
素材分组 素材分组
@ -23,7 +23,7 @@
v-for="i in 10" v-for="i in 10"
class="group flex items-center justify-between gap-2 h-8 rounded mb-1 pl-2 hover:bg-gray-100 cursor-pointer"> class="group flex items-center justify-between gap-2 h-8 rounded mb-1 pl-2 hover:bg-gray-100 cursor-pointer">
<div> <div>
<i class="icon-file-folder"></i> <i class="icon-file-folder text-gray-600"></i>
日常素材 日常素材
<span class="text-xs text-gray-400">(10)</span> <span class="text-xs text-gray-400">(10)</span>
</div> </div>

View File

@ -7,36 +7,59 @@ export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { 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']
AButton: typeof import('@arco-design/web-vue')['Button'] AButton: typeof import('@arco-design/web-vue')['Button']
ACard: typeof import('@arco-design/web-vue')['Card']
ACheckbox: typeof import('@arco-design/web-vue')['Checkbox'] 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'] ADivider: typeof import('@arco-design/web-vue')['Divider']
ADoption: typeof import('@arco-design/web-vue')['Doption'] 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'] ADropdownButton: typeof import('@arco-design/web-vue')['DropdownButton']
AEmpty: typeof import('@arco-design/web-vue')['Empty'] AEmpty: typeof import('@arco-design/web-vue')['Empty']
AForm: typeof import('@arco-design/web-vue')['Form'] AForm: typeof import('@arco-design/web-vue')['Form']
AFormItem: typeof import('@arco-design/web-vue')['FormItem'] AFormItem: typeof import('@arco-design/web-vue')['FormItem']
AImage: typeof import('@arco-design/web-vue')['Image']
AInput: typeof import('@arco-design/web-vue')['Input'] AInput: typeof import('@arco-design/web-vue')['Input']
AInputNumber: typeof import('@arco-design/web-vue')['InputNumber'] AInputNumber: typeof import('@arco-design/web-vue')['InputNumber']
AInputPassword: typeof import('@arco-design/web-vue')['InputPassword'] AInputPassword: typeof import('@arco-design/web-vue')['InputPassword']
AInputSearch: typeof import('@arco-design/web-vue')['InputSearch'] 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'] 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'] AMenu: typeof import('@arco-design/web-vue')['Menu']
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem'] AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
AMenuItemGroup: typeof import('@arco-design/web-vue')['MenuItemGroup']
AModal: typeof import('@arco-design/web-vue')['Modal'] AModal: typeof import('@arco-design/web-vue')['Modal']
APagination: typeof import('@arco-design/web-vue')['Pagination'] APagination: typeof import('@arco-design/web-vue')['Pagination']
APopover: typeof import('@arco-design/web-vue')['Popover'] APopover: typeof import('@arco-design/web-vue')['Popover']
ARadio: typeof import('@arco-design/web-vue')['Radio'] ARadio: typeof import('@arco-design/web-vue')['Radio']
ARadioButton: typeof import('@arco-design/web-vue')['RadioButton']
ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup'] ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup']
AScrollbar: typeof import('@arco-design/web-vue')['Scrollbar']
ASelect: typeof import('@arco-design/web-vue')['Select'] ASelect: typeof import('@arco-design/web-vue')['Select']
ASpace: typeof import('@arco-design/web-vue')['Space'] ASpace: typeof import('@arco-design/web-vue')['Space']
ASpin: typeof import('@arco-design/web-vue')['Spin'] 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'] ATag: typeof import('@arco-design/web-vue')['Tag']
ATextarea: typeof import('@arco-design/web-vue')['Textarea'] ATextarea: typeof import('@arco-design/web-vue')['Textarea']
ATooltip: typeof import('@arco-design/web-vue')['Tooltip'] 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'] BaseOption: typeof import('./../components/editor/components/BaseOption.vue')['default']
Block: typeof import('./../components/editor/panel-main/components/block.vue')['default'] Block: typeof import('./../components/editor/panel-main/components/block.vue')['default']
BlockAttr: typeof import('./../components/editor/panel-right/block-attr.vue')['default']
BreadCrumb: typeof import('./../components/breadcrumb/bread-crumb.vue')['default'] BreadCrumb: typeof import('./../components/breadcrumb/bread-crumb.vue')['default']
BreadPage: typeof import('./../components/breadcrumb/bread-page.vue')['default'] BreadPage: typeof import('./../components/breadcrumb/bread-page.vue')['default']
ColorPicker: typeof import('./../components/editor/components/ColorPicker.vue')['default'] ColorPicker: typeof import('./../components/editor/components/ColorPicker.vue')['default']
@ -47,17 +70,16 @@ declare module '@vue/runtime-core' {
InputColor: typeof import('./../components/editor/components/InputColor.vue')['default'] InputColor: typeof import('./../components/editor/components/InputColor.vue')['default']
InputImage: typeof import('./../components/editor/components/InputImage.vue')['default'] InputImage: typeof import('./../components/editor/components/InputImage.vue')['default']
Marquee: typeof import('./../components/editor/blocks/text/marquee.vue')['default'] Marquee: typeof import('./../components/editor/blocks/text/marquee.vue')['default']
Option: typeof import('./../components/editor/blocks/font/option.vue')['default'] Option: typeof import('./../components/editor/blocks/date/option.vue')['default']
Page403: typeof import('./../components/error/page-403.vue')['default'] Page403: typeof import('./../components/error/page-403.vue')['default']
PanelHeader: typeof import('./../components/editor/panel-header/index.vue')['default'] PanelHeader: typeof import('./../components/editor/panel-header/index.vue')['default']
PanelLeft: typeof import('./../components/editor/panel-left/index.vue')['default'] PanelLeft: typeof import('./../components/editor/panel-left/index.vue')['default']
PanelMain: typeof import('./../components/editor/panel-main/index.vue')['default'] PanelMain: typeof import('./../components/editor/panel-main/index.vue')['default']
PanelRight: typeof import('./../components/editor/panel-right/index.vue')['default'] PanelRight: typeof import('./../components/editor/panel-right/index.vue')['default']
Preview: typeof import('./../components/editor/preview/index.vue')['default'] Preview: typeof import('./../components/editor/preview/index.vue')['default']
Render: typeof import('./../components/editor/blocks/font/render.vue')['default'] Render: typeof import('./../components/editor/blocks/date/render.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
TextAttr: typeof import('./../components/editor/panel-right/text-attr.vue')['default']
Texter: typeof import('./../components/editor/panel-main/components/texter.vue')['default'] Texter: typeof import('./../components/editor/panel-main/components/texter.vue')['default']
Toast: typeof import('./../components/toast/toast.vue')['default'] Toast: typeof import('./../components/toast/toast.vue')['default']
} }