whj 11 meses atrás
pai
commit
ac92e2ee04

+ 4 - 1
src/utils/dict.js

@@ -350,7 +350,10 @@ DictCache.TYPE = {
   SO_TYPE: 'SO_TYPE', // 需求跟踪方式,
   LONG_YAN_PURCHASE_DETAIL_STATUS: 'LONG_YAN_PURCHASE_DETAIL_STATUS',
   // 设备闲置
-  SB_UNUSED_STATUS: 'SB_UNUSED_STATUS'
+  SB_UNUSED_STATUS: 'SB_UNUSED_STATUS',
+  // 自定义表单
+  CUSTOM_FORM_TYPE: 'CUSTOM_FORM_TYPE',
+  CATEGORY_TYPE: 'CATEGORY_TYPE'
 
 }
 DictCache.CODE = {

+ 4 - 4
src/views/custom/form/CustomForm.vue

@@ -1,7 +1,7 @@
 <template>
   <a-card :bordered="false">
     <a-row v-show="visible" :gutter="20">
-      <!-- <a-col :span="6">
+      <a-col :span="6">
         <a-tree
           @expand="onExpand"
           :expandedKeys="expandedKeys"
@@ -10,8 +10,8 @@
           :selectedKeys="selectedKeys"
           :treeData="treeData"
         />
-      </a-col> -->
-      <a-col :span="24">
+      </a-col>
+      <a-col :span="18">
         <div class="table-page-search-wrapper" @keyup.enter="handleEnter">
           <a-form layout="inline">
             <a-row :gutter="48" >
@@ -189,7 +189,7 @@ export default {
   created () {
     // 下拉框map
     this.typeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CUSTOM_FORM_TYPE)
-    this.categoryMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CATEGORY)
+    this.categoryMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CATEGORY_TYPE)
     this.tableOption()
     getCustomTree().then(res => {
       this.treeData = res.data

+ 123 - 75
src/views/custom/form/modules/BaseForm.vue

@@ -2,10 +2,12 @@
   <a-card :bordered="false" v-show="visible" class="card" :title="modalTitle">
     <a-row :gutter="48" slot="extra">
       <a-col :md="48" :sm="48">
-        <span class="table-page-search-submitButtons" style="float: right">
-          <a-button :loading="confirmLoading" type="primary" @click="save()">保存</a-button>
-          <a-button style="margin-left: 8px" type="default" @click="handleCancel()">返回</a-button>
-        </span>
+        <a-space class="table-page-search-submitButtons" >
+          <a-button v-show="current!==0" :loading="confirmLoading" type="primary" @click="current--">上一步</a-button>
+          <a-button v-show="current!==3" :loading="confirmLoading" type="primary" @click="next">下一步</a-button>
+          <a-button v-show="current===3" :loading="confirmLoading" type="primary" @click="save()">保存</a-button>
+          <a-button type="default" @click="handleCancel()">返回</a-button>
+        </a-space>
       </a-col>
     </a-row>
     <a-steps :current="current">
@@ -14,57 +16,66 @@
       <a-step title="表单查询字段设置" />
       <a-step title="关联流程" />
     </a-steps>
-    <a-form :form="form">
+    <br>
+    <br>
+    <a-form :form="form" v-show="current===0">
       <a-form-item v-show="false">
         <a-input v-decorator="['id']" type="hidden"/>
       </a-form-item>
-      <row-list :col="2">
-        <row-item>
-          <a-form-item
-            label="表单类型"
-            :labelCol="BaseTool.Constant.labelCol"
-            :wrapperCol="BaseTool.Constant.wrapperCol"
-          >
-            <a-input-number
-              style="width: 100%"
-              :min="0"
-              :formatter="BaseTool.Amount.formatter"
-              :parser="BaseTool.Amount.parser"
-              v-decorator="['type', {rules: [{required: true, message: '报废单  调拨单。。。不能为空'}]}]"/>
-          </a-form-item>
-        </row-item>
-        <row-item>
-
-          <a-form-item
-            label="表单json"
-            :labelCol="BaseTool.Constant.labelCol"
-            :wrapperCol="BaseTool.Constant.wrapperCol"
-          >
-          </a-form-item>
-        </row-item>
-        <row-item>
+      <a-form-item
+        label="模板名称"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-input
+          v-decorator="['name', {rules: [{required: true, message: '模板名称不能为空'}]}]"/>
+      </a-form-item>
+      <a-form-item
+        label="模板分类"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-select v-decorator="['category', {rules: [{required: true, message: '模板分类不能为空'}]}]">
+          <a-select-option v-for="(label,value) in categoryMap" :value="value" :key="value">
+            {{ label }}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item
+        label="表单类型"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-select v-decorator="['type', {rules: [{required: true, message: '表单类型不能为空'}]}]">
+          <a-select-option v-for="(label,value) in typeMap" :value="value" :key="value">
+            {{ label }}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
 
-          <a-form-item
-            label="流程ID"
-            :labelCol="BaseTool.Constant.labelCol"
-            :wrapperCol="BaseTool.Constant.wrapperCol"
-          >
-            <a-input
-              v-decorator="['flowId', {rules: [{required: true, message: '流程ID不能为空'}]}]"/>
-          </a-form-item>
-        </row-item>
-        <row-item>
+      <a-form-item
+        label="备注"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-input
+          v-decorator="['remark']"/>
+      </a-form-item>
 
-          <a-form-item
-            label="备注"
-            :labelCol="BaseTool.Constant.labelCol"
-            :wrapperCol="BaseTool.Constant.wrapperCol"
-          >
-            <a-input
-              v-decorator="['remark', {rules: [{required: true, message: '备注不能为空'}]}]"/>
-          </a-form-item>
-        </row-item>
-      </row-list>
+    </a-form>
+    <FormComponent v-show="current===1" ref="formComponent"/>
+    <a-form v-show="current===2">
+      <a-form-item
+        label="查询字段"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-select mode="multiple" :options="formComponentConfig.components" v-model="formValue.queryField">
+        <!-- <a-select-option v-for="item in detail.options" :value="item.value" :key="item.value">
+          {{ item.label }}
+        </a-select-option> -->
+        </a-select>
+      </a-form-item>
     </a-form>
   </a-card>
 </template>
@@ -72,23 +83,31 @@
 <script>
 import pick from 'lodash.pick'
 import { addCustomForm, updateCustomForm } from '@/api/custom/form'
+import FormComponent from './component/index.vue'
 export default {
   name: 'BaseCustomForm',
+  components: {
+    FormComponent
+  },
   data () {
     return {
       confirmLoading: false,
       modalTitle: null,
       form: this.$form.createForm(this),
       visible: false,
-      current: 0
+      current: 0,
       // 下拉框map
+      categoryMap: {},
+      typeMap: {},
+      formValue: {},
+      formComponentConfig: {}
     }
   },
   props: {},
   created () {
     // 下拉框map
     this.typeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CUSTOM_FORM_TYPE)
-    this.categoryMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CATEGORY)
+    this.categoryMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.CATEGORY_TYPE)
   },
   methods: {
     base (record) {
@@ -111,31 +130,60 @@ export default {
         ])))
       })
     },
