#
zhou zhou
1 天以前 4259deb19122a4807d50c99ed4a95405ebe4a47c
rsf-design/src/views/manager/task/modules/task-flow-step-dialog.vue
@@ -8,13 +8,27 @@
    @update:model-value="emit('update:visible', $event)"
  >
    <div class="flex flex-col gap-4">
      <div class="rounded-xl border border-[var(--el-border-color-lighter)] bg-[var(--el-fill-color-blank)] px-4 py-3">
        <div class="text-sm text-[var(--art-gray-500)]">{{ t('pages.task.flowStepDialog.currentTask') }}</div>
        <div class="mt-1 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-[var(--art-gray-900)]">
      <div
        class="rounded-xl border border-[var(--el-border-color-lighter)] bg-[var(--el-fill-color-blank)] px-4 py-3"
      >
        <div class="text-sm text-[var(--art-gray-500)]">{{
          t('pages.task.flowStepDialog.currentTask')
        }}</div>
        <div
          class="mt-1 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-[var(--art-gray-900)]"
        >
          <span>{{ t('pages.task.detail.taskCode') }}:{{ taskRow?.taskCode || '--' }}</span>
          <span>{{ t('pages.task.detail.taskStatus') }}:{{ taskRow?.taskStatusLabel || '--' }}</span>
          <span
            >{{ t('pages.task.detail.taskStatus') }}:{{ taskRow?.taskStatusLabel || '--' }}</span
          >
          <span>{{ t('pages.task.detail.taskType') }}:{{ taskRow?.taskTypeLabel || '--' }}</span>
        </div>
      </div>
      <div class="flex items-center justify-end">
        <ElButton v-auth="'add'" type="primary" plain @click="handleOpenCreate">
          {{ t('pages.task.flowStepDialog.create') }}
        </ElButton>
      </div>
      <ArtTable
@@ -26,14 +40,87 @@
        @pagination:current-change="handleCurrentChange"
      />
    </div>
    <ElDialog
      :model-value="editorVisible"
      :title="editorTitle"
      width="560px"
      append-to-body
      destroy-on-close
      @update:model-value="handleEditorVisibleChange"
    >
      <ElForm
        ref="formRef"
        :model="formData"
        :rules="formRules"
        label-width="96px"
        label-position="right"
      >
        <ElFormItem :label="t('pages.task.flowStepDialog.form.taskNo')" prop="taskNo">
          <ElInput v-model="formData.taskNo" disabled />
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.stepOrder')" prop="stepOrder">
          <ElInputNumber
            v-model="formData.stepOrder"
            class="w-full"
            :min="0"
            controls-position="right"
          />
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.stepCode')" prop="stepCode">
          <ElInput v-model.trim="formData.stepCode" />
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.stepName')" prop="stepName">
          <ElInput v-model.trim="formData.stepName" />
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.stepType')" prop="stepType">
          <ElInput v-model.trim="formData.stepType" />
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.status')" prop="status">
          <ElSelect v-model="formData.status" class="w-full">
            <ElOption
              v-for="item in statusOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem :label="t('pages.task.flowStepDialog.form.executeResult')" prop="executeResult">
          <ElInput
            v-model.trim="formData.executeResult"
            type="textarea"
            :rows="3"
            :placeholder="t('pages.task.flowStepDialog.form.executeResultPlaceholder')"
          />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <div class="flex justify-end gap-3">
          <ElButton @click="handleEditorVisibleChange(false)">{{ t('common.cancel') }}</ElButton>
          <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">
            {{ t('common.actions.save') }}
          </ElButton>
        </div>
      </template>
    </ElDialog>
  </ElDialog>
