diff --git a/src/components/piDraggable/index.vue b/src/components/piDraggable/index.vue
index 56bcd64..32fb6b8 100644
--- a/src/components/piDraggable/index.vue
+++ b/src/components/piDraggable/index.vue
@@ -93,5 +93,6 @@ function add() {
.add {
padding: 0 10px 10px 20px;
+ text-align: center;
}
diff --git a/src/pi.ts b/src/pi.ts
index 05171d4..a3bb32e 100644
--- a/src/pi.ts
+++ b/src/pi.ts
@@ -11,14 +11,12 @@ import errorHandler from "@/utils/errorHandler";
import piDialog from "@/components/piDialog"
import piTable from "@/components/piTable"
-import piUpload from "@/components/piUpload"
export default {
install(app: App) {
// 注册全局组件
app.component('piDialog', piDialog)
app.component('piTable', piTable)
- app.component('piUpload', piUpload)
//注册全局指令
app.directive('auth', auth)
diff --git a/src/views/tools/form/center.vue b/src/views/tools/form/center.vue
index 4018678..30b6b47 100644
--- a/src/views/tools/form/center.vue
+++ b/src/views/tools/form/center.vue
@@ -11,22 +11,47 @@
-
-
-
-
+ :required="fields[index].required">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ fields[index].btnText }}
+
+
+
+
+
+
+
+ {{ fields[index].tip }}
+
+
+
-
+
@@ -43,6 +68,11 @@
import draggable from 'vuedraggable'
import {nextTick, ref} from "vue";
import tools from "@/utils/tools"
+import {getComponent} from "./config"
+import piIcon from "@/components/piIcon"
+import PiAsset from "@/components/piAsset"
+
+defineExpose({clickAddComp})
const props = defineProps({
fields: {type: Array, default: []},
@@ -68,6 +98,14 @@ function addComp(e) {
emit('change', curComp.value)
}
+// 添加项时
+function clickAddComp(e) {
+ props.fields.push(e)
+ curIndex.value = props.fields.length-1
+ curComp.value = e
+ emit('change', curComp.value)
+}
+
// 选中项
function clickComp(element, index) {
if (curIndex.value === index) {
@@ -155,17 +193,16 @@ function copyComp(index) {
.item {
padding: 12px 10px;
- background: #f6f7ff;
- border: 1px dashed #f6f7ff;
+ border: 1px;
border-radius: 3px;
position: relative;
}
.tools-box {
position: absolute;
- right: -20px;
- top: 0;
- display: inline-grid;
+ right: 10px;
+ top: -16px;
+ display: inline-block;
padding: 5px;
border-radius: 4px;
@@ -181,8 +218,8 @@ function copyComp(index) {
color: var(--el-color-primary);
}
- .mt5 {
- margin-top: 5px;
+ .ml5 {
+ margin-left: 5px;
}
.disabled {
diff --git a/src/views/tools/form/config.ts b/src/views/tools/form/config.ts
new file mode 100644
index 0000000..9002ec8
--- /dev/null
+++ b/src/views/tools/form/config.ts
@@ -0,0 +1,226 @@
+/**
+ * 根据 fForm.name 决定要显示哪些设置项
+ */
+export const fieldEditors = {
+ text: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.prefixIcon', label: '前图标', type: 'icon'},
+ {key: 'props.suffixIcon', label: '后图标', type: 'icon'},
+ {key: 'props.minlength', label: '最少输入', type: 'number'},
+ {key: 'props.maxlength', label: '最多输入', type: 'number'},
+ {key: 'props.showWordLimit', label: '显示字数', type: 'switch'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ textarea: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.rows', label: '默认行数', type: 'number'},
+ {key: 'props.minlength', label: '最少输入', type: 'number'},
+ {key: 'props.maxlength', label: '最多输入', type: 'number'},
+ {key: 'props.showWordLimit', label: '显示字数', type: 'switch'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ password: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.prefixIcon', label: '前图标', type: 'icon'},
+ {key: 'props.suffixIcon', label: '后图标', type: 'icon'},
+ {key: 'props.minlength', label: '最少输入', type: 'number'},
+ {key: 'props.maxlength', label: '最多输入', type: 'number'},
+ {key: 'props.showWordLimit', label: '显示字数', type: 'switch'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ number: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.precision', label: '精度', type: 'number'},
+ {key: 'props.step', label: '步长', type: 'number'},
+ {key: 'props.stepStrictly', label: '严格步数', type: 'switch'},
+ {
+ key: 'props.controlsPosition', label: '按钮位置', type: 'radio', options: [
+ {label: '默认', value: ''},
+ {label: '右侧', value: 'right'},
+ ]
+ },
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ select: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.multiple', label: '是否多选', type: 'switch'},
+ {key: 'props.filterable', label: '能否筛选', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ cascader: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.placeholder', label: '占位提示', type: 'input'},
+ {key: 'props.separator', label: '分隔符', type: 'input'},
+ {key: 'props.showAllLevels', label: '展示全路径', type: 'switch'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.props.multiple', label: '是否多选', type: 'switch'},
+ {key: 'props.filterable', label: '能否筛选', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ radio: [
+ {
+ key: 'style', label: '选项样式', type: 'radio', options: [
+ {label: '默认', value: ''},
+ {label: '按钮', value: 'button'},
+ ]
+ },
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ checkbox: [
+ {key: 'props.min', label: '最少应选', type: 'number'},
+ {key: 'props.max', label: '最多可选', type: 'number'},
+ {
+ key: 'style', label: '选项样式', type: 'radio', options: [
+ {label: '默认', value: ''},
+ {label: '按钮', value: 'button'},
+ ]
+ },
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ switch: [
+ {key: 'props.activeText', label: '打开提示', type: 'input'},
+ {key: 'props.inactiveText', label: '关闭提示', type: 'input'},
+ {key: 'props.activeValue', label: '打开值', type: 'input'},
+ {key: 'props.inactiveValue', label: '关闭值', type: 'input'},
+ {key: 'props.activeActionIcon', label: '打开图标', type: 'icon'},
+ {key: 'props.inactiveActionIcon', label: '关闭图标', type: 'icon'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ slider: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {key: 'props.min', label: '最大值', type: 'number'},
+ {key: 'props.max', label: '最小值', type: 'number'},
+ {key: 'props.step', label: '步长', type: 'number'},
+ {key: 'props.showStops', label: '显示间隔点', type: 'switch'},
+ {key: 'props.range', label: '范围选择', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ rate: [
+ {key: 'props.max', label: '最大值', type: 'number'},
+ {key: 'props.allowHalf', label: '是否半选', type: 'switch'},
+ {key: 'props.showScore', label: '显示分数', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ color: [
+ {
+ key: 'props.colorFormat', label: '颜色格式', type: 'select', options: [
+ {label: 'hsl', value: 'hsl'},
+ {label: 'hsv', value: 'hsv'},
+ {label: 'hex(when show-alpha is false)', value: 'hex'},
+ {label: 'rgb(when show-alpha is true)', value: 'rgb'},
+ ]
+ },
+ {key: 'props.showAlpha', label: '透明度', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ upload: [
+ {key: 'props.name', label: '文件字段名', type: 'input'},
+ {key: 'btnText', label: '按钮文字', type: 'input'},
+ {key: 'props.accept', label: '文件类型', type: 'input'},
+ {
+ key: 'props.listType', label: '列表类型', type: 'radio', options: [
+ {label: 'text', value: 'text'},
+ {label: 'picture', value: 'picture'},
+ {label: 'picture-card', value: 'picture-card'}
+ ]
+ },
+ {key: 'tip', label: '提示信息', type: 'input'},
+ {key: 'props.multiple', label: '是否多选', type: 'switch'},
+ {key: 'props.autoUpload', label: '自动上传', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ date: [
+ {key: 'width', label: '组件宽度', type: 'input'},
+ {
+ key: 'props.type', label: '时间类型', type: 'select', options: [
+ {label: '日', value: 'date'},
+ {label: '周', value: 'week'},
+ {label: '月', value: 'month'},
+ {label: '年', value: 'year'},
+ {label: '日期时间', value: 'datetime'},
+ ]
+ },
+ {key: 'props.format', label: '显示格式', type: 'input'},
+ {key: 'props.valueFormat', label: '日期格式', type: 'input'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ daterange: [
+ {
+ key: 'props.type', label: '时间类型', type: 'select', options: [
+ {label: '日期范围', value: 'daterange'},
+ {label: '月范围', value: 'monthrange'},
+ {label: '日期时间范围', value: 'datetimerange'},
+ ]
+ },
+ {key: 'props.rangeSeparator', label: '分隔符', type: 'input'},
+ {key: 'props.format', label: '显示格式', type: 'input'},
+ {key: 'props.valueFormat', label: '日期格式', type: 'input'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ time: [
+ {key: 'props.editable', label: '可输入', type: 'switch'},
+ {key: 'props.rangeSeparator', label: '分隔符', type: 'input'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ],
+ timerange: [
+ {key: 'props.editable', label: '可输入', type: 'switch'},
+ {key: 'props.rangeSeparator', label: '分隔符', type: 'input'},
+ {key: 'props.clearable', label: '能否清空', type: 'switch'},
+ {key: 'props.readonly', label: '是否只读', type: 'switch'},
+ {key: 'props.disabled', label: '是否禁用', type: 'switch'},
+ ]
+}
+// 'year' | 'years' |'month' | 'months' | 'date' | 'dates' | 'datetime' | 'week' | 'datetimerange' | 'daterange' | 'monthrange' | 'yearrange'
+export const getComponent = (type) => {
+ const map = {
+ text: 'el-input',
+ textarea: 'el-input',
+ password: 'el-input',
+ number: 'el-input-number',
+ select: 'el-select',
+ cascader: 'el-cascader',
+ radio: 'el-radio-group',
+ checkbox: 'el-checkbox-group',
+ switch: 'el-switch',
+ slider: 'el-slider',
+ rate: 'el-rate',
+ color: 'el-color-picker',
+ upload: 'el-upload',
+ date: 'el-date-picker',
+ daterange: 'el-date-picker',
+ time: 'el-time-picker',
+ timerange: 'el-time-picker',
+ icon: 'pi-icon',
+ asset: 'pi-asset'
+ }
+ return map[type] || 'div'
+}
+
+export function getByPath(obj, path) {
+ return path.split('.').reduce((o, k) => o?.[k], obj)
+}
+
+export function setByPath(obj, path, value) {
+ const keys = path.split('.')
+ let o = obj
+ keys.slice(0, -1).forEach(k => o = o[k])
+ o[keys[keys.length - 1]] = value
+}
diff --git a/src/views/tools/form/index.vue b/src/views/tools/form/index.vue
index b10e148..6f4e1dd 100644
--- a/src/views/tools/form/index.vue
+++ b/src/views/tools/form/index.vue
@@ -1,9 +1,9 @@
-
+
-
+
@@ -27,12 +27,17 @@ let config = ref({
disabled: false
})
let curField = ref({})
+const centerRef = ref(null)
function setField(v) {
curField.value = v
curField.value.field = v.id
}
+function addField(e) {
+ centerRef.value.clickAddComp(e)
+}
+