Newer
Older
safe_production_front / src / views / system / resource / editResource.vue
dutingting 23 days ago 11 KB 审批功能开发
<script lang="ts" setup name="SystemEditResource">
import type { Ref } from 'vue'
import { nextTick, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import type { ResourceInfo, ResourceTypeInfo } from './resource-interface'
import { addResource, getResourceTreeList, updateResource } from '@/api/system/resource'
import { toTreeList } from '@/utils/structure'
import { getDictByCode } from '@/api/system/dict'
import type { dictType } from '@/global'
import { delResource, getResourceList, getResourceTypeList } from '@/api/system/resource'
import { approvalAdd } from '@/api/system/user'
const emits = defineEmits(['closeRefresh'])
const useApproval = ref('') // 是否走审批

// 对话框类型:create,update
const dialogStatus = ref('create')
const dialogVisible = ref(false)
// 显示标题
const textMap: { [key: string]: string } = {
  update: '编辑',
  create: '新增',
  detail: '详情',
}
// 表单数据对象
const formData: Ref<ResourceInfo> = ref({
  name: '',
  id: '',
  url: '',
  code: '',
  pid: '',
  resourceType: '',
  bizType: '', // 业务类型
  num: 0,
  icon: '',
})

// 保存按钮加载状态
const btnLoading = ref(false)

// ---------------表单提交--------------------------------
// 表单对象
const dataFormRef = ref<FormInstance>()
// 校验规则
const rules = reactive<FormRules>({
  name: [{ required: true, message: '资源名称不可为空', trigger: ['blur', 'change'] }],
  url: [{ required: true, message: '资源路径不可为空', trigger: ['blur', 'change'] }],
  code: [{ required: true, message: '资源编码不可为空', trigger: ['blur', 'change'] }],
  pid: [{ required: true, message: '父资源必选', trigger: ['blur', 'change'] }],
  resourceType: [{ required: true, message: '资源类型必选', trigger: ['blur', 'change'] }],
  num: [{ required: true, message: '排序不可为空', trigger: 'blur' }, { pattern: /^\d+(\.\d+)?$/, trigger: ['blur', 'change'], message: '' }],
  bizType: [{ required: true, message: '业务类型必选', trigger: ['blur', 'change'] }],
})

// -----------------------------------------字典--------------------------------------------------------------
const bizTypeList = ref<dictType[]>([]) // 业务类型
const resourceTypeList: any = ref([]) // 获取资源类型列表
const getDict = async () => {
  // 业务类型
  getDictByCode('bizType').then((response) => {
    bizTypeList.value = response.data
  })

  getResourceTypeList().then((res) => {
    resourceTypeList.value = res.data
  })
}
getDict()

// -------------------------------------------------------------------------------------------

function submitForm() {
  if (dataFormRef) {
    dataFormRef.value?.validate((valid: boolean) => {
      if (valid) {
        if (dialogStatus.value === 'create') {
          createData()
        }
        else if (dialogStatus.value === 'update') {
          updateData()
        }
      }
    })
  }
}
// 新增数据
function createData() {
  btnLoading.value = true
  if (useApproval.value !== 'true') {
    addResource(formData.value).then((res) => {
      ElMessageBox.confirm(
        '新增成功,是否继续新增?',
        '提示',
        {
          confirmButtonText: '是',
          cancelButtonText: '否',
          type: 'info',
        },
      ).then(() => {
        resetForm()
        nextTick(() => {
          console.log('clearValidate')
          dataFormRef.value?.clearValidate(['name', 'url'])
          fetchResourceTree()
        })
      }).catch(() => {
        closeRefresh()
      })
      btnLoading.value = false
    }).catch((_) => {
      btnLoading.value = false
    })
  }
  else {
    const params = {
      jsonContext: formData.value, // 操作内容
      operationRemark: '资源新增', // 操作备注
      title: '资源新增', // 申请标题
      status: '0',
      operationType: 'resource_add',
      id: '',
    }
    approvalAdd(params).then(() => {
      ElMessage.success('审批提交成功,请耐心等待审批!')
      resetForm()
      nextTick(() => {
        console.log('clearValidate')
        dataFormRef.value?.clearValidate(['name', 'url'])
        btnLoading.value = false
        fetchResourceTree()
        closeRefresh()
      })
    }).catch(() => {
      ElMessage.warning('审批提交失败,请重新申请或联系管理员!')
      btnLoading.value = false
    })
  }
}

// 更新数据
function updateData() {
  if (useApproval.value !== 'true') {
    updateResource(formData.value).then((res) => {
      ElMessage.success('修改成功')
      fetchResourceTree()
      btnLoading.value = false
      closeRefresh()
    }).catch((_) => { // 异常情况,loading置为false
      btnLoading.value = false
    })
  }
  else {
    const params = {
      jsonContext: formData.value, // 操作内容
      operationRemark: '资源修改', // 操作备注
      title: '资源修改', // 申请标题
      status: '0',
      operationType: 'resource_update',
      id: '',
    }
    approvalAdd(params).then(() => {
      ElMessage.success('审批提交成功,请耐心等待审批!')
      closeRefresh()
    }).catch(() => {
      ElMessage.warning('审批提交失败,请重新申请或联系管理员!')
      btnLoading.value = false
    })
  }
}

// 重置表单
function resetForm() {
  formData.value = {
    name: '',
    id: '',
    url: '',
    code: '',
    pid: '',
    resourceType: '',
    bizType: '', // 业务类型
    num: 0,
    icon: '',
  }
  console.log('resetForm')
  nextTick(() => {
    dataFormRef.value?.clearValidate()
  })
}

// 树列表配置
const resourceTreeProps = {
  parent: 'pid',
  value: 'id',
  label: 'name',
  children: 'children',
}
const resourceTree: Ref<ResourceInfo[]> = ref([])
// 获取资源树列表
function fetchResourceTree() {
  getResourceTreeList().then((response) => {
    if (response.data) {
      resourceTree.value = toTreeList(response.data, '0', true)
    }
  })
}
//
const filterTree = (value: string, data: { name: string }) => data.name?.includes(value)

onBeforeMount(() => {
  fetchResourceTree()
})
// ----------初始化、关闭对话框相关-----------------
function initDialog(dialogstatus: string, row: ResourceInfo, useApprovalParam = '') {
  dialogStatus.value = dialogstatus
  useApproval.value = useApprovalParam
  dialogVisible.value = true
  btnLoading.value = false
  if (dialogstatus === 'create') {
    resetForm()
    nextTick(() => {
      dataFormRef.value?.clearValidate()
    })
  }
  else if (dialogstatus === 'update' || dialogstatus === 'detail') {
    formData.value = {
      id: row.id,
      name: row.name,
      url: row.url,
      code: row.code,
      pid: row.pid,
      resourceType: row.resourceType,
      bizType: row.bizType, // 业务类型
      num: row.num,
      icon: row.icon,
    }

    if (dialogstatus === 'detail') {
      getResourceTypeList().then((res) => {
        resourceTypeList.value = res.data
      })
    }
  }
}

// 关闭并刷新
function closeRefresh() {
  dialogVisible.value = false
  resetForm()
  emits('closeRefresh')
}
// 关闭弹窗
function dialogClose() {
  dialogVisible.value = false
  resetForm()
}

// ----------------------- 以下是暴露的方法内容 ----------------------------
defineExpose({ initDialog })
</script>

<template>
  <el-dialog
    v-model="dialogVisible"
    :title="textMap[dialogStatus]"
    width="50%"
    :before-close="dialogClose"
    append-to-body
    :open-delay="0"
    :close-on-click-modal="false"
  >
    <el-form
      ref="dataFormRef" :model="formData" :rules="rules" label-position="left" label-width="80px" class="form-container"
      size="default" @submit.prevent
    >
      <el-row :gutter="10">
        <el-col :span="12" class="grid-cell">
          <el-form-item label="资源名称" prop="name" class="required">
            <el-input v-model="formData.name" :disabled="dialogStatus === 'detail'" type="text" placeholder="必填" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="资源路径" prop="url" class="required">
            <el-input v-model="formData.url" :disabled="dialogStatus === 'detail'" type="text" placeholder="必填" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="资源编码" prop="code" class="required">
            <el-input v-model="formData.code" :disabled="dialogStatus === 'detail'" type="text" placeholder="必填" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="父资源" prop="pid" class="required">
            <el-tree-select
              v-model="formData.pid"
              :data="resourceTree"
              node-key="id"
              :filter-node-method="filterTree"
              :props="resourceTreeProps"
              :expand-on-click-node="false"
              :render-after-expand="false"
              check-strictly
              check-on-click-node
              filterable
              class="full-width-input"
              :disabled="dialogStatus === 'detail'"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="资源类型" prop="resourceType" class="required">
            <el-select v-model="formData.resourceType" :disabled="dialogStatus === 'detail'" class="full-width-input" clearable placeholder="请选择">
              <el-option v-for="(item, index) in resourceTypeList" :key="index" :label="item.name" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="业务类型" prop="bizType" class="required">
            <el-select v-model="formData.bizType" :disabled="dialogStatus === 'detail'" class="full-width-input" clearable placeholder="请选择">
              <el-option v-for="(item, index) in bizTypeList" :key="index" :label="item.name" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="排序" prop="num" class="required">
            <el-input-number
              v-model="formData.num" class="full-width-input" controls-position="right"
              :min="0" :max="999" :precision="0" :step="1" :disabled="dialogStatus === 'detail'"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="grid-cell">
          <el-form-item label="图标" prop="icon">
            <el-input v-model="formData.icon" :disabled="dialogStatus === 'detail'" type="text" placeholder="非必填" clearable />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button v-if="dialogStatus !== 'detail'" :loading="btnLoading" type="primary" @click="submitForm">
          保存
        </el-button>
        <el-button @click="dialogClose">
          取消
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.form-container {
  width: 100%;

  .full-width-input {
    width: 100%;
  }
}
</style>