</template>
<script setup>
  import { computed, reactive, ref, watch } from 'vue'
  import { ElMessage, ElMessageBox } from 'element-plus'
  import { computed, h, reactive, ref, watch } from 'vue'
  import { useI18n } from 'vue-i18n'
  import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
  import { fetchFlowStepInstancePage } from '@/api/flow-step-instance'
  import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue'
  import {
    fetchFlowStepInstancePage,
    fetchJumpCurrentFlowStepInstance,
    fetchRemoveFlowStepInstance,
    fetchSaveFlowStepInstance,
    fetchUpdateFlowStepInstance
  } from '@/api/flow-step-instance'
  import { normalizeFlowStepInstanceRow } from '@/views/system/flow-step-instance/flowStepInstancePage.helpers'
  const props = defineProps({
@@ -50,13 +137,72 @@
  const emit = defineEmits(['update:visible'])
  const { t } = useI18n()
  const formRef = ref()
  const loading = ref(false)
  const rows = ref([])
  const editorVisible = ref(false)
  const submitLoading = ref(false)
  const editingId = ref(null)
  const pagination = reactive({
    current: 1,
    size: 20,
    total: 0
  })
  const formData = reactive(createFormState())
  const statusOptions = computed(() => [
    { value: 0, label: t('pages.task.flowStepDialog.statusOptions.0') },
    { value: 1, label: t('pages.task.flowStepDialog.statusOptions.1') },
    { value: 2, label: t('pages.task.flowStepDialog.statusOptions.2') },
    { value: 3, label: t('pages.task.flowStepDialog.statusOptions.3') },
    { value: 4, label: t('pages.task.flowStepDialog.statusOptions.4') },
    { value: 5, label: t('pages.task.flowStepDialog.statusOptions.5') },
    { value: 6, label: t('pages.task.flowStepDialog.statusOptions.6') }
  ])
  const formRules = computed(() => ({
    stepOrder: [
      {
        required: true,
        message: t('pages.task.flowStepDialog.validation.stepOrder'),
        trigger: 'blur'
      }
    ],
    stepCode: [
      {
        required: true,
        message: t('pages.task.flowStepDialog.validation.stepCode'),
        trigger: 'blur'
      }
    ],
    stepName: [
      {
        required: true,
        message: t('pages.task.flowStepDialog.validation.stepName'),
        trigger: 'blur'
      }
    ],
    stepType: [
      {
        required: true,
        message: t('pages.task.flowStepDialog.validation.stepType'),
        trigger: 'blur'
      }
    ],
    status: [
      {
        required: true,
        message: t('pages.task.flowStepDialog.validation.status'),
        trigger: 'change'
      }
    ]
  }))
  const editorTitle = computed(() =>
    editingId.value
      ? t('pages.task.flowStepDialog.editTitle')
      : t('pages.task.flowStepDialog.createTitle')
  )
  const columns = computed(() => [
    {
@@ -112,8 +258,61 @@
      label: t('pages.task.flowStepDialog.endTime'),
      minWidth: 180,
      showOverflowTooltip: true
    },
    {
      prop: 'operation',
      label: t('table.operation'),
      width: 120,
      align: 'center',
      fixed: 'right',
      formatter: (row) =>
        h(ArtButtonMore, {
          list: getActionList(row),
          onClick: (item) => handleActionClick(item, row)
        })
    }
  ])
  function createFormState() {
    return {
      id: '',
      taskNo: '',
      stepOrder: 0,
      stepCode: '',
      stepName: '',
      stepType: '',
      status: 0,
      executeResult: ''
    }
  }
  function resetFormState(seed = {}) {
    Object.assign(formData, createFormState(), seed)
  }
  function getActionList() {
    return [
      {
        key: 'edit',
        label: t('common.actions.edit'),
        icon: 'ri:pencil-line',
        auth: 'update'
      },
      {
        key: 'jumpCurrent',
        label: t('pages.task.flowStepDialog.jumpCurrent'),
        icon: 'ri:send-plane-line',
        auth: 'update'
      },
      {
        key: 'delete',
        label: t('common.actions.delete'),
        icon: 'ri:delete-bin-5-line',
        color: '#f56c6c',
        auth: 'delete'
      }
    ]
  }
  function updatePaginationState(response) {
    pagination.total = Number(response?.total || 0)
@@ -162,15 +361,141 @@
    void loadRows()
  }
  function handleOpenCreate() {
    editingId.value = null
    resetFormState({
      taskNo: props.taskRow?.taskCode || '',
      status: 0
    })
    editorVisible.value = true
  }
  function handleOpenEdit(row) {
    editingId.value = row.id
    resetFormState({
      ...row,
      id: row.id,
      taskNo: row.taskNo || props.taskRow?.taskCode || '',
      stepOrder: Number(row.stepOrder ?? 0),
      status: Number(row.status ?? 0)
    })
    editorVisible.value = true
  }
  function handleEditorVisibleChange(visible) {
    editorVisible.value = visible
    if (!visible) {
      editingId.value = null
      resetFormState({
        taskNo: props.taskRow?.taskCode || '',
        status: 0
      })
      formRef.value?.clearValidate()
    }
  }
  async function handleSubmit() {
    if (!formRef.value) {
      return
    }
    const valid = await formRef.value.validate().catch(() => false)
    if (!valid) {
      return
    }
    submitLoading.value = true
    try {
      const payload = {
        ...(editingId.value ? { id: editingId.value } : {}),
        taskNo: formData.taskNo,
        stepOrder: Number(formData.stepOrder ?? 0),
        stepCode: formData.stepCode,
        stepName: formData.stepName,
        stepType: formData.stepType,
        status: Number(formData.status ?? 0),
        executeResult: formData.executeResult
      }
      if (editingId.value) {
        await fetchUpdateFlowStepInstance(payload)
        ElMessage.success(t('pages.task.flowStepDialog.messages.updateSuccess'))
      } else {
        await fetchSaveFlowStepInstance(payload)
        ElMessage.success(t('pages.task.flowStepDialog.messages.createSuccess'))
      }
      handleEditorVisibleChange(false)
      await loadRows()
    } catch (error) {
      ElMessage.error(error?.message || t('pages.task.flowStepDialog.messages.submitFailed'))
    } finally {
      submitLoading.value = false
    }
  }
  async function handleDelete(row) {
    try {
      await ElMessageBox.confirm(
        t('pages.task.flowStepDialog.messages.deleteConfirm', {
          code: row.stepCode || row.id || ''
        }),
        t('crud.confirm.deleteTitle'),
        {
          type: 'warning',
          confirmButtonText: t('common.confirm'),
          cancelButtonText: t('common.cancel')
        }
      )
      await fetchRemoveFlowStepInstance(row.id)
      ElMessage.success(t('pages.task.flowStepDialog.messages.deleteSuccess'))
      await loadRows()
    } catch (error) {
      if (error === 'cancel' || error === 'close') {
        return
      }
      ElMessage.error(error?.message || t('pages.task.flowStepDialog.messages.deleteFailed'))
    }
  }
  async function handleJumpCurrent(row) {
    try {
      await fetchJumpCurrentFlowStepInstance(row.id)
      ElMessage.success(t('pages.task.flowStepDialog.messages.jumpSuccess'))
      await loadRows()
    } catch (error) {
      ElMessage.error(error?.message || t('pages.task.flowStepDialog.messages.jumpFailed'))
    }
  }
  function handleActionClick(action, row) {
    if (action.key === 'edit') {
      handleOpenEdit(row)
      return
    }
    if (action.key === 'jumpCurrent') {
      void handleJumpCurrent(row)
      return
    }
    if (action.key === 'delete') {
      void handleDelete(row)
    }
  }
  watch(
    () => [props.visible, props.taskRow?.taskCode],
    ([visible]) => {
      if (!visible) {
        rows.value = []
        pagination.current = 1
        handleEditorVisibleChange(false)
        return
      }
      pagination.current = 1
      resetFormState({
        taskNo: props.taskRow?.taskCode || '',
        status: 0
      })
      void loadRows()
    }
  )