feat: 添加表单模块 输入框组件

This commit is contained in:
yangmi 2022-07-27 15:16:53 +08:00
parent 1c72bc47df
commit 63a598b423
40 changed files with 445 additions and 29 deletions

View File

@ -16,7 +16,11 @@ module.exports = {
'vue/setup-compiler-macros': true,
node: true,
},
extends: ["plugin:vue/vue3-essential", "eslint:recommended"],
extends: [
"plugin:vue/vue3-essential",
"eslint:recommended",
"./.eslintrc-auto-import.json"
],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",

2
.gitignore vendored
View File

@ -1,4 +1,5 @@
node_modules
.history
.husky
.DS_Store
dist
@ -7,4 +8,5 @@ dist-ssr
.vscode
stats.html
auto-imports.d.ts
.eslintrc-auto-import.json
components.d.ts

View File

@ -0,0 +1,14 @@
import { CreateComponentType } from '@/packages/index.d';
import { publicConfig } from '@/packages/public/publicConfig';
import { ComponentConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
}
export default class Config extends publicConfig implements CreateComponentType
{
public key = ComponentConfig.key
public chartConfig = cloneDeep(ComponentConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,27 @@
<template>
<CollapseItem>
<SettingItem>
<SettingItemBox></SettingItemBox>
</SettingItem>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
</script>
<style></style>

View File

@ -0,0 +1,13 @@
import { FormCategoryEnum, FormCategoryEnumName } from './../../index.d';
import { PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { getComponentConfig } from '@/utils/componets';
export const ComponentConfig = getComponentConfig({
key: 'InputCommon',
title: '输入框',
category: FormCategoryEnum.INPUT,
categoryName: FormCategoryEnumName.INPUT,
package: PackagesCategoryEnum.FORM,
chartFrame: ChartFrameEnum.COMMON
})

View File

@ -0,0 +1,18 @@
<template>
<div>your component</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
</script>
<style></style>

View File

@ -0,0 +1,13 @@
export enum COMPONENT_SIZE_ENUM {
TINY = 'tiny',
SMALL = 'small',
MEDIUM = 'medium',
LARGE = 'large'
}
export const componentSizeMap = new Map([
[COMPONENT_SIZE_ENUM.TINY, '迷你'],
[COMPONENT_SIZE_ENUM.SMALL, '小'],
[COMPONENT_SIZE_ENUM.MEDIUM, '中'],
[COMPONENT_SIZE_ENUM.LARGE, '大'],
])

View File

@ -30,9 +30,25 @@ export const EventTriggerTypeMap = new Map(
]
)
export const CommonEventMap = new Map(
// 数据组件事件
export enum DATA_COMPONENT_EVENT_ENUM {
LOAD_DATA ='loadData'
}
export const dataComponentEventMap = new Map(
[
['forceUpdate', '强制更新'],
[DATA_COMPONENT_EVENT_ENUM.LOAD_DATA, '加载数据'],
]
)
// 公共事件
export enum COMMON_EVENT_ENUM {
FORCE_UPDATE ='forceUpdate'
}
export const CommonEventMap = new Map(
[
[COMMON_EVENT_ENUM.FORCE_UPDATE, '强制更新'],
]
)

View File

@ -5,6 +5,7 @@ import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
import { useIntervalFn } from '@vueuse/core'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
@ -21,11 +22,17 @@ export const useChartDataFetch = (
updateCallback?: (...args: any) => any
) => {
const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0
let pauseFn: any = null
let resumeFn: any = null
let fetchFn: any = null
const requestIntervalFn = () => {
const chartEditStore = useChartEditStore()
pauseFn = null
resumeFn = null
fetchFn = null
// 全局数据
const {
requestOriginUrl,
@ -55,9 +62,7 @@ export const useChartDataFetch = (
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
clearInterval(fetchInterval)
const fetchFn = async () => {
fetchFn = async (callback: () => any) => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.requestGlobalConfig))
if (res && res.data) {
try {
@ -73,6 +78,7 @@ export const useChartDataFetch = (
}
}
}
callback && callback()
} catch (error) {
console.error(error)
}
@ -87,11 +93,17 @@ export const useChartDataFetch = (
// 单位
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
if (time) {
const { pause, resume, isActive } = useIntervalFn(fetchFn, intervalUnitHandle(time, unit))
pauseFn = pause
resumeFn = resume
}
}
} catch (error) {}
} catch (error) {
console.error(error)
}
}
isPreview() && requestIntervalFn()
return { vChartRef }
return { vChartRef, pauseFn, resumeFn, fetchFn }
}

View File

@ -0,0 +1,13 @@
import { dataComponentEventMap } from '@/enums/eventEnum';
import { OptionsType } from '@/packages/index.d';
import { mapToOptions } from '@/utils';
//内置方法
export const methodList = mapToOptions(dataComponentEventMap) as Array<OptionsType>
export const config = {
key: 'BarCommon',
title: '柱状图',
methodList
}

View File

@ -2,10 +2,10 @@ import image from '@/assets/images/chart/charts/bar_x.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { getComponentConfig } from '@/utils'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
import { config } from './enum'
export const BarCommonConfig: ConfigType = getComponentConfig({
key: 'BarCommon',
title: '柱状图',
...config,
category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,

View File

@ -49,5 +49,15 @@ const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
const { vChartRef, pauseFn, resumeFn, fetchFn } = useChartDataFetch(props.chartConfig, useChartEditStore)
defineExpose({
loadData: async () => {
if(fetchFn){
pauseFn()
await fetchFn()
resumeFn()
}
}
})
</script>

View File

@ -0,0 +1,14 @@
import { CreateComponentType } from '@/packages/index.d';
import { publicConfig } from '@/packages/public/publicConfig';
import { DatePickerCommonConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
}
export default class Config extends publicConfig implements CreateComponentType
{
public key = DatePickerCommonConfig.key
public chartConfig = cloneDeep(DatePickerCommonConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,7 @@
<template>
<div>config</div>
</template>
<script setup lang="ts"></script>
<style></style>

View File

@ -0,0 +1,13 @@
import { FormCategoryEnum, FormCategoryEnumName } from '../../index.d';
import { PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { getComponentConfig } from '@/utils/componets';
export const DatePickerCommonConfig = getComponentConfig({
key: 'DatePickerCommon',
title: '日期选择',
category: FormCategoryEnum.DATE_PICKER,
categoryName: FormCategoryEnumName.DATE_PICKER,
package: PackagesCategoryEnum.FORM,
chartFrame: ChartFrameEnum.COMMON
})

View File

@ -0,0 +1,13 @@
<template>
<div>
<span>DATE_PICKER</span>
</div>
</template>
<script setup lang='ts'>
defineProps({})
</script>
<style>
</style>

View File

@ -0,0 +1,3 @@
import { DatePickerCommonConfig } from './DatePickerCommon/index'
export default [ DatePickerCommonConfig ]

View File

@ -0,0 +1,24 @@
import { CreateComponentType } from '@/packages/index.d';
import { publicConfig } from '@/packages/public/publicConfig';
import { InputCommonConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import { COMPONENT_SIZE_ENUM } from '@/enums/componentEnum';
export const option = {
// 参考 https://www.naiveui.com/zh-CN/os-theme/components/input
inputOption: {
clearable: true,
maxlength: 20,
placeholder: '',
round: false,
showCount: false,
size: COMPONENT_SIZE_ENUM.MEDIUM
}
}
export default class Config extends publicConfig implements CreateComponentType
{
public key = InputCommonConfig.key
public chartConfig = cloneDeep(InputCommonConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,48 @@
<template>
<CollapseItem name="属性配置" :expanded="true">
<n-form label-placement="left" label-align="right" label-width="auto">
<n-form-item label="可清空">
<n-switch v-model:value="inputOption.clearable"></n-switch>
</n-form-item>
<n-form-item label="最大长度">
<n-input-number v-model:value="inputOption.maxlength" :min="0" :max="200" :precision="0"/>
</n-form-item>
<n-form-item label="placeholder">
<n-input v-model:value="inputOption.placeholder"/>
</n-form-item>
<n-form-item label="圆角">
<n-switch v-model:value="inputOption.round"></n-switch>
</n-form-item>
<n-form-item label="显示字数统计">
<n-switch v-model:value="inputOption.showCount"></n-switch>
</n-form-item>
<n-form-item label="尺寸">
<n-select v-model:value="inputOption.size" :options="mapToOptions(componentSizeMap)"></n-select>
</n-form-item>
</n-form>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, toRefs } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { mapToOptions } from '@/utils';
import { componentSizeMap } from '@/enums/componentEnum'
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true
}
})
const { inputOption } = toRefs(props.optionData)
</script>
<style></style>

View File

@ -0,0 +1,13 @@
import { FormCategoryEnum, FormCategoryEnumName } from './../../index.d';
import { PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { getComponentConfig } from '@/utils/componets';
export const InputCommonConfig = getComponentConfig({
key: 'InputCommon',
title: '输入框',
category: FormCategoryEnum.INPUT,
categoryName: FormCategoryEnumName.INPUT,
package: PackagesCategoryEnum.FORM,
chartFrame: ChartFrameEnum.COMMON
})

View File

@ -0,0 +1,23 @@
<template>
<n-form-item>
<n-input v-bind="inputOption" v-model:value="val"/>
</n-form-item>
</template>
<script setup lang="ts">
import { PropType, computed, ref } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const inputOption = computed(() => props.chartConfig.option.inputOption)
const val = ref('')
</script>
<style></style>

View File

@ -0,0 +1,3 @@
import { InputCommonConfig } from './InputCommon/index'
export default [ InputCommonConfig ]

View File

@ -0,0 +1,14 @@
import { CreateComponentType } from '@/packages/index.d';
import { publicConfig } from '@/packages/public/publicConfig';
import { SelectCommonConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
}
export default class Config extends publicConfig implements CreateComponentType
{
public key = SelectCommonConfig.key
public chartConfig = cloneDeep(SelectCommonConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,7 @@
<template>
<div>config</div>
</template>
<script setup lang="ts"></script>
<style></style>

View File

@ -0,0 +1,13 @@
import { FormCategoryEnum, FormCategoryEnumName } from './../../index.d';
import { PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { getComponentConfig } from '@/utils/componets';
export const SelectCommonConfig = getComponentConfig({
key: 'SelectCommon',
title: '下拉框',
category: FormCategoryEnum.SELECT,
categoryName: FormCategoryEnumName.SELECT,
package: PackagesCategoryEnum.FORM,
chartFrame: ChartFrameEnum.COMMON
})

View File

@ -0,0 +1,13 @@
<template>
<div>
select
</div>
</template>
<script setup lang='ts'>
defineProps({})
</script>
<style>
</style>

View File

@ -0,0 +1,3 @@
import { SelectCommonConfig } from './SelectCommon/index'
export default [ SelectCommonConfig ]

13
src/packages/components/Form/index.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
export enum FormCategoryEnum {
INPUT = 'Inputs',
SELECT = 'Selects',
DATE_PICKER = 'DatePickers',
MORE = 'Mores'
}
export enum FormCategoryEnumName {
INPUT = '输入框',
SELECT = '下拉框',
DATE_PICKER = '日期选择',
MORE = '更多'
}

View File

@ -0,0 +1,5 @@
import Inputs from './Inputs'
import DatePickers from './DatePickers'
import Selects from './Selects'
export const FormList = [...Inputs, ...DatePickers, ...Selects]

View File

@ -33,7 +33,7 @@ export type ConfigType = {
chartFrame?: ChartFrameEnum
methodList?: Array<OptionsType>
eventList?: Array<OptionsType>
image: string | (() => Promise<typeof import('*.png')>)
image?: string | (() => Promise<typeof import('*.png')>)
}
@ -132,7 +132,8 @@ export enum PackagesCategoryEnum {
CHARTS = 'Charts',
TABLES = 'Tables',
INFORMATIONS = 'Informations',
DECORATES = 'Decorates'
DECORATES = 'Decorates',
FORM = 'Form',
}
// 包分类名称
@ -140,7 +141,8 @@ export enum PackagesCategoryName {
CHARTS = '图表',
TABLES = '列表',
INFORMATIONS = '信息',
DECORATES = '小组件'
DECORATES = '小组件',
FORM = '表单',
}
// 获取组件
@ -155,4 +157,5 @@ export type PackagesType = {
[PackagesCategoryEnum.INFORMATIONS]: ConfigType[]
[PackagesCategoryEnum.TABLES]: ConfigType[]
[PackagesCategoryEnum.DECORATES]: ConfigType[]
[PackagesCategoryEnum.FORM]: ConfigType[]
}

View File

@ -2,6 +2,7 @@ import { ChartList } from '@/packages/components/Charts/index'
import { DecorateList } from '@/packages/components/Decorates/index'
import { InformationList } from '@/packages/components/Informations/index'
import { TableList } from '@/packages/components/Tables/index'
import { FormList } from '@/packages/components/Form/index'
import {
PackagesCategoryEnum,
PackagesType,
@ -17,7 +18,8 @@ export let packagesList: PackagesType = {
[PackagesCategoryEnum.CHARTS]: ChartList,
[PackagesCategoryEnum.INFORMATIONS]: InformationList,
[PackagesCategoryEnum.TABLES]: TableList,
[PackagesCategoryEnum.DECORATES]: DecorateList
[PackagesCategoryEnum.DECORATES]: DecorateList,
[PackagesCategoryEnum.FORM]: FormList,
}
/**

View File

@ -90,6 +90,7 @@ import {
Filter as FilterIcon,
FilterEdit as FilterEditIcon,
Edit as EditIcon,
DataFormat as DataFormatIcon
} from '@vicons/carbon'
const ionicons5 = {
@ -218,6 +219,7 @@ const ionicons5 = {
const carbon = {
EditIcon,
DataFormatIcon,
// 图表
RoadmapIcon,
// 信息

View File

@ -20,6 +20,11 @@ export const loadAsyncComponent = (loader: AsyncComponentLoader<any>) =>
defineAsyncComponent({
loader,
loadingComponent: AsyncLoading,
errorComponent: {
render(){
return '加载失败'
}
},
delay: 20,
})

View File

@ -204,7 +204,7 @@ export const newFunctionHandle = (
try {
if (!funcStr) return data
const fn = new Function('data', funcStr)
const fnRes = fn(cloneDeep(data))
const fnRes = fn(data)
const resHandle = isToString ? toString(fnRes) : fnRes
// 成功回调
successCallBack && successCallBack(resHandle)

View File

@ -13,6 +13,7 @@ const {
RoadmapIcon,
SpellCheckIcon,
GraphicalDataFlowIcon,
DataFormatIcon,
} = icon.carbon
@ -44,6 +45,10 @@ const packagesListObj = {
icon: renderIcon(GraphicalDataFlowIcon),
label: PackagesCategoryName.DECORATES,
},
[PackagesCategoryEnum.FORM]: {
icon: renderIcon(DataFormatIcon),
label: PackagesCategoryName.FORM,
},
}
// 处理列表

View File

@ -70,6 +70,7 @@ const select = computed(() => {
border-radius: 5px;
background-color: #fff;
transform: translate(-40%, -30%);
cursor: col-resize;
&.t {
width: 30px;
transform: translate(-50%, -50%);

View File

@ -127,6 +127,12 @@ onMounted(() => {
})
</script>
<script lang="ts">
export default {
name: 'ContentEdit'
}
</script>
<style lang="scss" scoped>
@include goId('chart-edit-layout') {
position: relative;

View File

@ -1,5 +1,6 @@
<template>
<component
ref="componentRef"
:is="item.chartConfig.chartKey"
:chartConfig="item"
:themeSetting="themeSetting"
@ -10,14 +11,15 @@
</template>
<script lang='ts' setup>
import { PropType, toRefs, getCurrentInstance, ComponentInternalInstance } from 'vue'
import { PropType, toRefs, computed, getCurrentInstance, ComponentInternalInstance } from 'vue'
import { useEventBus } from '@/hooks'
import { convertEventBusListeners } from '@/hooks/useEventBus.hook'
import { getSizeStyle } from '../../utils'
import { EventTriggerType } from '@/enums/eventEnum'
import { CreateComponentType, EventConfig } from '@/packages/index.d'
import { CreateComponentType, EventConfig, PackagesCategoryEnum } from '@/packages/index.d'
import { newFunctionHandle } from '@/utils'
import isObject from 'lodash/isObject'
import { COMMON_EVENT_ENUM, DATA_COMPONENT_EVENT_ENUM } from '@/enums/eventEnum'
const props = defineProps({
item: {
@ -39,7 +41,8 @@ const props = defineProps({
})
const { item, themeSetting, themeColor, useEvent } = toRefs(props)
const { item, themeSetting, themeColor, useEvent } = toRefs(props);
const componentRef = ref(null)
const instance = getCurrentInstance() as ComponentInternalInstance
const bus = useEventBus()
/**
@ -56,17 +59,17 @@ const getEventList = (eventConfig: EventConfig) => {
// @ts-ignore
previousValue[currentValue] = eventConfig[currentValue].methodList.map((item: any) => {
if(item.type === EventTriggerType.JAVASCRIPT){
return (config: CreateComponentType) => {
return (e: any) => {
try {
newFunctionHandle(config, item.code)
newFunctionHandle(e, item.code)
} catch (error) {
console.error(error, item.code)
throw error
}
}
}else{
return () => {
bus.emit(`${item.componentId}:${item.componentMethod}`)
return (data: any) => {
bus.emit(`${item.componentId}:${item.componentMethod}`, data)
}
}
})
@ -74,15 +77,27 @@ const getEventList = (eventConfig: EventConfig) => {
}, {} as EventConfig)
return res;
}
//
const isDataComponent = computed(() => {
return item.value.chartConfig.package === PackagesCategoryEnum.CHARTS ||
item.value.chartConfig.package === PackagesCategoryEnum.TABLES
})
const listeners = {
const listeners: Record<string, any> = {
on: {
forceUpdate: () => {
[COMMON_EVENT_ENUM.FORCE_UPDATE]: () => {
instance.proxy?.$forceUpdate()
}
}
}
if(isDataComponent.value){
//
listeners.on[DATA_COMPONENT_EVENT_ENUM.LOAD_DATA] = () => {
componentRef.value.loadData()
}
}
useEventBus(convertEventBusListeners(listeners, item.value.id))
</script>

View File

@ -29,7 +29,13 @@ const devPlugins = [
imports: [
'vue',
'vue-router',
]
{
'vue': ['PropType']
}
],
eslintrc: {
enabled: true
}
}
),
Components({

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB