Просмотр исходного кода

Merge branch '深圳三院' of http://119.23.210.103:3000/wy/zdqy_firm_former into 深圳三院

zhonghuizhen 1 год назад
Родитель
Сommit
3a8256ef1f
43 измененных файлов с 1735 добавлено и 1103 удалено
  1. 14 0
      src/api/platform/file/attachment.js
  2. 88 74
      src/business/platform/bo/def/select.vue
  3. 4 1
      src/business/platform/bpmn/components/approval-history/index.vue
  4. 155 155
      src/business/platform/bpmn/form-ext/reject.vue
  5. 4 6
      src/business/platform/data/templatebuilder/right-aside/editors/display-column.vue
  6. 3 0
      src/business/platform/data/templatebuilder/right-aside/editors/query-column.vue
  7. 171 172
      src/business/platform/data/templatebuilder/right-aside/editors/result-column.vue
  8. 66 67
      src/business/platform/data/templatebuilder/right-aside/editors/sort-column.vue
  9. 22 0
      src/business/platform/file/image/index.vue
  10. 10 0
      src/business/platform/file/uploader/index.vue
  11. 20 0
      src/business/platform/file/uploader/upload.vue
  12. 100 0
      src/business/platform/file/utils/compress.js
  13. 28 2
      src/business/platform/file/utils/index.js
  14. 10 2
      src/business/platform/form/formbuilder/constants/helpTip.js
  15. 8 2
      src/business/platform/form/formbuilder/form-main/widget-form-field.vue
  16. 2 0
      src/business/platform/form/formbuilder/right-aside/editors/editor-base.vue
  17. 147 80
      src/business/platform/form/formbuilder/right-aside/editors/editor-field-image.vue
  18. 63 57
      src/business/platform/form/formbuilder/right-aside/field-types/ibps-field-image.vue
  19. 123 123
      src/business/platform/form/formbuilder/right-aside/index.vue
  20. 8 2
      src/business/platform/form/formrender/dynamic-form/dynamic-form-field.vue
  21. 0 1
      src/business/platform/form/formrender/dynamic-form/dynamic-form-table.vue
  22. 1 1
      src/store/modules/ibps/modules/user.js
  23. 9 1
      src/utils/query.js
  24. 148 62
      src/views/component/device/deviceDialog.vue
  25. 144 48
      src/views/component/device/index.vue
  26. 5 1
      src/views/component/device/maintenance.vue
  27. 5 1
      src/views/component/device/moreDevices.vue
  28. 1 0
      src/views/component/facility/facilityData.vue
  29. 4 4
      src/views/component/fileTraining/index.vue
  30. 20 1
      src/views/component/sop/pcr.vue
  31. 1 1
      src/views/platform/cat/type/manage.vue
  32. 2 1
      src/views/platform/data/dataTemplate/list.vue
  33. 6 6
      src/views/platform/examination/constants.js
  34. 2 1
      src/views/platform/examination/exam/edit.vue
  35. 4 1
      src/views/platform/examination/exam/list.vue
  36. 13 2
      src/views/platform/examination/question/edit.vue
  37. 62 13
      src/views/platform/examination/questionBank/detail.vue
  38. 30 6
      src/views/platform/examination/questionBank/edit.vue
  39. 4 3
      src/views/platform/examination/questionBank/test.vue
  40. 11 1
      src/views/platform/file/attachment/list.vue
  41. 2 1
      src/views/platform/form/formDef/list.vue
  42. 211 203
      src/views/platform/org/role/assign-resource.vue
  43. 4 1
      src/views/platform/org/role/list.vue

+ 14 - 0
src/api/platform/file/attachment.js

@@ -115,6 +115,19 @@ export function download(params) {
     params: params
   })
 }
+/**
+ * 打包下载文件
+ * @param {*} params
+ */
+export function downloadZip (params) {
+    return request({
+        url: SYSTEM_URL() + '/file/downloadZip',
+        method: 'get',
+        isLoading: true,
+        responseType: 'arraybuffer',
+        params: params
+    })
+}
 /**
  * 根据文件id获取文件流
  * @param {*} params
@@ -202,3 +215,4 @@ export function snapshoot(params) {
     params: params
   })
 }
+

+ 88 - 74
src/business/platform/bo/def/select.vue

@@ -1,89 +1,103 @@
 <template>
-  <ibps-tree-select
-    v-if="treeData"
-    v-model="selectData"
-    :data="treeData"
-    :props="props"
-    :node-key="valueKey"
-    :empty-text="emptyText"
-    :placeholder="placeholder"
-    :icon="(data)=>{ return 'ibps-icon-'+data.type}"
-    @change="(value,data) => $emit('change',value,data)"
-  />
+    <ibps-tree-select
+        v-if="treeData"
+        v-model="selectData"
+        :data="treeData"
+        :props="props"
+        :node-key="valueKey"
+        :empty-text="emptyText"
+        :placeholder="placeholder"
+        :icon="(data)=>{ return 'ibps-icon-'+data.type}"
+        :filterable="filterable"
+        :filter-method="filterMethod"
+        @change="(value,data) => $emit('change',value,data)"
+    />
 </template>
 <script>
 import IbpsTreeSelect from '@/components/ibps-tree-select'
 import TreeUtils from '@/utils/tree'
 
 export default {
-  components: {
-    IbpsTreeSelect
-  },
-  props: {
-    value: {
-      type: [String, Number, Array, Object],
-      default: ''
+    components: {
+        IbpsTreeSelect
     },
-    placeholder: {
-      type: String,
-      default: '请选择'
+    props: {
+        value: {
+            type: [String, Number, Array, Object],
+            default: ''
+        },
+        placeholder: {
+            type: String,
+            default: '请选择'
+        },
+        emptyText: {
+            type: String,
+            default: '无业务对象属性'
+        },
+        data: {
+            type: Array
+        },
+        valueKey: {
+            type: String,
+            default: 'key'
+        },
+        filterable: {
+            type: Boolean,
+            default: false
+        },
+        filterLabel: {
+            type: String,
+            default: ''
+        }
     },
-    emptyText: {
-      type: String,
-      default: '无业务对象属性'
+    data: function () {
+        return {
+            props: {
+                children: 'children',
+                label: 'name'
+            },
+            selectData: this.value,
+            treeData: []
+        }
     },
-    data: {
-      type: Array
+    watch: {
+        selectData (val, oldVal) {
+            this.$emit('input', val)
+        },
+        value: {
+            handler (val, oldVal) {
+                this.selectData = val
+            },
+            immediate: true
+        },
+        data (val, oldVal) {
+            if (this.$utils.isNotEmpty(val)) {
+                this.handlerData(val)
+            } else {
+                this.treeData = []
+            }
+        }
     },
-    valueKey: {
-      type: String,
-      default: 'key'
-    }
-  },
-  data: function() {
-    return {
-      props: {
-        children: 'children',
-        label: 'name'
-      },
-      selectData: this.value,
-      treeData: []
-    }
-  },
-  watch: {
-    selectData(val, oldVal) {
-      this.$emit('input', val)
+    mounted () {
+        this.handlerData(this.data)
+        this.selectData = this.value
     },
-    value: {
-      handler(val, oldVal) {
-        this.selectData = val
-      },
-      immediate: true
-    },
-    data(val, oldVal) {
-      if (this.$utils.isNotEmpty(val)) {
-        this.handlerData(val)
-      } else {
-        this.treeData = []
-      }
-    }
-  },
-  mounted() {
-    this.handlerData(this.data)
-    this.selectData = this.value
-  },
-  methods: {
-    handlerData(d) {
-      if (this.$utils.isEmpty(d)) {
-        this.treeData = []
-        return
-      }
-      const data = JSON.parse(JSON.stringify(d))
-      const treeData = data.filter((d) => {
-        return d.parentId !== '0'
-      })
-      this.treeData = TreeUtils.transformToTreeAndLevelFormat(treeData)
+    methods: {
+        handlerData (d) {
+            if (this.$utils.isEmpty(d)) {
+                this.treeData = []
+                return
+            }
+            const data = JSON.parse(JSON.stringify(d))
+            const treeData = data.filter((d) => {
+                return d.parentId !== '0'
+            })
+            this.treeData = TreeUtils.transformToTreeAndLevelFormat(treeData)
+        },
+        filterMethod (value, data) {
+            if (!value || !this.filterLabel) return true
+            return data[this.filterLabel].indexOf(value) !== -1
+        }
     }
-  }
 }
 </script>

+ 4 - 1
src/business/platform/bpmn/components/approval-history/index.vue

@@ -49,7 +49,10 @@
                 </span>
               </span>
               <span v-else>
-                <span v-if="item.auditor">
+                <span v-if="item.auditor &&item.status == 'pending'">
+                  暂定执行人:{{ item.auditorName }}
+                </span>
+                <span v-else-if="item.auditor &&item.status != 'pending'">
                   执行人:{{ item.auditorName }}<template v-if="item.interpose === 1"><span class="red">(干预审批)</span></template>
                 </span>
                 <span v-else-if="item.qualifiedExecutor">

+ 155 - 155
src/business/platform/bpmn/form-ext/reject.vue

@@ -81,7 +81,7 @@
                 </el-select>
             </el-form-item>
             <el-form-item v-if="!hideOpinion" label="审批意见:" prop="opinion">
-                <approval-opinion v-model="form.opinion" :action="action" />
+                <approval-opinion v-if="dialogVisible" v-model="form.opinion" :action="action" />
             </el-form-item>
         </el-form>
         <div slot="footer" class="el-dialog--center">
@@ -99,174 +99,174 @@
     </el-dialog>
 </template>
 <script>
-    import { toReject, toRejectToPrevious, toRejectToStart } from '@/api/platform/bpmn/bpmTask'
-    import ApprovalOpinion from '@/business/platform/bpmn/components/approval-opinion'
-    import { queryIncludeNull } from '@/api/platform/bpmn/bpmCommonStatment'
-    import ActionUtils from '@/utils/action'
+import { toReject, toRejectToPrevious, toRejectToStart } from '@/api/platform/bpmn/bpmTask'
+import ApprovalOpinion from '@/business/platform/bpmn/components/approval-opinion'
+import { queryIncludeNull } from '@/api/platform/bpmn/bpmCommonStatment'
+import ActionUtils from '@/utils/action'
 
-    export default {
-        components: {
-            ApprovalOpinion
+export default {
+    components: {
+        ApprovalOpinion
+    },
+    props: {
+        className: String,
+        visible: Boolean,
+        action: String,
+        title: String,
+        taskId: String,
+        data: [String, Object],
+        hideOpinion: {
+            // 隐藏意见
+            type: Boolean,
+            default: false
         },
-        props: {
-            className: String,
-            visible: Boolean,
-            action: String,
-            title: String,
-            taskId: String,
-            data: [String, Object],
-            hideOpinion: {
-                // 隐藏意见
-                type: Boolean,
-                default: false
+        formOpinion: {
+            // 表单意见
+            type: String
+        }
+    },
+    data () {
+        return {
+            dialogVisible: this.visible,
+            dialogLoading: false,
+            formName: 'form',
+            formLabelWidth: '130px',
+            actionName: '',
+            userNodeList: [],
+            bpmExecUserNode: [],
+            bpmExecGoMapUserNode: [],
+            form: {
+                rejectMode: 'reject',
+                backHandMode: 'normal',
+                destination: '',
+                opinion: ''
             },
-            formOpinion: {
-                // 表单意见
-                type: String
+            rules: {
+                destination: [
+                    {
+                        required: true,
+                        message: this.$t('validate.required')
+                    }
+                ],
+                opinion: [
+                    {
+                        required: true,
+                        message: this.$t('validate.required')
+                    }
+                ]
             }
-        },
-        data() {
-            return {
-                dialogVisible: this.visible,
-                dialogLoading: false,
-                formName: 'form',
-                formLabelWidth: '130px',
-                actionName: '',
-                userNodeList: [],
-                bpmExecUserNode: [],
-                bpmExecGoMapUserNode: [],
-                form: {
-                    rejectMode: 'reject',
-                    backHandMode: 'normal',
-                    destination: '',
-                    opinion: ''
-                },
-                rules: {
-                    destination: [
-                        {
-                            required: true,
-                            message: this.$t('validate.required')
-                        }
-                    ],
-                    opinion: [
-                        {
-                            required: true,
-                            message: this.$t('validate.required')
-                        }
-                    ]
-                }
+        }
+    },
+    computed: {
+        actionTitle () {
+            if (this.title) {
+                return this.title
             }
-        },
-        computed: {
-            actionTitle() {
-                if (this.title) {
-                    return this.title
-                }
-                if (this.actionName === 'rejectToPrevious') {
-                    return '驳回上一步'
-                } else if (this.actionName === 'rejectToStart') {
-                    return '驳回发起人'
-                } else if (this.actionName === 'reject') {
-                    return '驳回审批'
-                } else {
-                    return '驳回'
-                }
+            if (this.actionName === 'rejectToPrevious') {
+                return '驳回上一步'
+            } else if (this.actionName === 'rejectToStart') {
+                return '驳回发起人'
+            } else if (this.actionName === 'reject') {
+                return '驳回审批'
+            } else {
+                return '驳回'
+            }
+        }
+    },
+    watch: {
+        visible: {
+            handler: function (val, oldVal) {
+                this.dialogVisible = this.visible
+                this.actionName = this.action
+            },
+            immediate: true
+        }
+    },
+    methods: {
+        openedDialog () {
+            if (this.$utils.isNotEmpty(this.formOpinion)) {
+                this.form.opinion = this.formOpinion
+            } else {
+                queryIncludeNull(
+                    ActionUtils.formatParams({
+                        'Q^ACTION_^S': this.action,
+                        'Q^CREATE_BY_^S': this.$store.getters.userId
+                    })
+                ).then((response) => {
+                    const data = response.variables && response.variables.def ? response.variables.def.value || '' : ''
+                    if (this.$utils.isNotEmpty(data)) {
+                        this.form.opinion = data
+                    }
+                })
             }
         },
-        watch: {
-            visible: {
-                handler: function (val, oldVal) {
-                    this.dialogVisible = this.visible
-                    this.actionName = this.action
-                },
-                immediate: true
+        changeBackHandMode () {
+            if (this.actionName === 'reject' && this.form.rejectMode === 'rejectDest') {
+                this.formValidate()
+                this.userNodeList = this.form.backHandMode === 'normal' ? this.bpmExecGoMapUserNode : this.bpmExecUserNode
             }
         },
-        methods: {
-            openedDialog() {
-                if (this.$utils.isNotEmpty(this.formOpinion)) {
-                    this.form.opinion = this.formOpinion
+        closeDialog () {
+            this.form.opinion = ''
+            this.$emit('close', false)
+        },
+        handleSave () {
+            this.$refs[this.formName].validate((valid) => {
+                if (valid) {
+                    this.$emit('action-event', this.action, this.form)
                 } else {
-                    queryIncludeNull(
-                        ActionUtils.formatParams({
-                            'Q^ACTION_^S': this.action,
-                            'Q^CREATE_BY_^S': this.$store.getters.userId
-                        })
-                    ).then((response) => {
-                        const data = response.variables && response.variables.def ? response.variables.def.value || '' : ''
-                        if (this.$utils.isNotEmpty(data)) {
-                            this.form.opinion = data
-                        }
-                    })
-                }
-            },
-            changeBackHandMode() {
-                if (this.actionName === 'reject' && this.form.rejectMode === 'rejectDest') {
-                    this.formValidate()
-                    this.userNodeList = this.form.backHandMode === 'normal' ? this.bpmExecGoMapUserNode : this.bpmExecUserNode
+                    ActionUtils.saveErrorMessage()
                 }
-            },
-            closeDialog() {
-                this.form.opinion = ''
-                this.$emit('close', false)
-            },
-            handleSave() {
-                this.$refs[this.formName].validate((valid) => {
-                    if (valid) {
-                        this.$emit('action-event', this.action, this.form)
-                    } else {
-                        ActionUtils.saveErrorMessage()
-                    }
-                })
-            },
-            /**
+            })
+        },
+        /**
              * 表单验证
              */
-            formValidate() {
-                this.$nextTick(() => {
-                    this.$refs[this.formName].validate(() => {})
-                })
-            },
-            getFormData() {
-                this.openedDialog()
-                this.$nextTick(() => {
-                    this.$refs[this.formName].resetFields()
-                })
-                this.dialogLoading = true
-                switch (this.actionName) {
-                    case 'reject': // 驳回
-                        toReject({ taskId: this.taskId }).then((response) => {
-                            this.formValidate()
-                            this.dialogLoading = false
-                            const data = response.data
-                            this.userNodeList = this.bpmExecUserNode = data.bpmExecUserNode
-                            this.bpmExecGoMapUserNode = data.bpmExecGoMapUserNode
-                        }).catch(() => {
-                            this.dialogLoading = false
-                        })
-                        break
-                    case 'rejectToPrevious': // 驳回上一步
-                        toRejectToPrevious({ taskId: this.taskId }).then((response) => {
-                            this.formValidate()
-                            this.dialogLoading = false
-                            // TODO:默认意见
-                        }).catch(() => {
-                            this.dialogLoading = false
-                        })
-                        break
-                    case 'rejectToStart':
-                        toRejectToStart({ taskId: this.taskId }).then((response) => {
-                            this.formValidate()
-                            this.dialogLoading = false
-                            // TODO:默认意见
-                        }).catch(() => {
-                            this.dialogLoading = false
-                        })
-                        break
-                    default:
-                        break
-                }
+        formValidate () {
+            this.$nextTick(() => {
+                this.$refs[this.formName].validate(() => {})
+            })
+        },
+        getFormData () {
+            this.openedDialog()
+            this.$nextTick(() => {
+                this.$refs[this.formName].resetFields()
+            })
+            this.dialogLoading = true
+            switch (this.actionName) {
+                case 'reject': // 驳回
+                    toReject({ taskId: this.taskId }).then((response) => {
+                        this.formValidate()
+                        this.dialogLoading = false
+                        const data = response.data
+                        this.userNodeList = this.bpmExecUserNode = data.bpmExecUserNode
+                        this.bpmExecGoMapUserNode = data.bpmExecGoMapUserNode
+                    }).catch(() => {
+                        this.dialogLoading = false
+                    })
+                    break
+                case 'rejectToPrevious': // 驳回上一步
+                    toRejectToPrevious({ taskId: this.taskId }).then((response) => {
+                        this.formValidate()
+                        this.dialogLoading = false
+                        // TODO:默认意见
+                    }).catch(() => {
+                        this.dialogLoading = false
+                    })
+                    break
+                case 'rejectToStart':
+                    toRejectToStart({ taskId: this.taskId }).then((response) => {
+                        this.formValidate()
+                        this.dialogLoading = false
+                        // TODO:默认意见
+                    }).catch(() => {
+                        this.dialogLoading = false
+                    })
+                    break
+                default:
+                    break
             }
         }
     }
