|
@@ -0,0 +1,388 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <PagingTable url="/form/base" :where="where" ref="table">
|
|
|
|
|
+ <template #filter>
|
|
|
|
|
+ <ElButton :icon="Plus" @click="onEdit()">添加</ElButton>
|
|
|
|
|
+ <ElButton :icon="Refresh" @click="table.refresh()"></ElButton>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <ElTableColumn prop="id" label="#" width="80" />
|
|
|
|
|
+ <ElTableColumn prop="name" label="问卷名称" />
|
|
|
|
|
+ <ElTableColumn prop="remark" label="备注" />
|
|
|
|
|
+ <ElTableColumn prop="orgId" label="企业ID" />
|
|
|
|
|
+ <ElTableColumn prop="used" label="是否启用">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <!-- {{ row.used ? '启用' : '禁用' }} -->
|
|
|
|
|
+ <el-switch v-model="row.used" disabled />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElTableColumn>
|
|
|
|
|
+ <ElTableColumn prop="createdAt" label="创建时间" :formatter="timeFormatter" width="150" />
|
|
|
|
|
+ <ElTableColumn label="操作" align="center" width="200">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <ElButton @click="onEdit(row)">编辑</ElButton>
|
|
|
|
|
+ <ElButton @click="showFiles(row)">表单</ElButton>
|
|
|
|
|
+ <ElButton @click="deleteRow(row)" type="danger">删除</ElButton>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElTableColumn>
|
|
|
|
|
+ </PagingTable>
|
|
|
|
|
+ <EditDialog v-model="showEditDialog" :model="model" :rules="rules" :on-submit="submit" @success="table.refresh()">
|
|
|
|
|
+ <ElFormItem prop="name" label="名称">
|
|
|
|
|
+ <ElInput v-model="model.name" placeholder="请输入名称" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="remark" label="备注">
|
|
|
|
|
+ <ElInput v-model="model.remark" placeholder="请输入备注" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="orgId" label="企业ID" v-if="role === 'admin'">
|
|
|
|
|
+ <ElInputNumber :controls="false" v-model="model.orgId" placeholder="请输入企业ID" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="used" label="启用">
|
|
|
|
|
+ <el-switch v-model="model.used" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ </EditDialog>
|
|
|
|
|
+
|
|
|
|
|
+ <ElDialog v-model="showFileDialog" :title="selectedBase?.name" width="80%">
|
|
|
|
|
+ <PagingTable url="/form/fileds" :where="{ formId: selectedBase?.id }" :order="{ createdAt: 'ASC' }" ref="fileTable">
|
|
|
|
|
+ <template #filter>
|
|
|
|
|
+ <ElButton :icon="Plus" @click="onFiledEdit()">添加</ElButton>
|
|
|
|
|
+ <ElButton :icon="Refresh" @click="fileTable.refresh()"></ElButton>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <ElTableColumn prop="id" label="#" width="80" />
|
|
|
|
|
+ <ElTableColumn prop="name" label="字段名" />
|
|
|
|
|
+ <ElTableColumn prop="remark" label="备注" />
|
|
|
|
|
+ <ElTableColumn prop="placeholder" label="输入框占位" />
|
|
|
|
|
+ <ElTableColumn prop="formType" label="输入框类型">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ {{ getLabel(row.formType, formTypes) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElTableColumn>
|
|
|
|
|
+ <ElTableColumn prop="required" label="是否必填">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-switch v-model="row.required" disabled />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElTableColumn>
|
|
|
|
|
+ <ElTableColumn prop="optionsValue" width="220" show-overflow-tooltip label="选项值" />
|
|
|
|
|
+ <ElTableColumn prop="createdAt" label="创建时间" :formatter="timeFormatter" width="150" />
|
|
|
|
|
+ <ElTableColumn label="操作" align="center" width="180" fixed="right">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <ElButton @click="onFiledEdit(row)" type="primary">编辑</ElButton>
|
|
|
|
|
+ <ElButton @click="deleteFiled(row)" type="danger">删除</ElButton>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElTableColumn>
|
|
|
|
|
+ </PagingTable>
|
|
|
|
|
+ </ElDialog>
|
|
|
|
|
+
|
|
|
|
|
+ <EditDialog
|
|
|
|
|
+ v-model="showFieldDialog"
|
|
|
|
|
+ :model="filedModel"
|
|
|
|
|
+ :rules="filedRules"
|
|
|
|
|
+ :on-submit="submitFiledModel"
|
|
|
|
|
+ @success="fileTable.refresh()"
|
|
|
|
|
+ label-width="120px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <ElFormItem prop="name" label="名称">
|
|
|
|
|
+ <ElInput v-model="filedModel.name" placeholder="请输入名称" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="remark" label="备注">
|
|
|
|
|
+ <ElInput v-model="filedModel.remark" placeholder="请输入备注" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="placeholder" label="占位">
|
|
|
|
|
+ <ElInput v-model="filedModel.placeholder" placeholder="请输入输入框占位" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="required" label="">
|
|
|
|
|
+ <el-checkbox v-model="filedModel.required">必填</el-checkbox>
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="formType" label="表单类型">
|
|
|
|
|
+ <el-select v-model="filedModel.formType" clearable placeholder="请选择表单类型">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in formTypes"
|
|
|
|
|
+ :label="item.label"
|
|
|
|
|
+ :value="item.value"
|
|
|
|
|
+ :key="item.value"
|
|
|
|
|
+ ></el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+
|
|
|
|
|
+ <ElFormItem
|
|
|
|
|
+ prop="optionsValue"
|
|
|
|
|
+ label="选项值"
|
|
|
|
|
+ v-if="
|
|
|
|
|
+ filedModel.formType === 'select' ||
|
|
|
|
|
+ filedModel.formType === 'multiSelect' ||
|
|
|
|
|
+ filedModel.formType === 'radio' ||
|
|
|
|
|
+ filedModel.formType === 'checkbox'
|
|
|
|
|
+ "
|
|
|
|
|
+ >
|
|
|
|
|
+ <ElInput v-model="filedModel.optionsValue" placeholder="选项值">
|
|
|
|
|
+ <template #append>
|
|
|
|
|
+ <el-button type="text" @click="editOptions(filedModel)">编辑 </el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ElInput>
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="validate" label="">
|
|
|
|
|
+ <el-checkbox v-model="filedModel.validate">验证</el-checkbox>
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <template v-if="filedModel.validate">
|
|
|
|
|
+ <ElFormItem prop="validatorType" label="验证类型">
|
|
|
|
|
+ <el-select v-model="filedModel.validatorType" clearable placeholder="请选择验证类型">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in validatorTypes"
|
|
|
|
|
+ :label="item.label"
|
|
|
|
|
+ :value="item.value"
|
|
|
|
|
+ :key="item.value"
|
|
|
|
|
+ ></el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="minLength" label="最短长度">
|
|
|
|
|
+ <ElInput v-model="filedModel.minLength" placeholder="请输入最短长度" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="maxLength" label="最大长度">
|
|
|
|
|
+ <ElInput v-model="filedModel.maxLength" placeholder="请输入最大长度" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="min" label="最小值">
|
|
|
|
|
+ <ElInput v-model="filedModel.min" placeholder="请输入最小值" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ <ElFormItem prop="max" label="最大值">
|
|
|
|
|
+ <ElInput v-model="filedModel.max" placeholder="请输入最大值" />
|
|
|
|
|
+ </ElFormItem>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- <ElTableColumn prop="formType" label="表单类型" />
|
|
|
|
|
+ <ElTableColumn prop="required" label="必填" />
|
|
|
|
|
+ <ElTableColumn prop="validate" label="表单验证" />
|
|
|
|
|
+ <ElTableColumn prop="minLength" label="最短长度" />
|
|
|
|
|
+ <ElTableColumn prop="maxLength" label="最大长度" />
|
|
|
|
|
+ <ElTableColumn prop="min" label="最小值" />
|
|
|
|
|
+ <ElTableColumn prop="max" label="最大值" />
|
|
|
|
|
+ <ElTableColumn prop="validatorType" label="验证类型" /> -->
|
|
|
|
|
+ </EditDialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog title="编辑选项" v-model="showGenOptionsDialog" width="500px">
|
|
|
|
|
+ <el-table :data="options">
|
|
|
|
|
+ <el-table-column label="名称" prop="label">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-input v-model="row.label"></el-input>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="值" prop="value">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-input v-model="row.value"></el-input>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="类型">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-select v-model="row.type">
|
|
|
|
|
+ <el-option label="字符串" value="string"></el-option>
|
|
|
|
|
+ <el-option label="数字" value="number"></el-option>
|
|
|
|
|
+ <el-option label="布尔" value="boolean"></el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column>
|
|
|
|
|
+ <template #default="{ $index }">
|
|
|
|
|
+ <el-button @click="delOptions($index)" type="text">删除</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ <el-button @click="addOptions" type="text" icon="el-icon-plus">添加</el-button>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <span class="dialog-footer">
|
|
|
|
|
+ <el-button @click="showGenOptionsDialog = false">取 消</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="confirmOptions">确 定</el-button>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, computed, nextTick } from 'vue'
|
|
|
|
|
+import PagingTable from '@/components/PagingTable.vue'
|
|
|
|
|
+import { useEnumFormatter, useTimeFormatter } from '@/utils/formatter'
|
|
|
|
|
+import { Plus, Refresh } from '@vicons/tabler'
|
|
|
|
|
+import EditDialog from '@/components/EditDialog.vue'
|
|
|
|
|
+import { setupEditDialog } from '@/utils/editDialog'
|
|
|
|
|
+import { http } from '@/plugins/http'
|
|
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
+import { useClipboard } from '@vueuse/core'
|
|
|
|
|
+import { storeToRefs } from 'pinia'
|
|
|
|
|
+import { useUserStore } from '@/stores/user'
|
|
|
|
|
+import { FileStatus } from '@/enums'
|
|
|
|
|
+import { useFileDialog } from '@vueuse/core'
|
|
|
|
|
+
|
|
|
|
|
+const { user } = storeToRefs(useUserStore())
|
|
|
|
|
+const role = computed(() => user.value?.roles[0])
|
|
|
|
|
+const where = computed(() => {
|
|
|
|
|
+ if (role.value === 'admin') return {}
|
|
|
|
|
+ return {
|
|
|
|
|
+ orgId: user.value.orgId
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+const timeFormatter = useTimeFormatter()
|
|
|
|
|
+const table = ref(null)
|
|
|
|
|
+const model = ref({
|
|
|
|
|
+ used: false
|
|
|
|
|
+})
|
|
|
|
|
+const rules = {
|
|
|
|
|
+ name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
|
|
|
|
+ // remark: [{ required: true, message: '请输入备注', trigger: 'blur' }],
|
|
|
|
|
+ orgId: [{ required: true, message: '请输入企业ID', trigger: 'blur' }]
|
|
|
|
|
+}
|
|
|
|
|
+const { showEditDialog, onEdit } = setupEditDialog(model)
|
|
|
|
|
+async function submit() {
|
|
|
|
|
+ if (!model.value.orgId) {
|
|
|
|
|
+ model.value.orgId = user.value.orgId
|
|
|
|
|
+ }
|
|
|
|
|
+ await http.put(model.value.id ? `/form/base/${model.value.id}` : '/form/base', model.value)
|
|
|
|
|
+ ElMessage.success('保存成功')
|
|
|
|
|
+}
|
|
|
|
|
+async function deleteRow(row) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await ElMessageBox.confirm('此操作将永久删除数据, 是否继续?', '提示', {
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ })
|
|
|
|
|
+ await http.delete(`/form/base/${row.id}`)
|
|
|
|
|
+ ElMessage.success('删除成功')
|
|
|
|
|
+ table.value.refresh()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ if ('cancel' !== error) ElMessage.error(error.message)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+const selectedBase = ref(null)
|
|
|
|
|
+const fileTable = ref(null)
|
|
|
|
|
+function showFiles(row) {
|
|
|
|
|
+ selectedBase.value = row
|
|
|
|
|
+ showFileDialog.value = true
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ fileTable.value.refresh()
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+const showFileDialog = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const fieldTypes = ['char', 'varchar', 'int', 'bit', 'text', 'timestamp', 'datetime', 'decimal', 'float', 'vue']
|
|
|
|
|
+const searchMethods = ['=', '!=', '>', '>=', '<', '<=', 'between', 'like', 'left like', 'right like']
|
|
|
|
|
+const formTypes = [
|
|
|
|
|
+ { label: '单行文本', value: 'singleLineText' },
|
|
|
|
|
+ { label: '数字', value: 'number' },
|
|
|
|
|
+ { label: '日期选择', value: 'date' },
|
|
|
|
|
+ { label: '日期时间选择', value: 'datetime' },
|
|
|
|
|
+ { label: '登录名', value: 'loginName' },
|
|
|
|
|
+ { label: '当前时间', value: 'currentTime' },
|
|
|
|
|
+ { label: '当前日期', value: 'currentDate' },
|
|
|
|
|
+ { label: '单选框', value: 'radio' },
|
|
|
|
|
+ { label: '单选下拉框', value: 'select' },
|
|
|
|
|
+ { label: '多选框', value: 'checkbox' },
|
|
|
|
|
+ { label: '多选下拉框', value: 'multiSelect' },
|
|
|
|
|
+ { label: '单图上传', value: 'singleImage' },
|
|
|
|
|
+ { label: '多图上传', value: 'multiImage' },
|
|
|
|
|
+ { label: '文件上传', value: 'fileUpload' },
|
|
|
|
|
+ { label: '树形选择', value: 'tree' },
|
|
|
|
|
+ { label: '开关', value: 'switch' },
|
|
|
|
|
+ { label: '多行文本', value: 'textarea' },
|
|
|
|
|
+ { label: '富文本', value: 'richText' }
|
|
|
|
|
+]
|
|
|
|
|
+const validatorTypes = [
|
|
|
|
|
+ { label: '英文', value: 'english' },
|
|
|
|
|
+ { label: '数字', value: 'number' },
|
|
|
|
|
+ { label: '手机', value: 'phone' },
|
|
|
|
|
+ { label: '网址', value: 'url' },
|
|
|
|
|
+ { label: '电子邮件', value: 'email' },
|
|
|
|
|
+ { label: '身份证', value: 'id' }
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+function getLabel(val = '', list = []) {
|
|
|
|
|
+ console.log(val)
|
|
|
|
|
+ console.log(list)
|
|
|
|
|
+ let info = list.find((item) => {
|
|
|
|
|
+ return item.value === val
|
|
|
|
|
+ })
|
|
|
|
|
+ console.log(info)
|
|
|
|
|
+ return info ? info.label : ''
|
|
|
|
|
+}
|
|
|
|
|
+const filedRules = {
|
|
|
|
|
+ name: [
|
|
|
|
|
+ { required: true, message: '请填写表名', trigger: 'blur' },
|
|
|
|
|
+ {
|
|
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ if (/^[\u4e00-\u9fa5a-zA-Z0-9_]*$/.test(value)) {
|
|
|
|
|
+ callback()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback(new Error('表名不正确'))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ trigger: 'blur'
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ formType: [
|
|
|
|
|
+ {
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '请选择表单类型',
|
|
|
|
|
+ trigger: 'blur'
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const filedModel = ref({
|
|
|
|
|
+ apiFlag: 'singleLineText',
|
|
|
|
|
+ optionsValue: ''
|
|
|
|
|
+})
|
|
|
|
|
+const { showEditDialog: showFieldDialog, onEdit: onFiledEdit } = setupEditDialog(filedModel)
|
|
|
|
|
+async function submitFiledModel() {
|
|
|
|
|
+ if (!filedModel.value.formId) {
|
|
|
|
|
+ filedModel.value.formId = selectedBase.value.id
|
|
|
|
|
+ }
|
|
|
|
|
+ await http.put(
|
|
|
|
|
+ filedModel.value.id ? `/form/updateFiled/${filedModel.value.id}` : '/form/createFiled',
|
|
|
|
|
+ filedModel.value
|
|
|
|
|
+ )
|
|
|
|
|
+ ElMessage.success('保存成功')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const tempRow = ref({})
|
|
|
|
|
+
|
|
|
|
|
+const { showEditDialog: showGenOptionsDialog, onEdit: editOptions } = setupEditDialog(tempRow)
|
|
|
|
|
+const options = ref([
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ type: 'string'
|
|
|
|
|
+ }
|
|
|
|
|
+])
|
|
|
|
|
+
|
|
|
|
|
+function addOptions() {
|
|
|
|
|
+ options.value.push({
|
|
|
|
|
+ label: '',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ type: 'string'
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function confirmOptions() {
|
|
|
|
|
+ let arr = []
|
|
|
|
|
+ for (let i = 0; i < options.value.length; i++) {
|
|
|
|
|
+ if (!options.value[i].label || !options.value[i].value) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let label = options.value[i].label
|
|
|
|
|
+ let value
|
|
|
|
|
+ switch (options.value[i].type) {
|
|
|
|
|
+ case 'string':
|
|
|
|
|
+ value = options.value[i].value.toString()
|
|
|
|
|
+ break
|
|
|
|
|
+ case 'number':
|
|
|
|
|
+ value = Number(options.value[i].value)
|
|
|
|
|
+ break
|
|
|
|
|
+ case 'boolean':
|
|
|
|
|
+ value = 'false' !== options.value[i].value
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ arr.push({
|
|
|
|
|
+ label: label,
|
|
|
|
|
+ value: value
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ filedModel.value.optionsValue = JSON.stringify(arr)
|
|
|
|
|
+ showGenOptionsDialog.value = false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function delOptions(index) {
|
|
|
|
|
+ options.value.splice(index, 1)
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|