+    next () {
+      switch (this.current) {
+        case 0 :
+          const { form: { validateFieldsAndScroll } } = this
+          validateFieldsAndScroll((errors, values) => {
+            if (errors) {
+              this.confirmLoading = false
+              return
+            }
+            // 日期处理
+            this.current++
+            this.formValue = values
+          })
+          break
+        case 1 :
+          this.formComponentConfig = {
+            components: this.$refs.formComponent.list2,
+            config: this.$refs.formComponent.config
+          }
+          this.current++
+          break
+        default:
+          this.current++
+
+          break
+      }
+    },
+    prev () {
+      if (this.current > 0) {
+        this.current--
+      }
+    },
     save () {
-      const { form: { validateFieldsAndScroll } } = this
       this.confirmLoading = true
-      validateFieldsAndScroll((errors, values) => {
-        if (errors) {
-          this.confirmLoading = false
-          return
-        }
-        // 日期处理
-        if (this.BaseTool.String.isBlank(values.id)) {
-          addCustomForm(values)
-            .then(() => {
-              this.handleCancel(values)
-            }).catch(() => {
-              this.confirmLoading = false
-            })
-        } else {
-          updateCustomForm(values)
-            .then(() => {
-              this.handleCancel(values)
-            }).catch(() => {
-              this.confirmLoading = false
-            })
-        }
-      })
+      // 日期处理
+      const values = {
+        ...this.formValue,
+        jsonString: JSON.stringify(this.formComponentConfig)
+      }
+      if (this.BaseTool.String.isBlank(values.id)) {
+        addCustomForm(values)
+          .then(() => {
+            this.handleCancel(values)
+          }).catch(() => {
+            this.confirmLoading = false
+          })
+      } else {
+        updateCustomForm(values)
+          .then(() => {
+            this.handleCancel(values)
+          }).catch(() => {
+            this.confirmLoading = false
+          })
+      }
     },
     handleCancel (values) {
       this.visible = false

+ 62 - 62
src/views/custom/form/modules/Detail.vue

@@ -1,69 +1,69 @@
 <template>
-    <a-card :bordered="false" v-show="visible" class="card" :title="modalTitle">
-        <a-row :gutter="48" slot="extra">
-            <a-col :md="48" :sm="48">
-              <span class="table-page-search-submitButtons" style="float: right">
-                <a-button style="margin-left: 8px" type="default" @click="handleCancel()">返回</a-button>
-              </span>
-            </a-col>
-        </a-row>
-        <detail-list title="" :col="2">
-                                                                                                    <detail-list-item term="报废单  调拨单。。。">{{ model.type }}</detail-list-item>
-                                                                                                            <detail-list-item term="表单json">{{ model.jsonString }}</detail-list-item>
-                                                                                                            <detail-list-item term="流程ID">{{ model.flowId }}</detail-list-item>
-                                                                                                            <detail-list-item term="备注">{{ model.remark }}</detail-list-item>
-                                                                                                            <detail-list-item term="创建人ID">{{ model.createdUserId }}</detail-list-item>
-                                                                                                                                                                    <detail-list-item term="更新人ID">{{ model.updateUserId }}</detail-list-item>
-                                                                                                            <detail-list-item term="更新人">{{ model.updateUserName }}</detail-list-item>
-                                                                                                            <detail-list-item term="更新时间">{{ model.updateTime }}</detail-list-item>
-                                                        </detail-list>
-    </a-card>
+  <a-card :bordered="false" v-show="visible" class="card" :title="modalTitle">
+    <a-row :gutter="48" slot="extra">
+      <a-col :md="48" :sm="48">
+        <span class="table-page-search-submitButtons" style="float: right">
+          <a-button style="margin-left: 8px" type="default" @click="handleCancel()">返回</a-button>
+        </span>
+      </a-col>
+    </a-row>
+    <detail-list title="" :col="2">
+      <detail-list-item term="报废单  调拨单。。。">{{ model.type }}</detail-list-item>
+      <detail-list-item term="表单json">{{ model.jsonString }}</detail-list-item>
+      <detail-list-item term="流程ID">{{ model.flowId }}</detail-list-item>
+      <detail-list-item term="备注">{{ model.remark }}</detail-list-item>
+      <detail-list-item term="创建人ID">{{ model.createdUserId }}</detail-list-item>
+      <detail-list-item term="更新人ID">{{ model.updateUserId }}</detail-list-item>
+      <detail-list-item term="更新人">{{ model.updateUserName }}</detail-list-item>
+      <detail-list-item term="更新时间">{{ model.updateTime }}</detail-list-item>
+    </detail-list>
+  </a-card>
 </template>
 
 <script>
-    import DetailList from '@/components/tools/DetailList'
-    const DetailListItem = DetailList.Item
+import DetailList from '@/components/tools/DetailList'
+const DetailListItem = DetailList.Item
 
-    export default {
-        name: 'CustomFormDetail',
-        components: {
-            DetailList,
-            DetailListItem
-        },
-        data () {
-            return {
-                confirmLoading: false,
-                mdl: {},
-                modalTitle: null,
-                visible: false,
-                // 下拉框map
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            model: {
-                                                                                                                    'type': null,
-                                                                                                'jsonString': null,
-                                                                                                'flowId': null,
-                                                                                                'remark': null,
-                                                                                                'createdUserId': null,
-                                                                                                                                                                                        'updateUserId': null,
-                                                                                                'updateUserName': null,
-                                                                                                'updateTime': null,
-                                                            }
-            }
-        },
-        created () {
-            // 下拉框map
-            
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        },
-        methods: {
-            base (record) {
-                this.visible = true
-                this.modalTitle = '详情'
-                this.model = record
-            },
-            handleCancel () {
-                this.visible = false
-                this.confirmLoading = false
-                this.$emit('ok')
-            }
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        }
+export default {
+  name: 'CustomFormDetail',
+  components: {
+    DetailList,
+    DetailListItem
+  },
+  data () {
+    return {
+      confirmLoading: false,
+      mdl: {},
+      modalTitle: null,
+      visible: false,
+      // 下拉框map
+      model: {
+        'type': null,
+        'jsonString': null,
+        'flowId': null,
+        'remark': null,
+        'createdUserId': null,
+        'updateUserId': null,
+        'updateUserName': null,
+        'updateTime': null
+      }
     }
+  },
+  created () {
+    // 下拉框map
+
+  },
+  methods: {
+    base (record) {
+      this.visible = true
+      this.modalTitle = '详情'
+      this.model = record
+    },
+    handleCancel () {
+      this.visible = false
+      this.confirmLoading = false
+      this.$emit('ok')
+    }
+  }
+}
 </script>

+ 220 - 0
src/views/custom/form/modules/component/index.vue

@@ -0,0 +1,220 @@
+<template>
+  <a-row :gutter="10">
+    <a-col :span="5">
+      <a-card title="基础" >
+        <a-row>
+          <VueDraggable
+            v-model="componentBaseList"
+            :animation="150"
+            :group="{ name: 'people', pull: 'clone', put: false }"
+            :sort="false"
+            :clone="onClone"
+          >
+            <a-col
+              :span="12"
+              v-for="item in componentBaseList"
+              :key="item.id">
+              <div
+                class="hover type"
+              >
+                <a-space>
+                  <a-icon type="profile" /> {{ item.name }}
+                </a-space>
+              </div>
+            </a-col>
+          </VueDraggable>
+        </a-row>
+      </a-card>
+      <a-card title="高级" >
+        <a-row>
+          <VueDraggable
+            v-model="componenHidetList"
+            :animation="150"
+            :group="{ name: 'people', pull: 'clone', put: false }"
+            :sort="false"
+            :clone="onClone"
+          >
+            <a-col
+              :span="12"
+              v-for="item in componenHidetList"
+              :key="item.id">
+              <div
+                class="hover type"
+              >
+                <a-space>
+                  <a-icon type="profile" /> {{ item.name }}
+                </a-space>
+              </div>
+            </a-col>
+          </VueDraggable>
+        </a-row>
+      </a-card>
+    </a-col>
+    <a-col :span="15">
+      <a-card>
+        <a-form
+          :form="form"
+          :labelCol="BaseTool.Constant.labelCol"
+          :wrapperCol="BaseTool.Constant.wrapperCol">
+          <a-row>
+            <VueDraggable
+              v-model="list2"
+              :animation="150"
+              group="people"
+              style="min-height:600px"
+            >
+              <MComponent
+                class="hover"
+                v-for="item in list2"
+                :key="item.id"
+                :config="config"
+                :detail="item"
+                @select="handleSelect"
+                @selectInfo="handleInfoSelect"
+              />
+            </VueDraggable>
+          </a-row>
+        </a-form>
+      </a-card>
+    </a-col>
+    <a-col :span="4">
+      <Detail :config="config" ref="detail" @delete="handleDelete" @addForm="addForm"/>
+    </a-col>
+    <SelectInfo ref="selectInfo" @selected="handleInfoSelected" />
+  </a-row>
+</template>
+
+<script>
+import { VueDraggable } from 'vue-draggable-plus'
+import Detail from './modules/Detail.vue'
+import MComponent from './modules/Component.vue'
+import SelectInfo from './modules/SelectInfo'
+
+import { componentBaseList, componenHidetList } from './modules/components'
+export default {
+  name: 'Test1',
+  components: {
+    VueDraggable,
+    Detail,
+    MComponent,
+    SelectInfo
+  },
+  data () {
+    return {
+      form: this.$form.createForm(this),
+      componentBaseList,
+      componenHidetList,
+      list2: [],
+      num: 1,
+      detail: {},
+      config: {
+        layout: 2
+      }
+    }
+  },
+  provide () {
+    return {
+      getFormList: () => {
+        return this.list2
+      }
+    }
+  },
+  watch: {
+    list2: {
+      deep: true,
+      handler (val) {
+        this.num++
+      }
+    }
+  },
+  created () {
+  },
+  mounted () {
+    this.handleSelect({}, this.config)
+  },
+  methods: {
+    onClone (element) {
+      // 生成随机id
+      const val = {
+        ...JSON.parse(JSON.stringify(element)),
+        value: `${element.value}${this.num}`,
+        id: Math.floor(Math.random() * 10000000000000)
+      }
+      this.handleSelect(val)
+      return val
+    },
+    update (val) {
+      console.log(val)
+    },
+    addForm (val) {
+      val.forEach(item => {
+        this.list2.push({
+          id: item.bind,
+          name: '单行文本',
+          type: 'input',
+          value: item.bind,
+          dependentId: false,
+          required: true,
+          label: item.columnComment,
+          attrs: {
+            placeholder: '请输入',
+            disabled: true
+          }
+        })
+      })
+    },
+    handleDelete (val) {
+      this.list2 = this.list2.filter(v => v.id !== val.id)
+    },
+    handleSubmit () {
+      const {
+        form: { validateFieldsAndScroll }
+      } = this
+      this.confirmLoading = true
+      validateFieldsAndScroll((errors, values) => {
+        console.log(values)
+        if (errors) {
+          this.confirmLoading = false
+        }
+      })
+    },
+    handleSelect (item) {
+      this.$refs.detail.base(item, this.config)
+    },
+    handleInfoSelect (item) {
+      this.$refs.selectInfo.base(item)
+    },
+    handleInfoSelected (keys, rows, detail) {
+      const {
+        form: { setFieldsValue }
+      } = this
+      if (detail.attrs.selectType === 'radio') {
+        const data = rows[0]
+        const value = {}
+        detail.attrs.connect.forEach(item => {
+          value[item.bind] = data[item.columnName]
+        })
+        this.$nextTick(() => {
+          setFieldsValue(value)
+        })
+      } else {
+        this.$nextTick(() => {
+          setFieldsValue({
+            [detail.attrs.connect[0].bind]: keys
+          })
+        })
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.type{
+border: 1px solid #ccc;
+padding: 5px;
+margin: 5px;
+border-radius: 5px;
+}
+
+</style>

+ 70 - 0
src/views/custom/form/modules/component/modules/BindTable.vue

@@ -0,0 +1,70 @@
+<template>
+  <a-modal
+    title="数据绑定"
+    :visible="visible"
+    @cancel="handleCancel"
+    :width="800"
+    @ok="handleOk">
+    <a-table :columns="columns" :data-source="data">
+      <span slot="bind" slot-scope="text,record">
+        <a-select allowClear style="width:150px" v-model="record.bind" :options="selectList">
+        </a-select>
+      </span>
+    </a-table>
+  </a-modal>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      visible: false,
+      confirmLoading: false,
+      selectList: [],
+      columns: [
+        {
+          title: '字段名',
+          dataIndex: 'columnComment',
+          key: 'columnComment'
+        },
+        {
+          title: '字段值',
+          dataIndex: 'columnName',
+          key: 'columnName'
+        },
+        {
+          title: '绑定值',
+          dataIndex: 'bind',
+          key: 'bind',
+          scopedSlots: { customRender: 'bind' }
+        }
+      ],
+      data: []
+    }
+  },
+  inject: ['getFormList'],
+  created () {
+
+  },
+  methods: {
+    base (record) {
+      this.visible = true
+      this.data = record
+      const arr = this.getFormList()
+      this.selectList = arr.filter(item => item.type !== 'divider')
+    },
+    handleOk () {
+      const bindList = this.data.filter(item => item.bind)
+      this.$emit('bind', bindList)
+      this.visible = false
+    },
+    handleCancel () {
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 70 - 0
src/views/custom/form/modules/component/modules/Component.vue

@@ -0,0 +1,70 @@
+<template>
+  <a-col @click="handleSelect" :span="detail.type==='divider'?24:24/config.layout">
+    <a-form-item :label="detail.label" v-if="detail.type!=='divider'">
+      <!-- 输入框 -->
+      <a-input v-if="detail.type==='input'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 数字输入框 -->
+      <a-input-number style="width:100%" v-if="detail.type==='number'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 文本域 -->
+      <a-textarea v-if="detail.type==='textarea'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 下拉框 -->
+      <a-select v-if="detail.type==='select'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" >
+        <!-- <a-select-option v-for="item in detail.options" :value="item.value" :key="item.value">
+          {{ item.label }}
+        </a-select-option> -->
+      </a-select>
+      <!-- 日期时间 -->
+      <a-date-picker style="width:100%" v-if="detail.type==='date'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 文件上传 -->
+      <UploadFile v-if="detail.type==='uploadFile'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 图片上传 -->
+      <UploadImg v-if="detail.type==='uploadImg'" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+      <!-- 选择数据 -->
+      <template v-if="detail.type==='dataSelect'">
+        <a-input style="width:70%" v-bind="detail.attrs" v-decorator="[detail.value, { rules: [{ required: detail.required, message: detail.attrs.placeholder}] }]" />
+        <a-button style="width:30%" type="primary" @click="handleSelectData">选择</a-button>
+      </template>
+    </a-form-item>
+    <!-- 分割线 -->
+    <a-divider v-bind="detail.attrs" v-if="detail.type==='divider'">
+      <template v-if="detail.label">
+        {{ detail.label }}
+      </template>
+    </a-divider>
+  </a-col>
+</template>
+
+<script>
+import UploadFile from '@/components/Upload/CUploadFile.vue'
+import UploadImg from '@/components/Upload/CUploadImg.vue'
+export default {
+  name: 'MComponent',
+  components: {
+    UploadFile,
+    UploadImg
+  },
+  props: {
+    detail: {
+      type: Object,
+      required: true,
+      default: () => {}
+    },
+    config: {
+      type: Object,
+      required: true
+    }
+  },
+  methods: {
+    handleSelect () {
+      this.$emit('select', this.detail)
+    },
+    handleSelectData () {
+      this.$emit('selectInfo', this.detail)
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 258 - 0
src/views/custom/form/modules/component/modules/Detail.vue

@@ -0,0 +1,258 @@
+<template>
+  <a-card
+    :tab-list="tabList"
+    size="small"
+    style="min-height:600px"
+    :active-tab-key="selectKey"
+    @tabChange="onTabChange">
+    <a-form
+      v-show="model.id"
+      size="small"
+      v-if="selectKey === '0'">
+      <a-form-item label="标题">
+        <a-input v-model="model.label" />
+      </a-form-item>
+      <template v-if="model.type!=='divider'">
+        <a-form-item label="字段名称">
+          <a-input v-model="model.value" />
+        </a-form-item>
+        <a-form-item label="是否必填">
+          <a-switch v-model="model.required" />
+        </a-form-item>
+        <a-form-item label="默认提示" v-if="model.attrs">
+          <a-input v-model="model.attrs.placeholder" />
+        </a-form-item>
+      </template>
+      <template v-else>
+        <a-form-item label="布局">
+          <a-radio-group name="radioGroup" v-model="model.attrs.orientation">
+            <a-radio value="left">
+              左边
+            </a-radio>
+            <a-radio value="center">
+              中间
+            </a-radio>
+            <a-radio value="right">
+              右边
+            </a-radio>
+          </a-radio-group>
+        </a-form-item>
+      </template>
+      <!-- 数字输入框 -->
+      <template v-if="model.type === 'number'">
+        <a-form-item label="最小值">
+          <a-input-number v-model="model.min" />
+        </a-form-item>
+        <a-form-item label="最大值">
+          <a-input-number v-model="model.max" />
+        </a-form-item>
+        <a-form-item label="数值精度">
+          <a-input-number v-model="model.precision" />
+        </a-form-item>
+      </template>
+      <!-- 下拉框 -->
+      <template v-if="model.type === 'select'">
+        <a-form-item label="选项">
+          <VueDraggable
+            v-model="model.attrs.options"
+            :animation="150"
+            handle=".handle"
+          >
+            <div
+              v-for="(item, index) in model.attrs.options"
+              :key="index"
+              class="options"
+            >
+              <a-space>
+                <a-icon class="handle cursor-move" type="unordered-list" />
+                <a-input-group compact>
+                  <a-input style="width:50%" v-model="item.label" />
+                  <a-input style="width:50%" v-model="item.value" />
+                </a-input-group>
+                <a-icon type="close" @click="deleteOption(index)" />
+              </a-space>
+            </div>
+          </VueDraggable>
+          <a-button @click="addOption" style="width:100%"><a-icon type="plus" /></a-button>
+        </a-form-item>
+      </template>
+      <!-- 日期选择 -->
+      <template v-if="model.type === 'date'">
+        <a-form-item label="是否显示时间">
+          <a-switch v-model="model.attrs.showTime" />
+        </a-form-item>
+        <a-form-item label="时间格式">
+          <a-input placeholder="YYYY-MM-DD HH:mm:ss" v-model="model.attrs.format" ></a-input>
+        </a-form-item>
+      </template>
+      <!-- 上传 -->
+      <template v-if="model.type === 'uploadFile'||model.type === 'uploadImg'">
+        <a-form-item label="最大上传数">
+          <a-input-number v-model="model.attrs.maxSize" />
+        </a-form-item>
+      </template>
+      <!-- 选择数据 -->
+      <template v-if="model.type === 'dataSelect'">
+        <a-form-item label="选择表单">
+          <a-select v-model="model.attrs.dict" placeholder="请选择" :options="DictCache.getChildrenList('TABLE_MAPPING')" @change="dictChange">
+          </a-select>
+        </a-form-item>
+        <a-form-item label="选择类型">
+          <a-radio-group name="radioGroup" v-model="model.attrs.selectType" @change="selectTypeChange">
+            <a-radio value="radio">
+              单选
+            </a-radio>
+            <a-radio value="checkbox">
+              多选
+            </a-radio>
+          </a-radio-group>
+        </a-form-item>
+        <a-form-item label="默认字段" v-if="model.attrs.connect.length">
+          <a-select v-model="model.attrs.connect[0].columnName" placeholder="请选择">
+            <a-select-option v-for="item in tableList" :value="item.columnName" :key="item.columnName">
+              {{ item.columnComment }}
+            </a-select-option>
+          </a-select>
+        </a-form-item>
+        <!-- <a-form-item label="附加字段" v-if="model.attrs.connect.length&&model.attrs.selectType=='radio'">
+          <a-select mode="multiple" v-model="additionalField" placeholder="请选择" @change="additionalFieldChange">
+            <a-select-option v-for="item in tableList" :value="item.columnName" :key="item.columnName" :label=" item.columnComment">
+              {{ item.columnComment }}
+            </a-select-option>
+          </a-select>
+          <a-button type="primary" @click="addForm()">添加到表单</a-button>
+        </a-form-item> -->
+      </template>
+      <a-popconfirm
+        title="确定删除该组件?"
+        ok-text="确定"
+        cancel-text="取消"
+        @confirm="deleteModel"
+      >
+        <a-button type="danger" style="width:100%">删除</a-button>
+      </a-popconfirm>
+    </a-form>
+    <a-form
+      size="small"
+      v-if="selectKey === '1'">
+      <a-form-item label="布局">
+        <a-radio-group name="radioGroup" v-model="config.layout">
+          <a-radio :value="1">
+            单列
+          </a-radio>
+          <a-radio :value="2">
+            双列
+          </a-radio>
+          <a-radio :value="3">
+            三列
+          </a-radio>
+        </a-radio-group>
+      </a-form-item>
+    </a-form>
+    <BindTable ref="bindTable" @bind="handleBind" />
+  </a-card>
+</template>
+
+<script>
+
+import { VueDraggable } from 'vue-draggable-plus'
+import { getTableInfos } from '@/api/custom/form'
+import BindTable from './BindTable.vue'
+export default {
+  components: {
+    VueDraggable,
+    BindTable
+  },
+  data () {
+    return {
+      model: {
+        attrs: {
+          placeholder: ''
+        }
+      },
+      config: {},
+      selectKey: '0',
+      tabList: [
+        {
+          key: '0',
+          tab: '字段属性'
+        },
+        {
+          key: '1',
+          tab: '表单属性'
+        }
+      ],
+      tableList: [],
+      additionalField: []
+    }
+  },
+  created () {
+  },
+  methods: {
+    base (val, config) {
+      this.model = val
+      this.config = config
+      if (this.model.attrs.dict !== undefined && this.model.attrs.dict !== '') {
+        this.dictChange(this.model.attrs.dict)
+      }
+      this.additionalField = val.attrs.connect && val.attrs.connect.length > 1 ? val.attrs.connect.slice(1, val.attrs.connect.length).map(item => item.columnName) : []
+    },
+    addOption () {
+      this.model.attrs.options.push({
+        label: '选项' + (this.model.attrs.options.length + 1),
+        value: 'newValue' + (this.model.attrs.options.length + 1)
+      })
+    },
+    deleteOption (i) {
+      this.model.attrs.options.splice(i, 1)
+    },
+    deleteModel () {
+      this.$emit('delete', this.model)
+    },
+    dictChange (tableName) {
+      getTableInfos({ tableName }).then(res => {
+        this.tableList = res.data
+        if (this.model.attrs.connect.length === 0) {
+          this.model.attrs.connect.push({
+            bind: 'id',
+            columnName: 'id',
+            columnComment: 'id'
+          })
+        }
+      })
+    },
+    selectTypeChange () {
+      this.model.attrs.connect.splice(1)
+      this.additionalField = []
+    },
+    additionalFieldChange (val, e) {
+      const arr = e.map(item => {
+        return {
+          bind: item.key,
+          columnName: item.key,
+          columnComment: item.componentOptions.propsData.label
+        }
+      })
+      this.model.attrs.connect.splice(1, this.model.attrs.connect.length - 1, ...arr)
+    },
+    addForm () {
+      this.$emit('addForm', this.model.attrs.connect.slice(1, this.model.attrs.connect.length))
+    },
+    bindTable (tableName) {
+      this.$refs.bindTable.base(this.tableList)
+    },
+    handleBind (val) {
+      this.model.attrs.connect = val
+    },
+    onTabChange (key) {
+      this.selectKey = key
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.options{
+  margin-bottom:5px ;
+}
+</style>

+ 358 - 0
src/views/custom/form/modules/component/modules/SbInfoSelectModal.vue

@@ -0,0 +1,358 @@
+<template>
+  <a-modal
+    :title="modalTitle"
+    :width="1300"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    class="ant-modal2"
+    @cancel="handleCancel"
+  >
+    <a-card :bordered="false">
+      <div class="table-page-search-wrapper">
+        <a-form layout="inline">
+          <a-row :gutter="48">
+            <a-col :md="8" :sm="24">
+              <a-form-item label="关键字">
+                <a-input v-model.trim="queryParam.keyword" placeholder="请输入名称/编码"/>
+              </a-form-item>
+            </a-col>
+            <!--            <a-col :md="8" :sm="24">
+              <a-form-item label="上层设备类型">
+                <a-tree-select
+                  style="width: 100%"
+                  :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
+                  :treeData="treeData"
+                  :treeNodeFilterProp="'title'"
+                  :showSearch="true"
+                  v-model="queryParam.parentId"
+                  placeholder="请选择"
+                >
+                </a-tree-select>
+              </a-form-item>
+            </a-col>-->
+            <a-col :md="6" :sm="24">
+              <a-form-item label="车间位置">
+                <a-select v-model="queryParam.positionId" placeholder="请选择">
+                  <a-select-option
+                    v-for="({id,name}) in sbPositionData"
+                    :key="id"
+                    :label="name"
+                    :value="id">{{ name }}
+                  </a-select-option>
+                </a-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="6" :sm="24">
+              <a-form-item label="设备类型">
+                <a-tree-select
+                  style="width: 100%"
+                  :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
+                  :treeData="treeData"
+                  :treeNodeFilterProp="'title'"
+                  :showSearch="true"
+                  placeholder="请选择"
+                  @change="handleChange"
+                >
+                </a-tree-select>
+              </a-form-item>
+            </a-col>
+            <a-col :md="8 || 24" :sm="24">
+              <span class="table-page-search-submitButtons">
+                <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+                <a-button style="margin-left: 8px" @click="resetSearchForm">重置</a-button>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+
+      <div class="table-operator" style="margin-bottom: 8px;">
+      </div>
+
+      <s-table
+        ref="table"
+        size="default"
+        rowKey="id"
+        :columns="columns"
+        :data="loadData"
+        :alert="options.alert"
+        :customRow="options.customRow"
+        :rowSelection="options.rowSelection"
+        :scroll="{ x: 1300, y: BaseTool.Constant.scrollY }"
+        showPagination="auto"
+      >
+        <span slot="action" slot-scope="record">
+          <template>
+
+          </template>
+        </span>
+        <span slot="status" slot-scope="text">
+          <badge :status="DictCache.COLOR.SB_INFO_STATUS[text]" :text="statusMap[text]" />
+        </span>
+      </s-table>
+    </a-card>
+    <template slot="footer">
+      <a-button :loading="confirmLoading" type="primary" @click="handleCancel()">取消</a-button>
+      <a-button :loading="confirmLoading" type="primary" @click="handleSelect()">选择</a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { STable, Ellipsis } from '@/components'
+import { getSbInfoPage, fetchSbInfo, getSbInfoTree } from '@/api/sb/info'
+import { querySbPosition } from '@/api/sb/position'
+import { fetchSbTypeTree } from '@/api/sb/type'
+
+export default {
+  name: 'SbInfoSelectModal',
+  components: {
+    STable,
+    Ellipsis
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'radio'
+    },
+    selectedRowKey: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    selectedRow: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data () {
+    return {
+      confirmLoading: false,
+      mdl: {},
+      modalTitle: null,
+      visible: false,
+      // 查询参数
+      queryParam: {
+      },
+      extraQueryParam: {
+      },
+      depreciationTypeMap: {},
+      levelMap: {},
+      statusMap: {},
+      unitMap: {},
+      useTypeMap: {},
+      sourceTypeMap: {},
+      treeData: [],
+      sbPositionData: [],
+      typeList: [],
+      // 表头
+      columns: [
+        {
+          title: '设备名称',
+          checked: true,
+          dataIndex: 'name'
+        },
+        {
+          title: '设备编号',
+          dataIndex: 'no',
+          checked: true
+        },
+        {
+          title: '设备位号',
+          checked: true,
+          dataIndex: 'positionNo'
+        },
+        {
+          title: '型号',
+          checked: true,
+          dataIndex: 'model'
+        },
+        {
+          title: '设备类型',
+          dataIndex: 'type',
+          checked: true,
+          width: 200,
+          customRender: (text, record, index) => {
+            return record.typeName
+          }
+        },
+        {
+          title: '设备等级',
+          dataIndex: 'level',
+          checked: true,
+          width: 200,
+          customRender: (text, record, index) => {
+            return this.BaseTool.Object.getField(this.levelMap, text)
+          }
+        },
+        {
+          title: '状态',
+          dataIndex: 'status',
+          checked: true,
+          width: 200,
+          scopedSlots: { customRender: 'status' }
+        },
+        {
+          title: '备注',
+          dataIndex: 'remark',
+          width: 200
+        },
+        {
+          title: '操作',
+          key: 'action',
+          width: '200px',
+          align: 'center',
+          fixed: 'right',
+          scopedSlots: { width: 200, customRender: 'action' }
+        }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        parameter = {
+          ...parameter,
+          ...this.queryParam,
+          ...this.extraQueryParam,
+          typeList: this.typeList,
+          dataScope: {
+            sortBy: 'asc',
+            sortName: 'no'
+          }
+        }
+        return getSbInfoPage(Object.assign(parameter, this.queryParam))
+          .then(res => {
+            return res.data
+          })
+      },
+      selectedRowKeys: [],
+      selectedRows: [],
+
+      options: {
+        alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+        rowSelection: {
+          selectedRowKeys: this.selectedRowKeys,
+          onChange: this.onSelectChange
+        }
+      },
+      optionAlertShow: true,
+      isCreated: false
+    }
+  },
+  created () {
+    this.tableOption()
+    this.depreciationTypeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SBINFO_DEPRECIATIONTYPE)
+    this.levelMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SBINFO_LEVEL)
+    this.statusMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SB_INFO_STATUS)
+    this.unitMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SBINFO_UNIT)
+    this.sourceTypeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SBTYPE_SOURCETYPE)
+    this.useTypeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.SB_UES_TYPE)
+    querySbPosition().then(res => {
+      this.sbPositionData = res.data
+    })
+    fetchSbTypeTree().then(res => {
+      this.treeData = res.data
+    })
+  },
+  methods: {
+    tableOption () {
+      // this.setTree()
+      if (!this.optionAlertShow) {
+        this.options = {
+          alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+          rowSelection: {
+            selectedRowKeys: this.selectedRowKeys,
+            onChange: this.onSelectChange,
+            type: this.type,
+            getCheckboxProps: record => ({
+              props: {
+                disabled: false,
+                name: record.id
+              }
+            })
+          },
+          customRow: (record) => {
+            return {
+              on: { // 事件
+                click: (event) => { // 点击行
+                  // 选择对象
+                  this.mySelect([record.id], [record])
+                },
+                dblclick: (event) => {
+                  this.mySelect([record.id], [record])
+                  this.handleSelect()
+                }
+              }
+            }
+          }
+        }
+        this.optionAlertShow = true
+      } else {
+        this.options = {
+          alert: false,
+          rowSelection: null
+        }
+        this.optionAlertShow = false
+      }
+    },
+    handleOk () {
+      // this.setTree()
+      this.$refs.table.refresh()
+    },
+    onSelectChange (selectedRowKeys, selectedRows) {
+      this.selectedRowKeys = selectedRowKeys
+      this.selectedRows = selectedRows
+    },
+    resetSearchForm () {
+      this.queryParam = {
+      }
+      this.$refs.table.refresh(true)
+    },
+    /**
+     * 设置设备类型树
+     */
+    base (record, queryParam = {}) {
+      this.visible = true
+      this.modalTitle = '选择设备'
+      this.queryParam = queryParam
+      if (this.isCreated) {
+        console.log(this.$refs.table)
+        this.$refs.table.clearSelected()
+        this.options.rowSelection.type = this.type
+        this.handleOk()
+      } else {
+        this.tableOption()
+        this.isCreated = true
+      }
+      // this.mySelect(this.selectedRowKeys, this.selectedRows)
+    },
+    handleCancel () {
+      this.visible = false
+      this.confirmLoading = false
+    },
+    handleSelect () {
+      if (this.selectedRowKeys.length === 0) {
+        this.$message.warn('请至少选择一项信息')
+      } else {
+        this.confirmLoading = true
+        this.$emit('selected', this.selectedRowKeys, this.selectedRows)
+        this.confirmLoading = false
+        this.visible = false
+      }
+    },
+    mySelect (selectedRowKeys, selectedRows) {
+      this.$refs.table.updateSelect(selectedRowKeys, selectedRows)
+      this.$refs.table.rowSelection.onChange(selectedRowKeys, selectedRows)
+    },
+    handleChange (value, label, extra) {
+      const data = this.treeData.find(item => item.id === value)
+      if (data && data.children && data.children.length > 0) {
+        this.typeList = data.children.map(item => item.id)
+      } else {
+        this.typeList = [value]
+      }
+    }
+  }
+}
+</script>

+ 49 - 0
src/views/custom/form/modules/component/modules/SelectInfo.vue

@@ -0,0 +1,49 @@
+<template>
+  <div>
+    <StoreSelectModal :type="detail.attrs.selectType" v-if="active === 't_store'" ref="select" @selected="selected"/>
+    <SpareStoreSelectModal :type="detail.attrs.selectType" v-else-if="active === 't_spare_part_info'" ref="select" @selected="selected"/>
+    <SbInfoSelectModal :type="detail.attrs.selectType" v-else-if="active === 't_sb_info'" ref="select" @selected="selected" />
+  </div>
+</template>
+
+<script>
+import SbInfoSelectModal from './SbInfoSelectModal.vue'
+import SpareStoreSelectModal from './SpareStoreSelectModal.vue'
+import StoreSelectModal from './StoreSelectModal.vue'
+export default {
+  components: {
+    SbInfoSelectModal,
+    SpareStoreSelectModal,
+    StoreSelectModal
+  },
+  data () {
+    return {
+      active: '',
+      detail: {}
+    }
+  },
+  methods: {
+    base (item) {
+      if (!item.attrs.dict) {
+        this.$message.warning('请配置表单!')
+        return
+      }
+      this.active = item.attrs.dict
+      this.detail = item
+      this.$nextTick(() => {
+        this.$refs.select.base()
+      })
+    },
+    selected (keys, rows) {
+      this.$emit('selected', keys, rows, this.detail)
+    }
+  },
+  created () {
+
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 351 - 0
src/views/custom/form/modules/component/modules/SpareStoreSelectModal.vue

@@ -0,0 +1,351 @@
+<template>
+  <a-modal
+    :title="modalTitle"
+    :width="1300"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    class="ant-modal2"
+    @cancel="handleCancel"
+  >
+    <a-card :bordered="false">
+      <a-row :gutter="8">
+        <!--        <a-col :span="5">
+          <a-tree
+            @expand="onExpand"
+            :expandedKeys="expandedKeys"
+            :autoExpandParent="true"
+            @select="onSelect"
+            :selectedKeys="selectedKeys"
+            :treeData="spareTypeTreeData"
+          />
+        </a-col>-->
+        <a-col :span="24">
+          <div class="table-page-search-wrapper">
+            <a-form layout="inline">
+              <a-row :gutter="48">
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="仓库编码">
+                    <a-input v-model.trim="queryParam.storeNo" placeholder="仓库编码"/>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="仓库名称">
+                    <a-input v-model.trim="queryParam.storeName" placeholder="仓库名称"/>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="存货编码">
+                    <a-input v-model.trim="queryParam.spareNo" placeholder="存货名称"/>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="存货名称">
+                    <a-input v-model.trim="queryParam.spareName" placeholder="存货名称"/>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="6" :sm="24">
+                  <a-form-item label="规格型号">
+                    <a-input v-model.trim="queryParam.ggxh" placeholder="规格型号"/>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="6 || 24" :sm="24">
+                  <a-form-item label="厂区">
+                    <a-select v-model="queryParam.tokenType" placeholder="请选择">
+                      <a-select-option
+                        v-for="(label,value) in flagMap"
+                        :key="value"
+                        :label="label"
+                        :value="parseInt(value)">{{ label }}
+                      </a-select-option>
+                    </a-select>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="8 || 24" :sm="24">
+                  <span class="table-page-search-submitButtons">
+                    <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+                    <a-button style="margin-left: 8px" @click="resetSearchForm">重置</a-button>
+                  </span>
+                </a-col>
+              </a-row>
+            </a-form>
+          </div>
+
+          <div class="table-operator" style="margin-bottom: 8px;">
+          </div>
+
+          <s-table
+            ref="table"
+            size="default"
+            rowKey="autoId"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert"
+            :customRow="options.customRow"
+            :rowSelection="options.rowSelection"
+            showPagination="auto"
+          >
+          </s-table>
+        </a-col>
+      </a-row>
+      <detail ref="detailModal"/>
+    </a-card>
+    <template slot="footer">
+      <a-button :loading="confirmLoading" type="primary" @click="handleCancel()">取消</a-button>
+      <a-button :loading="confirmLoading" type="primary" @click="handleSelect()">选择</a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { STable, Ellipsis } from '@/components'
+import { fetchSpareTypeTree } from '@/api/sqarepartmanage/sparetype'
+import { fetchStoreTree } from '@/api/store/store'
+
+import { getSpareStorePageYY } from '@/api/yongyou/yongyou'
+export default {
+  name: 'SpareStoreSelectModalYY',
+  components: {
+    STable,
+    Ellipsis
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'radio'
+    },
+    selectedRowKey: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    selectedRow: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data () {
+    return {
+      confirmLoading: false,
+      mdl: {},
+      storeTreeDate: [],
+      modalTitle: null,
+      visible: false,
+      record: null,
+      spareTypeTreeData: [],
+      expandedKeys: [],
+      selectedKeys: [],
+      isSpecial: null,
+      // 查询参数
+      queryParam: {
+        storeNo: '09',
+        tokenType: 1
+      },
+      // 表头
+      columns: [
+        {
+          title: '序号',
+          dataIndex: 'index',
+          customRender: (text, record, index) => {
+            return `${(this.$refs.table.localPagination.current - 1) * this.$refs.table.localPagination.pageSize + index + 1}`
+          }
+        },
+        {
+          title: '存货编号',
+          dataIndex: 'no'
+        },
+        {
+          title: '存货名称',
+          dataIndex: 'spareName'
+        },
+        {
+          title: '规格型号',
+          dataIndex: 'ggxh'
+        },
+        {
+          title: '仓库名称',
+          dataIndex: 'storeName'
+        },
+        {
+          title: '货架号',
+          dataIndex: 'storePosition'
+        },
+        {
+          title: '批号',
+          dataIndex: 'cbatch'
+        },
+        {
+          title: '库存数量',
+          dataIndex: 'num'
+        },
+        {
+          title: '单位',
+          dataIndex: 'unit'
+        }
+      ],
+      // 下拉框map
+      delFlagMap: {},
+      flagMap: {},
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        parameter = {
+          ...parameter,
+          ...this.queryParam,
+          dataScope: {
+            sortBy: 'desc',
+            sortName: 'update_time'
+          }
+        }
+        return getSpareStorePageYY(Object.assign(parameter, this.queryParam)).then(res => {
+          if (res.data.rows === null) {
+            const data = { total: 0, rows: [], pageNum: 1, pageSize: 10, pages: 1 }
+            return data
+          } else {
+            return res.data
+          }
+        })
+      },
+      selectedRowKeys: [],
+      selectedRows: [],
+      options: {
+        alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+        rowSelection: {
+          selectedRowKeys: this.selectedRowKeys,
+          onChange: this.onSelectChange
+        }
+      },
+      optionAlertShow: false,
+      isCreated: false
+    }
+  },
+  created () {
+    // 下拉框map
+    this.delFlagMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.DELFLAG)
+    this.flagMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.PROJECT_NEW_AND_OLD)
+
+    // this.tableOption()
+    fetchSpareTypeTree({}).then(res => {
+      this.spareTypeTreeData = res.data
+    })
+    fetchStoreTree({}).then(res => {
+      this.storeTreeDate = res.data
+    })
+  },
+  methods: {
+    tableOption () {
+      if (!this.optionAlertShow) {
+        this.options = {
+          alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+          rowSelection: {
+            selectedRowKeys: this.selectedRowKeys,
+            onChange: this.onSelectChange,
+            type: this.type,
+            getCheckboxProps: record => ({
+              props: {
+                disabled: false,
+                name: record.id
+              }
+            })
+          }
+          // customRow: (record) => {
+          //   return {
+          //     on: { // 事件
+          //       click: (event) => { // 点击行
+          //         // 选择对象
+          //         this.mySelect([record.id], [record])
+          //       },
+          //       dblclick: (event) => {
+          //         this.mySelect([record.id], [record])
+          //         this.handleSelect()
+          //       }
+          //     }
+          //   }
+          // }
+        }
+        this.optionAlertShow = true
+      } else {
+        this.options = {
+          alert: false,
+          rowSelection: null
+        }
+        this.optionAlertShow = false
+      }
+    },
+    handleOk () {
+      this.$refs.table.refresh()
+    },
+    onSelectChange (selectedRowKeys, selectedRows) {
+      this.selectedRows = [...new Set([...this.selectedRows, ...selectedRows])]
+      this.selectedRowKeys = selectedRowKeys
+    },
+    resetSearchForm () {
+      this.queryParam = {
+        storeNo: '09'
+      }
+      this.$refs.table.refresh(true)
+    },
+    base (record, queryParam = { storeNo: '09' }) {
+      this.visible = true
+      this.modalTitle = '选择信息'
+      this.queryParam = queryParam
+      this.queryParam.tokenType = record && record.tokenType ? record.tokenType : 1
+      if (queryParam.isSpecial !== undefined) {
+        this.isSpecial = queryParam.isSpecial
+        this.record = record
+      }
+      if (this.isCreated) {
+        this.$refs.table.clearSelected()
+        // this.options.rowSelection.type = this.type
+        this.handleOk()
+      } else {
+        this.tableOption()
+        this.isCreated = true
+      }
+    },
+    handleCancel () {
+      this.visible = false
+      this.confirmLoading = false
+    },
+    handleSelect () {
+      if (this.selectedRowKeys.length === 0) {
+        this.$message.warn('请至少选择一项信息')
+      } else {
+        /* console.log(this.selectedRows[0].num)
+         if (this.selectedRows[0].num == 0) {
+         this.$message.error('不能选择库存为0的物品,请重新选择')
+         return
+       } */
+        this.confirmLoading = true
+        if (this.record !== null) {
+          this.record.isSpecial = this.isSpecial
+        }
+        this.selectedRows = this.selectedRows.filter(item => this.selectedRowKeys.includes(+item.id))
+        this.$emit('selected', this.selectedRowKeys, this.selectedRows)
+        this.confirmLoading = false
+        this.visible = false
+      }
+    },
+    // mySelect (selectedRowKeys, selectedRows) {
+    //   this.selectedRowKeys = selectedRowKeys
+    //   this.selectedRows = selectedRows
+    //   console.log(this.selectedRowKeys, this.selectedRows)
+    //   this.$refs.table.updateSelect(this.selectedRowKeys, this.selectedRows)
+    //   this.$refs.table.rowSelection.onChange(this.selectedRowKeys, this.selectedRows)
+    // },
+    onSelect: function (selectedKeys, info) {
+      this.selectedKeys = selectedKeys
+      this.queryParam.typeId = selectedKeys.length > 0 ? selectedKeys[0] : ''
+      this.$refs.table.refresh(true)
+    },
+    onExpand (expandedKeys) {
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+    handleAdd () {
+      this.$refs.addSpareForm.base()
+    }
+  }
+}
+</script>

+ 281 - 0
src/views/custom/form/modules/component/modules/StoreSelectModal.vue

@@ -0,0 +1,281 @@
+<template>
+  <a-modal
+    :title="modalTitle"
+    :width="1000"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    class="ant-modal2"
+    @cancel="handleCancel"
+  >
+    <a-card :bordered="false">
+      <div class="table-page-search-wrapper">
+        <a-form layout="inline">
+          <a-row :gutter="48">
+            <a-col :md="8" :sm="24">
+              <a-form-item label="关键字">
+                <a-input v-model.trim="queryParam.keyword" placeholder="请输入名称/编码"/>
+              </a-form-item>
+            </a-col>
+            <a-col :md="8 || 24" :sm="24">
+              <span class="table-page-search-submitButtons">
+                <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+                <a-button style="margin-left: 8px" @click="resetSearchForm">重置</a-button>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+
+      <div class="table-operator" style="margin-bottom: 8px;">
+      </div>
+
+      <s-table
+        ref="table"
+        size="default"
+        rowKey="id"
+        :columns="columns"
+        :data="loadData"
+        :alert="options.alert"
+        :customRow="options.customRow"
+        :rowSelection="options.rowSelection"
+        showPagination="auto"
+      >
+        <span slot="delFlag" slot-scope="text">
+          <badge
+            :status="DictCache.COLOR.DELFLAG[text]"
+            :text="delFlagMap[text]" />
+        </span>
+      </s-table>
+    </a-card>
+    <template slot="footer">
+      <a-button :loading="confirmLoading" type="primary" @click="handleCancel()">取消</a-button>
+      <a-button :loading="confirmLoading" type="primary" @click="handleSelect()">选择</a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { STable, Ellipsis } from '@/components'
+import { getStorePage, fetchStore } from '@/api/store/store'
+
+export default {
+  name: 'StoreSelectModal',
+  components: {
+    STable,
+    Ellipsis
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'radio'
+    },
+    selectedRowKey: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    selectedRow: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data () {
+    return {
+      confirmLoading: false,
+      mdl: {},
+      modalTitle: null,
+      visible: false,
+      record: null,
+      // 查询参数
+      queryParam: {
+      },
+      extraQueryParam: {
+      },
+      // 表头
+      columns: [
+        {
+          title: '序号',
+          dataIndex: 'index',
+          customRender: (text, record, index) => {
+            return `${(this.$refs.table.localPagination.current - 1) * this.$refs.table.localPagination.pageSize + index + 1}`
+          }
+        },
+        {
+          title: '编码',
+          dataIndex: 'no'
+        },
+        {
+          title: '名称',
+          dataIndex: 'name'
+        },
+        {
+          title: '等級',
+          dataIndex: 'level',
+          customRender: (text, record, index) => {
+            return this.BaseTool.Object.getField(this.levelMap, text)
+          }
+        },
+        {
+          title: '类型',
+          dataIndex: 'type',
+          customRender: (text, record, index) => {
+            return this.BaseTool.Object.getField(this.typeMap, text)
+          }
+        },
+        {
+          title: '上层仓库',
+          dataIndex: 'parentId',
+          customRender: (text, record, index) => {
+            return record.parentName
+          }
+        },
+        {
+          title: '备注',
+          dataIndex: 'remark'
+        },
+        {
+          title: '是否删除',
+          dataIndex: 'delFlag',
+          scopedSlots: { customRender: 'delFlag' }
+        },
+        {
+          title: '创建日期',
+          dataIndex: 'createdTime'
+        }
+      ],
+      // 下拉框map
+      typeMap: {},
+      levelMap: {},
+      delFlagMap: {},
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        parameter = {
+          ...parameter,
+          ...this.queryParam,
+          ...this.extraQueryParam,
+          dataScope: {
+          }
+        }
+        return getStorePage(Object.assign(parameter, this.queryParam))
+          .then(res => {
+            return res.data
+          })
+      },
+      selectedRowKeys: [],
+      selectedRows: [],
+
+      options: {
+        alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+        rowSelection: {
+          selectedRowKeys: this.selectedRowKeys,
+          onChange: this.onSelectChange
+        }
+      },
+      optionAlertShow: false,
+      isCreated: false
+    }
+  },
+  created () {
+    // 下拉框map
+    this.levelMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.STORE_LEVEL)
+    this.typeMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.STORE_TYPE)
+    this.delFlagMap = this.DictCache.getLabelByValueMapByType(this.DictCache.TYPE.DELFLAG)
+  },
+  methods: {
+    tableOption () {
+      if (!this.optionAlertShow) {
+        this.options = {
+          alert: { show: true, clear: () => { this.selectedRowKeys = [] } },
+          rowSelection: {
+            selectedRowKeys: this.selectedRowKeys,
+            onChange: this.onSelectChange,
+            type: this.type,
+            getCheckboxProps: record => ({
+              props: {
+                disabled: false,
+                name: record.id
+              }
+            })
+          },
+          customRow: (record) => {
+            return {
+              on: { // 事件
+                click: (event) => { // 点击行
+                  // 选择对象
+                  this.mySelect([record.id], [record])
+                },
+                dblclick: (event) => {
+                  this.mySelect([record.id], [record])
+                  this.handleSelect()
+                }
+              }
+            }
+          }
+        }
+        this.optionAlertShow = true
+      } else {
+        this.options = {
+          alert: false,
+          rowSelection: null
+        }
+        this.optionAlertShow = false
+      }
+    },
+    handleView (record) {
+      fetchStore({ id: record.id }).then(res => {
+        const modal = this.$refs.detailModal
+        modal.base(res.data)
+      })
+    },
+    handleOk () {
+      this.$refs.table.refresh()
+    },
+    onSelectChange (selectedRowKeys, selectedRows) {
+      this.selectedRowKeys = selectedRowKeys
+      this.selectedRows = selectedRows
+    },
+    resetSearchForm () {
+      this.queryParam = {
+      }
+      this.$refs.table.refresh(true)
+    },
+    base (record, queryParam = {}, extraQueryParam = {}) {
+      this.visible = true
+      this.modalTitle = '选择信息'
+      this.queryParam = queryParam
+      this.extraQueryParam = extraQueryParam
+      this.record = record
+      if (this.isCreated) {
+        this.$refs.table.clearSelected()
+        console.log(this.options.rowSelection, 9999)
+        this.options.rowSelection.type = this.type
+        this.handleOk()
+      } else {
+        this.tableOption()
+        this.isCreated = true
+      }
+    },
+    handleCancel () {
+      this.visible = false
+      this.confirmLoading = false
+    },
+    handleSelect () {
+      if (this.selectedRowKeys.length === 0) {
+        this.$message.warn('请至少选择一项信息')
+      } else {
+        this.confirmLoading = true
+        this.$emit('selected', this.selectedRowKeys, this.selectedRows)
+        this.confirmLoading = false
+        this.visible = false
+      }
+    },
+    mySelect (selectedRowKeys, selectedRows) {
+      this.$refs.table.updateSelect(selectedRowKeys, selectedRows)
+      this.$refs.table.rowSelection.onChange(selectedRowKeys, selectedRows)
+    }
+  }
+}
+</script>

+ 138 - 0
src/views/custom/form/modules/component/modules/components.js

@@ -0,0 +1,138 @@
+export const componentBaseList = [
+  {
+    id: 1,
+    name: '单行文本',
+    type: 'input',
+    value: 'input',
+    dependentId: false,
+    required: true,
+    label: '单行文本',
+    attrs: {
+      placeholder: '请输入'
+    }
+  },
+  {
+    id: 2,
+    name: '多行文本',
+    type: 'textarea',
+    value: 'textarea',
+    dependentId: false,
+    required: true,
+    label: '多行文本',
+    attrs: {
+      placeholder: '请输入'
+    }
+  },
+  {
+    id: 3,
+    name: '数字',
+    type: 'number',
+    value: 'number',
+    dependentId: false,
+    required: true,
+    label: '数字',
+    attrs: {
+      placeholder: '请输入',
+      max: Infinity,
+      min: -Infinity,
+      precision: 2
+    }
+  },
+  {
+    id: 4,
+    name: '下拉框',
+    type: 'select',
+    value: 'select',
+    dependentId: false,
+    required: true,
+    label: '下拉框',
+    attrs: {
+      options: [
+        {
+          label: '选项1',
+          value: '1'
+        },
+        {
+          label: '选项2',
+          value: '2'
+        },
+        {
+          label: '选项3',
+          value: '3'
+        }
+      ],
+      placeholder: '请输入'
+    }
+  },
+  {
+    id: 5,
+    name: '日期时间',
+    type: 'date',
+    value: 'date',
+    dependentId: false,
+    required: true,
+    label: '日期时间',
+    attrs: {
+      placeholder: '请输入',
+      format: 'YYYY-MM-DD HH:mm:ss',
+      showTime: false
+    }
+  },
+  {
+    id: 8,
+    name: '分割线',
+    type: 'divider',
+    value: 'divider',
+    dependentId: false,
+    required: true,
+    label: '分割线',
+    attrs: {
+      orientation: 'center'
+    }
+  }
+]
+// 高级
+export const componenHidetList = [
+  {
+    id: 6,
+    name: '文件上传',
+    type: 'uploadFile',
+    value: 'uploadFile',
+    dependentId: false,
+    required: true,
+    label: '文件上传',
+    attrs: {
+      placeholder: '请输入',
+      maxSize: 5
+    }
+  },
+  {
+    id: 7,
+    name: '图片上传',
+    type: 'uploadImg',
+    value: 'uploadImg',
+    dependentId: false,
+    required: true,
+    label: '图片上传',
+    attrs: {
+      placeholder: '请输入',
+      maxSize: 5
+    }
+  },
+  {
+    id: 9,
+    name: '选择数据',
+    type: 'dataSelect',
+    value: 'id',
+    dependentId: false,
+    required: true,
+    label: '选择数据',
+    attrs: {
+      placeholder: '请选择',
+      disabled: true,
+      selectType: 'radio',
+      dict: '',
+      connect: []
+    }
+  }
+]