+}
 </script>

+ 4 - 6
src/business/platform/data/templatebuilder/right-aside/editors/display-column.vue

@@ -11,12 +11,10 @@
         <el-form-item label="显示名称" prop="label">
             <el-input v-model="formData.label" placeholder="显示名称" />
         </el-form-item>
-        <!-- 默认显示标识 -->
-        <template v-if="1 || datasetType === 'thirdparty'">
-            <el-form-item label="标识(name)" prop="name">
-                <el-input v-model="formData.name" placeholder="标识(name)" readonly />
-            </el-form-item>
-        </template>
+        <!-- 默认显示字段标识 原显示条件: v-if="datasetType === 'thirdparty'"-->
+        <el-form-item label="字段标识" prop="name">
+            <el-input v-model="formData.name" placeholder="字段标识" readonly disabled />
+        </el-form-item>
         <el-form-item label="权限" prop="rights">
             <rights-selector v-model="formData.rights" />
         </el-form-item>

+ 3 - 0
src/business/platform/data/templatebuilder/right-aside/editors/query-column.vue

@@ -11,6 +11,9 @@
         <el-form-item label="显示名称" prop="label">
             <el-input v-model="formData.label" placeholder="显示名称" />
         </el-form-item>
+        <el-form-item label="字段标识" prop="name">
+            <el-input v-model="formData.name" placeholder="字段标识" readonly disabled />
+        </el-form-item>
         <template v-if="datasetType === 'thirdparty'">
             <!-- <el-form-item label="参数类型">
                 <el-select v-model="formData.paramType" placeholder="">

+ 171 - 172
src/business/platform/data/templatebuilder/right-aside/editors/result-column.vue

@@ -1,129 +1,128 @@
 <template>
-  <el-form
-    ref="form"
-    :model="formData"
-    :rules="rules"
-    label-width="120px"
-    size="mini"
-    class="template-result-column"
-    @submit.native.prevent
-  >
-    <el-form-item label="显示名称" prop="label">
-      <el-input v-model="formData.label" placeholder="显示名称" />
-    </el-form-item>
-    <template v-if="datasetType === 'thirdparty'">
-      <el-form-item label="标识(name)" prop="name">
-        <el-input v-model="formData.name" placeholder="标识(name)" />
-      </el-form-item>
-    </template>
-    <el-form-item label="跟字段控件一致">
-      <el-switch v-model="formData.same" active-value="Y" inactive-value="N" />
-    </el-form-item>
-    <!--控件类型-->
-    <template v-if="formData.same === 'N'">
-      <el-form-item label="返回格式">
-        <el-select v-model="formData.field_type" @change="changeFieldType">
-          <el-option
-            v-for="item in resultFieldTypeOptions"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-      </el-form-item>
-      <!-- 枚举值格式 -->
-      <el-form-item v-if="formData.field_type === 'radio' ||formData.field_type === 'checkbox' ||formData.field_type === 'select'" label-width="0" prop="options">
-        <field-options v-model="formData.field_options.options" />
-      </el-form-item>
-      <!-- 日期格式 -->
-      <el-form-item v-if="formData.field_type === 'datePicker'" label="日期格式" prop="datefmt_type">
-        <el-select v-model="formData.field_options.datefmt_type">
-          <el-option
-            v-for="(item,index) in datefmtTypeOptions"
-            :key="index"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-        <el-input
-          v-if="formData.field_options.datefmt_type ==='custom'"
-          v-model="formData.field_options.datefmt"
-        />
-      </el-form-item>
-
-      <!-- 数据字典 -->
-      <el-form-item v-if="formData.field_type === 'dictionary'" label="数据字典" prop="dictionary">
-        <ibps-type-select
-          v-model="formData.field_options.dictionary"
-          category-key="DIC_TYPE"
-          node-key="typeKey"
-          clearable
-        />
-      </el-form-item>
-      <!-- 选择器 -->
-      <template v-if="formData.field_type === 'selector'">
-        <el-form-item label="选择器类型" prop="selector_type">
-          <el-select v-model="formData.field_options.selector_type">
-            <el-option
-              v-for="item in selectorTypeOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="存储格式" prop="store">
-          <el-select v-model="formData.field_options.store">
-            <el-option
-              v-for="item in selectorStoreOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="是否多选" prop="label">
-          <el-switch
-            v-model="formData.field_options.multiple"
-            active-value="Y"
-            inactive-value="N"
-          />
-        </el-form-item>
-      </template>
-      <!-- 自定义对话框 -->
-      <template v-if="formData.field_type === 'customDialog'">
-        <el-form-item>
-          <template slot="label">自定义对话框</template>
-          <ibps-data-template-selector2
-            v-model="formData.field_options.dialog"
-            type="dialog"
-            placeholder="请选择自定义对话框"
-          />
+    <el-form
+        ref="form"
+        :model="formData"
+        :rules="rules"
+        label-width="120px"
+        size="mini"
+        class="template-result-column"
+        @submit.native.prevent
+    >
+        <el-form-item label="显示名称" prop="label">
+            <el-input v-model="formData.label" placeholder="显示名称" />
         </el-form-item>
-        <el-form-item>
-          <template slot="label">是否多选</template>
-          <el-switch
-            v-model="formData.field_options.multiple"
-            active-value="Y"
-            inactive-value="N"
-          />
+        <!-- 默认显示字段标识 原显示条件: v-if="datasetType === 'thirdparty'"-->
+        <el-form-item label="字段标识" prop="name">
+            <el-input v-model="formData.name" placeholder="字段标识" readonly disabled />
         </el-form-item>
-        <el-form-item>
-          <template slot="label">存储格式</template>
-          <el-select v-model="formData.field_options.store" style="width:100%;">
-            <el-option
-              v-for="item in dialogStoreOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
+        <el-form-item label="跟字段控件一致">
+            <el-switch v-model="formData.same" active-value="Y" inactive-value="N" />
         </el-form-item>
-      </template>
-      <!-- end -->
+        <!--控件类型-->
+        <template v-if="formData.same === 'N'">
+            <el-form-item label="返回格式">
+                <el-select v-model="formData.field_type" @change="changeFieldType">
+                    <el-option
+                        v-for="item in resultFieldTypeOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                    />
+                </el-select>
+            </el-form-item>
+            <!-- 枚举值格式 -->
+            <el-form-item v-if="formData.field_type === 'radio' ||formData.field_type === 'checkbox' ||formData.field_type === 'select'" label-width="0" prop="options">
+                <field-options v-model="formData.field_options.options" />
+            </el-form-item>
+            <!-- 日期格式 -->
+            <el-form-item v-if="formData.field_type === 'datePicker'" label="日期格式" prop="datefmt_type">
+                <el-select v-model="formData.field_options.datefmt_type">
+                    <el-option
+                        v-for="(item,index) in datefmtTypeOptions"
+                        :key="index"
+                        :label="item.label"
+                        :value="item.value"
+                    />
+                </el-select>
+                <el-input
+                    v-if="formData.field_options.datefmt_type ==='custom'"
+                    v-model="formData.field_options.datefmt"
+                />
+            </el-form-item>
 
-    </template>
-  </el-form>
+            <!-- 数据字典 -->
+            <el-form-item v-if="formData.field_type === 'dictionary'" label="数据字典" prop="dictionary">
+                <ibps-type-select
+                    v-model="formData.field_options.dictionary"
+                    category-key="DIC_TYPE"
+                    node-key="typeKey"
+                    clearable
+                />
+            </el-form-item>
+            <!-- 选择器 -->
+            <template v-if="formData.field_type === 'selector'">
+                <el-form-item label="选择器类型" prop="selector_type">
+                    <el-select v-model="formData.field_options.selector_type">
+                        <el-option
+                            v-for="item in selectorTypeOptions"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="存储格式" prop="store">
+                    <el-select v-model="formData.field_options.store">
+                        <el-option
+                            v-for="item in selectorStoreOptions"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        />
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="是否多选" prop="label">
+                    <el-switch
+                        v-model="formData.field_options.multiple"
+                        active-value="Y"
+                        inactive-value="N"
+                    />
+                </el-form-item>
+            </template>
+            <!-- 自定义对话框 -->
+            <template v-if="formData.field_type === 'customDialog'">
+                <el-form-item>
+                    <template slot="label">自定义对话框</template>
+                    <ibps-data-template-selector2
+                        v-model="formData.field_options.dialog"
+                        type="dialog"
+                        placeholder="请选择自定义对话框"
+                    />
+                </el-form-item>
+                <el-form-item>
+                    <template slot="label">是否多选</template>
+                    <el-switch
+                        v-model="formData.field_options.multiple"
+                        active-value="Y"
+                        inactive-value="N"
+                    />
+                </el-form-item>
+                <el-form-item>
+                    <template slot="label">存储格式</template>
+                    <el-select v-model="formData.field_options.store" style="width:100%;">
+                        <el-option
+                            v-for="item in dialogStoreOptions"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        />
+                    </el-select>
+                </el-form-item>
+            </template>
+            <!-- end -->
+
+        </template>
+    </el-form>
 </template>
 <script>
 import { resultFieldTypeOptions } from '../constants/editor-column'
