fix: todo

pull/2/head
xingyu 2022-11-28 23:13:20 +08:00
parent 227e11f9c7
commit 583921112b
5 changed files with 198 additions and 24 deletions

View File

@ -16,7 +16,7 @@ export interface ConfigType {
export interface FileConfigVO {
id: number
name: string
storage: string
storage: number
master: boolean
visible: boolean
config: ConfigType

View File

@ -40,14 +40,14 @@ const crudSchemas = reactive<VxeCrudSchema>({
{
title: '存储器',
field: 'storage',
dictType: DICT_TYPE.INFRA_FILE_STORAGE, // TODO @星语:不同存储器,不同表单
dictType: DICT_TYPE.INFRA_FILE_STORAGE,
dictClass: 'number',
isSearch: true
},
{
title: '主配置',
field: 'master',
dictType: DICT_TYPE.INFRA_BOOLEAN_STRING, // TODO @星语:新增时,不选择主配置
dictType: DICT_TYPE.INFRA_BOOLEAN_STRING,
dictClass: 'boolean'
},
{

View File

@ -9,7 +9,7 @@
preIcon="ep:zoom-in"
:title="t('action.add')"
v-hasPermi="['infra:file-config:create']"
@click="handleCreate()"
@click="handleCreate(formRef)"
/>
</template>
<template #actionbtns_default="{ row }">
@ -53,12 +53,94 @@
</ContentWrap>
<XModal v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form
v-if="['create', 'update'].includes(actionType)"
:schema="allSchemas.formSchema"
:rules="rules"
<el-form
ref="formRef"
/>
v-if="['create', 'update'].includes(actionType)"
:model="form"
:rules="rules"
label-width="120px"
>
<el-form-item label="配置名" prop="name">
<el-input v-model="form.name" placeholder="请输入配置名" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="存储器" prop="storage">
<el-select v-model="form.storage" placeholder="请选择存储器" :disabled="form.id !== 0">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_FILE_STORAGE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- DB -->
<!-- Local / FTP / SFTP -->
<el-form-item
v-if="form.storage >= 10 && form.storage <= 12"
label="基础路径"
prop="config.basePath"
>
<el-input v-model="form.config.basePath" placeholder="请输入基础路径" />
</el-form-item>
<el-form-item
v-if="form.storage >= 11 && form.storage <= 12"
label="主机地址"
prop="config.host"
>
<el-input v-model="form.config.host" placeholder="请输入主机地址" />
</el-form-item>
<el-form-item
v-if="form.storage >= 11 && form.storage <= 12"
label="主机端口"
prop="config.port"
>
<el-input-number :min="0" v-model="form.config.port" placeholder="请输入主机端口" />
</el-form-item>
<el-form-item
v-if="form.storage >= 11 && form.storage <= 12"
label="用户名"
prop="config.username"
>
<el-input v-model="form.config.username" placeholder="请输入密码" />
</el-form-item>
<el-form-item
v-if="form.storage >= 11 && form.storage <= 12"
label="密码"
prop="config.password"
>
<el-input v-model="form.config.password" placeholder="请输入密码" />
</el-form-item>
<el-form-item v-if="form.storage === 11" label="连接模式" prop="config.mode">
<el-radio-group v-model="form.config.mode">
<el-radio key="Active" label="Active">主动模式</el-radio>
<el-radio key="Passive" label="Passive">主动模式</el-radio>
</el-radio-group>
</el-form-item>
<!-- S3 -->
<el-form-item v-if="form.storage === 20" label="节点地址" prop="config.endpoint">
<el-input v-model="form.config.endpoint" placeholder="请输入节点地址" />
</el-form-item>
<el-form-item v-if="form.storage === 20" label="存储 bucket" prop="config.bucket">
<el-input v-model="form.config.bucket" placeholder="请输入 bucket" />
</el-form-item>
<el-form-item v-if="form.storage === 20" label="accessKey" prop="config.accessKey">
<el-input v-model="form.config.accessKey" placeholder="请输入 accessKey" />
</el-form-item>
<el-form-item v-if="form.storage === 20" label="accessSecret" prop="config.accessSecret">
<el-input v-model="form.config.accessSecret" placeholder="请输入 accessSecret" />
</el-form-item>
<!-- 通用 -->
<el-form-item v-if="form.storage === 20" label="自定义域名">
<!-- 无需参数校验所以去掉 prop -->
<el-input v-model="form.config.domain" placeholder="请输入自定义域名" />
</el-form-item>
<el-form-item v-else-if="form.storage" label="自定义域名" prop="config.domain">
<el-input v-model="form.config.domain" placeholder="请输入自定义域名" />
</el-form-item>
</el-form>
<!-- 对话框(详情) -->
<Descriptions
v-if="actionType === 'detail'"
@ -73,7 +155,7 @@
type="primary"
:title="t('action.save')"
:loading="actionLoading"
@click="submitForm()"
@click="submitForm(formRef)"
/>
<!-- 按钮关闭 -->
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
@ -82,15 +164,26 @@
</template>
<script setup lang="ts" name="FileConfig">
// import
import { ref, unref } from 'vue'
import { reactive, ref } from 'vue'
import {
ElForm,
ElFormItem,
FormInstance,
ElSelect,
ElOption,
ElInput,
ElInputNumber,
ElRadio,
ElRadioGroup
} from 'element-plus'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
import { VxeGridInstance } from 'vxe-table'
import { FormExpose } from '@/components/Form'
// import
import * as FileConfigApi from '@/api/infra/fileConfig'
import { rules, allSchemas } from './fileConfig.data'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
const { t } = useI18n() //
const message = useMessage() //
@ -107,8 +200,30 @@ const actionLoading = ref(false) // 遮罩层
const actionType = ref('') //
const dialogVisible = ref(false) //
const dialogTitle = ref('edit') //
const formRef = ref<FormExpose>() // Ref
const formRef = ref<FormInstance>() // Ref
const detailData = ref() // Ref
let form = reactive<FileConfigApi.FileConfigVO>({
id: 0,
name: '',
storage: 0,
master: false,
visible: false,
config: {
basePath: '',
host: '',
port: '',
username: '',
password: '',
mode: '',
endpoint: '',
bucket: '',
accessKey: '',
accessSecret: '',
domain: ''
},
remark: '',
createTime: ''
})
//
const setDialogTile = (type: string) => {
dialogTitle.value = t('action.' + type)
@ -117,16 +232,17 @@ const setDialogTile = (type: string) => {
}
//
const handleCreate = () => {
const handleCreate = (formEl: FormInstance | undefined) => {
setDialogTile('create')
formEl?.resetFields()
}
//
const handleUpdate = async (rowId: number) => {
setDialogTile('update')
//
const res = await FileConfigApi.getFileConfigApi(rowId)
unref(formRef)?.setValues(res)
form = res
setDialogTile('update')
}
//
@ -153,20 +269,18 @@ const handleDelete = async (rowId: number) => {
}
//
const submitForm = async () => {
const elForm = unref(formRef)?.getElFormRef()
if (!elForm) return
elForm.validate(async (valid) => {
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate(async (valid) => {
if (valid) {
actionLoading.value = true
//
try {
const data = unref(formRef)?.formModel as FileConfigApi.FileConfigVO
if (actionType.value === 'create') {
await FileConfigApi.createFileConfigApi(data)
await FileConfigApi.createFileConfigApi(form)
message.success(t('common.createSuccess'))
} else {
await FileConfigApi.updateFileConfigApi(data)
await FileConfigApi.updateFileConfigApi(form)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false

View File

@ -100,7 +100,9 @@
<template #monitorTimeout="{ row }">
<span>{{ row.monitorTimeout > 0 ? row.monitorTimeout + ' 毫秒' : '未开启' }}</span>
</template>
<!-- TODO @星语有个后续执行时间字段2022-11-26 23:03:16; 2022-11-26 23:03:17; 2022-11-26 23:03:18; 2022-11-26 23:03:19; 2022-11-26 23:03:20 -->
<template #nextTimes>
<span>{{ Array.from(nextTimes, (x) => parseTime(x)).join('; ') }}</span>
</template>
</Descriptions>
<!-- 操作按钮 -->
<template #footer>
@ -151,6 +153,7 @@ const dialogTitle = ref('edit') // 弹出层标题
const formRef = ref<FormExpose>() // Ref
const detailRef = ref() // Ref
const cronExpression = ref('')
const nextTimes = ref([])
const shortcuts = ref([
{
text: '每天8点和12点 (自定义追加)',
@ -169,10 +172,12 @@ const handleCreate = () => {
cronExpression.value = ''
setDialogTile('create')
}
//
const handleExport = async () => {
await exportList(xGrid, '定时任务.xls')
}
//
const handleUpdate = async (rowId: number) => {
setDialogTile('update')
@ -187,8 +192,57 @@ const handleDetail = async (rowId: number) => {
//
const res = await JobApi.getJobApi(rowId)
detailRef.value = res
//
const jobNextTime = await JobApi.getJobNextTimesApi(rowId)
nextTimes.value = jobNextTime
setDialogTile('detail')
}
const parseTime = (time) => {
if (!time) {
return null
}
const format = '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time
.replace(new RegExp(/-/gm), '/')
.replace('T', ' ')
.replace(new RegExp(/\.[\d]{3}/gm), '')
}
if (typeof time === 'number' && time.toString().length === 10) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
//
const handleDelete = async (rowId: number) => {
await deleteData(xGrid, rowId)

View File

@ -48,6 +48,12 @@ const crudSchemas = reactive<VxeCrudSchema>({
title: 'CRON 表达式',
field: 'cronExpression'
},
{
title: '后续执行时间',
field: 'nextTimes',
isTable: false,
isForm: false
},
{
title: '重试次数',
field: 'retryCount',