Yue 2 жил өмнө
parent
commit
f242c1b8b3

+ 7 - 0
components.d.ts

@@ -14,6 +14,7 @@ declare module '@vue/runtime-core' {
     BaseChart: typeof import('./src/components/charts/BaseChart.vue')['default']
     CodeHighlighter: typeof import('./src/components/highlighters/CodeHighlighter.vue')['default']
     CodeHighlighter2: typeof import('./src/components/highlighters/CodeHighlighter2.vue')['default']
+    copy: typeof import('./src/components/Forms/VbForm copy.vue')['default']
     DateRangeSelect: typeof import('./src/components/select/DateRangeSelect.vue')['default']
     DynamicTreeSelect: typeof import('./src/components/select/DynamicTreeSelect.vue')['default']
     DySearchSelect: typeof import('./src/components/select/DySearchSelect.vue')['default']
@@ -21,6 +22,7 @@ declare module '@vue/runtime-core' {
     DySelectCascade: typeof import('./src/components/select/DySelectCascade.vue')['default']
     DySelectTree: typeof import('./src/components/select/DySelectTree.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
@@ -30,9 +32,12 @@ declare module '@vue/runtime-core' {
     ElInput: typeof import('element-plus/es')['ElInput']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElTree: typeof import('element-plus/es')['ElTree']
+    Form: typeof import('./src/components/Forms/Form.vue')['default']
+    FormItem: typeof import('./src/components/Forms/FormItem.vue')['default']
     Loading: typeof import('./src/components/Table/table-partials/Loading.vue')['default']
     MenuComponent: typeof import('./src/components/menu/MenuComponent.vue')['default']
     OrgCompany: typeof import('./src/components/Tree/OrgCompany.vue')['default']
@@ -50,6 +55,8 @@ declare module '@vue/runtime-core' {
     TableRightFixed: typeof import('./src/components/Table/table-partials/table-content/table-fixed/TableRightFixed.vue')['default']
     TableTreeRow: typeof import('./src/components/Table/table-partials/table-content/table-body/TableTreeRow.vue')['default']
     VbDataTable: typeof import('./src/components/Table/VbDataTable.vue')['default']
+    VbForm: typeof import('./src/components/Forms/VbForm.vue')['default']
+    VbFormItem: typeof import('./src/components/Forms/VbFormItem.vue')['default']
     VbModal: typeof import('./src/components/Modals/VbModal.vue')['default']
     VbTreeTable: typeof import('./src/components/Table/VbTreeTable.vue')['default']
   }

+ 93 - 0
src/components/Forms/VbForm.vue

@@ -0,0 +1,93 @@
+<script setup lang="ts">
+import { ref, toRefs, withDefaults, nextTick } from "vue"
+import type { FormItemRule } from "element-plus/es/components/form/src/types"
+import type { VbFormItem as VbFormColItem, VbFormRowItem } from "@/components/Forms/models"
+import VbFormItem from "@/components/Forms/VbFormItem.vue"
+const props = withDefaults(
+  defineProps<{
+    data: object
+    rowItems?: Array<VbFormRowItem>
+    items?: Array<VbFormColItem>
+    class?: string
+    labelWidth?: number | string
+    rules?: Array<FormItemRule>
+    gutter?: number
+    span?: number
+    size?: "large" | "default" | "small"
+  }>(),
+  {
+    rowItems: () => [],
+    items: () => [],
+    labelWidth: "auto",
+    class: "vb-form",
+    gutter: 20,
+    span: 24,
+    size: "large",
+  }
+)
+//const emits = defineEmits<{ (e: "update:data", v: any): void }>()
+const { data } = toRefs(props)
+
+// 表单
+const VbForm = ref<HTMLFormElement>()
+
+// 重置表单
+function resetFields() {
+  nextTick(() => {
+    VbForm.value?.resetFields()
+  })
+}
+// 清除表单校验
+const clearValidate = () => {
+  nextTick(() => {
+    VbForm.value?.clearValidate()
+  })
+}
+// 验证表单,返回 Promise<boolean>
+async function validate() {
+  const valid = await VbForm.value?.validate()
+  return valid
+}
+
+defineExpose({ resetFields, clearValidate, validate, VbForm })
+</script>
+<template>
+  <el-form
+    ref="VbForm"
+    v-bind="$attrs"
+    :model="data"
+    :class="props.class"
+    :label-width="`${Number(labelWidth) ? labelWidth + 'px' : labelWidth}`"
+  >
+    <template v-if="rowItems && rowItems.length">
+      <el-row v-for="(v, i) in rowItems" :key="i" :gutter="v.gutter || gutter">
+        <template v-if="v.children && v.children.length">
+          <VbFormItem
+            v-for="vv in v.children"
+            :key="vv.field"
+            v-model:data="data"
+            :item="vv"
+            :labelWidth="labelWidth"
+            :rules="rules"
+            :gutter="gutter"
+            :span="span"
+          ></VbFormItem>
+        </template>
+      </el-row>
+    </template>
+    <template v-if="items && items.length">
+      <el-row :gutter="gutter">
+        <VbFormItem
+          v-for="vv in items"
+          :key="vv.field"
+          v-model:data="data"
+          :item="vv"
+          :labelWidth="labelWidth"
+          :rules="rules"
+          :gutter="gutter"
+          :span="span"
+        ></VbFormItem>
+      </el-row>
+    </template>
+  </el-form>
+</template>

+ 152 - 0
src/components/Forms/VbFormItem.vue

@@ -0,0 +1,152 @@
+<script setup lang="ts">
+import { withDefaults, onMounted, computed, type WritableComputedRef } from "vue"
+import { ElSelect, ElRadioGroup, ElCheckboxGroup } from "element-plus"
+import type { FormItemRule } from "element-plus/es/components/form/src/types"
+import type { VbFormItem } from "@/components/Forms/models"
+import getConfigRule, { RULE_KEYS } from "@/core/config/rules"
+
+const props = withDefaults(
+  defineProps<{
+    data: any
+    item: VbFormItem
+    labelWidth?: number | string
+    rules?: Array<FormItemRule>
+    gutter?: number
+    span?: number
+    size?: "large" | "default" | "small"
+  }>(),
+  {
+    gutter: 20,
+    span: 24,
+    size: "large",
+  }
+)
+const emits = defineEmits<{ (e: "update:data", v: any): void }>()
+
+const data: WritableComputedRef<any> = computed({
+  get(): any {
+    return props.data
+  },
+  set(value: any): void {
+    emits("update:data", value)
+  },
+})
+
+const getRules = (item: VbFormItem): Array<FormItemRule> => {
+  const _rules = [] as Array<FormItemRule>
+  if (item.rules) {
+    for (let i = 0; i < item.rules.length; i++) {
+      const r = item.rules[i]
+      let rule
+      if (typeof r == "string") {
+        if (props.rules) {
+          rule = props.rules.find((v: any) => {
+            return v.name == r
+          })
+        }
+        if (!rule) {
+          rule = getConfigRule(r, item.ruleFormat ? item.ruleFormat[i] : undefined)
+        }
+        if (rule) {
+          _rules.push(rule)
+        }
+      } else if (typeof r == "object") {
+        _rules.push(r)
+      }
+    }
+  }
+
+  //添加默认的 required 规则
+  if (
+    item.required &&
+    _rules.find((v) => {
+      return v.required == true
+    }) == null
+  ) {
+    const rule = getConfigRule(RULE_KEYS.REQUIRED, [item.label?.toString() ?? ""])
+    if (rule) {
+      _rules.push(rule)
+    }
+  }
+  //console.log("RULES===", _rules)
+  return _rules
+}
+
+function init() {
+  //
+}
+
+onMounted(() => {
+  init()
+})
+</script>
+<template>
+  <el-col :span="item.hidden ? 0 : item.span || span">
+    <el-form-item
+      v-if="!item.hidden"
+      :prop="item.field"
+      :class="item.itemClass"
+      :style="item.itemStyle"
+      :required="item.required"
+      :rules="getRules(item)"
+      :label="item.label"
+      :label-width="
+        Number(item.labelWidth || labelWidth) ? (item.labelWidth || labelWidth) + 'px' : item.labelWidth || labelWidth
+      "
+      v-bind="item.itemProps"
+    >
+      <slot v-if="item.component === 'slot'" :name="item.field"></slot>
+      <div v-else-if="item.component === 'innerText'" :class="item.class" :style="item.style">
+        {{ item.innerText || data[item.field] }}
+      </div>
+      <template v-else>
+        <component
+          :is="item.component"
+          v-model="data[item.field]"
+          v-model:value="data[item.field]"
+          :required="item.required"
+          :type="item.type || 'text'"
+          :class="item.class"
+          :style="item.style"
+          :size="item.size"
+          v-bind="item.props"
+          v-on="item.listeners"
+        >
+          <template v-if="item.component == ElSelect">
+            <el-option
+              v-for="(select, selectIndex) in item.data"
+              :key="selectIndex"
+              :value="select.value"
+              :label="select.label"
+              :class="select.class"
+              :style="select.style"
+              :disabled="select.disabled"
+            ></el-option>
+          </template>
+          <template v-else-if="item.component == ElRadioGroup">
+            <el-radio
+              v-for="(radio, radioIndex) in item.data"
+              :key="radioIndex"
+              :label="radio.value"
+              :class="radio.class"
+              :style="radio.style"
+              :disabled="radio.disabled"
+            >
+              {{ radio.label }}
+            </el-radio>
+          </template>
+          <template v-else-if="item.component == ElCheckboxGroup">
+            <el-checkbox
+              v-for="(checkbox, checkboxIndex) in item.data"
+              :key="checkboxIndex"
+              :label="checkbox.label"
+              :class="checkbox.class"
+              :style="checkbox.style"
+              :disabled="checkbox.disabled"
+            ></el-checkbox>
+          </template>
+        </component>
+      </template>
+    </el-form-item>
+  </el-col>
+</template>

+ 32 - 0
src/components/Forms/models.ts

@@ -0,0 +1,32 @@
+import type { Component } from "vue"
+import type { FormItemRule } from "element-plus/es/components/form/src/types"
+
+export type VbFormItem = {
+  field: string
+  label?: string
+  required?: boolean
+  itemClass?: string
+  class?: string
+  itemStyle?: string
+  style?: string
+  type?: string
+  component?: string | "slot" | "innerText" | Component //支持 slot、innerText、string 时就是指组件名
+  innerText?: string //component 为 innerText 时,优先显示的文本,否则会显示当前的字段值
+  span?: number
+  hidden?: boolean
+  labelWidth?: number
+  size?: "large" | "default" | "small"
+  placeholder?: string
+  rules?: Array<string | FormItemRule> //全局规则的KEY 或 自定义的规则
+  ruleFormat?: Array<Array<string | number> | undefined> //数组索引对应rules顺序,对应的rule是自定义的(或者没有format数据)要填undefined  eg: [[0,1],undfiend,["名称"]]
+  data?: Array<{ label: string; value: string; class?: string; style?: string; disabled?: boolean }>
+  itemProps?: object // 注入到 el-form-item 的属性
+  props?: object // 当 component 为渲染组件时,注入到渲染组件当中的属性
+  listeners?: object // 当 component 为渲染组件时,注入到渲染组件当中的事件
+}
+
+export type VbFormRowItem = {
+  children: VbFormItem[]
+  gutter?: number
+  className?: string
+}

+ 54 - 33
src/components/Modals/VbModal.vue

@@ -1,16 +1,30 @@
 <script setup lang="ts">
-import { ref, toRefs, withDefaults, defineExpose, onMounted, watch, nextTick } from "vue"
+import { ref, toRefs, withDefaults, defineExpose, onMounted, watch } from "vue"
 import { getAssetPath } from "@/core/helpers/assets"
+import type { FormItemRule } from "element-plus/es/components/form/src/types"
+import type { VbFormItem, VbFormRowItem } from "@/components/Forms/models"
+import VbForm from "@/components/Forms/VbForm.vue"
 import { dialog } from "@/core/utils/message"
 import { Modal } from "bootstrap"
+
 const props = withDefaults(
   defineProps<{
     modal: any //初始化后会把bootstrap的modal对象绑定在外部的modal上,外部请使用 v-model:modal=""
     id?: string
     titlePrefix?: string
     title?: string
+    formData?: any // 模态框表单数据
+    formRowItems?: Array<VbFormRowItem>
+    formItems?: Array<VbFormItem>
+    formRules?: Array<FormItemRule>
+    formLabelWidth?: string | number // 表单label宽度
+    formSize?: "large" | "default" | "small"
+    gutter?: number
+    span?: number
+    formProps?: object
+    formListeners?: object
     backdrop?: boolean | "static" //是否有遮罩, 设置"static"时点击遮罩不关闭modal
-    focus?: boolean //初始化时焦点放在modal上
+    focus?: boolean //初始化时焦点放在modal上 设为true可能会导致打开modal时,表单自动校验,必填的input会显示错误
     keyboard?: boolean //true时按下esc关闭modal
     showEvent?: (event: Event) => void
     shownEvent?: (event: Event) => void
@@ -21,9 +35,6 @@ const props = withDefaults(
     validateFormCallback?: (isValid: boolean, invalidFields?: any) => void //验证表单
     saveAutoClose?: boolean // 保存时自动关闭modal
     closeNeedConfrim?: boolean // 关闭模态框需要确认
-    modalFormData?: any // 模态框表单数据
-    formLabelWidth?: string | number // 表单label宽度
-    formSize?: "large" | "default" | "small"
     closeBtn?: boolean //显示关闭按钮
     closeBtnText?: string
     closeBtnClass?: string
@@ -56,13 +67,13 @@ const props = withDefaults(
       return `vb_${Math.floor(Math.random() * 999999)}`
     },
     backdrop: true,
-    focus: true,
+    focus: false,
     keyboard: true,
     saveAutoClose: true,
     validateForm: true,
     formLabelWidth: "100px",
     formSize: "large",
-    closeNeedConfrim: true,
+    closeNeedConfrim: false,
     closeBtn: true,
     closeBtnText: "关闭",
     closeBtnClass: "btn btn-light",
@@ -77,7 +88,7 @@ const props = withDefaults(
     modalHeaderClass: "",
     modalTitleClass: "",
     modalBodyClass: "",
-    modalFormClass: "",
+    modalFormClass: "vb-form",
     modalFooterClass: "",
     modalStyle: "",
     modalDialogStyle: "",
@@ -89,9 +100,10 @@ const props = withDefaults(
     modalFooterStyle: "",
   }
 )
-const { modal } = toRefs(props)
+const { modal, formData } = toRefs(props)
 const emits = defineEmits<{
   (e: "update:modal", modal: Modal): boolean
+  (e: "update:formData", dara: any): boolean
   (e: "cancel", form: HTMLFormElement | undefined | null, callback?: (v: boolean) => void): boolean
   (e: "confirm", form: HTMLFormElement | undefined | null): void
 }>()
@@ -109,13 +121,8 @@ function cancel() {
     console.log("cancel", result)
     //callback传false 阻止modal关闭
     if (result) {
-      nextTick(() => {
-        //modalFormEl.value?.resetFields()
-        modalFormEl.value?.clearValidate()
-      })
-      //modalFormEl.value?.clearValidate()
-      //modalFormEl.value?.resetFields()
-      console.log(" modalFormEl.value", modalFormEl.value)
+      modalFormEl.value?.resetFields()
+      modalFormEl.value?.clearValidate()
       modal.value.hide()
     }
   }
@@ -133,16 +140,14 @@ function cancel() {
 
 function confirm() {
   if (props.validateForm) {
-    modalFormEl.value?.validate((valid: boolean, fields: any) => {
-      if (props.validateFormCallback) {
-        props.validateFormCallback(valid, fields)
-      } else if (valid) {
+    modalFormEl.value?.validate().then((valid: boolean) => {
+      if (valid) {
         emits("confirm", modalFormEl.value)
         if (props.saveAutoClose) {
           modal.value.hide()
         }
       } else {
-        console.error("FORM 验证失败", fields)
+        console.error("FORM 验证失败")
       }
     })
   } else {
@@ -219,19 +224,35 @@ defineExpose({ show })
           <template v-if="$slots.body">
             <slot name="body" />
           </template>
-          <el-form
-            v-else
-            ref="modalFormEl"
-            :model="modalFormData"
-            :label-width="`${Number(formLabelWidth) ? formLabelWidth + 'px' : formLabelWidth}`"
-            :size="formSize"
-            :class="modalFormClass"
-            :style="modalFormStyle"
-          >
-            <template v-if="$slots.form">
+          <template v-else-if="$slots.form">
+            <el-form
+              ref="modalFormEl"
+              :model="formData"
+              :label-width="`${Number(formLabelWidth) ? formLabelWidth + 'px' : formLabelWidth}`"
+              :size="formSize"
+              :class="modalFormClass"
+              :style="modalFormStyle"
+            >
               <slot name="form" />
-            </template>
-          </el-form>
+            </el-form>
+          </template>
+          <template v-else-if="formRowItems || formItems">
+            <VbForm
+              ref="modalFormEl"
+              v-model:data="formData"
+              :row-items="formRowItems"
+              :items="formItems"
+              :label-width="formLabelWidth"
+              :rules="formRules"
+              :size="formSize"
+              :class="modalFormClass"
+              :style="modalFormStyle"
+              :span="span"
+              :gutter="gutter"
+              v-bind="formProps"
+              v-on="formListeners"
+            ></VbForm>
+          </template>
         </div>
         <div class="modal-footer" :class="modalFooterClass" :style="modalFooterStyle">
           <button v-if="closeBtn" type="button" :class="closeBtnClass" :style="closeBtnStyle" @click="cancel">

+ 6 - 3
src/components/Tree/OrgCompany.vue

@@ -153,9 +153,12 @@ onMounted(() => {
       <div>
         <i class="me-5" :class="getIconClass(node)"></i>
         <span>
-          {{ node.label }} (
-          <span class="px-2 text-danger">{{ data.attr }}</span>
-          家企业)
+          {{ node.label }}
+          <span v-if="data.attr">
+            (
+            <span class="px-2 text-danger">{{ data.attr }}</span>
+            家企业)
+          </span>
         </span>
       </div>
       <span v-if="!node.isLeaf">

+ 8 - 0
src/components/select/AreaCascadeSelect.vue

@@ -16,11 +16,19 @@ const provinceData = ref<Array<any>>([])
 const cityData = ref<Array<any>>([])
 const districtData = ref<Array<any>>([])
 function provinceChange() {
+  cityData.value =
+    provinceData.value.find((vv) => {
+      return vv.value == province.value
+    })?.children ?? []
   city.value = ""
   district.value = ""
   change()
 }
 function cityChange() {
+  districtData.value =
+    cityData.value.find((vv) => {
+      return vv.value == city.value
+    })?.children ?? []
   district.value = ""
   change()
 }

+ 77 - 0
src/core/config/rules.ts

@@ -0,0 +1,77 @@
+import { formatString } from "@/core/utils/utils"
+export default function (key: string, arr?: Array<string | number>) {
+  let rule = undefined
+
+  if (arr) {
+    let ruleFormat = rulesFormat[key]
+    if (ruleFormat) {
+      ruleFormat = formatString(ruleFormat, ...arr)
+      //console.log("===>", ruleFormat)
+      rule = JSON.parse(ruleFormat)
+    }
+  }
+  //rulesFormat里没有找到再从rules找一下
+  if (!rule) {
+    rule = rules[key]
+  }
+  return rule
+}
+export const RULE_KEYS = {
+  REQUIRED: "VB_REQUIRED",
+  NUMBER: "VB_NUMBER",
+  INT: "VB_INT",
+  FLOAT: "VB_FLOAT",
+  HEX: "VB_HEX",
+  URL: "VB_URL",
+  EMAIL: "VB_EMAIL",
+  DATE: "VB_DATE",
+  DATETIME: "VB_DATETIME",
+  REQUIRED_NUMBER: "VB_REQUIRED_NUMBER",
+  REQUIRED_INT: "VB_REQUIRED_INT",
+  REQUIRED_FLOAT: "VB_REQUIRED_FLOAT",
+  REQUIRED_HEX: "VB_REQUIRED_HEX",
+  REQUIRED_URL: "VB_REQUIRED_URL",
+  REQUIRED_EMAIL: "VB_REQUIRED_EMAIL",
+  REQUIRED_DATE: "VB_REQUIRED_DATE",
+  REQUIRED_DATETIME: "VB_REQUIRED_DATETIME",
+  MIN: "VB_MIN",
+  MAX: "VB_MAX",
+  MIN_MAX: "VB_MIN_MAX",
+  N_MIN: "VB_N_MIN",
+  N_MAX: "VB_N_MAX",
+  N_MIN_MAX: "VB_N_MIN_MAX",
+}
+export const rules = {
+  VB_REQUIRED: { required: true, message: "必填", trigger: "blur" },
+  VB_NUMBER: { type: "number", message: "请输入数字", trigger: ["blur"] },
+  VB_INT: { type: "integer", message: "请输入整数", trigger: ["blur"] },
+  VB_FLOAT: { type: "float", message: "请输入浮点数", trigger: ["blur"] },
+  VB_HEX: { type: "hex", message: "请输入16进制数字", trigger: ["blur"] },
+  VB_URL: { type: "url", message: "请输入正确的URL地址", trigger: ["blur"] },
+  VB_EMAIL: { type: "email", message: "请输入正确的电子邮箱", trigger: ["blur"] },
+  VB_DATE: { type: "date", message: "请选择日期", trigger: ["blur"] },
+  VB_DATETIME: { type: "date", message: "请选择时间", trigger: ["blur"] },
+  VB_REQUIRED_NUMBER: { type: "number", required: true, message: "请输入数字", trigger: ["blur"] },
+  VB_REQUIRED_INT: { type: "integer", required: true, message: "请输入整数", trigger: ["blur"] },
+  VB_REQUIRED_FLOAT: { type: "float", required: true, message: "请输入浮点数", trigger: ["blur"] },
+  VB_REQUIRED_HEX: { type: "hex", required: true, message: "请输入16进制数字", trigger: ["blur"] },
+  VB_REQUIRED_URL: [
+    { type: "string", required: true, message: "请输入URL地址", trigger: "blur" },
+    { type: "url", message: "请输入正确的URL地址", trigger: ["blur"] },
+  ],
+  VB_REQUIRED_EMAIL: [
+    { type: "string", required: true, message: "请输入电子邮箱", trigger: "blur" },
+    { type: "email", message: "请输入正确的电子邮箱", trigger: ["blur"] },
+  ],
+  VB_REQUIRED_DATE: { type: "date", required: true, message: "请选择日期", trigger: ["blur"] },
+  VB_REQUIRED_DATETIME: { type: "date", required: true, message: "请选择时间", trigger: ["blur"] },
+}
+export const rulesFormat = {
+  VB_REQUIRED: '{ "required": true, "message": "请输入{0}", "trigger": ["blur"] }',
+  VB_MIN: '{"type": "string","min": {0}, "message": "至少{0}个字符", "trigger": ["blur"] }',
+  VB_MAX: '{"type": "string","max": {0}, "message": "最多{0}个字符", "trigger": ["blur" ]}',
+  VB_MIN_MAX: '{"type": "string","min": {0}, "max": {1}, "message": "长度在 {0} 到 {1} 个字符", "trigger": ["blur"]}',
+  VB_N_MIN: '{"type": "number","min": {0}, "message": "最小{0}", "trigger": ["blur"] }',
+  VB_N_MAX: '{"type": "number","max": {0}, "message": "最大{0}", "trigger": ["blur" ]}',
+  VB_N_MIN_MAX: '{"type": "number","min": {0}, "max": {1}, "message": "请输入 {0} 到 {1} 的数字", "trigger": ["blur"]}',
+}

+ 168 - 77
src/views/overAnalysis/overParam.vue

@@ -3,7 +3,12 @@ import { ref, computed } from "vue"
 import type { Header } from "@/components/Table/table-partials/models"
 import { maper } from "@/core/utils/utils"
 import Rs from "@/core/services/RequestService"
-
+import type { VbFormItem } from "@/components/Forms/models"
+import OrgSelectTree from "@/components/Tree/OrgSelectTree.vue"
+import AreaCascadeSelect from "@/components/select/AreaCascadeSelect.vue"
+import { ElInput } from "element-plus"
+import { RULE_KEYS } from "@/core/config/rules"
+import { ElSelect, ElRadioGroup, ElCheckboxGroup } from "element-plus"
 const table = ref<any>()
 const cols = ref<Array<Header>>([
   { name: "名称", field: "name", align: "left", width: "200px" },
@@ -34,11 +39,17 @@ const saveUrl = computed(() => {
     ? "sys/organizational/delById"
     : ""
 })
-
+const areaData = ref([])
+function load() {
+  Rs.get("sys/dict/getArea").then((res) => {
+    areaData.value = res.data
+  })
+}
+load()
 //只放增改传到后台的共用参数,其余需要modal显示的参数另外定义
 const emptyData = {
   org_id: "",
-  parent_id: "",
+  parent_id: "0",
   name: "",
   simple_name: "",
   code: "",
@@ -47,26 +58,113 @@ const emptyData = {
   city: "",
   district: "",
 }
-const formData = ref(emptyData)
-
-const province_city_district = ref(["", "", ""])
-
+const formData = ref<any>(
+  Object.assign({}, emptyData, { province_city_district: ["", "", ""], simple_name2: [], simple_name3: false })
+)
+const items: Array<VbFormItem> = [
+  {
+    field: "parent_id",
+    label: "父组织",
+    required: false,
+    component: OrgSelectTree,
+    span: 12,
+  },
+  {
+    field: "code",
+    label: "CODE",
+    required: true,
+    component: ElInput,
+    rules: [RULE_KEYS.REQUIRED, RULE_KEYS.MIN, RULE_KEYS.MAX],
+    ruleFormat: [["CODE"], [2], [4]],
+    span: 12,
+  },
+  {
+    field: "name",
+    label: "名称",
+    required: true,
+    component: ElInput,
+    span: 12,
+  },
+  {
+    field: "simple_name",
+    label: "简称",
+    component: ElInput,
+    span: 12,
+  },
+  {
+    field: "province_city_district",
+    label: "省/市/区",
+    component: AreaCascadeSelect,
+    listeners: { change: pcdChange },
+    //component: ElCascader,
+    // props: {
+    //   expandTrigger: "hover" as const,
+    //   clearable: true,
+    //   checkStrictly: true,
+    //   options: areaData.value,
+    // },
+  },
+  {
+    field: "description",
+    label: "描述",
+    component: ElInput,
+    type: "textarea",
+  },
+  {
+    field: "simple_name",
+    label: "简称",
+    component: ElSelect,
+    span: 12,
+    data: [
+      { label: "Q", value: "Q" },
+      { label: "W", value: "W" },
+      { label: "E", value: "E", disabled: true },
+    ],
+  },
+  {
+    field: "simple_name",
+    label: "简称",
+    component: ElRadioGroup,
+    span: 12,
+    data: [
+      { label: "Q", value: "Q" },
+      { label: "W", value: "W" },
+      { label: "E", value: "E", disabled: true },
+    ],
+  },
+  {
+    field: "simple_name2", //多选时 对象属性应该是 []
+    label: "简称2",
+    component: ElCheckboxGroup,
+    span: 12,
+    data: [
+      { label: "Q1", value: "Q" },
+      { label: "W1", value: "W" },
+      { label: "E1", value: "E", disabled: true },
+    ],
+  },
+  {
+    field: "simple_name3", //单选时 对象属性应该是 bool
+    label: "简称3",
+    component: ElCheckboxGroup,
+    span: 12,
+    data: [{ label: "Q1", value: "1" }],
+  },
+]
 function pcdChange(v: Array<string>) {
+  console.log("PCD", v)
   formData.value.province = v[0]
   formData.value.city = v[1]
   formData.value.district = v[2]
 }
 function add() {
   opreationType.value = "A"
-  formData.value = Object.assign({}, emptyData)
+  formData.value = Object.assign({ province_city_district: ["", "", ""] }, emptyData)
   modal.value.show()
 }
 function edit(row: any) {
-  //console.log("ROW", row)
   opreationType.value = "U"
-  province_city_district.value = row.province_city_district
-  formData.value = Object.assign({}, emptyData)
-  maper(formData.value, row)
+  formData.value = Object.assign({}, row)
   modal.value.show()
 }
 
@@ -77,75 +175,21 @@ function deleteRow(row: any) {
     table.value.search()
   })
 }
-function onCancel(form: any) {
-  console.log("CANCEL", form)
+function onCancel() {
+  //console.log("CANCEL", form)
 }
-function onSave(form: any) {
-  console.log("SAVE", form)
+function onSave() {
   if (saveUrl.value) {
-    Rs.post(saveUrl.value, { data: formData.value }).then(() => {
-      console.log("TABLE", table.value.search, "==", table.value)
+    const data = Object.assign({}, emptyData)
+    maper(data, formData.value)
+    Rs.post(saveUrl.value, { data: data }).then(() => {
       table.value.search()
     })
   }
 }
-function test(e: Event) {
-  console.log(e)
-}
 /**
  * 
-
-
- */
-</script>
-
-<template>
-  <VbTreeTable
-    ref="table"
-    url="sys/organizational/selectForPage"
-    method="post"
-    :header="cols"
-    key-field="org_id"
-    children-field="children"
-    :expand-depth="1"
-    :interval-left="10"
-    :fixed-column="true"
-    :fixed-number="1"
-    :fixed-right-number="1"
-  >
-    <template #table-tool="">
-      <el-button class="ms-3 mt-0 btn btn-sm btn-primary" @click="add">新增</el-button>
-    </template>
-    <template #province_city_district="{ row }">
-      {{
-        `${row.province_name ?? ""}${row.city_name ? `/${row.city_name}` : ``}${
-          row.district_name ? `/${row.district_name}` : ``
-        }`
-      }}
-    </template>
-    <template #action="{ row }">
-      <span class="text-primary table-action" @click="edit(row)">编辑</span>
-      <span class="text-danger table-action" @click="deleteRow(row)">删除</span>
-    </template>
-  </VbTreeTable>
-  <VbModal
-    v-model:modal="modal"
-    :modal-form-data="formData"
-    backdrop="static"
-    :keyboard="false"
-    :title-prefix="modalTitlePrefix"
-    title="组织机构"
-    form-label-width="70"
-    modal-body-class="px-10"
-    @cancel="onCancel"
-    @confirm="onSave"
-    :show-event="test"
-    :shown-event="test"
-    :hidden-event="test"
-    :hide-event="test"
-    :hide-prevented-event="test"
-  >
-    <template #form>
+   <template #form>
       <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item
@@ -163,8 +207,8 @@ function test(e: Event) {
             prop="code"
             required
             :rules="[
-              { required: true, message: '必填', trigger: 'blur' },
-              { min: 2, max: 4, message: '2至4个字符', trigger: 'blur' },
+              { required: true, message: '必填', trigger: ['blur'] },
+              { min: 2, max: 4, message: '2至4个字符', trigger: ['blur'] },
             ]"
           >
             <el-input v-model="formData.code"></el-input>
@@ -175,7 +219,7 @@ function test(e: Event) {
             label="名称"
             prop="name"
             required
-            :rules="[{ required: true, message: '必填', trigger: 'blur' }]"
+            :rules="[{ required: true, message: '必填', trigger: ['blur'] }]"
           >
             <el-input v-model="formData.name"></el-input>
           </el-form-item>
@@ -197,5 +241,52 @@ function test(e: Event) {
         </el-col>
       </el-row>
     </template>
-  </VbModal>
+    <template #body>
+      <VbForm :items="items" v-model:data="formData"></VbForm>
+    </template>
+ */
+</script>
+
+<template>
+  <VbTreeTable
+    ref="table"
+    url="sys/organizational/selectForPage"
+    method="post"
+    :header="cols"
+    key-field="org_id"
+    children-field="children"
+    :expand-depth="1"
+    :interval-left="10"
+    :fixed-column="true"
+    :fixed-number="1"
+    :fixed-right-number="1"
+  >
+    <template #table-tool="">
+      <el-button class="ms-3 mt-0 btn btn-sm btn-primary" @click="add">新增</el-button>
+    </template>
+    <template #province_city_district="{ row }">
+      {{
+        `${row.province_name ?? ""}${row.city_name ? `/${row.city_name}` : ``}${
+          row.district_name ? `/${row.district_name}` : ``
+        }`
+      }}
+    </template>
+    <template #action="{ row }">
+      <span class="text-primary table-action" @click="edit(row)">编辑</span>
+      <span class="text-danger table-action" @click="deleteRow(row)">删除</span>
+    </template>
+  </VbTreeTable>
+  <VbModal
+    v-model:modal="modal"
+    v-model:form-data="formData"
+    :form-items="items"
+    backdrop="static"
+    :keyboard="false"
+    :title-prefix="modalTitlePrefix"
+    title="组织机构"
+    form-label-width="70"
+    modal-body-class="px-10"
+    @cancel="onCancel"
+    @confirm="onSave"
+  ></VbModal>
 </template>