@@ -135,65 +134,65 @@ import IbpsTypeSelect from '@/business/platform/cat/type/select'
 import IbpsDataTemplateSelector2 from '@/business/platform/data/dataTemplate/selector2'
 
 export default {
-  components: {
-    FieldOptions,
-    IbpsTypeSelect,
-    IbpsDataTemplateSelector2
-  },
-  mixins: [FieldTypeMixin],
-  props: {
-    data: {
-      type: Object
+    components: {
+        FieldOptions,
+        IbpsTypeSelect,
+        IbpsDataTemplateSelector2
     },
-    datasetType: {
-      type: String,
-      default: 'table'
-    }
-  },
-  data() {
-    return {
-      resultFieldTypeOptions,
-      datefmtTypeOptions,
-      selectorTypeOptions,
-      selectorStoreOptions,
-      dialogStoreOptions,
-      formName: 'form',
-      formData: {},
-      rules: {
-        name: [{ required: true, message: this.$t('validate.required') }],
-        label: [{ required: true, message: this.$t('validate.required') }]
-      }
-    }
-  },
-  watch: {
-    data: {
-      handler(val) {
-        if (val) {
-          this.formData = val
+    mixins: [FieldTypeMixin],
+    props: {
+        data: {
+            type: Object
+        },
+        datasetType: {
+            type: String,
+            default: 'table'
         }
-      },
-      immediate: true
-    }
-  },
-  methods: {
-  // 获取表单数据
-    getFormData(callback) {
-      this.$refs[this.formName].validate((valid) => {
-        if (valid) {
-          callback(this.formData)
-        } else {
-          callback()
+    },
+    data () {
+        return {
+            resultFieldTypeOptions,
+            datefmtTypeOptions,
+            selectorTypeOptions,
+            selectorStoreOptions,
+            dialogStoreOptions,
+            formName: 'form',
+            formData: {},
+            rules: {
+                name: [{ required: true, message: this.$t('validate.required') }],
+                label: [{ required: true, message: this.$t('validate.required') }]
+            }
+        }
+    },
+    watch: {
+        data: {
+            handler (val) {
+                if (val) {
+                    this.formData = val
+                }
+            },
+            immediate: true
+        }
+    },
+    methods: {
+        // 获取表单数据
+        getFormData (callback) {
+            this.$refs[this.formName].validate((valid) => {
+                if (valid) {
+                    callback(this.formData)
+                } else {
+                    callback()
+                }
+            })
         }
-      })
     }
-  }
 }
 </script>
 
 <style lang="scss">
 .template-result-column {
-  .el-select {
-    width:100%;
-  }
+    .el-select {
+        width:100%;
+    }
 }
 </style>

+ 66 - 67
src/business/platform/data/templatebuilder/right-aside/editors/sort-column.vue

@@ -1,84 +1,83 @@
 <template>
-  <el-form
-    ref="form"
-    :model="formData"
-    :rules="rules"
-    label-width="120px"
-    size="mini"
-    class="template-result-column"
-    @submit.native.prevent
-  >
-    <el-form-item label="显示名称" prop="name">
-      <el-input v-model="formData.label" placeholder="显示名称" />
-    </el-form-item>
-    <template v-if="datasetType === 'thirdparty'">
-      <el-form-item label="标识(name)" prop="name">
-        <el-input v-model="formData.name" placeholder="标识(name)" />
-      </el-form-item>
-    </template>
-    <el-form-item label="排序">
-      <el-switch
-        v-model="formData.direction"
-        active-text="降序"
-        inactive-text="升序"
-        active-value="desc"
-        inactive-value="asc"
-      />
-    </el-form-item>
+    <el-form
+        ref="form"
+        :model="formData"
+        :rules="rules"
+        label-width="120px"
+        size="mini"
+        class="template-result-column"
+        @submit.native.prevent
+    >
+        <el-form-item label="显示名称" prop="name">
+            <el-input v-model="formData.label" placeholder="显示名称" />
+        </el-form-item>
+        <!-- 默认显示字段标识 原显示条件: v-if="datasetType === 'thirdparty'"-->
+        <el-form-item label="字段标识" prop="name">
+            <el-input v-model="formData.name" placeholder="字段标识" readonly disabled />
+        </el-form-item>
+        <el-form-item label="排序">
+            <el-switch
+                v-model="formData.direction"
+                active-text="降序"
+                inactive-text="升序"
+                active-value="desc"
+                inactive-value="asc"
+            />
+        </el-form-item>
 
-  </el-form>
+    </el-form>
 </template>
 <script>
 
 export default {
-  props: {
-    data: {
-      type: Object
+    props: {
+        data: {
+            type: Object
+        },
+        datasetType: {
+            type: String,
+            default: 'table'
+        }
     },
-    datasetType: {
-      type: String,
-      default: 'table'
-    }
-  },
-  data() {
-    return {
-      formName: 'form',
-      formData: {},
-      rules: {
-        name: [{ required: true, message: this.$t('validate.required') }],
-        label: [{ required: true, message: this.$t('validate.required') }]
-      }
-    }
-  },
-  watch: {
-    data: {
-      handler(val) {
-        if (val) {
-          this.formData = val
+    data () {
+        return {
+            formName: 'form',
+            formData: {},
+            rules: {
+                name: [{ required: true, message: this.$t('validate.required') }],
+                label: [{ required: true, message: this.$t('validate.required') }]
+            }
         }
-      },
-      immediate: true
-    }
-  },
-  methods: {
-  // 获取表单数据
-    getFormData(callback) {
-      this.$refs[this.formName].validate((valid) => {
-        if (valid) {
-          callback(this.formData)
-        } else {
-          callback()
+    },
+    watch: {
+        data: {
+            handler (val) {
+                if (val) {
+                    this.formData = val
+                }
+            },
+            immediate: true
+        }
+    },
+    methods: {
+        // 获取表单数据
+        getFormData (callback) {
+            this.$refs[this.formName].validate((valid) => {
+                if (valid) {
+                    callback(this.formData)
+                } else {
+                    callback()
+                }
+            })
         }
-      })
     }
-  }
 }
 </script>
 
 <style lang="scss">
 .template-result-column {
-  .el-select {
-    width:100%;
-  }
+    .el-select {
+        width:100%;
+    }
 }
 </style>

+ 22 - 0
src/business/platform/file/image/index.vue

@@ -85,6 +85,8 @@
             :multiple="multiple"
             :accept="accept"
             :file-size="size"
+            :compress-option="compressOption"
+            file-type="image"
             @close="visible => uploaderSelectorVisible = visible"
             @action-event="handleUpload"
         />
@@ -103,6 +105,7 @@ import IbpsUploaderSelectorDialog from '@/business/platform/file/uploader'
 import IbpsImageViewer from '@/components/ibps-file-viewer/image'
 import { TRANSFER_DATA } from '@/constant'
 import VueDraggable from 'vuedraggable'
+import { compress } from '../utils/compress.js'
 
 export default {
     name: 'ibps-image',
@@ -145,6 +148,15 @@ export default {
             type: String,
             default: 'attachment'
         },
+        compressOption: {
+            type: Object,
+            default: () => ({
+                isCompress: 'Y', // 是否压缩
+                maxWidth: 1000, // 最大宽度(px)
+                maxFileSize: Math.round(1024 * 1024 * 0.2), // 200KB
+                quality: 0.8 // 图片质量(0-1)
+            })
+        },
         store: {
             type: String,
             default: 'json',
@@ -414,6 +426,16 @@ export default {
          * 文件上传
          */
         httpRequest (options) {
+            const { isCompress, maxWidth, maxFileSize, quality } = this.compressOption || {}
+            if (isCompress === 'Y') {
+                return compress(options.file, maxWidth, maxFileSize, quality).then((file) => {
+                    return uploadFile(file, {}).then((response) => {
+                        const data = response.data
+                        this.setCacheData(data)
+                        this.fileList.push(data)
+                    })
+                })
+            }
             return uploadFile(options.file, {}).then((response) => {
                 const data = response.data
                 this.setCacheData(data)

+ 10 - 0
src/business/platform/file/uploader/index.vue

@@ -25,6 +25,8 @@
                     :init="dialogVisible"
                     :limit="limit"
                     :upload-method="uploadMethod"
+                    :compress-option="compressOption"
+                    :file-type="fileType"
                     @callback="uploadCallback"
                 />
             </el-tab-pane>
@@ -101,6 +103,14 @@ export default {
         uploadMethod: {
             type: String,
             default: 'normal'
+        },
+        compressOption: {
+            type: Object,
+            default: () => {}
+        },
+        fileType: {
+            type: String,
+            default: 'attachment'
         }
     },
     data () {

+ 20 - 0
src/business/platform/file/uploader/upload.vue

@@ -62,6 +62,8 @@
 import { uploadFile, remove, deleteFile } from '@/api/platform/file/attachment'
 import { uploadTemplateFile } from '@/api/platform/file/onlyoffice'
 import { fileTypes, allFileTypes, accept as acceptTypes } from '@/business/platform/file/constants/fileTypes'
+import { compress } from '../utils/compress.js'
+
 export default {
     props: {
         height: String,
@@ -74,6 +76,16 @@ export default {
         uploadMethod: {
             type: String,
             default: 'normal'
+        },
+        // 图片压缩配置
+        compressOption: {
+            type: Object,
+            default: () => {}
+        },
+        // 控件类型:附图上传-image, 附件上传-attachment
+        fileType: {
+            type: String,
+            default: 'attachment'
         }
     },
     data () {
@@ -107,6 +119,14 @@ export default {
                 normal: uploadFile,
                 onlyoffice: uploadTemplateFile
             }
+
+            const { isCompress, maxWidth, maxFileSize, quality } = this.compressOption || {}
+            // 仅满足压缩条件的附图组件需压缩,附件组件中的图片不做压缩处理
+            if (isCompress !== 'N' && this.fileType === 'image') {
+                return compress(options.file, maxWidth, maxFileSize, quality).then((file) => {
+                    return uploadFile(file, {})
+                })
+            }
             return uploadMap[this.uploadMethod || 'normal'](options.file, {})
         },
         // 做文件校验

+ 100 - 0
src/business/platform/file/utils/compress.js

@@ -0,0 +1,100 @@
+const url = window.URL || window.webkitURL
+
+if (!HTMLCanvasElement.prototype.toBlob) {
+    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
+        value (cb, type, quality) {
+            const s = atob(this.toDataURL(type, quality).split(',')[1])
+            const n = s.length
+            const r = new Uint8Array(n)
+
+            for (let i = 0; i < n; i++) {
+                r[i] = s.charCodeAt(i)
+            }
+
+            cb(new Blob([r], { type: 'image/jpeg' }))
+        }
+    })
+}
+
+export const compress = (file, maxWidth = 1000, maxFileSize = 0.2, quality = 1) => new Promise((resolve, reject) => {
+    console.log(file, maxWidth, maxFileSize, quality)
+    if (!file.type.startsWith('image/')) {
+        reject(new Error('File is not an image'))
+        return
+    }
+
+    // GIF 文件不压缩
+    if ((/^image\/gif$/).test(file.type)) {
+        resolve(file)
+        return
+    }
+
+    const img = new Image()
+    img.src = url.createObjectURL(file)
+    img.onerror = () => {
+        url.revokeObjectURL(img.src)
+        reject(new Error('Failed to load image'))
+    }
+
+    img.onload = () => {
+        const [imgWidth, imgHeight] = [img.width, img.height]
+
+        // 判断是否需要压缩:宽度超限 或 文件大小超限
+        const needCompress = imgWidth > maxWidth || (maxFileSize > 0 && file.size > Math.round(maxFileSize * 1024 * 1024))
+
+        if (!needCompress) {
+            resolve(file)
+            return
+        }
+
+        // 计算缩放后的尺寸(仅当宽度超限时才缩放)
+        let targetWidth = imgWidth
+        let targetHeight = imgHeight
+        if (imgWidth > maxWidth) {
+            targetWidth = maxWidth
+            targetHeight = (imgHeight / imgWidth) * maxWidth
+        }
+
+        // 创建 Canvas
+        const canvas = document.createElement('canvas')
+        const ctx = canvas.getContext('2d')
+        canvas.width = targetWidth
+        canvas.height = targetHeight
+        // canvas.setAttribute('width', maxWidth)
+        // canvas.setAttribute('height', scaledHeight)
+
+        // 绘制图片到 Canvas(仅在需要缩放时绘制)
+        if (imgWidth > maxWidth) {
+            ctx.drawImage(img, 0, 0, targetWidth, targetHeight)
+        } else {
+            ctx.drawImage(img, 0, 0)
+        }
+
+        // PNG图片背景透明压缩后变黑色处理。处理原理:将透明颜色的值强制改成白色255
+        if ((/png/).test(file.type)) {
+            const dt = ctx.getImageData(0, 0, targetWidth, targetHeight)
+
+            for (let i = 0; i < dt.data.length; i += 4) {
+                if (dt.data[i + 3] === 0) {
+                    dt.data[i] = 255
+                    dt.data[i + 1] = 255
+                    dt.data[i + 2] = 255
+                    dt.data[i + 3] = 255
+                }
+            }
+
+            ctx.putImageData(dt, 0, 0)
+        }
+
+        const outputType = file.type === 'image/png' ? 'image/png' : 'image/jpeg'
+        canvas.toBlob(blob => {
+            url.revokeObjectURL(img.src)
+            // 将 Blob 转换为 File 对象
+            const compressedFile = new File([blob], file.name, {
+                type: outputType,
+                lastModified: Date.now()
+            })
+            resolve(compressedFile)
+        }, outputType, quality)
+    }
+})

+ 28 - 2
src/business/platform/file/utils/index.js

@@ -1,9 +1,9 @@
-import { download } from '@/api/platform/file/attachment'
+import { download, downloadZip } from '@/api/platform/file/attachment'
 import Utils from '@/utils/util'
 import ActionUtils from '@/utils/action'
 import { Loading } from 'element-ui'
 
-export function downloadFile (file) {
+export const downloadFile = (file) => {
     const loadingInstance = Loading.service({
         lock: true,
         text: '下载中..'
@@ -23,3 +23,29 @@ export function downloadFile (file) {
         loadingInstance.close()
     })
 }
+
+export const downloadFileByZip = (ids) => {
+    const loadingInstance = Loading.service({
+        lock: true,
+        text: '下载中..'
+    })
+    downloadZip({
+        attachmentIds: ids
+    }).then(response => {
+        loadingInstance.close()
+        if (!response) {
+            return
+        }
+        ActionUtils.exportFile(
+            response.data,
+            '批量下载文件.zip'
+        )
+    }).catch(() => {
+        loadingInstance.close()
+    })
+}
+
+export default {
+    downloadFile,
+    downloadFileByZip
+}

+ 10 - 2
src/business/platform/form/formbuilder/constants/helpTip.js

@@ -297,10 +297,18 @@ export default {
             【单位】:M </br>`
     },
     imageWidthAndHeight: {
-        title: '关于图片宽高尺寸',
-        content: ` 此属性用于设置图片宽和高。</br>
+        title: '关于图片展示宽高',
+        content: ` 此属性用于设置图片组件展示的宽和高。</br>
             【单位】:px </br>`
     },
+    imageCompressWidth: {
+        title: '关于图片限宽',
+        content: ` 当图片大小超出时或宽度超限时,将触发压缩,图片将被缩放至该宽度。默认1000px</br>【单位】:px </br>`
+    },
+    imageCompressSize: {
+        title: '关于图片压缩大小',
+        content: ` 当图片大小超出时或宽度超限时,将触发压缩。默认0.2Mb</br>【单位】:Mb </br>`
+    },
     imageLimit: {
         title: '关于图片数量限制',
         content: ` 此属性用于限制图片最大上传数量。`

+ 8 - 2
src/business/platform/form/formbuilder/form-main/widget-form-field.vue

@@ -54,7 +54,7 @@
                 :key="o.val+i"
                 :label="i"
                 :border="fieldOptions.border"
-                :style="{marginTop: '5px', display: fieldOptions.arrangement==='vertical' ? 'block' : null}"
+                :style="{marginTop: '5px', display: fieldOptions.arrangement === 'vertical' ? 'block' : ''}"
             >
                 {{ o.label }}
             </component>
@@ -71,7 +71,7 @@
                 :key="o.val+i"
                 :label="i"
                 :border="fieldOptions.border"
-                :style="{ display: fieldOptions.arrangement==='vertical' ? 'block' : null}"
+                :style="{ display: fieldOptions.arrangement==='vertical' ? 'block' : ''}"
                 disabled
             > {{ o.label }}
             </component>
@@ -272,6 +272,12 @@
             :tip="fieldOptions.tip"
             :size="fieldOptions.size"
             :upload-type="fieldOptions.uploadType"
+            :compress-option="{
+                isCompress: fieldOptions.is_compress,
+                maxWidth: fieldOptions.compress_width,
+                maxFileSize: fieldOptions.compress_size,
+                quality: fieldOptions.quality
+            }"
         />
         <!-- =======================系统字段==============================-->
         <!-- 当前层级 -->

+ 2 - 0
src/business/platform/form/formbuilder/right-aside/editors/editor-base.vue

@@ -41,6 +41,8 @@
           :data="boFields"
           placeholder="请绑定属性"
           :empty-text="emptyText"
+          :filterable="true"
+          filter-label="name"
           @change="changeBoName"
         />
       </el-form-item>

+ 147 - 80
src/business/platform/form/formbuilder/right-aside/editors/editor-field-image.vue

@@ -1,91 +1,158 @@
 <template>
-  <div class="panel panel-default">
-    <div class="panel-heading">图片设置</div>
-    <div class="panel-body">
-      <el-form-item>
-        <template slot="label">图片类型<help-tip prop="imageType" /></template>
-        <el-select v-model="fieldOptions.accept" style="width:100%;">
-          <el-option value="" label="不限制" />
-          <el-option
-            v-for="item in imageTypeOptions"
-            :key="item.value"
-            :value="item.value"
-            :label="item.label"
-          />
-          <el-option value="custom" label="自定义" />
-        </el-select>
-        <el-input
-          v-if="fieldOptions.accept==='custom'"
-          v-model="fieldOptions.media"
-          type="textarea"
-          rows="1"
-          resize="none"
-          autosize
-          placeholder="自定义图片类型,逗号[,]分割"
-          style="padding-top:5px;"
-        />
-      </el-form-item>
-      <el-form-item>
-        <template slot="label">图片大小<help-tip prop="imageSize" /></template>
-        <el-input v-model="fieldOptions.size" placeholder="图片大小(单个)" type="text" @change="(val)=>changeImageSet(val,'size')"><template slot="append">M</template></el-input>
-      </el-form-item>
-      <el-form-item>
-        <template slot="label">图片尺寸<help-tip prop="imageWidthAndHeight" /></template>
-        <el-input v-model="fieldOptions.width" placeholder="宽度" type="text" @change="(val)=>changeImageSet(val,'width')">
-          <template slot="prepend">宽度大小</template>
-          <template slot="append">px</template>
-        </el-input>
-        <p />
-        <el-input v-model="fieldOptions.height" placeholder="高度" type="text" @change="(val)=>changeImageSet(val,'height')">
-          <template slot="prepend">高度大小</template>
-          <template slot="append">px</template>
-        </el-input>
-      </el-form-item>
-      <el-form-item>
-        <template slot="label">图片数量<help-tip prop="imageLimit" /></template>
-        <el-input-number v-model="fieldOptions.limit" :min="1" style="width:100%" />
-      </el-form-item>
-      <el-form-item>
-        <template slot="label">上传方式<help-tip prop="uploadType" /></template>
-        <el-select v-model="fieldOptions.uploadType" style="width:100%;">
-          <el-option
-            v-for="item in uploadTypeOptions"
-            :key="item.value"
-            :value="item.value"
-            :label="item.label"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <template slot="label">提示信息<help-tip prop="imagePlaceholder" /></template>
-        <el-input v-model="fieldOptions.tip" rows="3" placeholder="" type="textarea" />
-      </el-form-item>
+    <div class="panel panel-default">
+        <div class="panel-heading">图片设置</div>
+        <div class="panel-body">
+            <el-form-item>
+                <template slot="label">图片类型<help-tip prop="imageType" /></template>
+                <el-select v-model="fieldOptions.accept" style="width:100%;">
+                    <el-option value="" label="不限制" />
+                    <el-option
+                        v-for="item in imageTypeOptions"
+                        :key="item.value"
+                        :value="item.value"
+                        :label="item.label"
+                    />
+                    <el-option value="custom" label="自定义" />
+                </el-select>
+                <el-input
+                    v-if="fieldOptions.accept==='custom'"
+                    v-model="fieldOptions.media"
+                    type="textarea"
+                    rows="1"
+                    resize="none"
+                    autosize
+                    placeholder="自定义图片类型,逗号[,]分割"
+                    style="padding-top:5px;"
+                />
+            </el-form-item>
+            <el-form-item>
+                <template slot="label">图片大小<help-tip prop="imageSize" /></template>
+                <el-input
+                    v-model="fieldOptions.size"
+                    placeholder="图片大小(单个)"
+                    type="text"
+                    @change="(val)=>changeImageSet(val,'size')"
+                ><template slot="append">M</template></el-input>
+            </el-form-item>
+            <el-form-item>
+                <template slot="label">图片展示尺寸<help-tip prop="imageWidthAndHeight" /></template>
+                <el-input
+                    v-model="fieldOptions.width"
+                    placeholder="宽度"
+                    type="text"
+                    @change="(val)=>changeImageSet(val,'width')"
+                >
+                    <template slot="prepend">宽度大小</template>
+                    <template slot="append">px</template>
+                </el-input>
+                <p />
+                <el-input
+                    v-model="fieldOptions.height"
+                    placeholder="高度"
+                    type="text"
+                    @change="(val)=>changeImageSet(val,'height')"
+                >
+                    <template slot="prepend">高度大小</template>
+                    <template slot="append">px</template>
+                </el-input>
+            </el-form-item>
+            <el-form-item>
+                <template slot="label">图片数量<help-tip prop="imageLimit" /></template>
+                <el-input-number v-model="fieldOptions.limit" :min="1" style="width:100%" />
+            </el-form-item>
+            <el-form-item>
+                <template slot="label">是否压缩</template>
+                <el-radio-group v-model="fieldOptions.is_compress" @input="changeCompress">
+                    <el-radio-button label="N">否</el-radio-button>
+                    <el-radio-button label="Y">是</el-radio-button>
+                </el-radio-group>
+            </el-form-item>
+            <template v-if="fieldOptions.is_compress === 'Y'">
+                <el-form-item>
+                    <template slot="label">图片限宽<help-tip prop="imageCompressWidth" /></template>
+                    <el-input
+                        v-model="fieldOptions.compress_width"
+                        placeholder="最大宽度"
+                        type="text"
+                        @change="(val)=>changeImageSet(val, 'compress_width')"
+                    >
+                        <template slot="prepend">宽度大小</template>
+                        <template slot="append">px</template>
+                    </el-input>
+                </el-form-item>
+                <el-form-item>
+                    <template slot="label">图片压缩大小<help-tip prop="imageCompressSize" /></template>
+                    <el-input
+                        v-model="fieldOptions.compress_size"
+                        placeholder="图片压缩大小"
+                        type="text"
+                        @change="(val)=>changeImageSet(val, 'compress_size')"
+                    ><template slot="append">M</template></el-input>
+                </el-form-item>
+                <el-form-item>
+                    <template slot="label">压缩质量</template>
+                    <el-slider
+                        v-model="fieldOptions.quality"
+                        :step="0.1"
+                        :min="0.1"
+                        :max="1"
+                    />
+                </el-form-item>
+            </template>
+            <el-form-item>
+                <template slot="label">上传方式<help-tip prop="uploadType" /></template>
+                <el-select v-model="fieldOptions.uploadType" style="width:100%;">
+                    <el-option
+                        v-for="item in uploadTypeOptions"
+                        :key="item.value"
+                        :value="item.value"
+                        :label="item.label"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item>
+                <template slot="label">提示信息<help-tip prop="imagePlaceholder" /></template>
+                <el-input v-model="fieldOptions.tip" rows="3" placeholder="" type="textarea" />
+            </el-form-item>
+        </div>
     </div>
-  </div>
 </template>
 <script>
 import { imageTypeOptions, uploadTypeOptions } from '@/business/platform/form/constants/fieldOptions'
 import EditorMixin from '../mixins/editor'
 
 export default {
-  mixins: [EditorMixin],
-  data() {
-    return {
-      imageTypeOptions: imageTypeOptions,
-      uploadTypeOptions: uploadTypeOptions
-    }
-  },
-  methods: {
-    changeImageSet(val, property) {
-      const imagePropertyValue = parseInt(val)
-      if (imagePropertyValue < 0) {
-        property === 'size' ? this.fieldOptions.size = '' : property === 'width' ? this.fieldOptions.width = '' : this.fieldOptions.height = ''
-        this.$message({
-          message: '该设置不能输入小于0',
-          type: 'warning'
-        })
-      }
+    mixins: [EditorMixin],
+    data () {
+        return {
+            imageTypeOptions: imageTypeOptions,
+            uploadTypeOptions: uploadTypeOptions
+        }
+    },
+    methods: {
+        changeImageSet (val, property) {
+            const imagePropertyValue = parseInt(val, 10)
+
+            if (imagePropertyValue < 0) {
+                const resetFields = ['size', 'compress_size', 'compress_width', 'width', 'height']
+
+                if (resetFields.includes(property)) {
+                    this.fieldOptions[property] = ''
+                }
+
+                this.$message({
+                    message: '该设置不能输入小于0',
+                    type: 'warning'
+                })
+            }
+        },
+        changeCompress (val) {
+            if (val === 'Y') {
+                this.fieldOptions.compress_width = 1000
+                this.fieldOptions.compress_size = 0.2
+                this.fieldOptions.quality = 0.8
+            }
+        }
     }
-  }
 }
 </script>

+ 63 - 57
src/business/platform/form/formbuilder/right-aside/field-types/ibps-field-image.vue

@@ -1,47 +1,53 @@
 <template>
-  <div>
-    <el-form v-bind="$attrs" v-on="$listeners" @submit.native.prevent>
-      <!-- 基本属性 -->
-      <editor-base
-        :field-item="fieldItem"
-        :bo-data="boData"
-        :fields="fields"
-        default-value-types="fixed"
-      >
-        <template slot="fixedValue">
-          <ibps-image
-            v-model="fieldOptions.default_value"
-            :width="fieldOptions.width"
-            :height="fieldOptions.height"
-            :limit="fieldOptions.limit"
-            :accept="imagesAccept"
-            :media="fieldOptions.media"
-            :tip="fieldOptions.tip"
-            :size="fieldOptions.size"
-            :upload-type="fieldOptions.uploadType"
-          />
-        </template>
-      </editor-base>
-      <!-- 参数设置 -->
-      <editor-field-image
-        :field-item="fieldItem"
-      />
-      <!-- 校验规则 -->
-      <editor-rules
-        :field-item="fieldItem"
-        types="required"
-      />
-      <!-- 字段权限 -->
-      <editor-rights
-        :field-item="fieldItem"
-      />
-      <!-- 布局设置 -->
-      <editor-layout
-        :field-item="fieldItem"
-        types="labelWidth,customClass,mobile"
-      />
-    </el-form>
-  </div>
+    <div>
+        <el-form v-bind="$attrs" v-on="$listeners" @submit.native.prevent>
+            <!-- 基本属性 -->
+            <editor-base
+                :field-item="fieldItem"
+                :bo-data="boData"
+                :fields="fields"
+                default-value-types="fixed"
+            >
+                <template slot="fixedValue">
+                    <ibps-image
+                        v-model="fieldOptions.default_value"
+                        :width="fieldOptions.width"
+                        :height="fieldOptions.height"
+                        :limit="fieldOptions.limit"
+                        :accept="imagesAccept"
+                        :media="fieldOptions.media"
+                        :tip="fieldOptions.tip"
+                        :size="fieldOptions.size"
+                        :upload-type="fieldOptions.uploadType"
+                        :compress-option="{
+                            isCompress: fieldOptions.is_compress,
+                            maxWidth: fieldOptions.compress_width,
+                            maxFileSize: fieldOptions.compress_size,
+                            quality: fieldOptions.quality
+                        }"
+                    />
+                </template>
+            </editor-base>
+            <!-- 参数设置 -->
+            <editor-field-image
+                :field-item="fieldItem"
+            />
+            <!-- 校验规则 -->
+            <editor-rules
+                :field-item="fieldItem"
+                types="required"
+            />
+            <!-- 字段权限 -->
+            <editor-rights
+                :field-item="fieldItem"
+            />
+            <!-- 布局设置 -->
+            <editor-layout
+                :field-item="fieldItem"
+                types="labelWidth,customClass,mobile"
+            />
+        </el-form>
+    </div>
 </template>
 
 <script>
@@ -50,20 +56,20 @@ import IbpsImage from '@/business/platform/file/image'
 import typeMixin from '../mixins/type'
 
 export default {
-  name: 'ibps-field-image',
-  components: {
-    IbpsImage
-  },
-  mixins: [typeMixin],
-  computed: {
-    imagesAccept() {
-      const accept = this.fieldOptions.accept
-      if (this.$utils.isEmpty(accept)) { return ACCEPT['images'] }
-      if (accept === 'custom') {
-        return this.fieldOptions.media
-      }
-      return accept
+    name: 'ibps-field-image',
+    components: {
+        IbpsImage
+    },
+    mixins: [typeMixin],
+    computed: {
+        imagesAccept () {
+            const accept = this.fieldOptions.accept
+            if (this.$utils.isEmpty(accept)) { return ACCEPT['images'] }
+            if (accept === 'custom') {
+                return this.fieldOptions.media
+            }
+            return accept
+        }
     }
-  }
 }
 </script>

+ 123 - 123
src/business/platform/form/formbuilder/right-aside/index.vue

@@ -1,44 +1,44 @@
 <template>
-  <div :style="{ width:`${width}px`}">
-    <el-tabs v-model="activeName" type="border-card" class="formbuilder-tab-container" @tab-click="clickTab">
-      <el-tab-pane :style="{ width:`${width}px`}" label="字段配置" class="field-config" name="field-config">
-        <template v-if="hasField">
-          <template v-show="switchingField">
-            <component
-              :is="fieldType"
-              v-if="switchingField"
-              v-loading="loading"
-              :field-item="curField"
-              :bo-data="boData"
-              :fields="formFields"
-              size="mini"
-              label-position="right"
-              label-width="90px"
-              @update="updateSelectField"
-              @select="updateSelectField"
-            />
-            <template v-else>
-              <div
-                v-loading="!switchingField"
-                element-loading-text="加载中"
-                style="height:300px;"
-              />
-            </template>
-          </template>
+    <div :style="{ width:`${width}px`}">
+        <el-tabs v-model="activeName" type="border-card" class="formbuilder-tab-container" @tab-click="clickTab">
+            <el-tab-pane :style="{ width:`${width}px`}" label="字段配置" class="field-config" name="field-config">
+                <template v-if="hasField">
+                    <div v-show="switchingField">
+                        <component
+                            :is="fieldType"
+                            v-if="switchingField"
+                            v-loading="loading"
+                            :field-item="curField"
+                            :bo-data="boData"
+                            :fields="formFields"
+                            size="mini"
+                            label-position="left"
+                            label-width="100px"
+                            @update="updateSelectField"
+                            @select="updateSelectField"
+                        />
+                        <template v-else>
+                            <div
+                                v-loading="!switchingField"
+                                element-loading-text="加载中"
+                                style="height:300px;"
+                            />
+                        </template>
+                    </div>
 
-        </template>
-        <p v-else class="empty-field" data-content="请选择或拖入控件" />
-      </el-tab-pane>
-      <el-tab-pane :style="{ width:`${width}px`}" label="表单属性" class="form-property" name="form-property">
-        <form-property
-          :id="id"
-          :data="data"
-          :bo-data="boData"
-          @update="updateFormDef"
-        />
-      </el-tab-pane>
-    </el-tabs>
-  </div>
+                </template>
+                <p v-else class="empty-field" data-content="请选择或拖入控件" />
+            </el-tab-pane>
+            <el-tab-pane :style="{ width:`${width}px`}" label="表单属性" class="form-property" name="form-property">
+                <form-property
+                    :id="id"
+                    :data="data"
+                    :bo-data="boData"
+                    @update="updateFormDef"
+                />
+            </el-tab-pane>
+        </el-tabs>
+    </div>
 </template>
 <script>
 import Vue from 'vue'
@@ -49,99 +49,99 @@ import FormProperty from './propertys'
 Vue.component('HelpTip', () => import('./components/help-tip.vue'))
 
 export default {
-  name: 'right-aside',
-  components: Object.assign(FieldTypes, {
-    FormProperty
-  }),
-  props: {
-    id: String,
-    data: Object,
-    select: Object,
-    asideActiveName: String,
-    boData: {
-      type: Array
-    }
-  },
-  data() {
-    return {
-      width: 350,
-      curField: null,
-      switchingField: false,
-      loading: true,
-      activeName: 'form-property'
-    }
-  },
-  computed: {
-    fieldType() {
-      const name = camelCase(this.curField.field_type)
-      return `ibps-field-${name}`
+    name: 'right-aside',
+    components: Object.assign(FieldTypes, {
+        FormProperty
+    }),
+    props: {
+        id: String,
+        data: Object,
+        select: Object,
+        asideActiveName: String,
+        boData: {
+            type: Array
+        }
     },
-    hasField() {
-      if (!this.curField) {
-        return false
-      }
-      const componentName = upperFirst(camelCase(this.fieldType))
-      return !!this.$options.components[componentName]
+    data () {
+        return {
+            width: 350,
+            curField: null,
+            switchingField: false,
+            loading: true,
+            activeName: 'form-property'
+        }
     },
-    formFields() {
-      return this.data.fields || []
-    }
-  },
-  watch: {
-    select(val, oldVal) {
-      this.loading = true
-      this.curField = val
-      if (val !== oldVal) {
-        this.switchingField = false
-        setTimeout(() => {
-          this.switchingField = true
-          this.loading = false
-        }, 100)
-      } else {
-        this.loading = false
-      }
+    computed: {
+        fieldType () {
+            const name = camelCase(this.curField.field_type)
+            return `ibps-field-${name}`
+        },
+        hasField () {
+            if (!this.curField) {
+                return false
+            }
+            const componentName = upperFirst(camelCase(this.fieldType))
+            return !!this.$options.components[componentName]
+        },
+        formFields () {
+            return this.data.fields || []
+        }
     },
-    asideActiveName: {
-      handler: function(val, oldVal) {
-        this.activeName = this.asideActiveName
-      },
-      immediate: true
+    watch: {
+        select (val, oldVal) {
+            this.loading = true
+            this.curField = val
+            if (val !== oldVal) {
+                this.switchingField = false
+                setTimeout(() => {
+                    this.switchingField = true
+                    this.loading = false
+                }, 100)
+            } else {
+                this.loading = false
+            }
+        },
+        asideActiveName: {
+            handler: function (val, oldVal) {
+                this.activeName = this.asideActiveName
+            },
+            immediate: true
+        },
+        activeName (val, oldVal) {
+            this.$emit('active-name', val)
+        }
     },
-    activeName(val, oldVal) {
-      this.$emit('active-name', val)
+    methods: {
+        clickTab (tab) {
+            if (tab.name === 'field-config' && !this.hasField && this.data.fields && this.data.fields.length > 0) {
+                this.updateSelectField(this.data.fields[0])
+            }
+        },
+        updateFormDef (data) {
+            this.$emit('update-form-def', data)
+        },
+        updateSelectField (field) {
+            this.$emit('update:select', field)
+        }
     }
-  },
-  methods: {
-    clickTab(tab) {
-      if (tab.name === 'field-config' && !this.hasField && this.data.fields && this.data.fields.length > 0) {
-        this.updateSelectField(this.data.fields[0])
-      }
-    },
-    updateFormDef(data) {
-      this.$emit('update-form-def', data)
-    },
-    updateSelectField(field) {
-      this.$emit('update:select', field)
-    }
-  }
 
 }
 </script>
 <style scoped>
-  .empty-field {
-      position: relative;
-      opacity: 0.5;
-      box-shadow: none;
-      height: 100%;
+    .empty-field {
+        position: relative;
+        opacity: 0.5;
+        box-shadow: none;
+        height: 100%;
     }
 
-  .empty-field:after {
-    content: attr(data-content);
-    position: absolute;
-    text-align: center;
-    top: 40%;
-    left: 0;
-    width: 100%;
-    font-size: 18px;
-  }
+    .empty-field:after {
+        content: attr(data-content);
+        position: absolute;
+        text-align: center;
+        top: 40%;
+        left: 0;
+        width: 100%;
+        font-size: 18px;
+    }
 </style>

+ 8 - 2
src/business/platform/form/formrender/dynamic-form/dynamic-form-field.vue

@@ -132,7 +132,7 @@
                     :key="o.val"
                     :label="o.val"
                     :border="fieldOptions.border"
-                    :style="{ display: fieldOptions.arrangement === 'vertical' ? 'block' : null }"
+                    :style="{ display: fieldOptions.arrangement === 'vertical' ? 'block' : '' }"
                     class="ibps-pt-5"
                     @click.native.stop.prevent="handleRadioChange(o.val)"
                 >
@@ -160,7 +160,7 @@
                     :key="o.val"
                     :label="o.val"
                     :border="fieldOptions.border"
-                    :style="{ display: fieldOptions.arrangement === 'vertical' ? 'block' : null }"
+                    :style="{ display: fieldOptions.arrangement === 'vertical' ? 'block' : '' }"
                 >
                     {{ o.label }}
                 </component>
@@ -508,6 +508,12 @@
             :tip="fieldOptions.tip"
             :size="fieldOptions.size"
             :upload-type="fieldOptions.uploadType"
+            :compress-option="{
+                isCompress: fieldOptions.is_compress,
+                maxWidth: fieldOptions.compress_width,
+                maxFileSize: fieldOptions.compress_size,
+                quality: fieldOptions.quality
+            }"
             :disabled="readonly"
             v-on="$listeners"
         />

+ 0 - 1
src/business/platform/form/formrender/dynamic-form/dynamic-form-table.vue

@@ -593,7 +593,6 @@ export default {
          * 获取真实的权限
          */
         getRealRights (rights) {
-            // console.log(this.timeModification, '000')
             if (this.tableReadonly) {
                 return rights === FormOptions.t.PERMISSIONS.HIDE ? rights : FormOptions.t.PERMISSIONS.READ
             } else {

+ 1 - 1
src/store/modules/ibps/modules/user.js

@@ -183,7 +183,7 @@ export default {
          */
         getUserList ({ state, dispatch }, { first, second }) {
             const params = second ? `'%${second}%' or entity.id_ = '${first}'` : first ? `'%${first}%'` : '%%'
-            const sql = `select users.id_ as userId, users.name_ as userName, ifnull(users.mobile_, '') as phone, ifnull(group_concat(distinct positions.id_ order by positions.id_ separator ','), '') as positionId, ifnull(group_concat(distinct positions.name_ order by positions.id_ separator ','), '') as positions, ifnull(group_concat(distinct roles.id_ order by roles.role_note_ asc separator ','), '') as roleId, ifnull(group_concat(distinct roles.name_ order by roles.role_note_ asc separator ','), '') as roles, (select ifnull(people.qian_zi_tu_wen_, '') from t_ryjbqk as people where people.parent_id_ = users.id_ order by create_time_ desc limit 1) as signatureId, (select ifnull(files.file_name_, '') from ibps_file_attachment as files where files.id_ = signatureId) as signatureName from ibps_party_employee as users left join (select ur.user_id_, r.role_note_, group_concat(distinct r.id_ order by r.id_ separator ',') as id_, group_concat(distinct r.name_ order by r.id_ separator ',') as name_ from ibps_party_user_role as ur join ibps_party_role as r on ur.role_id_ = r.id_ group by ur.user_id_) as roles on users.id_ = roles.user_id_ left join ibps_party_entity as positions on find_in_set(positions.id_, users.positions_) where exists (select 1 from ibps_party_entity as entity where find_in_set(entity.id_, users.positions_) and (entity.path_ like ${params})) group by users.id_`
+            const sql = `select users.id_ as userId, users.name_ as userName, ifnull(users.mobile_, '') as phone, ifnull(group_concat(distinct positions.id_ order by positions.id_ separator ','), '') as positionId, ifnull(group_concat(distinct positions.name_ order by positions.id_ separator ','), '') as positions, ifnull(group_concat(distinct roles.id_ order by roles.role_note_ asc separator ','), '') as roleId, ifnull(group_concat(distinct roles.name_ order by roles.role_note_ asc separator ','), '') as roles, (select ifnull(people.qian_zi_tu_wen_, '') from t_ryjbqk as people where people.parent_id_ = users.id_ order by create_time_ desc limit 1) as signatureId, (select ifnull(files.file_name_, '') from ibps_file_attachment as files where files.id_ = signatureId) as signatureName from ibps_party_employee as users left join (select ur.user_id_, r.role_note_, group_concat(distinct r.id_ order by r.id_ separator ',') as id_, group_concat(distinct r.name_ order by r.id_ separator ',') as name_ from ibps_party_user_role as ur join ibps_party_role as r on ur.role_id_ = r.id_ group by ur.user_id_) as roles on users.id_ = roles.user_id_ left join ibps_party_entity as positions on find_in_set(positions.id_, users.positions_) where exists (select 1 from ibps_party_entity as entity where find_in_set(entity.id_, users.positions_) and (entity.path_ like ${params})) and users.status_ = 'actived' group by users.id_`
             common.request('sql', sql).then(res => {
                 const { data = [] } = res.variables || {}
                 dispatch('ibps/param/setUserList', data, {

Разница между файлами не показана из-за своего большого размера
+ 9 - 1
src/utils/query.js


+ 148 - 62
src/views/component/device/deviceDialog.vue

@@ -30,7 +30,7 @@
                                                 v-model="form.sheBeiMingChen"
                                                 size="mini"
                                                 template-key="sbysdhk"
-                                                :disabled="false"
+                                                :disabled="readonly"
                                                 type="dialog"
                                                 class="custom-dialog"
                                                 placeholder="请选择"
@@ -45,7 +45,8 @@
                                             <template slot="label">
                                                 <span class="required">设备名称:</span>
                                             </template>
-                                            <el-input v-model="form.sheBeiMingCheng" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.sheBeiMingCheng" size="mini" />
+                                            <span v-else>{{ form.sheBeiMingCheng ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                 </el-row>
@@ -59,7 +60,7 @@
                                                 v-model="form.bianZhiBuMen"
                                                 type="position"
                                                 readonly-text="text"
-                                                :disabled="false"
+                                                :disabled="readonly"
                                                 :multiple="false"
                                                 size="mini"
                                                 :filter="filter"
@@ -89,6 +90,7 @@
                                                 <span class="required">建档时间:</span>
                                             </template>
                                             <el-date-picker
+                                                v-if="!readonly"
                                                 v-model="form.bianZhiShiJian"
                                                 style="width:100%"
                                                 type="datetime"
@@ -98,11 +100,12 @@
                                                 value-format="yyyy-MM-dd HH:mm"
                                                 size="mini"
                                             />
+                                            <span v-else>{{ form.bianZhiShiJian ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                 </el-row>
                                 <el-row :gutter="20">
-                                    <el-col :span="8">
+                                    <el-col v-if="!hideSysDeviceNo" :span="8">
                                         <el-form-item label="设备编号:" prop="sheBeiShiBieH">
                                             <template slot="label">
                                                 <span>设备编号</span>
@@ -110,34 +113,36 @@
                                                     <i class="el-icon-question question-icon">:</i>
                                                 </el-tooltip>
                                             </template>
-                                            <span>{{ form.sheBeiShiBieH }}</span>
+                                            <span>{{ form.sheBeiShiBieH || '/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="原设备编号:" prop="yuanSheBeiBian">
                                             <template slot="label">
-                                                <span class="required">原设备编号:</span>
+                                                <span class="required">{{ hideSysDeviceNo?'设备编号':'原设备编号' }}:</span>
                                             </template>
-                                            <el-input v-model="form.yuanSheBeiBian" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.yuanSheBeiBian" size="mini" />
+                                            <span v-else>{{ form.yuanSheBeiBian ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="设备状态:" prop="sheBeiZhuangTa">
-                                            <span>{{ showState }}</span>
+                                            <span>{{ showState ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                 </el-row>
                                 <el-row :gutter="20">
                                     <el-col :span="8">
                                         <el-form-item label="设备类型:" prop="sheBeiLeiXing">
-                                            <el-select v-model="form.sheBeiLeiXing" placeholder="请选择" size="mini" style="width:100%">
+                                            <el-select v-if="!readonly" v-model="form.sheBeiLeiXing" placeholder="请选择" size="mini" style="width:100%">
                                                 <el-option
-                                                    v-for="item in ['检验系统','通用设备','软件','信息系统']"
-                                                    :key="item"
-                                                    :label="item"
-                                                    :value="item"
+                                                    v-for="(v,k) in typeList"
+                                                    :key="k"
+                                                    :label="v"
+                                                    :value="k"
                                                 />
                                             </el-select>
+                                            <span v-else>{{ typeList[form.sheBeiLeiXing]|| form.sheBeiLeiXing ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
@@ -145,7 +150,8 @@
                                             <template slot="label">
                                                 <span class="required">规格型号:</span>
                                             </template>
-                                            <el-input v-model="form.guiGeXingHao" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.guiGeXingHao" size="mini" />
+                                            <span v-else>{{ form.guiGeXingHao ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
@@ -153,7 +159,7 @@
                                             <template slot="label">
                                                 <span class="required">接收时状态:</span>
                                             </template>
-                                            <el-select v-model="form.jieShouZhuangTai" placeholder="请选择" size="mini" style="width:100%">
+                                            <el-select v-if="!readonly" v-model="form.jieShouZhuangTai" placeholder="请选择" size="mini" style="width:100%">
                                                 <el-option
                                                     v-for="item in ['新设备','二手或翻新设备']"
                                                     :key="item"
@@ -161,6 +167,7 @@
                                                     :value="item"
                                                 />
                                             </el-select>
+                                            <span v-else>{{ form.jieShouZhuangTai ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                 </el-row>
@@ -174,7 +181,7 @@
                                                 v-model="form.guanLiRen"
                                                 type="user"
                                                 readonly-text="text"
-                                                :disabled="false"
+                                                :disabled="readonly"
                                                 :multiple="false"
                                                 size="mini"
                                                 :filter="filter"
@@ -192,7 +199,7 @@
                                                 v-model="form.cunFangWeiZhi"
                                                 size="mini"
                                                 template-key="fjxzkdd"
-                                                :disabled="false"
+                                                :disabled="readonly"
                                                 type="dialog"
                                                 class="custom-dialog"
                                                 placeholder="请选择"
@@ -203,7 +210,8 @@
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="固定资产号:">
-                                            <el-input v-model="form.ziChanBianHao" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.ziChanBianHao" size="mini" />
+                                            <span v-else>{{ form.ziChanBianHao ||'/' }}</span>
                                         </el-form-item>
 
                                     </el-col>
@@ -211,7 +219,8 @@
                                 <el-row :gutter="20">
                                     <el-col :span="8">
                                         <el-form-item label="厂家/品牌:">
-                                            <el-input v-model="form.changShang" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.changShang" size="mini" />
+                                            <span v-else>{{ form.changShang ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
@@ -220,6 +229,7 @@
                                                 <span class="required">出厂日期</span>
                                             </template>
                                             <el-date-picker
+                                                v-if="!readonly"
                                                 v-model="form.chuChangRiQi"
                                                 style="width:100%"
                                                 type="date"
@@ -228,11 +238,13 @@
                                                 value-format="yyyy-MM-dd"
                                                 size="mini"
                                             />
+                                            <span v-else>{{ form.chuChangRiQi ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="出厂编号:">
-                                            <el-input v-model="form.jiShenXuHao" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.jiShenXuHao" size="mini" />
+                                            <span v-else>{{ form.jiShenXuHao ||'/' }}</span>
                                         </el-form-item>
 
                                     </el-col>
@@ -244,7 +256,7 @@
                                                 v-model="form.shiFouQiJianH"
                                                 size="mini"
                                                 template-key="gysxxdhk"
-                                                :disabled="false"
+                                                :disabled="readonly"
                                                 type="dialog"
                                                 class="custom-dialog"
                                                 placeholder="请选择"
@@ -256,12 +268,14 @@
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="供应商电话:">
-                                            <el-input v-model="form.lianXiFangShi" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.lianXiFangShi" size="mini" />
+                                            <span v-else>{{ form.lianXiFangShi ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                     <el-col :span="8">
                                         <el-form-item label="注册证号:">
-                                            <el-input v-model="form.zhuCeZhengHao" size="mini" />
+                                            <el-input v-if="!readonly" v-model="form.zhuCeZhengHao" size="mini" />
+                                            <span v-else>{{ form.zhuCeZhengHao ||'/' }}</span>
                                         </el-form-item>
                                     </el-col>
                                 </el-row>
@@ -304,6 +318,7 @@
                                                     <el-col>
                                                         <el-form-item label="购进日期:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.gouJinRiQi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -312,6 +327,7 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.gouJinRiQi ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -319,6 +335,7 @@
                                                     <el-col>
                                                         <el-form-item label="接收日期:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.jieShouRiQi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -327,6 +344,7 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.jieShouRiQi ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -334,6 +352,7 @@
                                                     <el-col>
                                                         <el-form-item label="验收日期:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.yanShouRiQi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -342,6 +361,7 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.yanShouRiQi ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -349,6 +369,7 @@
                                                     <el-col>
                                                         <el-form-item label="投入日期:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.qiYongRiQi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -357,6 +378,7 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.qiYongRiQi ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -364,6 +386,7 @@
                                                     <el-col>
                                                         <el-form-item label="核查日期:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.biXuSheShi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -372,6 +395,7 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.biXuSheShi ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -382,7 +406,7 @@
                                                                 v-model="form.biXuDeHuanJin"
                                                                 type="user"
                                                                 readonly-text="text"
-                                                                :disabled="false"
+                                                                :disabled="readonly"
                                                                 :multiple="false"
                                                                 size="mini"
                                                                 style="width:100%"
@@ -395,28 +419,35 @@
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="电源要求:">
-                                                            <el-input v-model="form.dianYuanYaoQiu" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.dianYuanYaoQiu" size="mini" />
+                                                            <span v-else>{{ form.dianYuanYaoQiu ||'/' }}</span>
+
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="环境要求:">
-                                                            <el-input v-model="form.huanJingYaoQiu" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.huanJingYaoQiu" size="mini" />
+                                                            <span v-else>{{ form.huanJingYaoQiu ||'/' }}</span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="使用年限(年):">
-                                                            <el-input v-model="form.heChaXiaoZhun" size="mini" type="number" />
+                                                            <el-input v-if="!readonly" v-model="form.heChaXiaoZhun" size="mini" type="number" />
+                                                            <span v-else>{{ form.heChaXiaoZhun ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="资产原值(元):">
-                                                            <el-input v-model="form.ziChanYuanZhi" size="mini" type="number" />
+                                                            <el-input v-if="!readonly" v-model="form.ziChanYuanZhi" size="mini" type="number" />
+                                                            <span v-else>{{ form.ziChanYuanZhi ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -426,7 +457,7 @@
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="是否维护:">
-                                                            <el-select v-model="form.shiFouWeiHu" placeholder="请选择" size="mini" style="width:100%">
+                                                            <el-select v-if="!readonly" v-model="form.shiFouWeiHu" placeholder="请选择" size="mini" style="width:100%">
                                                                 <el-option
                                                                     v-for="item in ['是','否']"
                                                                     :key="item"
@@ -434,6 +465,8 @@
                                                                     :value="item"
                                                                 />
                                                             </el-select>
+                                                            <span v-else>{{ form.shiFouWeiHu ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -445,7 +478,7 @@
                                                                 size="mini"
                                                                 template-key="sbbqdhk"
                                                                 multiple
-                                                                :disabled="false"
+                                                                :disabled="readonly"
                                                                 type="dialog"
                                                                 class="custom-dialog"
                                                                 placeholder="请选择"
@@ -458,7 +491,7 @@
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="是否24H开机:">
-                                                            <el-select v-model="form.jianKongYiJu" placeholder="请选择" size="mini" style="width:100%">
+                                                            <el-select v-if="!readonly" v-model="form.jianKongYiJu" placeholder="请选择" size="mini" style="width:100%">
                                                                 <el-option
                                                                     v-for="item in ['是','否']"
                                                                     :key="item"
@@ -466,6 +499,8 @@
                                                                     :value="item"
                                                                 />
                                                             </el-select>
+                                                            <span v-else>{{ form.jianKongYiJu ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -473,12 +508,15 @@
                                                     <el-col>
                                                         <el-form-item label="开机时间:">
                                                             <el-time-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.kaiShiShiYong"
                                                                 placeholder="任意时间点"
                                                                 size="mini"
                                                                 style="width:100%"
                                                                 value-format="HH:mm:ss"
                                                             />
+                                                            <span v-else>{{ form.kaiShiShiYong ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -486,13 +524,15 @@
                                                     <el-col>
                                                         <el-form-item label="关机时间:">
                                                             <el-time-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.shiJiShiYongF"
                                                                 placeholder="任意时间点"
                                                                 size="mini"
                                                                 style="width:100%"
                                                                 value-format="HH:mm:ss"
                                                             />
-                                                        </el-form-item>
+                                                            <span v-else>{{ form.shiJiShiYongF ||'/' }}
+                                                            </span></el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <!-- <el-row>
@@ -533,7 +573,7 @@
                                                 <el-row>
                                                     <el-col>
                                                         <el-form-item label="是否校准:" prop="shiFouXiaoZhun">
-                                                            <el-select v-model="form.shiFouXiaoZhun" placeholder="请选择" size="mini" style="width:100%">
+                                                            <el-select v-if="!readonly" v-model="form.shiFouXiaoZhun" placeholder="请选择" size="mini" style="width:100%">
                                                                 <el-option
                                                                     v-for="item in ['是','否']"
                                                                     :key="item"
@@ -541,13 +581,17 @@
                                                                     :value="item"
                                                                 />
                                                             </el-select>
+                                                            <span v-else>{{ form.shiFouXiaoZhun ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是'">
                                                     <el-col>
                                                         <el-form-item label="检定/校准周期(月):" label-width="140">
-                                                            <el-input v-model="form.xiaoZhunZQ" size="mini" type="number" style="width:100%" />
+                                                            <el-input v-if="!readonly" v-model="form.xiaoZhunZQ" size="mini" type="number" style="width:100%" />
+                                                            <span v-else>{{ form.xiaoZhunZQ ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -558,7 +602,7 @@
                                                                 v-model="form.shiYongKeShi"
                                                                 size="mini"
                                                                 template-key="gysxxdhk"
-                                                                :disabled="false"
+                                                                :disabled="readonly"
                                                                 type="dialog"
                                                                 class="custom-dialog"
                                                                 placeholder="请选择"
@@ -572,6 +616,7 @@
                                                     <el-col>
                                                         <el-form-item label="最近校准时间:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.yiXiaoRiQi"
                                                                 style="width:100%"
                                                                 type="date"
@@ -580,6 +625,8 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.yiXiaoRiQi ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -587,6 +634,7 @@
                                                     <el-col>
                                                         <el-form-item label="校准有效期至:">
                                                             <el-date-picker
+                                                                v-if="!readonly"
                                                                 v-model="form.xiaoZhunYouXia"
                                                                 style="width:100%"
                                                                 type="date"
@@ -595,48 +643,62 @@
                                                                 value-format="yyyy-MM-dd"
                                                                 size="mini"
                                                             />
+                                                            <span v-else>{{ form.xiaoZhunYouXia ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是'">
                                                     <el-col>
                                                         <el-form-item label="校准证书编号:">
-                                                            <el-input v-model="form.zhengShuBianHa" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.zhengShuBianHa" size="mini" />
+                                                            <span v-else>{{ form.zhengShuBianHa ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="false">
                                                     <el-col>
                                                         <el-form-item label="校准机构:">
-                                                            <el-input v-model="form.shiWuShuoMing" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.shiWuShuoMing" size="mini" />
+                                                            <span v-else>{{ form.shiWuShuoMing ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是' && !isSheKou">
                                                     <el-col>
                                                         <el-form-item label="检定/校准参数:">
-                                                            <el-input v-model="form.jianDingXiao" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.jianDingXiao" size="mini" />
+                                                            <span v-else>{{ form.jianDingXiao ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是' && !isSheKou">
                                                     <el-col>
                                                         <el-form-item label="测量范围:">
-                                                            <el-input v-model="form.ceLiangGongZuo" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.ceLiangGongZuo" size="mini" />
+                                                            <span v-else>{{ form.ceLiangGongZuo ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是' && !isSheKou">
                                                     <el-col>
                                                         <el-form-item label="U/精确度/最大允差:" label-width="130">
-                                                            <el-input v-model="form.zuiDaYunCha" size="mini" style="width:100%" />
+                                                            <el-input v-if="!readonly" v-model="form.zuiDaYunCha" size="mini" style="width:100%" />
+                                                            <span v-else>{{ form.zuiDaYunCha ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
                                                 <el-row v-if="form.shiFouXiaoZhun==='是' && !isSheKou">
                                                     <el-col>
                                                         <el-form-item label="修正值:">
-                                                            <el-input v-model="form.xiuZhengZhiXiu" size="mini" />
+                                                            <el-input v-if="!readonly" v-model="form.xiuZhengZhiXiu" size="mini" />
+                                                            <span v-else>{{ form.xiuZhengZhiXiu ||'/' }}
+                                                            </span>
                                                         </el-form-item>
                                                     </el-col>
                                                 </el-row>
@@ -668,7 +730,7 @@
                                                         :download="true"
                                                         multiple
                                                         accept="*"
-                                                        :readonly="false"
+                                                        :readonly="readonly"
                                                         style="width:100%"
                                                     />
                                                 </el-form-item>
@@ -680,7 +742,7 @@
                                                         :download="true"
                                                         multiple
                                                         accept="*"
-                                                        :readonly="false"
+                                                        :readonly="readonly"
                                                         style="width:100%"
                                                     />
                                                 </el-form-item>
@@ -692,7 +754,7 @@
                                                         :download="true"
                                                         multiple
                                                         accept="*"
-                                                        :readonly="false"
+                                                        :readonly="readonly"
                                                         style="width:100%"
                                                     />
                                                 </el-form-item>
@@ -720,7 +782,7 @@
                                         </keep-alive>
                                     </template>
                                     <template v-else>
-                                        <component :is="item.component" :ref="item.ref" :list-data="form[item.data]" />
+                                        <component :is="item.component" :ref="item.ref" :readonly="readonly" :list-data="form[item.data]" />
                                     </template>
                                 </el-tab-pane>
                             </el-tabs>
@@ -733,7 +795,6 @@
 </template>
 
 <script>
-import { getSetting } from '@/utils/query'
 import dayjs from 'dayjs'
 import ibpsUserSelector from '@/business/platform/org/selector'
 import { getequipmentCard, saveEquipmentCard } from '@/api/platform/device/device'
@@ -754,6 +815,10 @@ export default {
         IbpsImage: () => import('@/business/platform/file/image')
     },
     props: {
+        readonly: {
+            type: Boolean,
+            default: false
+        },
         params: {
             type: Object,
             default: function () {
@@ -765,6 +830,22 @@ export default {
             default: function () {
                 return { '停用': '停用', '报废': '报废', '合格': '合格' }
             }
+        },
+        hideSysDeviceNo: {
+            type: Boolean,
+            default: false
+        },
+        tabList: {
+            type: Object,
+            default: function () {
+                return {}
+            }
+        },
+        typeList: {
+            type: Object,
+            default: function () {
+                return { '检验系统': '检验系统', '通用设备': '通用设备', '软件': '软件', '信息系统': '信息系统' }
+            }
         }
     },
     data () {
@@ -779,7 +860,6 @@ export default {
                 { label: '停用、报废记录', name: 'seven', component: 'ScrappedRecord', isKeepAlive: true },
                 { label: '性能验证记录', name: 'eight', component: 'PvRecord', isKeepAlive: true }
             ],
-            tabList: {},
             filter: [{
                 descVal: '1',
                 includeSub: true,
@@ -793,7 +873,6 @@ export default {
             isFirstyiXiaoRiQi: true,
             isFirstbianZhiBuMen: true,
             isSheKou: false,
-            readonly: false,
             activeName: 'one',
             dialogVisible: true,
             userId: userId,
@@ -804,7 +883,7 @@ export default {
             loading: false,
             title: '设备档案卡',
             toolbars: [
-                { key: 'save', label: '保存' },
+                { key: 'save', label: '保存', hidden: () => { return this.readonly } },
                 { key: 'cancel', label: '退出', type: 'danger', icon: 'ibps-icon-close' }
             ],
             initWidth: '1480px',
@@ -880,9 +959,6 @@ export default {
                 sheBeiMingCheng: [
                     { required: true, message: '设备名称不能为空', trigger: 'blur' }
                 ],
-                sheBeiShiBieH: [
-                    { required: true, message: '设备编号不能为空', trigger: 'blur' }
-                ],
                 yuanSheBeiBian: [
                     { required: true, message: '原设备编号不能为空', trigger: 'blur' }
                 ],
@@ -991,12 +1067,7 @@ export default {
         }
     },
 
-    async mounted () {
-        const tabList = await getSetting('device', 'tabList')
-        if (tabList) {
-            console.debug(tabList)
-            this.tabList = tabList
-        }
+    mounted () {
         this.init()
     },
     methods: {
@@ -1127,6 +1198,7 @@ export default {
         async goAdd () {
             try {
                 this.loading = true
+                this.form.sheBeiShiBieH = await this.getNextAlias()
                 await saveEquipmentCard(this.form)
                 this.$message.success('添加成功')
                 this.closeDialog(true)
@@ -1211,7 +1283,21 @@ export default {
         generateRandomString () {
             return `JYK-${Math.floor(Math.random() * 88888) + 10000}`
         },
+        getNextAlias () {
+            return new Promise((resolve, reject) => {
+                this.$common.getNextIdByAlias({
+                    'alias': 'sbbh'
+                }).then(response => {
+                    resolve(response.data)
+                }).catch((error) => {
+                    reject(error)
+                })
+            })
+        },
         async init () {
+            if (this.hideSysDeviceNo) {
+                this.rules.yuanSheBeiBian[0].message = '设备编号不能为空'
+            }
             this.loading = true
             this.isEdit = !!(this.params && this.params.id)
             this.isSheKou = this.deptList[0].positionId === '1166372468122714112' // 判断是否是蛇口医院
@@ -1239,10 +1325,10 @@ export default {
                 this.isFirstbianZhiBuMen = false
                 this.isFirstyiXiaoRiQi = false
                 // 随机生成一个不重复的设备编号
-                this.form.sheBeiShiBieH = this.generateRandomString()
-                for (; await this.checkIsRepeat(this.form.sheBeiShiBieH);) {
-                    this.form.sheBeiShiBieH = this.generateRandomString()
-                }
+                // this.form.sheBeiShiBieH = this.generateRandomString()
+                // for (; await this.checkIsRepeat(this.form.sheBeiShiBieH);) {
+                //     this.form.sheBeiShiBieH = this.generateRandomString()
+                // }
                 this.form.jieShouRiQi = dayjs().format('YYYY-MM-DD')
                 this.form.qiYongRiQi = dayjs().format('YYYY-MM-DD')
                 this.form.xiaoZhunWuCha = '否'

+ 144 - 48
src/views/component/device/index.vue

@@ -28,7 +28,7 @@
                             v-model="row.bianZhiBuMen"
                             type="position"
                             readonly-text="text"
-                            :multiple="true"
+                            :multiple="false"
                             :disabled="true"
                         />
 
@@ -69,7 +69,13 @@
                         slot="deviceStateSlot"
                         slot-scope="{row}"
                     >
-                        <span>{{ stateList[row.sheBeiZhuangTa] || row.sheBeiZhuangTa }}</span>
+                        <span>{{ stateList[row.sheBeiZhuangTa] || row.sheBeiZhuangTa || '' }}</span>
+                    </template>
+                    <template
+                        slot="deviceTypeSlot"
+                        slot-scope="{row}"
+                    >
+                        <span>{{ typeList[row.sheBeiLeiXing] || row.sheBeiLeiXing || '' }}</span>
                     </template>
 
                     <template
@@ -94,7 +100,7 @@
                         slot="customButton"
                         slot-scope="{row}"
                     >
-                        <el-button type="text" icon="el-icon-edit-outline" @click="goEdit(row)">修改</el-button>
+                        <el-button type="text" :icon="hasRole?'el-icon-edit-outline':'ibps-icon-eye'" @click="goEdit(row)">{{ hasRole?'修改':'查阅' }}</el-button>
                         <!-- <el-button type="text" icon="el-icon-view" @click="goLook(row)">查阅</el-button> -->
                         <el-button type="text" icon="ibps-icon-table" @click="goLookForm(row)">表单</el-button>
 
@@ -262,10 +268,10 @@
                     <template slot="deviceType">
                         <el-select v-model="search.deviceType" placeholder="请选择" size="mini" :clearable="true">
                             <el-option
-                                v-for="item in ['检验系统','通用设备','软件','信息系统']"
-                                :key="item"
-                                :label="item"
-                                :value="item"
+                                v-for="(v,k) in typeList"
+                                :key="k"
+                                :label="v"
+                                :value="k"
                             />
                         </el-select>
                     </template>
@@ -309,7 +315,16 @@
                 </ibps-crud>
             </template>
         </ibps-container>
-        <DeviceDialog v-if="deviceDialogShow" :params="params" :state-list="stateList" @close="close" />
+        <DeviceDialog
+            v-if="deviceDialogShow"
+            :params="params"
+            :state-list="stateList"
+            :type-list="typeList"
+            :tab-list="tabList"
+            :hide-sys-device-no="hideSysDeviceNo"
+            :readonly="!hasRole"
+            @close="close"
+        />
         <input id="" ref="file1" type="file" name="" accept=".xlsx,.xls" @change="handleUploadChange1">
         <input id="" ref="file2" type="file" name="" accept=".xlsx,.xls" @change="handleUploadChange2">
 
@@ -349,6 +364,7 @@ import image02 from '@/assets/images/device/02.png'
 import image03 from '@/assets/images/device/03.png'
 import image04 from '@/assets/images/device/04.png'
 import { getImage } from '@/api/platform/file/attachment'
+import { download } from '@/api/platform/file/attachment'
 
 import xlsx from 'xlsx'
 import fs from 'file-saver'
@@ -465,7 +481,7 @@ export default {
                     { key: 'customExport', label: '导出数据', icon: 'ibps-icon-sign-in', type: 'primary' },
                     { key: 'customImport', label: '导入数据', icon: 'ibps-icon-sign-in', type: 'primary' },
                     { key: 'customSetting', label: '设置分组配置', icon: 'ibps-icon-cogs', type: 'info' },
-                    { key: 'customRemove', label: '删除', icon: 'ibps-icon-close', type: 'danger' }
+                    { key: 'customRemove', label: '删除', icon: 'ibps-icon-close', type: 'danger', hidden: () => { return !this.hasRole } }
                 ],
                 // 查询条件
                 searchForm: {
@@ -491,7 +507,7 @@ export default {
                     { prop: 'sheBeiShiBieH', label: '设备编号', sortable: true },
                     { prop: 'yuanSheBeiBian', label: '原设备编号', sortable: true },
                     { prop: 'sheBeiMingCheng', label: '设备名称', sortable: true },
-                    { prop: 'sheBeiLeiXing', label: '设备类型', sortable: true },
+                    { prop: 'sheBeiLeiXing', label: '设备类型', sortable: true, slotName: 'deviceTypeSlot' },
                     { prop: 'guiGeXingHao', label: '规格型号', sortable: true },
                     { prop: 'sheBeiZhuangTa', label: '设备状态', sortable: true, slotName: 'deviceStateSlot' },
                     { prop: 'guanLiRen', label: '保管人', slotName: 'userSlot', sortable: true },
@@ -509,51 +525,53 @@ export default {
             deviceColumns: {
                 bianZhiBuMen: '部门',
                 sheBeiMingCheng: '设备名称',
-                sheBeiShiBieH: '设备编号(导入无需填写)',
+                // sheBeiShiBieH: '设备编号(导入无需填写)',
                 yuanSheBeiBian: '原设备编号(必填,且不可重复)',
                 sheBeiZhuangTa: '设备状态(合格/停用/限用)',
                 sheBeiLeiXing: '设备类型(检验系统/通用设备/软件/信息系统)',
+                shiFouWeiHu: '是否维护(是/否)',
+                shiFouXiaoZhun: '是否校准(是/否)',
+                weiHuFangShi: '设备分组',
                 guiGeXingHao: '规格型号',
-                cunFangDiDian: '存放地点',
+                cunFangDiDian: '存放地点(格式:房间号+空格+房间名)',
                 guanLiRen: '保管人',
                 ziChanBianHao: '资产编号',
+                ziChanYuanZhi: '资产原值(元)',
                 gongYingShang: '供应商',
                 lianXiFangShi: '联系方式',
                 changShang: '厂商',
-                chuChangRiQi: '出厂日期',
                 jiShenXuHao: '机身序号',
                 zhuCeZhengHao: '注册证号',
-                ceLiangGongZuo: '测量范围',
-                huanJingYaoQiu: '环境要求',
-                dianYuanYaoQiu: '电源要求',
+                heChaXiaoZhun: '使用年限(年)',
+                chuChangRiQi: '出厂日期',
                 yanShouRiQi: '验收日期',
                 jieShouRiQi: '接收日期',
-                jieShouZhuangTai: '接收时状态(新设备/二手或翻新设备)',
                 qiYongRiQi: '投入日期',
-                shiFouXiaoZhun: '是否校准(是/否)',
                 yiXiaoRiQi: '已校日期',
                 xiaoZhunZQ: '检定/校准周期(以月为单位)',
                 xiaoZhunYouXia: '校准有效期至',
+                shiYongKeShi: '检定/校准单位',
+                ceLiangGongZuo: '测量/工作范围',
+                huanJingYaoQiu: '环境要求',
+                dianYuanYaoQiu: '电源要求',
+                jieShouZhuangTai: '接收时状态(新设备/二手或翻新设备)',
                 jianDingXiao: '检定/校准参数',
                 zuiDaYunCha: 'U/精确度/最大允差',
                 zhengShuBianHa: '证书编号',
                 xiuZhengZhiXiu: '修正值/修正因子',
-                // wenDuYingYong:'温度应用修正值',
-                // shiDuYingYong:'湿度应用修正值',
-                shiFouWeiHu: '是否维护(是/否)',
-                biXuDeHuanJin: '核查人',
-                biXuSheShi: '核查日期',
-                weiHuFangShi: '设备分组',
-                heChaXiaoZhun: '使用年限(年)'
+                wenDuYingYong: '温度应用修正值',
+                shiDuYingYong: '湿度应用修正值'
+                // biXuDeHuanJin: '核查人',
+                // biXuSheShi: '核查日期',
             },
             projectColums: {
-                yuanSheBeiBian: '设备编号*',
+                yuanSheBeiBian: '原设备编号*',
                 sheBeiMingCheng: '设备名称*',
                 weiHuLeiXing: '维护类型*(日保养/周保养/月保养/季度保养/半年保养/年保养/按需保养)',
                 weiHuRiQi: '维护日期*',
                 weiHuXiangMuC: '维护项目*'
             },
-            dateFieldRange: ['chuChangRiQi', 'yanShouRiQi', 'jieShouRiQi', 'qiYongRiQi', 'yiXiaoRiQi', 'xiaoZhunYouXia', 'biXuSheShi'],
+            dateFieldRange: ['chuChangRiQi', 'yanShouRiQi', 'jieShouRiQi', 'qiYongRiQi', 'yiXiaoRiQi', 'xiaoZhunYouXia'],
             requiredFieldMap: {
                 bianZhiBuMen: '部门',
                 sheBeiMingCheng: '设备名称',
@@ -569,8 +587,8 @@ export default {
                 'jieShouRiQi': '接收日期',
                 'qiYongRiQi': '投入日期',
                 'yiXiaoRiQi': '已校日期',
-                'xiaoZhunYouXia': '校准有效期至',
-                'biXuSheShi': '核查日期'
+                'xiaoZhunYouXia': '校准有效期至'
+                // 'biXuSheShi': '核查日期'
             },
             validationRules: {
                 '设备状态': {
@@ -596,7 +614,8 @@ export default {
             },
             numberFieldsMap: {
                 'xiaoZhunZQ': '检定/校准周期(以月为单位)',
-                'heChaXiaoZhun': '使用年限(年)'
+                'heChaXiaoZhun': '使用年限(年)',
+                'ziChanYuanZhi': '资产原值(元)'
             },
             maintenanceRequiredFieldMap: {
                 yuanSheBeiBian: '原设备编号',
@@ -620,15 +639,41 @@ export default {
                 '年保养': this.generateRule(12, `每年第`, `个月`),
                 '按需保养': ['/']
             },
-            stateList: { '停用': '停用', '报废': '报废', '合格': '合格' }
+            stateList: { '停用': '停用', '报废': '报废', '合格': '合格' },
+            hideSysDeviceNo: false,
+            tabList: {},
+            hasRole: true,
+            typeList: { '检验系统': '检验系统', '通用设备': '通用设备', '软件': '软件', '信息系统': '信息系统' }
         }
     },
     async mounted () {
-        const stateList = await getSetting('device', 'stateList')
+        const { stateList, hideSysDeviceNo, tabList, hasDeviceRole, typeList } = await getSetting('device') || {}
+        if (hasDeviceRole) {
+            console.debug('hasDeviceRole', hasDeviceRole)
+            const { role, isSuper } = this.$store.getters || {}
+            this.hasRole = isSuper || role.some(r => hasDeviceRole.includes(r.alias))
+        }
         if (stateList) {
-            console.debug(stateList)
+            console.debug('stateList', stateList)
             this.stateList = stateList
         }
+        if (typeList) {
+            console.debug('typeList', typeList)
+            this.typeList = typeList
+        }
+        if (hideSysDeviceNo) {
+            this.hideSysDeviceNo = hideSysDeviceNo
+            // 列表隐藏设备编号 将原设备编号改为设备编号
+            this.listConfig.columns = this.listConfig.columns.filter(i => i.prop !== 'sheBeiShiBieH')
+            this.listConfig.columns.find(i => i.prop === 'yuanSheBeiBian').label = '设备编号'
+            // 查询条件隐藏设备编号 将原设备编号改为设备编号
+            this.listConfig.searchForm.forms = this.listConfig.searchForm.forms.filter(i => i.slotName !== 'nowNumber')
+            this.listConfig.searchForm.forms.find(i => i.slotName === 'preNumber').label = '设备编号'
+        }
+        if (tabList) {
+            console.debug('tabList', tabList)
+            this.tabList = tabList
+        }
         this.getDatas()
     },
     methods: {
@@ -842,6 +887,7 @@ export default {
             this.customDialogVisible = true
         },
         handleCustomRemove (selection) {
+            if (!this.hasRole) return
             console.log('selection', selection)
             if (!selection || selection.length === 0) {
                 return this.$message.warning('请选择要删除的数据!')
@@ -959,14 +1005,23 @@ export default {
         },
         async switchExportData (data) {
             const deviceGroupSql = `select id_,wei_hu_gang_wei_ from t_sbwhgwpzb` // 设备分组信息
+            const supplierSql = `select id_,gong_ying_shang_m from t_gysxxb` // 供应商信息
             const { variables: { data: deviceGroupData }} = await this.$common.request('sql', deviceGroupSql)
+            const { variables: { data: gysData }} = await this.$common.request('sql', supplierSql)
             const exportData = JSON.parse(JSON.stringify(data))
             for (let i = 0; i < exportData.length; i++) {
                 const item = exportData[i]
                 item.bianZhiBuMen = this.switchIdToDept(item.bianZhiBuMen.split(',')[0])
                 item.guanLiRen = this.switchIdToUserName(item.guanLiRen.split(',')[0])
-                item.biXuDeHuanJin = this.switchIdToUserName(item.biXuDeHuanJin.split(',')[0])
+                // item.biXuDeHuanJin = this.switchIdToUserName(item.biXuDeHuanJin.split(',')[0])
                 item.weiHuFangShi = this.switchDeviceIdToName(item.weiHuFangShi, deviceGroupData)
+                item.shiYongKeShi = this.switchGYSIdToName(item.shiYongKeShi, gysData)
+                if (this.stateList[item.sheBeiZhuangTa]) {
+                    item.sheBeiZhuangTa = this.stateList[item.sheBeiZhuangTa]
+                }
+                if (this.typeList[item.sheBeiLeiXing]) {
+                    item.sheBeiLeiXing = this.typeList[item.sheBeiLeiXing]
+                }
             }
             return exportData
         },
@@ -977,6 +1032,11 @@ export default {
             valList.forEach(item => result.push((deviceGroupList?.find(i => i.id_ === item)?.wei_hu_gang_wei_) || ''))
             return result.join(',')
         },
+        // 供应商id 转 供应商名称 检定/校准单位
+        switchGYSIdToName (val, gysList) {
+            const result = gysList.find(item => item.id_ === val)?.gong_ying_shang_m || ''
+            return result
+        },
         // 部门id 转 部门名称
         switchIdToDept (id) {
             const { deptList } = this.$store.getters
@@ -1015,8 +1075,25 @@ export default {
                 const sql = `select b.yuan_she_bei_bian as yuanSheBeiBian,b.she_bei_ming_cheng_ as sheBeiMingCheng,a.parent_id_,a.wei_hu_xiang_mu_c as weiHuXiangMuC,a.wei_hu_ri_qi_ as weiHuRiQi,a.wei_hu_lei_xing_ as weiHuLeiXing,a.ri_qi_shu_zi_ as riQiShuZi from t_whzqjxm a,t_sbdj b where a.parent_id_=b.id_ and a.parent_id_ in (${selection.map(i => `'${i}'`).join(',')})`
                 const { variables: { data }} = await this.$common.request('sql', sql)
                 exportData = data
+                this.xlsx(exportData, this.projectColums, '设备维护项目数据' + this.getTimeStamp())
+            } else {
+                const attachmentId = 'device_maintainProject'
+                const res = await download({ attachmentId })
+                // 判断 ArrayBuffer 的大小,主要用于兼容没有文件的情况
+                if (res.data?.byteLength === 0) {
+                    this.xlsx([], this.projectColums, '设备维护项目模板' + this.getTimeStamp())
+                } else {
+                    // const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
+                    const a = document.createElement('a')
+                    a.style.display = 'none'
+                    // a.href = URL.createObjectURL(blob)
+                    a.href = res.request.responseURL
+                    // a.download = '设备维护项目导入模板'
+                    document.body.appendChild(a)
+                    a.click()
+                    document.body.removeChild(a)
+                }
             }
-            this.xlsx(exportData, this.projectColums, '设备维护项目数据' + this.getTimeStamp())
             this.$message.success('导出维护项目成功!')
         },
         // value 转 key
@@ -1294,6 +1371,17 @@ export default {
                 } else {
                     element.shiFouQiJianH = ''
                 }
+
+                if (element.shiYongKeShi.trim()) {
+                    const supplier = supplierList.find(i => i.gong_ying_shang_m === element.shiYongKeShi.trim())
+                    if (supplier) {
+                        element.shiYongKeShi = supplier.id_
+                    } else {
+                        element.shiYongKeShi = ''
+                    }
+                } else {
+                    element.shiYongKeShi = ''
+                }
             })
         },
         /**
@@ -1332,17 +1420,17 @@ export default {
                     element.guanLiRen = ''
                 }
                 // 处理核查人
-                if (element.biXuDeHuanJin !== '') {
-                    const checkPerson = employeeList.find(i => i.userName === element.biXuDeHuanJin.trim())
-                    if (checkPerson) {
-                        const checkPersonId = checkPerson.userId
-                        element.biXuDeHuanJin = checkPersonId
-                    } else {
-                        element.biXuDeHuanJin = ''
-                    }
-                } else {
-                    element.biXuDeHuanJin = ''
-                }
+                // if (element.biXuDeHuanJin !== '') {
+                //     const checkPerson = employeeList.find(i => i.userName === element.biXuDeHuanJin.trim())
+                //     if (checkPerson) {
+                //         const checkPersonId = checkPerson.userId
+                //         element.biXuDeHuanJin = checkPersonId
+                //     } else {
+                //         element.biXuDeHuanJin = ''
+                //     }
+                // } else {
+                //     element.biXuDeHuanJin = ''
+                // }
             })
         },
         handleDeviceGroupInfo (list, deviceGroupList) {
@@ -1363,7 +1451,15 @@ export default {
             let importData = this.switchDeviceObj(data, this.deviceColumns)
             importData.forEach(i => {
                 delete i.sheBeiShiBieH // 设备编号需自动生成
-                i.sheBeiZhuangTa = '合格'
+                // i.sheBeiZhuangTa = '合格'
+                const keyFound = Object.entries(this.stateList).find(([key, value]) => value === i.sheBeiZhuangTa)
+                if (keyFound) {
+                    i.sheBeiZhuangTa = keyFound[0]
+                }
+                const keyFound2 = Object.entries(this.typeList).find(([key, value]) => value === i.sheBeiLeiXing)
+                if (keyFound2) {
+                    i.sheBeiLeiXing = keyFound2[0]
+                }
             })
             const currentPosition = this.level
             const { userList = [], deptList = [] } = this.$store.getters || {}
@@ -1371,7 +1467,7 @@ export default {
             const supplierSql = `select id_,gong_ying_shang_m from t_gysxxb where di_dian_ = ${currentPosition}` // 供应商信息
             const deviceGroupSql = `select id_,suo_shu_bu_men_,wei_hu_gang_wei_ from t_sbwhgwpzb where di_dian_ =  ${currentPosition}` // 设备分组信息
             const currentTime = dayjs().format('YYYY-MM-DD HH:mm')
-            const currentApartment = this.$store.getters.userInfo.employee.positions
+            const currentApartment = this.$store.getters.userInfo.employee.positions.split(',').at(-1) || ''
             const currentUser = this.userId
 
             const partOneInvalidResult = this.deviceInvalidPartOne(importData)

+ 5 - 1
src/views/component/device/maintenance.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="table">
-        <div class="button">
+        <div v-if="!readonly" class="button">
             <el-button size="mini" icon="el-icon-plus" type="success" @click="goAdd">添加</el-button>
             <el-button size="mini" icon="el-icon-close" type="danger" @click="goDelete">删除</el-button>
         </div>
@@ -59,6 +59,10 @@ export default {
         listData: {
             type: Array,
             default: () => []
+        },
+        readonly: {
+            type: Boolean,
+            default: false
         }
     },
     data () {

+ 5 - 1
src/views/component/device/moreDevices.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="table">
-        <div class="button">
+        <div v-if="!readonly" class="button">
             <el-button size="mini" icon="el-icon-plus" type="success" @click="goAdd">添加</el-button>
             <el-button size="mini" icon="el-icon-close" type="danger" @click="goDelete">删除</el-button>
         </div>
@@ -65,6 +65,10 @@ export default {
         listData: {
             type: Array,
             default: () => []
+        },
+        readonly: {
+            type: Boolean,
+            default: false
         }
     },
     data () {

+ 1 - 0
src/views/component/facility/facilityData.vue

@@ -180,6 +180,7 @@ export default {
         },
         // 初始化数据
         initData (data) {
+            data = data.replace(/\n/g, '')
             const ans = JSON.parse(data)
             const result = []
             if (this.isFirst) {

+ 4 - 4
src/views/component/fileTraining/index.vue

@@ -253,10 +253,10 @@ export default {
         // 页面切换时改变计时状态
         document.addEventListener('visibilitychange', this.handlePageChange)
         this.checkDialogBody()
-        const roleKey = ['xtgljs']
-        const curRole = this.role.map(i => i.alias)
-        const isPower = curRole.some(item => roleKey.includes(item))
-        this.deleteShow = !!((isPower || this.isPower))
+        // task-3972 删除权限仅开放给超级用户和文件管理员
+        const roleList = ['wjgly']
+        const isPower = this.role.some(item => roleList.includes(item.alias))
+        this.deleteShow = this.isSuper || isPower
     },
     methods: {
         getUserName (data) {

+ 20 - 1
src/views/component/sop/pcr.vue

@@ -30,7 +30,7 @@
                             </template>
                             <template v-if="col.type==='input'">
                                 <span class="col-item">
-                                    <el-input v-if="!readonly" v-model="col.value" size="mini" style="width:120px" />
+                                    <el-input v-if="!readonly" v-model="col.value" size="mini" style="width:186px" />
                                     <template v-else>{{ col.value }}</template>
                                 </span>
                             </template>
@@ -82,6 +82,7 @@ export default {
             handler (val) {
                 if (val && val.length && this.isFirst) {
                     this.isFirst = false
+                    this.activeName = val[0].peiZhiId
                     this.tableList = val.map(item => ({
                         ...item,
                         lieBiaoShuJu: JSON.parse(item.lieBiaoShuJu)
@@ -89,6 +90,23 @@ export default {
                 }
             }
         },
+        'formData.xuanZeWangQi': {
+            async handler (val) {
+                if (val) {
+                    const sql = `select * from t_PCRjygzrzxqb where parent_id_='${val}' order by pei_zhi_id_`
+                    const { variables: { data = [] } = {}} = await this.$common.request('sql', sql)
+                    // console.log('data', data)
+                    const arr = data.map(item => ({
+                        quYuMing: item.qu_yu_ming_,
+                        lieBiaoShuJu: JSON.parse(item.lie_biao_shu_ju_),
+                        peiZhiId: item.pei_zhi_id_,
+                        bianZhiRen: item.bian_zhi_ren_,
+                        lieBiaoWenBen: item.lie_biao_wen_ben_
+                    }))
+                    this.tableList = arr
+                }
+            }
+        },
         tableList: {
             async handler (val) {
                 // console.log('tableList', val)
@@ -135,6 +153,7 @@ export default {
             let { variables: { data = [] } = {}} = await this.$common.request('sql', sql)
             if (!this.isFirst) return
             data = data.filter(item => item.lei_xing_ === this.formData.leiXing)
+            data.length > 0 && (this.activeName = data[0].id_)
             this.tableList = data.map(item => {
                 let t = []
                 if (item.lie_biao_shu_ju_) {

+ 1 - 1
src/views/platform/cat/type/manage.vue

@@ -225,7 +225,7 @@ export default {
             })
         },
         handleTreeAction (command, position, selection, data) {
-            if (data.sn === 0 && data.name === '文件分类') {
+            if (data?.sn === 0 && data?.name === '文件分类') {
                 const object = {
                     diDian: this.level,
                     buMen: '',

+ 2 - 1
src/views/platform/data/dataTemplate/list.vue

@@ -187,7 +187,8 @@ export default {
                 // 工具栏
                 toolbars: [
                     { key: 'import' },
-                    { key: 'export' }
+                    { key: 'export' },
+                    { key: 'remove', type: 'primary' }
                 ],
 
                 // 表格字段配置

+ 6 - 6
src/views/platform/examination/constants.js

@@ -120,12 +120,12 @@ export const statusOption = [
         label: '已发布',
         value: '已发布',
         type: 'primary'
-    },
-    {
-        label: '已结束',
-        value: '已结束',
-        type: 'success'
     }
+    // {
+    //     label: '已结束',
+    //     value: '已结束',
+    //     type: 'success'
+    // }
 ]
 
 const qualifiedType = [
@@ -157,7 +157,7 @@ export const basicColumn = [
 
 export const infoColumn = [
     { prop: 'questionCount', label: '题数', width: 65 },
-    { prop: 'duration', label: '考试时长', width: 85 },
+    { prop: 'duration', label: '考试时长', slotName: 'examTime', width: 85 },
     { prop: 'limitCount', label: '限考次数', width: 85 },
     { prop: 'limitDate', label: '限考时间', width: 120 },
     { prop: 'isRand', label: '是否随机', slotName: 'isRand', width: 65 },

+ 2 - 1
src/views/platform/examination/exam/edit.vue

@@ -874,7 +874,8 @@ export default {
                         bei_zhu_: item.bei_zhu_ || '',
                         zhuang_tai_: item.zhuang_tai_,
                         biao_qian_: item.biao_qian_ || '',
-                        nan_du_: item.nan_du_ || 0
+                        nan_du_: item.nan_du_ || 0,
+                        da_an_jie_xi_: item.da_an_jie_xi_ || ''
                     }))
                 }
                 await this.$common.request('add', addParams)

+ 4 - 1
src/views/platform/examination/exam/list.vue

@@ -40,6 +40,9 @@
             <template slot="randWay" slot-scope="{row}">
                 <div>{{ row.isRand==='1' ?['未知','题型','难度'][+row.randWay]:'/' }}</div>
             </template>
+            <template slot="examTime" slot-scope="{row}">
+                <div>{{ transformTime(row.duration) }}</div>
+            </template>
         </ibps-crud>
         <exam-edit
             v-if="showEditDialog"
@@ -288,7 +291,7 @@ export default {
                                 bankName: item.bankName,
                                 examinee: item.examinee,
                                 questionCount: item.isRand === '1' ? parseFloat(item.randTotal) : parseFloat(item.questionCount),
-                                duration: this.transformTime(item.duration),
+                                duration: item.duration,
                                 limitCount: item.limitCount,
                                 limitDate: item.limitDate,
                                 qualifiedRadio: item.qualifiedRadio,

+ 13 - 2
src/views/platform/examination/question/edit.vue

@@ -280,6 +280,16 @@
                     />
                 </el-form-item>
             </template>
+            <el-form-item label="答案解析:" prop="da_an_jie_xi_">
+                <el-input
+                    v-model="form.da_an_jie_xi_"
+                    type="textarea"
+                    :rows="3"
+                    :autosize="readonly"
+                    :disabled="readonly"
+                    placeholder="请输入题目答案解析"
+                />
+            </el-form-item>
             <el-form-item label="备注:" prop="bei_zhu_">
                 <el-input
                     v-model="form.bei_zhu_"
@@ -369,7 +379,8 @@ export default {
                 fen_zhi_: '',
                 bei_zhu_: '',
                 zhuang_tai_: '启用',
-                nan_du_: 0
+                nan_du_: 0,
+                da_an_jie_xi_: ''
             },
             questionTags: [],
             toolbars: [
@@ -504,7 +515,7 @@ export default {
             if (this.$utils.isEmpty(this.id)) {
                 return
             }
-            const sql = `select id_, chu_ti_ren_, bu_men_, chu_ti_shi_jian_, ti_gan_, ti_xing_, xuan_xiang_lei_xi, biao_qian_, da_an_, zheng_que_da_an_, ping_fen_fang_shi, ping_fen_ren_, fen_zhi_, zhuang_tai_, xuan_xiang_shu_, fu_tu_, bei_zhu_,nan_du_ from t_questions where id_ = '${this.id}'`
+            const sql = `select id_, chu_ti_ren_, bu_men_, chu_ti_shi_jian_, ti_gan_, ti_xing_, xuan_xiang_lei_xi, biao_qian_, da_an_, zheng_que_da_an_, ping_fen_fang_shi, ping_fen_ren_, fen_zhi_, zhuang_tai_, xuan_xiang_shu_, fu_tu_, bei_zhu_,nan_du_,da_an_jie_xi_ from t_questions where id_ = '${this.id}'`
             this.$common.request('sql', sql).then(res => {
                 const { data = [] } = res.variables || {}
                 if (!data.length) {

+ 62 - 13
src/views/platform/examination/questionBank/detail.vue

@@ -92,8 +92,19 @@
                         class="card"
                     >
                         <div class="stem">
-                            <span>{{ `【${qIndex + 1}】${q.stem}` }}</span>
-                            <el-tag type="primary" size="small">{{ `${q.questionScore}分` }}</el-tag>
+                            <div class="left">
+                                <span>{{ `【${qIndex + 1}】${q.stem}` }}</span>
+                                <el-tag type="primary" size="small">{{ `${q.questionScore}分` }}</el-tag>
+                            </div>
+                            <span v-if="q.rate>0">
+                                <el-rate
+                                    :value="q.rate"
+                                    show-text
+                                    :texts="texts"
+                                    :colors="colors"
+                                    disabled
+                                />
+                            </span>
                         </div>
                         <div v-if="q.img && q.img.length" class="img">
                             <ibps-image
@@ -148,22 +159,26 @@
                                 </div>
                             </div>
                             <div class="right">
-                                <div class="title">参考答案:</div>
+                                <div class="title">
+                                    <span>参考答案</span>
+                                </div>
                                 <div class="answer-content">
-                                    <el-radio-group v-if="q.questionType === '单选题'" :value="q.rightKey">
+                                    <span v-if="q.questionType === '单选题'">{{ q.rightKey || '' }}</span>
+                                    <!-- <el-radio-group v-if="q.questionType === '单选题'" :value="q.rightKey">
                                         <el-radio
                                             v-for="(o, i) in q.options"
                                             :key="`${index}${qIndex}${i}`"
                                             :label="o.label"
                                         >{{ `${o.label}.${o.value}` }}</el-radio>
-                                    </el-radio-group>
-                                    <el-checkbox-group v-else-if="q.questionType === '多选题'" :value="q.rightKey">
+                                    </el-radio-group> -->
+                                    <span v-else-if="q.questionType === '多选题'">{{ q.rightKey.join(';') || '' }}</span>
+                                    <!-- <el-checkbox-group v-else-if="q.questionType === '多选题'" :value="q.rightKey">
                                         <el-checkbox
                                             v-for="(o, i) in q.options"
                                             :key="`${index}${qIndex}${i}`"
                                             :label="o.label"
                                         >{{ `${o.label}.${o.value}` }}</el-checkbox>
-                                    </el-checkbox-group>
+                                    </el-checkbox-group> -->
                                     <el-radio-group v-else-if="q.questionType === '判断题'" :value="q.rightKey">
                                         <el-radio-button label="√">√</el-radio-button>
                                         <el-radio-button label="×">×</el-radio-button>
@@ -179,6 +194,10 @@
                                         />
                                     </template>
                                 </div>
+                                <div class="title" style="margin-top:20px">
+                                    <span>答案解析</span>
+                                </div>
+                                <div style="white-space: pre-wrap;" class="answer-content">{{ q.resolution || '无' }}</div>
                             </div>
                         </div>
                     </div>
@@ -265,6 +284,7 @@ export default {
         return {
             title: '考试详情',
             dialogVisible: this.visible,
+            showResolution: false,
             toolbars: [{ key: 'cancel', label: '退出' }],
             paperList: [],
             paperData: [],
@@ -277,7 +297,9 @@ export default {
                 { value: 'true', label: '正确' },
                 { value: 'noFinished', label: '未评分' }
             ],
-            paperStatus: 'all'
+            paperStatus: 'all',
+            texts: ['易', '偏易', '适中', '偏难', '难'],
+            colors: { 1: '#00FF00', 2: '#7FFF00', 3: '#FFFF00', 4: '#FFA500', 5: '#FF0000' }
         }
     },
     computed: {
@@ -324,6 +346,21 @@ export default {
         window.removeEventListener('keyup', this.handleKeyPress)
     },
     methods: {
+        changeResolution (index, qIndex) {
+            this.paperData.list[index].questions[qIndex].showResolution = !this.paperData.list[index].questions[qIndex].showResolution
+        },
+        changeAll () {
+            this.showResolution = !this.showResolution
+            this.paperList.forEach(item => {
+                item.list.forEach(i => {
+                    i.questions.forEach(ii => {
+                        ii.showResolution = this.showResolution
+                    })
+                })
+            })
+            const t = this.toolbars.find(item => item.key === 'change')
+            t.label = this.showResolution ? '查看答案' : '查看解析'
+        },
         // 获取题库数据
         async loadData () {
             if (!this.bankId) {
@@ -347,6 +384,9 @@ export default {
                 case 'cancel':
                     this.closeDialog()
                     break
+                case 'change':
+                    this.changeAll()
+                    break
                 default:
                     break
             }
@@ -363,7 +403,7 @@ export default {
         },
         getQuestionData () {
             const param = this.examId ? `and e.exam_id_ = '${this.examId}'` : 'and e.exam_id_ is null'
-            const sql = `select e.id_ as dataId, e.exam_id_ as examId, e.kao_shi_ren_ as examinee, e.bu_men_ as dept, e.zhuang_tai_ as status, e.bao_ming_shi_jian as applyTime, e.kai_shi_shi_jian_ as startTime, e.jie_shu_shi_jian_ as endTime, e.ti_ku_zong_fen_ as totalScore, e.de_fen_ as resultScore, ed.ti_mu_id_ as questionId, ed.ti_gan_ as stem, ed.ti_xing_ as questionType, ed.fen_zhi_ as questionScore, ed.fu_tu_ as img, ed.xuan_xiang_lei_xi as optionsType, ed.xuan_xiang_ as options, ed.can_kao_da_an_ as rightKey, ed.ping_fen_fang_shi as rateType, ed.ping_fen_ren_ as rater, ed.hui_da_ as answer, ed.ping_yue_shi_jian as rateTime, ed.de_fen_ as score, ed.jie_xi_ as analysis, q.ti_ku_ming_cheng_ as paperName, case when e.exam_id_ is not null then ex.da_biao_zhan_bi_ else q.da_biao_zhan_bi_ end as qualifiedRadio, case when e.exam_id_ is not null then ex.ji_fen_fang_shi_ else q.ji_fen_fang_shi_ end as scoringType, case when e.exam_id_ is not null then ex.kao_shi_ming_chen else '自主考核' end as examName, case when e.exam_id_ is not null then ex.xian_kao_shi_jian else '不限' end as limitDate from t_examination e left join t_examination_detail ed on e.id_ = ed.parent_id_ left join  t_question_bank q on e.ti_ku_id_ = q.id_ left join  t_exams ex on e.exam_id_ = ex.id_ where e.ti_ku_id_ = '${this.bankId}' ${param} and e.kao_shi_ren_ = '${this.examineeId}' and (e.zhuang_tai_ = '已完成' or e.zhuang_tai_ = '已交卷') order by field(ed.ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
+            const sql = `select e.id_ as dataId, e.exam_id_ as examId,ed.nan_du_+0 as rate,ed.da_an_jie_xi_ as resolution, e.kao_shi_ren_ as examinee, e.bu_men_ as dept, e.zhuang_tai_ as status, e.bao_ming_shi_jian as applyTime, e.kai_shi_shi_jian_ as startTime, e.jie_shu_shi_jian_ as endTime, e.ti_ku_zong_fen_ as totalScore, e.de_fen_ as resultScore, ed.ti_mu_id_ as questionId, ed.ti_gan_ as stem, ed.ti_xing_ as questionType, ed.fen_zhi_ as questionScore, ed.fu_tu_ as img, ed.xuan_xiang_lei_xi as optionsType, ed.xuan_xiang_ as options, ed.can_kao_da_an_ as rightKey, ed.ping_fen_fang_shi as rateType, ed.ping_fen_ren_ as rater, ed.hui_da_ as answer, ed.ping_yue_shi_jian as rateTime, ed.de_fen_ as score, ed.jie_xi_ as analysis, q.ti_ku_ming_cheng_ as paperName, case when e.exam_id_ is not null then ex.da_biao_zhan_bi_ else q.da_biao_zhan_bi_ end as qualifiedRadio, case when e.exam_id_ is not null then ex.ji_fen_fang_shi_ else q.ji_fen_fang_shi_ end as scoringType, case when e.exam_id_ is not null then ex.kao_shi_ming_chen else '自主考核' end as examName, case when e.exam_id_ is not null then ex.xian_kao_shi_jian else '不限' end as limitDate from t_examination e left join t_examination_detail ed on e.id_ = ed.parent_id_ left join  t_question_bank q on e.ti_ku_id_ = q.id_ left join  t_exams ex on e.exam_id_ = ex.id_ where e.ti_ku_id_ = '${this.bankId}' ${param} and e.kao_shi_ren_ = '${this.examineeId}' and (e.zhuang_tai_ = '已完成' or e.zhuang_tai_ = '已交卷') order by field(ed.ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
             return new Promise((resolve, reject) => {
                 this.$common.request('sql', sql).then(res => {
                     const { data = [] } = res.variables || {}
@@ -374,6 +414,7 @@ export default {
                     }
                     const result = []
                     data.map(item => {
+                        item.showResolution = false
                         // 数据转换
                         if (['单选题', '多选题'].includes(item.questionType)) {
                             item.options = JSON.parse(item.options)
@@ -575,10 +616,15 @@ export default {
                     .stem {
                         display: flex;
                         margin-bottom: 10px;
-                        align-items: flex-start;
-                        > span:first-child {
-                            line-height: 1.5;
-                            margin-right: 10px;
+                        justify-content: space-between;
+                        align-items: center;
+                        .left{
+                            display: flex;
+                            align-items: center;
+                             > span:first-child {
+                                line-height: 1.5;
+                                margin-right: 10px;
+                            }
                         }
                     }
                     .img {
@@ -597,6 +643,9 @@ export default {
                                 font-size: 16px;
                                 color: #01a39e;
                                 margin-bottom: 10px;
+                                display: flex;
+                                align-items: center;
+                                justify-content: space-between;
                                 .score {
                                     vertical-align: middle;
                                 }

+ 30 - 6
src/views/platform/examination/questionBank/edit.vue

@@ -601,7 +601,7 @@ export default {
                 return
             }
             const sql1 = `select id_, bian_zhi_ren_, bian_zhi_bu_men_, bian_zhi_shi_jian, ti_ku_ming_cheng_, ti_ku_fen_lei_, ti_ku_zhuang_tai_, shi_fou_gong_kai_, xian_kao_ci_shu_, ping_fen_ren_, miao_shu_, suo_shu_fan_wei_, kao_shi_shi_chang, da_biao_zhan_bi_ from t_question_bank where id_ = '${this.formId}'`
-            const sql2 = `select id_ as quesId, chu_ti_ren_ as creator, bu_men_ as createDept, chu_ti_shi_jian_ as createTime, xu_hao_ as sn, ti_gan_ as content, ti_xing_ as quesType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as answer, zheng_que_da_an_ as rightKey, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, fen_zhi_ as score, bei_zhu_ as note, xuan_xiang_shu_ as optionCount, biao_qian_ as quesTag, zhuang_tai_ as quesState,nan_du_ as questionLevel from t_questions where parent_id_ = '${this.formId}' order by chu_ti_shi_jian_ desc`
+            const sql2 = `select id_ as quesId, chu_ti_ren_ as creator, bu_men_ as createDept, chu_ti_shi_jian_ as createTime, xu_hao_ as sn, ti_gan_ as content, ti_xing_ as quesType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as answer, zheng_que_da_an_ as rightKey, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, fen_zhi_ as score, bei_zhu_ as note, xuan_xiang_shu_ as optionCount, biao_qian_ as quesTag, zhuang_tai_ as quesState,nan_du_ as questionLevel,da_an_jie_xi_ as resolution from t_questions where parent_id_ = '${this.formId}' order by chu_ti_shi_jian_ desc`
             Promise.all([this.$common.request('sql', sql1), this.$common.request('sql', sql2)]).then(([res1, res2]) => {
                 const { data: bankData = [] } = res1.variables || {}
                 const { data: questionData = [] } = res2.variables || {}
@@ -629,17 +629,40 @@ export default {
             })
         },
         addSelectQuestion () {
-            const sql = `select id_ as quesId, chu_ti_ren_ as creator, bu_men_ as createDept, chu_ti_shi_jian_ as createTime, xu_hao_ as sn, ti_gan_ as content, ti_xing_ as quesType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as answer, zheng_que_da_an_ as rightKey, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, fen_zhi_ as score, bei_zhu_ as note, xuan_xiang_shu_ as optionCount, biao_qian_ as quesTag, zhuang_tai_ as quesState,nan_du_ as questionLevel from t_questions where find_in_set(id_, '${this.quesIdList}')`
+            const sql = `select id_ as quesId, chu_ti_ren_ as creator, bu_men_ as createDept, chu_ti_shi_jian_ as createTime, xu_hao_ as sn, ti_gan_ as content, ti_xing_ as quesType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as answer, zheng_que_da_an_ as rightKey, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, fen_zhi_ as score, bei_zhu_ as note, xuan_xiang_shu_ as optionCount, biao_qian_ as quesTag, zhuang_tai_ as quesState,nan_du_ as questionLevel,da_an_jie_xi_ as resolution from t_questions where find_in_set(id_, '${this.quesIdList}')`
             this.$common.request('sql', sql).then(res => {
                 const { data = [] } = res.variables || {}
                 this.questionData = data.concat(this.questionData)
             })
         },
+        // 查询使用该题库的考试
+        async checkExistExam () {
+            if (this.formId) {
+                const sql = `select id_,kao_shi_ming_chen from t_exams where ti_ku_id_='${this.formId}' order by create_time_ desc`
+                const { variables: { data = [] } = {}} = await this.$common.request('sql', sql)
+                return data
+            }
+            return []
+        },
         handleSubmit () {
-            this.$refs.form.validate((valid) => {
+            this.$refs.form.validate(async (valid) => {
                 if (valid) {
-                    // 表单验证通过,提交表单
-                    this.submitForm()
+                    if (this.form.suo_shu_fan_wei_ === '组级' && !this.form.bian_zhi_bu_men_) {
+                        this.$message.warning('所属范围为组级,请选择对应的专业组!')
+                    } else {
+                        const examsList = await this.checkExistExam()
+                        if (examsList.length > 0) {
+                            this.$confirm(`当前题库存在正在进行中的“${examsList.length}场”考试,考试名称为:【${examsList.map(i => i.kao_shi_ming_chen).join(',')}】,考试中更改题库可能会影响考试数据结果,是否继续?`, '提示', {
+                                confirmButtonText: '继续',
+                                cancelButtonText: '取消',
+                                type: 'warning'
+                            }).then(() => {
+                                this.submitForm()
+                            }).catch(() => {})
+                        } else {
+                            this.submitForm()
+                        }
+                    }
                 } else {
                     ActionUtils.saveErrorMessage()
                 }
@@ -690,7 +713,8 @@ export default {
                 bei_zhu_: item.note || '',
                 zhuang_tai_: item.quesState,
                 biao_qian_: item.quesTag || '',
-                nan_du_: item.questionLevel || 0
+                nan_du_: item.questionLevel || 0,
+                da_an_jie_xi_: item.resolution || ''
             }))
             await this.$common.request('add', {
                 tableName: 't_questions',

+ 4 - 3
src/views/platform/examination/questionBank/test.vue

@@ -359,7 +359,7 @@ export default {
         },
         getQuestionData () {
             this.loading = true
-            const sql = `select id_ as questionId, ti_gan_ as stem, ti_xing_ as questionType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as options, xuan_xiang_shu_ as optionsLength, fen_zhi_ as score, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, zheng_que_da_an_ as rightKey,nan_du_ as questionLevel from t_questions where parent_id_ = '${this.bankId}' and zhuang_tai_ = '启用' order by field(ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
+            const sql = `select id_ as questionId, ti_gan_ as stem, ti_xing_ as questionType, fu_tu_ as img, xuan_xiang_lei_xi as optionType, da_an_ as options, xuan_xiang_shu_ as optionsLength, fen_zhi_ as score, ping_fen_fang_shi as rateType, ping_fen_ren_ as rater, zheng_que_da_an_ as rightKey,nan_du_ as questionLevel,da_an_jie_xi_ as resolution from t_questions where parent_id_ = '${this.bankId}' and zhuang_tai_ = '启用' order by field(ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
             return new Promise((resolve, reject) => {
                 this.$common.request('sql', sql).then(res => {
                     let { data = [] } = res.variables || {}
@@ -553,7 +553,8 @@ export default {
                     ping_yue_shi_jian: autoType ? time : '',
                     de_fen_: autoType ? this.getScore(item) : '',
                     jie_xi_: '',
-                    nan_du_: item.questionLevel || 0
+                    nan_du_: item.questionLevel || 0,
+                    da_an_jie_xi_: item.resolution || ''
                 })
             })
             return submitData
@@ -581,7 +582,7 @@ export default {
                     }
                 ]
             }
-            console.log(addParams, updateParams)
+            // console.log(addParams, updateParams)
             this.$common.request('add', addParams).then(() => {
                 this.$common.request('update', updateParams).then(() => {
                     this.$message.success('提交成功!')

+ 11 - 1
src/views/platform/file/attachment/list.vue

@@ -57,7 +57,7 @@
 
 <script>
 import { queryPageList, deleteFile } from '@/api/platform/file/attachment'
-import { downloadFile } from '@/business/platform/file/utils'
+import { downloadFile, downloadFileByZip } from '@/business/platform/file/utils'
 import ActionUtils from '@/utils/action'
 import FixHeight from '@/mixins/height'
 import IbpsUploader from '@/business/platform/file/uploader'
@@ -125,6 +125,11 @@ export default {
                         label: '上传',
                         icon: 'ibps-icon-upload'
                     },
+                    {
+                        key: 'downloadZip',
+                        label: '批量下载',
+                        icon: 'ibps-icon-download'
+                    },
                     {
                         key: 'remove'
                     }
@@ -295,6 +300,11 @@ export default {
                 case 'download': // 下载
                     this.handleDownload(data)
                     break
+                case 'downloadZip': // 批量下载
+                    ActionUtils.selectedMultiRecord(selection).then((id) => {
+                        downloadFileByZip(id)
+                    })
+                    break
                 case 'remove': // 删除
                     ActionUtils.removeRecord(selection).then((ids) => {
                         this.handleRemove(ids)

+ 2 - 1
src/views/platform/form/formDef/list.vue

@@ -158,7 +158,8 @@ export default {
                 // 工具栏
                 toolbars: [
                     { key: 'import' },
-                    { key: 'export' }
+                    { key: 'export' },
+                    { key: 'remove', type: 'primary' }
                 ],
 
                 // 表格字段配置

+ 211 - 203
src/views/platform/org/role/assign-resource.vue

@@ -1,46 +1,47 @@
 <template>
-  <el-dialog
-    :visible.sync="dialogVisible"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    append-to-body
-    :title="(type==='app'?'App':'')+'资源分配'"
-    top="5vh"
-    class="role-resource-dialog"
-    @open="loadData"
-    @close="closeDialog"
-  >
-    <!-- <el-select
-      v-model="systemId"
-      placeholder="请选择子系统"
-      style="width:100%;"
-      @change="changeSystem">
-      <el-option
-        v-for="item in subsystemList"
-        :key="item.id"
-        :label="item.name"
-        :value="item.id"
-      />
-    </el-select> -->
-    <tree
-      ref="tree"
-      v-loading="dialogLoading"
-      :check-strictly="strictly"
-      :width="width"
-      :height="height"
-      :element-loading-text="$t('common.loading')"
-      :data="treeData"
-      :default-checked-keys="checkedIds"
-      :first-check-node="firstCheck"
-      @check="checkData"
-    />
-    <div slot="footer" class="el-dialog--center">
-      <ibps-toolbar
-        :actions="toolbars"
-        @action-event="handleActionEvent"
-      />
-    </div>
-  </el-dialog>
+    <el-dialog
+        :visible.sync="dialogVisible"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        append-to-body
+        :title="(type==='app'?'App':'')+'资源分配'"
+        top="5vh"
+        class="role-resource-dialog"
+        @open="loadData"
+        @close="closeDialog"
+    >
+        <el-select
+            v-model="systemId"
+            placeholder="请选择子系统"
+            style="width:100%;"
+            @change="changeSystem"
+        >
+            <el-option
+                v-for="item in subsystemList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+            />
+        </el-select>
+        <tree
+            ref="tree"
+            v-loading="dialogLoading"
+            :check-strictly="strictly"
+            :width="width"
+            :height="height"
+            :element-loading-text="$t('common.loading')"
+            :data="treeData"
+            :default-checked-keys="checkedIds"
+            :first-check-node="firstCheck"
+            @check="checkData"
+        />
+        <div slot="footer" class="el-dialog--center">
+            <ibps-toolbar
+                :actions="toolbars"
+                @action-event="handleActionEvent"
+            />
+        </div>
+    </el-dialog>
 </template>
 <script>
 import { findRoleResTreeChecked as getTreeData, updateResource as save } from '@/api/platform/auth/resources'
@@ -51,175 +52,182 @@ import ActionUtils from '@/utils/action'
 import Tree from '../components/tree'
 
 export default {
-  components: {
-    Tree
-  },
-  props: {
-    visible: {
-      type: Boolean,
-      default: false
+    components: {
+        Tree
     },
-    id: String,
-    systemId: String,
-    type: String
-  },
-  data() {
-    return {
-      strictly: true,
-      firstCheck: true,
-      dialogLoading: false,
-      dialogVisible: false,
-      width: 600,
-      height: document.clientHeight,
-      // systemId: '',
-      // subsystemList: [],
-
-      treeData: [],
-      checkedIds: [],
-      toolbars: [
-        { key: 'save', label: '保存' },
-        { key: 'cancel' }
-      ]
-    }
-  },
-  watch: {
-    visible: {
-      handler: function(val, oldVal) {
-        this.dialogVisible = this.visible
-        this.height = document.body.clientHeight - 210
-      },
-      immediate: true
-    }
-  },
-  methods: {
-    handleActionEvent({ key }) {
-      switch (key) {
-        case 'save':
-          this.handleSave()
-          break
-        case 'cancel':
-          this.closeDialog()
-          break
-        default:
-          break
-      }
-    },
-    loadData() {
-      this.loadTreeData()
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        },
+        id: String,
+        systemId: String,
+        type: String
     },
-    // loadSubsystemData() {
-    //   findAllSubsystem().then(response => {
-    //     this.subsystemList = response.data
-    //     this.systemId = this.subsystemList && this.subsystemList.length > 0 ? this.subsystemList[0].id : ''
-    //     this.loadTreeData()
-    //   }).catch(() => {
-    //     // 异常
-    //   })
-    // },
-    // changeSystem(value) {
-    //   this.systemId = value
-    //   this.loadTreeData()
-    // },
-    // 获取tree数据
-    loadTreeData() {
-      this.dialogLoading = true
-      if (this.type === 'app') {
-        getAppTreeData({
-          // systemId: this.systemId,
-          roleId: this.id
-        }).then(response => {
-          const data = response.data
-          const checked = data.filter((d) => {
-            return d.checked === 'true'
-          })
-          this.checkedIds = checked.map((item) => { return item.id })
-          this.treeData = data
-          this.dialogLoading = false
-        }).catch(() => {
-        // 异常
-          this.dialogLoading = false
-        })
-      } else {
-        getTreeData({
-          systemId: this.systemId,
-          roleId: this.id
-        }).then(response => {
-          const data = response.data
-          const checked = data.filter((d) => {
-            return d.checked === 'true'
-          })
-          this.checkedIds = checked.map((item) => { return item.id })
-          this.treeData = data
-          this.dialogLoading = false
-        }).catch(() => {
-        // 异常
-          this.dialogLoading = false
-        })
-      }
+    data () {
+        const { isSuper } = this.$store.getters || {}
+        return {
+            strictly: true,
+            firstCheck: true,
+            dialogLoading: false,
+            dialogVisible: false,
+            width: 600,
+            height: document.clientHeight,
+            // systemId: '',
+            // subsystemList: [],
+
+            isSuper,
+            treeData: [],
+            checkedIds: [],
+            toolbars: [
+                { key: 'save', label: '保存' },
+                { key: 'cancel' }
+            ]
+        }
     },
-    // 保存数据
-    handleSave() {
-      const getCheckedKeys = this.$refs.tree ? this.$refs.tree.getCheckedKeys() : []
-      const getHalfCheckedNodes = this.$refs.tree ? this.$refs.tree.getHalfCheckedNodes() : []
-      getHalfCheckedNodes.forEach(halfChecked => {
-        if (halfChecked.id !== '0') {
-          getCheckedKeys.push(halfChecked.id)
+    watch: {
+        visible: {
+            handler: function (val, oldVal) {
+                this.dialogVisible = this.visible
+                this.height = document.body.clientHeight - 210
+            },
+            immediate: true
         }
-      })
-
-      const resIds = getCheckedKeys.join(',')
-      if (this.type === 'app') {
-        saveApp({
-          resIds: resIds,
-          roleId: this.id
-        })
-          .then(response => {
-            this.dialogLoading = false
-            ActionUtils.saveSuccessMessage(response.message, r => {
-              if (r) {
-                this.closeDialog()
-              }
+    },
+    methods: {
+        handleActionEvent ({ key }) {
+            switch (key) {
+                case 'save':
+                    this.handleSave()
+                    break
+                case 'cancel':
+                    this.closeDialog()
+                    break
+                default:
+                    break
+            }
+        },
+        loadData () {
+            this.loadTreeData()
+        },
+        // loadSubsystemData () {
+        //     findAllSubsystem().then(response => {
+        //         this.subsystemList = response.data
+        //         this.systemId = this.subsystemList && this.subsystemList.length > 0 ? this.subsystemList[0].id : ''
+        //         this.loadTreeData()
+        //     }).catch(() => {
+        //     // 异常
+        //     })
+        // },
+        // changeSystem (value) {
+        //     this.systemId = value
+        //     this.loadTreeData()
+        // },
+        // 获取tree数据
+        loadTreeData () {
+            this.dialogLoading = true
+            if (this.type === 'app') {
+                getAppTreeData({
+                    // systemId: this.systemId,
+                    roleId: this.id
+                }).then(response => {
+                    const data = response.data
+                    const checked = data.filter((d) => {
+                        return d.checked === 'true'
+                    })
+                    this.checkedIds = checked.map((item) => { return item.id })
+                    this.treeData = data
+                    this.dialogLoading = false
+                }).catch(() => {
+                    // 异常
+                    this.dialogLoading = false
+                })
+            } else {
+                getTreeData({
+                    systemId: this.systemId,
+                    roleId: this.id
+                }).then(response => {
+                    const data = response.data
+                    const checked = data.filter((d) => {
+                        return d.checked === 'true'
+                    })
+                    this.checkedIds = checked.map((item) => { return item.id })
+                    this.treeData = this.dealTreeData(data)
+                    this.dialogLoading = false
+                }).catch(() => {
+                    // 异常
+                    this.dialogLoading = false
+                })
+            }
+        },
+        // 非超级用户过滤不可购资源
+        dealTreeData (data) {
+            if (this.isSuper) {
+                return data
+            }
+            return data.filter((item) => {
+                return !item.tenantType === 'forbidden'
             })
-          })
-          .catch(() => {
-            this.dialogLoading = false
-          })
-      } else {
-        save({
-          resIds: resIds,
-          systemId: this.systemId,
-          roleId: this.id
-        })
-          .then(response => {
-            this.dialogLoading = false
-            ActionUtils.saveSuccessMessage(response.message, r => {
-              if (r) {
-                this.closeDialog()
-              }
+        },
+        // 保存数据
+        handleSave () {
+            const getCheckedKeys = this.$refs.tree ? this.$refs.tree.getCheckedKeys() : []
+            const getHalfCheckedNodes = this.$refs.tree ? this.$refs.tree.getHalfCheckedNodes() : []
+            getHalfCheckedNodes.forEach(halfChecked => {
+                if (halfChecked.id !== '0') {
+                    getCheckedKeys.push(halfChecked.id)
+                }
             })
-          })
-          .catch(() => {
-            this.dialogLoading = false
-          })
-      }
-    },
-    checkData() {
-      this.firstCheck = false
-      this.strictly = false
-    },
-    closeDialog() {
-      this.$emit('close', false)
-      this.strictly = true
-      this.firstCheck = true
+
+            const resIds = getCheckedKeys.join(',')
+            if (this.type === 'app') {
+                saveApp({
+                    resIds: resIds,
+                    roleId: this.id
+                }).then(response => {
+                    this.dialogLoading = false
+                    ActionUtils.saveSuccessMessage(response.message, r => {
+                        if (r) {
+                            this.closeDialog()
+                        }
+                    })
+                }).catch(() => {
+                    this.dialogLoading = false
+                })
+            } else {
+                save({
+                    resIds: resIds,
+                    systemId: this.systemId,
+                    roleId: this.id
+                }).then(response => {
+                    this.dialogLoading = false
+                    ActionUtils.saveSuccessMessage(response.message, r => {
+                        if (r) {
+                            this.closeDialog()
+                        }
+                    })
+                }).catch(() => {
+                    this.dialogLoading = false
+                })
+            }
+        },
+        checkData () {
+            this.firstCheck = false
+            this.strictly = false
+        },
+        closeDialog () {
+            this.$emit('close', false)
+            this.strictly = true
+            this.firstCheck = true
+        }
     }
-  }
 }
 </script>
 <style lang="scss">
-.role-resource-dialog{
-  .el-dialog__body{
-    height:  calc(100vh - 200px) !important;
-    padding: 0px;
-  }
-}
+    .role-resource-dialog{
+        .el-dialog__body{
+            height:  calc(100vh - 200px) !important;
+            padding: 0px;
+        }
+    }
 </style>

+ 4 - 1
src/views/platform/org/role/list.vue

@@ -152,7 +152,10 @@ export default {
                     }, {
                         key: 'assignResource',
                         label: '资源分配',
-                        icon: 'ibps-icon-dashboard'
+                        icon: 'ibps-icon-dashboard',
+                        hidden () {
+                            return !isSuper
+                        }
                     }, {
                         key: 'appAssignResource',
                         label: 'App资源分配',

Некоторые файлы не были показаны из-за большого количества измененных файлов