|
@@ -0,0 +1,411 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <a-space
|
|
|
+ align="center"
|
|
|
+ style="justify-content: space-between; width: 100%; margin-top: 10px"
|
|
|
+ >
|
|
|
+ <h3 style="color: var(--color-text-2)">
|
|
|
+ {{ props.fields.title
|
|
|
+ }}<span
|
|
|
+ style="margin: 10px 10px; color: var(--color-text-3); font-size: 12px"
|
|
|
+ >{{ props.fields.description }}</span
|
|
|
+ >
|
|
|
+ </h3>
|
|
|
+ <a-button long type="dashed" @click="showAddFormData()">
|
|
|
+ <template #icon> <icon-plus /> </template
|
|
|
+ >{{ props.fields.title }}</a-button
|
|
|
+ >
|
|
|
+ </a-space>
|
|
|
+
|
|
|
+ <a-table
|
|
|
+ :columns="tableColumnsData"
|
|
|
+ :data="tableData"
|
|
|
+ :pagination="pagination"
|
|
|
+ class="modalTable"
|
|
|
+ style="margin: 10px 0"
|
|
|
+ table-layout-fixed
|
|
|
+ @page-change="pageChangeHandler"
|
|
|
+ >
|
|
|
+ <template
|
|
|
+ v-for="key in orderProperties(
|
|
|
+ Object.keys(props.fields.items.properties),
|
|
|
+ props.fields.items['ui:order']
|
|
|
+ )"
|
|
|
+ :key="key"
|
|
|
+ #[key]="{ record }"
|
|
|
+ >
|
|
|
+ <component
|
|
|
+ :is="getFieldComponent(props.fields.items.properties[key])"
|
|
|
+ v-model="record[key]"
|
|
|
+ ></component>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #empty>
|
|
|
+ <span
|
|
|
+ style="margin: 10px 10px; color: var(--color-text-3); font-size: 12px"
|
|
|
+ >暂无数据</span
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template #operator="record">
|
|
|
+ <a-button
|
|
|
+ type="text"
|
|
|
+ status="success"
|
|
|
+ title="删除信息"
|
|
|
+ size="small"
|
|
|
+ @click="modifyData(record)"
|
|
|
+ >
|
|
|
+ <template #icon>
|
|
|
+ <icon-edit :size="18" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ <a-button
|
|
|
+ type="text"
|
|
|
+ status="danger"
|
|
|
+ title="删除信息"
|
|
|
+ size="small"
|
|
|
+ @click="removeData(record)"
|
|
|
+ >
|
|
|
+ <template #icon>
|
|
|
+ <icon-delete :size="18" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ <a-button
|
|
|
+ type="text"
|
|
|
+ title="复制信息"
|
|
|
+ size="small"
|
|
|
+ @click="copyData(record)"
|
|
|
+ >
|
|
|
+ <template #icon>
|
|
|
+ <icon-copy :size="18" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ <vModal
|
|
|
+ v-model:visible="visibleModal"
|
|
|
+ :title="modalTitle"
|
|
|
+ :width="600"
|
|
|
+ @modal-handle-ok="modelHandleOk"
|
|
|
+ @modal-handle-cancel="modelHandleCancel"
|
|
|
+ >
|
|
|
+ <a-form :model="form" :auto-label-width="true" label-align="right">
|
|
|
+ <DynamicForm
|
|
|
+ :cur-node-path="props.curNodePath"
|
|
|
+ :form-data="form.formData"
|
|
|
+ :schema="form.schema"
|
|
|
+ ></DynamicForm>
|
|
|
+ </a-form>
|
|
|
+ </vModal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import {
|
|
|
+ PaginationProps,
|
|
|
+ TableColumnData,
|
|
|
+ Input,
|
|
|
+ InputNumber,
|
|
|
+ Switch,
|
|
|
+ TimePicker,
|
|
|
+ Textarea,
|
|
|
+ DatePicker,
|
|
|
+ MonthPicker,
|
|
|
+ YearPicker
|
|
|
+} from '@arco-design/web-vue'
|
|
|
+import { ref, computed, PropType, onMounted, reactive, watch, h } from 'vue'
|
|
|
+import { orderProperties } from '@/utils/index'
|
|
|
+import DynamicForm from '@/components/dynamicForm/index.vue'
|
|
|
+import vModal from '@/components/modal/index.vue'
|
|
|
+import { useEmitt } from '@/logics/mitt/useEmitt'
|
|
|
+
|
|
|
+import CustomSelect from './Select.vue'
|
|
|
+
|
|
|
+const pagination = reactive<PaginationProps>({
|
|
|
+ showTotal: false,
|
|
|
+ current: 1,
|
|
|
+ pageSize: 10
|
|
|
+})
|
|
|
+const modalType = ref<number>(0)
|
|
|
+const rowIndex = ref<number>(0)
|
|
|
+const { emitter } = useEmitt()
|
|
|
+const props = defineProps({
|
|
|
+ rootFormData: {
|
|
|
+ type: Object as PropType<object>
|
|
|
+ },
|
|
|
+ curNodePath: {
|
|
|
+ type: String
|
|
|
+ },
|
|
|
+ fields: {
|
|
|
+ type: Object as PropType<any>,
|
|
|
+ default: () => {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ placeholder: {
|
|
|
+ type: String
|
|
|
+ },
|
|
|
+ formData: {
|
|
|
+ type: Array as PropType<any[]>,
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const form = reactive<{
|
|
|
+ formData: { [key: string]: any }
|
|
|
+ schema: { [key: string]: any }
|
|
|
+}>({
|
|
|
+ formData: {},
|
|
|
+ schema: {}
|
|
|
+})
|
|
|
+
|
|
|
+const tableData = reactive<any[]>([]) // 设备列表
|
|
|
+const tableColumnsData = ref<TableColumnData[]>([])
|
|
|
+const type = computed(() => {
|
|
|
+ return props.fields.items.type
|
|
|
+})
|
|
|
+const visibleModal = ref<boolean>(false)
|
|
|
+const selectedKeys = ref<string[]>([])
|
|
|
+const modalTitle = ref<string>('')
|
|
|
+
|
|
|
+const pageChangeHandler = (current: number) => {
|
|
|
+ pagination.current = current
|
|
|
+}
|
|
|
+
|
|
|
+const getTableColumnsData = (): TableColumnData[] => {
|
|
|
+ const { items } = props.fields
|
|
|
+ if (type.value === 'string') {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ align: 'center',
|
|
|
+ title: props.fields.title,
|
|
|
+ dataIndex: 'key',
|
|
|
+ bodyCellClass: 'miniCellPadding'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ const keys = orderProperties(Object.keys(items.properties), items['ui:order'])
|
|
|
+ return keys.map((item: string) => {
|
|
|
+ return {
|
|
|
+ align: 'left',
|
|
|
+ title: items.properties[item].title,
|
|
|
+ slotName: item,
|
|
|
+ ellipsis: true,
|
|
|
+ tooltip: true,
|
|
|
+ dataIndex: item,
|
|
|
+ bodyCellClass: 'miniCellPadding'
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 显示添加form data
|
|
|
+ */
|
|
|
+const showAddFormData = () => {
|
|
|
+ modalTitle.value = props.fields.title
|
|
|
+ if (props.fields.items.type === 'object') {
|
|
|
+ form.schema = props.fields.items
|
|
|
+ } else {
|
|
|
+ const object: { [key: string]: any } = { ...props.fields }
|
|
|
+ object.type = props.fields.items.type
|
|
|
+ const properties: { [key: string]: any } = {}
|
|
|
+ properties.key = object
|
|
|
+ form.schema = {
|
|
|
+ title: props.fields.title,
|
|
|
+ required: ['key'],
|
|
|
+ properties
|
|
|
+ }
|
|
|
+ }
|
|
|
+ modalType.value = 0
|
|
|
+ visibleModal.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const modifyData = (data: any) => {
|
|
|
+ rowIndex.value = data.rowIndex
|
|
|
+ modalTitle.value = props.fields.title
|
|
|
+ if (props.fields.items.type === 'object') {
|
|
|
+ form.schema = props.fields.items
|
|
|
+ } else {
|
|
|
+ const object: { [key: string]: any } = { ...props.fields }
|
|
|
+ object.type = props.fields.items.type
|
|
|
+ const properties: { [key: string]: any } = {}
|
|
|
+ properties.key = object
|
|
|
+ form.schema = {
|
|
|
+ title: props.fields.title,
|
|
|
+ required: ['key'],
|
|
|
+ properties
|
|
|
+ }
|
|
|
+ }
|
|
|
+ modalType.value = 1
|
|
|
+ form.formData = data.record
|
|
|
+ visibleModal.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 删除列表数据
|
|
|
+const removeData = (data: any) => {
|
|
|
+ const index = (pagination.current! - 1) * pagination.pageSize! + data.rowIndex
|
|
|
+ tableData.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+// 复制列表数据
|
|
|
+const copyData = (data: any) => {
|
|
|
+ const { record } = data
|
|
|
+ // console.log(record)
|
|
|
+ // const index = (pagination.current! - 1) * pagination.pageSize! + data.rowIndex
|
|
|
+ tableData.push({ ...record })
|
|
|
+ const len = tableData.length
|
|
|
+ const current = Math.ceil(len / 10)
|
|
|
+ pagination.current = current
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 隐藏model 对话框,重置表单
|
|
|
+ */
|
|
|
+const modelHandleCancel = () => {
|
|
|
+ form.formData = {}
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 点击确认增加list
|
|
|
+ * @param cb
|
|
|
+ */
|
|
|
+const modelHandleOk = async (cb: (closed: boolean) => void) => {
|
|
|
+ if (modalType.value === 0) {
|
|
|
+ tableData.push(form.formData)
|
|
|
+ } else {
|
|
|
+ const index = rowIndex.value
|
|
|
+ tableData[index] = form.formData
|
|
|
+ }
|
|
|
+ return cb(true)
|
|
|
+}
|
|
|
+
|
|
|
+const getFieldComponent = (field: { [key: string]: any }): any => {
|
|
|
+ if (field.enum) {
|
|
|
+ return h(CustomSelect, {
|
|
|
+ options: field.enum.map((item: any) => {
|
|
|
+ return {
|
|
|
+ key: item.value || item,
|
|
|
+ value: item.value || item,
|
|
|
+ label: `${item}`
|
|
|
+ }
|
|
|
+ }),
|
|
|
+ multiple: field.multiple,
|
|
|
+ placeholder: `请输入${field.title}`
|
|
|
+ })
|
|
|
+ }
|
|
|
+ switch (field.type) {
|
|
|
+ case 'string':
|
|
|
+ switch (field.format) {
|
|
|
+ case 'time':
|
|
|
+ return h(TimePicker, { placeholder: `请选择${field.title}` })
|
|
|
+ case 'date':
|
|
|
+ return h(DatePicker, {
|
|
|
+ placeholder: `请选择${field.title}`
|
|
|
+ })
|
|
|
+ case 'datetime':
|
|
|
+ return h(DatePicker, { showTime: true })
|
|
|
+ case 'month':
|
|
|
+ return h(MonthPicker, {
|
|
|
+ placeholder: `请选择${field.title}`
|
|
|
+ })
|
|
|
+ case 'year':
|
|
|
+ return h(YearPicker, {
|
|
|
+ placeholder: `请选择${field.title}`
|
|
|
+ })
|
|
|
+ case 'textarea':
|
|
|
+ return h(Textarea, {
|
|
|
+ placeholder: `请输入${field.title}`
|
|
|
+ })
|
|
|
+ default:
|
|
|
+ return h(Input, {
|
|
|
+ placeholder: `请输入${field.title}`,
|
|
|
+ allowClear: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ case 'integer':
|
|
|
+ case 'number':
|
|
|
+ return h(InputNumber, {
|
|
|
+ precision: field.type === 'integer' ? 0 : 2,
|
|
|
+ min: field.minimum,
|
|
|
+ max: field.maximum,
|
|
|
+ placeholder: `请输入${field.title}`
|
|
|
+ })
|
|
|
+ case 'boolean':
|
|
|
+ return Switch
|
|
|
+ default:
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => tableData,
|
|
|
+ value => {
|
|
|
+ emitter.emit('setCustomeFormData', {
|
|
|
+ rootFormData: props.rootFormData!,
|
|
|
+ curNodePath: props.curNodePath!,
|
|
|
+ value:
|
|
|
+ type.value === 'object'
|
|
|
+ ? value
|
|
|
+ : value.map(item => {
|
|
|
+ return item.key
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ const operator: TableColumnData[] = [
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ align: 'center',
|
|
|
+ slotName: 'operator',
|
|
|
+ width: 100,
|
|
|
+ fixed: 'right',
|
|
|
+ bodyCellClass: 'miniCellPadding'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ tableColumnsData.value = getTableColumnsData()
|
|
|
+ tableColumnsData.value = tableColumnsData.value.concat(operator)
|
|
|
+ // console.log(props.formData)
|
|
|
+ if (props.formData?.length > 0) {
|
|
|
+ if (type.value === 'object') {
|
|
|
+ tableData.push(...props.formData)
|
|
|
+ } else {
|
|
|
+ const list = {
|
|
|
+ ...props.formData.map(item => {
|
|
|
+ return { key: item }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ tableData.push(...list)
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="less">
|
|
|
+:deep(.arco-table-th) {
|
|
|
+ &:last-child {
|
|
|
+ .arco-table-th-item-title {
|
|
|
+ margin-left: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.arco-table-td-content) {
|
|
|
+ .arco-checkbox {
|
|
|
+ padding-left: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+.modalTable {
|
|
|
+ .arco-btn + .arco-btn {
|
|
|
+ margin-left: 0px;
|
|
|
+ }
|
|
|
+
|
|
|
+ // }
|
|
|
+}
|
|
|
+:deep(.miniCellPadding) {
|
|
|
+ .arco-table-cell {
|
|
|
+ padding: 6px 2px 6px 3px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|