From 26a11d77aaec3321cde6a23beb06bc56936e5cba Mon Sep 17 00:00:00 2001 From: syd <syidong@aliyun.com> Date: Sun, 19 Mar 2023 14:40:31 +0800 Subject: [PATCH 01/12] =?UTF-8?q?vue3=20=E9=87=8D=E6=9E=84=EF=BC=9A?= =?UTF-8?q?=E6=95=8F=E6=84=9F=E8=AF=8D=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/sensitiveWord/form.vue | 129 +++++++ src/views/system/sensitiveWord/index.vue | 360 ++++++++++-------- .../sensitiveWord/sensitiveWord.data.ts | 74 ---- 3 files changed, 325 insertions(+), 238 deletions(-) create mode 100644 src/views/system/sensitiveWord/form.vue delete mode 100644 src/views/system/sensitiveWord/sensitiveWord.data.ts diff --git a/src/views/system/sensitiveWord/form.vue b/src/views/system/sensitiveWord/form.vue new file mode 100644 index 00000000..a0ed7a21 --- /dev/null +++ b/src/views/system/sensitiveWord/form.vue @@ -0,0 +1,129 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="80px" + v-loading="formLoading" + > + <el-form-item label="敏感词" prop="name"> + <el-input v-model="formData.name" placeholder="请输入敏感词" /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="dict.value" + > + {{ dict.label }} + </el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="备注" prop="description"> + <el-input v-model="formData.description" placeholder="请输入内容" /> + </el-form-item> + <el-form-item label="标签" prop="tags"> + <el-select + v-model="formData.tags" + multiple + filterable + allow-create + placeholder="请选择文章标签" + style="width: 380px" + > + <el-option v-for="tag in tags" :key="tag" :label="tag" :value="tag" /> + </el-select> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import * as SensitiveWordApi from '@/api/system/sensitiveWord' + +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const tags = ref([]) +const formData = ref({ + id: undefined, + name: '', + status: true, + description: '', + tags: [] +}) +const formRules = reactive({ + name: [{ required: true, message: '敏感词不能为空', trigger: 'blur' }], + tags: [{ required: true, message: '标签不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 打开弹窗 */ +const openModal = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await SensitiveWordApi.getSensitiveWordApi(id) + console.log(formData.value) + } finally { + formLoading.value = false + } + } +} +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as unknown as SensitiveWordApi.SensitiveWordVO + if (formType.value === 'create') { + await SensitiveWordApi.createSensitiveWordApi(data) + message.success(t('common.createSuccess')) + } else { + await SensitiveWordApi.updateSensitiveWordApi(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + name: '', + status: true, + description: '', + tags: [] + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/sensitiveWord/index.vue b/src/views/system/sensitiveWord/index.vue index c3de895d..0eb8287d 100644 --- a/src/views/system/sensitiveWord/index.vue +++ b/src/views/system/sensitiveWord/index.vue @@ -1,191 +1,223 @@ <template> - <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <template #toolbar_buttons> - <!-- 操作:新增 --> - <XButton - type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" - v-hasPermi="['system:sensitive-word:create']" - @click="handleCreate()" + <!-- 搜索 --> + <content-wrap> + <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form-item label="敏感词" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入敏感词" + clearable + @keyup.enter="handleQuery" /> - <!-- 操作:导出 --> - <XButton - type="warning" - preIcon="ep:download" - :title="t('action.export')" - v-hasPermi="['system:sensitive-word:export']" - @click="exportList('敏感词数据.xls')" - /> - </template> - <template #tags_default="{ row }"> - <el-tag - :disable-transitions="true" - :key="index" - v-for="(tag, index) in row.tags" - :index="index" + </el-form-item> + <el-form-item label="标签" prop="tag"> + <el-select + v-model="queryParams.tag" + placeholder="请选择标签" + clearable + @keyup.enter="handleQuery" > - {{ tag }} - </el-tag> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:修改 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['system:sensitive-word:update']" - @click="handleUpdate(row.id)" - /> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['system:sensitive-word:update']" - @click="handleDetail(row.id)" - /> - <!-- 操作:删除 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.del')" - v-hasPermi="['system:sensitive-word:delete']" - @click="deleteData(row.id)" - /> - </template> - </XTable> - </ContentWrap> - - <XModal v-model="dialogVisible" :title="dialogTitle"> - <!-- 对话框(添加 / 修改) --> - <Form - v-if="['create', 'update'].includes(actionType)" - :schema="allSchemas.formSchema" - :rules="rules" - ref="formRef" - > - <template #tags="form"> - <el-select v-model="form['tags']" multiple placeholder="请选择"> - <el-option v-for="item in tagsOptions" :key="item" :label="item" :value="item" /> + <el-option v-for="tag in tags" :key="tag" :label="tag" :value="tag" /> </el-select> - </template> - </Form> - <!-- 对话框(详情) --> - <Descriptions - v-if="actionType === 'detail'" - :schema="allSchemas.detailSchema" - :data="detailData" - > - <template #tags="{ row }"> - <el-tag - :disable-transitions="true" - :key="index" - v-for="(tag, index) in row.tags" - :index="index" + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + value-format="YYYY-MM-DD HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + /> + </el-form-item> + + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button + type="primary" + @click="openModal('create')" + v-hasPermi="['system:sensitive-word:create']" > - {{ tag }} - </el-tag> - </template> - </Descriptions> - <!-- 操作按钮 --> - <template #footer> - <!-- 按钮:保存 --> - <XButton - v-if="['create', 'update'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitForm()" + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['system:sensitive-word:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + </content-wrap> + + <!-- 列表 --> + <content-wrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="编号" align="center" prop="id" /> + <el-table-column label="敏感词" align="center" prop="name" /> + <el-table-column label="状态" align="center" prop="status"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="描述" align="center" prop="description" /> + <el-table-column label="标签" align="center" prop="tags"> + <template #default="scope"> + <el-tag + :disable-transitions="true" + :key="index" + v-for="(tag, index) in scope.row.tags" + :index="index" + > + {{ tag }} + </el-tag> + </template> + </el-table-column> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + :formatter="dateFormatter" /> - <!-- 按钮:关闭 --> - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openModal('update', scope.row.id)" + v-hasPermi="['infra:config:update']" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['infra:config:delete']" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + + <!-- 表单弹窗:添加/修改 --> + <config-form ref="modalRef" @success="getList" /> </template> <script setup lang="ts" name="SensitiveWord"> -import type { FormExpose } from '@/components/Form' +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' +import download from '@/utils/download' import * as SensitiveWordApi from '@/api/system/sensitiveWord' -import { rules, allSchemas } from './sensitiveWord.data' - -const { t } = useI18n() // 国际化 +import ConfigForm from './form.vue' const message = useMessage() // 消息弹窗 -// 列表相关的变量 -const [registerTable, { reload, deleteData, exportList }] = useXTable({ - allSchemas: allSchemas, - getListApi: SensitiveWordApi.getSensitiveWordPageApi, - deleteApi: SensitiveWordApi.deleteSensitiveWordApi, - exportListApi: SensitiveWordApi.exportSensitiveWordApi +const { t } = useI18n() // 国际化 + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const tags = ref([]) +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + name: undefined, + tag: undefined, + status: undefined, + createTime: [] }) -const actionLoading = ref(false) // 遮罩层 -const actionType = ref('') // 操作按钮的类型 -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('edit') // 弹出层标题 -const formRef = ref<FormExpose>() // 表单 Ref -const detailData = ref() // 详情 Ref +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 -// 获取标签 -const tagsOptions = ref() +/** 查询参数列表 */ +const getList = async () => { + loading.value = true + try { + const data = await SensitiveWordApi.getSensitiveWordPageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} + +/** 初始化标签select*/ const getTags = async () => { - const res = await SensitiveWordApi.getSensitiveWordTagsApi() - tagsOptions.value = res + const data = await SensitiveWordApi.getSensitiveWordTagsApi() + tags.value = data } -// 设置标题 -const setDialogTile = (type: string) => { - dialogTitle.value = t('action.' + type) - actionType.value = type - dialogVisible.value = true +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() } -// 新增操作 -const handleCreate = () => { - setDialogTile('create') +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() } -// 修改操作 -const handleUpdate = async (rowId: number) => { - setDialogTile('update') - // 设置数据 - const res = await SensitiveWordApi.getSensitiveWordApi(rowId) - unref(formRef)?.setValues(res) +/** 添加/修改操作 */ +const modalRef = ref() +const openModal = (type: string, id?: number) => { + modalRef.value.openModal(type, id) } -// 详情操作 -const handleDetail = async (rowId: number) => { - setDialogTile('detail') - const res = await SensitiveWordApi.getSensitiveWordApi(rowId) - detailData.value = res +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await SensitiveWordApi.deleteSensitiveWordApi(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} } -// 提交按钮 -const submitForm = async () => { - const elForm = unref(formRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid) { - actionLoading.value = true - // 提交请求 - try { - const data = unref(formRef)?.formModel as SensitiveWordApi.SensitiveWordVO - if (actionType.value === 'create') { - await SensitiveWordApi.createSensitiveWordApi(data) - message.success(t('common.createSuccess')) - } else { - await SensitiveWordApi.updateSensitiveWordApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - // 刷新列表 - await reload() - } - } - }) +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await SensitiveWordApi.exportSensitiveWordApi(queryParams) + download.excel(data, '敏感词.xls') + } catch { + } finally { + exportLoading.value = false + } } -// ========== 初始化 ========== -onMounted(async () => { - await getTags() +/** 初始化 **/ +onMounted(() => { + getTags() + getList() }) </script> diff --git a/src/views/system/sensitiveWord/sensitiveWord.data.ts b/src/views/system/sensitiveWord/sensitiveWord.data.ts deleted file mode 100644 index d21bb94c..00000000 --- a/src/views/system/sensitiveWord/sensitiveWord.data.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -const { t } = useI18n() // 国际化 - -// 表单校验 -export const rules = reactive({ - name: [required], - tags: [required] -}) - -// CrudSchema -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: 'id', - primaryTitle: '敏感词编号', - action: true, - columns: [ - { - title: '敏感词', - field: 'name', - isSearch: true - }, - { - title: '标签', - field: 'tag', - isTable: false, - isForm: false, - isDetail: false, - isSearch: true - }, - { - title: '标签', - field: 'tags', - table: { - slots: { - default: 'tags_default' - } - } - }, - { - title: t('common.status'), - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number', - isSearch: true - }, - { - title: '描述', - field: 'description', - form: { - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - } - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false, - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) From 5d062d5877ec0fffd525ab2360870706a9330072 Mon Sep 17 00:00:00 2001 From: Theo <koutianyu@163.com> Date: Sun, 19 Mar 2023 16:48:27 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/dict/types.ts | 18 +- src/router/modules/remaining.ts | 25 ++ src/views/system/dict/data.form.vue | 182 ++++++++++++ src/views/system/dict/data.vue | 203 +++++++++++++ src/views/system/dict/dict.data.ts | 104 ------- src/views/system/dict/dict.type.ts | 65 ----- src/views/system/dict/form.vue | 122 ++++++++ src/views/system/dict/index.vue | 436 ++++++++++++---------------- 8 files changed, 736 insertions(+), 419 deletions(-) create mode 100644 src/views/system/dict/data.form.vue create mode 100644 src/views/system/dict/data.vue delete mode 100644 src/views/system/dict/dict.data.ts delete mode 100644 src/views/system/dict/dict.type.ts create mode 100644 src/views/system/dict/form.vue diff --git a/src/api/system/dict/types.ts b/src/api/system/dict/types.ts index b630dccb..3421cd23 100644 --- a/src/api/system/dict/types.ts +++ b/src/api/system/dict/types.ts @@ -1,16 +1,18 @@ export type DictTypeVO = { - id: number + id: number | undefined name: string type: string - status: number + status: number | undefined remark: string createTime: Date } export type DictTypePageReqVO = { + pageNo: number + pageSize: number name: string type: string - status: number + status: number | undefined createTime: Date[] } @@ -22,8 +24,8 @@ export type DictTypeExportReqVO = { } export type DictDataVO = { - id: number - sort: number + id: number | undefined + sort: number | undefined label: string value: string dictType: string @@ -31,12 +33,14 @@ export type DictDataVO = { colorType: string cssClass: string remark: string - createTime: Date + createTime: Date | undefined } export type DictDataPageReqVO = { + pageNo: number + pageSize: number label: string dictType: string - status: number + status: number | undefined } export type DictDataExportReqVO = { diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 43375961..d5970267 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -104,6 +104,31 @@ const remainingRouter: AppRouteRecordRaw[] = [ } ] }, + + { + path: '/dict', + component: Layout, + name: 'dict', + meta: { + hidden: true + }, + children: [ + { + path: 'type/data/:dictType', + component: () => import('@/views/system/dict/data.vue'), + name: 'data', + meta: { + title: '字典数据', + noCache: true, + hidden: true, + canTo: true, + icon: '', + activeMenu: 'system/dict/data' + } + } + ] + }, + { path: '/codegen', component: Layout, diff --git a/src/views/system/dict/data.form.vue b/src/views/system/dict/data.form.vue new file mode 100644 index 00000000..5c85b946 --- /dev/null +++ b/src/views/system/dict/data.form.vue @@ -0,0 +1,182 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="80px" + v-loading="formLoading" + > + <el-form-item label="字典类型" prop="type"> + <el-input + :disabled="typeof formData.id !== 'undefined'" + v-model="formData.dictType" + placeholder="请输入参数名称" + /> + </el-form-item> + <el-form-item label="数据标签" prop="label"> + <el-input v-model="formData.label" placeholder="请输入数据标签" /> + </el-form-item> + + <el-form-item label="数据键值" prop="value"> + <el-input v-model="formData.value" placeholder="请输入数据键值" /> + </el-form-item> + <el-form-item label="显示排序" prop="sort"> + <el-input-number v-model="formData.sort" controls-position="right" :min="0" /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="parseInt(dict.value)" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + <el-form-item label="颜色类型" prop="colorType"> + <el-select v-model="formData.colorType"> + <el-option + v-for="item in colorTypeOptions" + :key="item.value" + :label="item.label + '(' + item.value + ')'" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item label="CSS Class" prop="cssClass"> + <el-input v-model="formData.cssClass" placeholder="请输入 CSS Class" /> + </el-form-item> + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import { DICT_TYPE, getDictOptions } from '@/utils/dict' + +import * as DictDataApi from '@/api/system/dict/dict.data' +import { DictDataVO } from '@/api/system/dict/types' +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const formData = ref({ + id: undefined, + sort: 0, + label: '', + value: '', + dictType: '', + status: 0, + colorType: '', + cssClass: '', + remark: '', + createTime: undefined +}) +const formRules = reactive({ + label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], + value: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }], + sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +// 数据标签回显样式 + +const colorTypeOptions = readonly([ + { + value: 'default', + label: '默认' + }, + { + value: 'primary', + label: '主要' + }, + { + value: 'success', + label: '成功' + }, + { + value: 'info', + label: '信息' + }, + { + value: 'warning', + label: '警告' + }, + { + value: 'danger', + label: '危险' + } +]) + +/** 打开弹窗 */ +const openModal = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await DictDataApi.getDictDataApi(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as DictDataVO + if (formType.value === 'create') { + await DictDataApi.createDictDataApi(data) + message.success(t('common.createSuccess')) + } else { + await DictDataApi.updateDictDataApi(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + sort: undefined, + label: '', + value: '', + dictType: '', + status: 0, + colorType: '', + cssClass: '', + remark: '', + createTime: undefined + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue new file mode 100644 index 00000000..2c1b373a --- /dev/null +++ b/src/views/system/dict/data.vue @@ -0,0 +1,203 @@ +<template> + <content-wrap> + <el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" label-width="68px"> + <el-form-item label="字典名称" prop="dictType"> + <el-select v-model="queryParams.dictType"> + <el-option + v-for="item in simpleDictList" + :key="item.id" + :label="item.name" + :value="item.type" + /> + </el-select> + </el-form-item> + <el-form-item label="字典标签" prop="label"> + <el-input + v-model="queryParams.label" + placeholder="请输入字典标签" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select v-model="queryParams.status" placeholder="数据状态" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" @click="openModal('create')" v-hasPermi="['system:dict:create']"> + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['system:dict:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + <!-- 列表 --> + <el-table v-loading="loading" :data="list"> + <el-table-column label="字典编码" align="center" prop="id" /> + <el-table-column label="字典标签" align="center" prop="label" /> + <el-table-column label="字典键值" align="center" prop="value" /> + <el-table-column label="字典排序" align="center" prop="sort" /> + <el-table-column label="状态" align="center" prop="status"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="颜色类型" align="center" prop="colorType" /> + <el-table-column label="CSS Class" align="center" prop="cssClass" /> + <el-table-column + label="备注" + align="center" + prop="remark" + :show-overflow-tooltip="tableTooltipConfig" + /> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + :formatter="dateFormatter" + /> + + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + @click="openModal('update', scope.row.id)" + v-hasPermi="['system:dict:update']" + ><Icon icon="ic:outline-mode" class="mr-5px" />修改</el-button + > + <el-button link @click="handleDelete(scope.row.id)" v-hasPermi="['system:dict:delete']" + ><Icon icon="material-symbols:delete-forever-sharp" class="mr-5px" />删除</el-button + > + </template> + </el-table-column> + </el-table> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + <!-- 表单弹窗:添加/修改 --> + <data-form ref="modalRef" @success="getList" /> +</template> + +<script setup lang="ts" name="Data"> +import * as DictDataApi from '@/api/system/dict/dict.data' +import { listSimpleDictTypeApi } from '@/api/system/dict/dict.type' +import { getDictOptions, DICT_TYPE } from '@/utils/dict' +import download from '@/utils/download' +import { dateFormatter } from '@/utils/formatTime' +import DataForm from './data.form.vue' +import { DictTypeVO } from '@/api/system/dict/types' +import { useRoute } from 'vue-router' +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 + +const route = useRoute() + +const simpleDictList = ref<DictTypeVO[]>() + +const tableTooltipConfig = readonly({ + appendTo: 'body' +}) + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + label: '', + status: undefined, + dictType: route.params.dictType +}) +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 + +/** 查询参数列表 */ +const getList = async () => { + loading.value = true + try { + const data = await DictDataApi.getDictDataPageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} +// 查询字典(精简)列表 +const getSimpleDictList = async () => { + const data = await listSimpleDictTypeApi() + simpleDictList.value = data +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ +const modalRef = ref() +const openModal = (type: string, id?: number) => { + modalRef.value.openModal(type, id) +} + +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await DictDataApi.deleteDictDataApi(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} +} + +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await DictDataApi.exportDictDataApi(queryParams) + download.excel(data, '字典数据.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +/** 初始化 **/ +onMounted(() => { + getList() +}) +// 查询字典(精简)列表 +getSimpleDictList() +</script> diff --git a/src/views/system/dict/dict.data.ts b/src/views/system/dict/dict.data.ts deleted file mode 100644 index cdfe4538..00000000 --- a/src/views/system/dict/dict.data.ts +++ /dev/null @@ -1,104 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -// 国际化 -const { t } = useI18n() -// 表单校验 -export const dictDataRules = reactive({ - label: [required], - value: [required], - sort: [required] -}) -// crudSchemas -export const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: null, - action: true, - actionWidth: '140px', - searchSpan: 12, - columns: [ - { - title: '字典类型', - field: 'dictType', - isTable: false, - isForm: false - }, - { - title: '数据标签', - field: 'label', - isSearch: true - }, - { - title: '数据键值', - field: 'value' - }, - // { - // title: '标签类型', - // field: 'colorType', - // form: { - // component: 'Select', - // componentProps: { - // options: [ - // { - // label: 'default', - // value: '' - // }, - // { - // label: 'success', - // value: 'success' - // }, - // { - // label: 'info', - // value: 'info' - // }, - // { - // label: 'warning', - // value: 'warning' - // }, - // { - // label: 'danger', - // value: 'danger' - // } - // ] - // } - // }, - // isTable: false - // }, - { - title: '颜色', - field: 'cssClass', - isTable: false, - form: { - component: 'ColorPicker', - componentProps: { - predefine: ['#ffffff', '#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399', '#c71585'] - } - } - }, - { - title: '显示排序', - field: 'sort', - isTable: false - }, - { - title: t('common.status'), - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number' - }, - { - title: t('form.remark'), - field: 'remark', - form: { - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - }, - isTable: false - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) diff --git a/src/views/system/dict/dict.type.ts b/src/views/system/dict/dict.type.ts deleted file mode 100644 index 73b5a021..00000000 --- a/src/views/system/dict/dict.type.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -const { t } = useI18n() // 国际化 - -// 表单校验 -export const dictTypeRules = reactive({ - name: [required], - type: [required] -}) -// 新增 + 修改 -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: null, - action: true, - actionWidth: '140px', - searchSpan: 12, - columns: [ - { - title: '字典名称', - field: 'name', - isSearch: true - }, - { - title: '字典类型', - field: 'type', - isSearch: true - }, - { - title: t('common.status'), - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number', - table: { - width: 70 - } - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false, - isTable: false, - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - } - }, - { - title: t('form.remark'), - field: 'remark', - isTable: false, - form: { - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) diff --git a/src/views/system/dict/form.vue b/src/views/system/dict/form.vue new file mode 100644 index 00000000..28b42c9d --- /dev/null +++ b/src/views/system/dict/form.vue @@ -0,0 +1,122 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="80px" + v-loading="formLoading" + > + <el-form-item label="字典名称" prop="name"> + <el-input v-model="formData.name" placeholder="请输入字典名称" /> + </el-form-item> + <el-form-item label="字典类型" prop="type"> + <el-input + :disabled="typeof formData.id !== 'undefined'" + v-model="formData.type" + placeholder="请输入参数名称" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="parseInt(dict.value)" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import * as DictTypeApi from '@/api/system/dict/dict.type' +import { DictTypeVO } from '@/api/system/dict/types' +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const formData = ref({ + id: undefined, + name: '', + type: '', + status: 0, + remark: '' +}) +const formRules = reactive({ + name: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }], + type: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 打开弹窗 */ +const openModal = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await DictTypeApi.getDictTypeApi(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as DictTypeVO + if (formType.value === 'create') { + await DictTypeApi.createDictTypeApi(data) + message.success(t('common.createSuccess')) + } else { + await DictTypeApi.updateDictTypeApi(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + type: '', + name: '', + status: undefined, + remark: '' + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue index 713fde97..367cc9d4 100644 --- a/src/views/system/dict/index.vue +++ b/src/views/system/dict/index.vue @@ -1,257 +1,207 @@ <template> - <div class="flex"> - <!-- ====== 字典分类 ====== --> - <el-card class="w-1/2 dict" :gutter="12" shadow="always"> - <template #header> - <div class="card-header"> - <span>字典分类</span> - </div> - </template> - <XTable @register="registerType" @cell-click="cellClickEvent"> - <!-- 操作:新增类型 --> - <template #toolbar_buttons> - <XButton - type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" - v-hasPermi="['system:dict:create']" - @click="handleTypeCreate()" + <content-wrap> + <el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" label-width="68px"> + <el-form-item label="字典名称" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入字典名称" + clearable + style="width: 240px" + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="字典类型" prop="type"> + <el-input + v-model="queryParams.type" + placeholder="请输入字典类型" + clearable + style="width: 240px" + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="字典状态" + clearable + style="width: 240px" + > + <el-option + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="dict.value" /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="daterange" + range-separator="-" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" @click="openModal('create')" v-hasPermi="['system:dict:create']"> + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['system:dict:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + + <!-- 列表 --> + <el-table v-loading="loading" :data="list"> + <el-table-column label="字典编号" align="center" prop="id" /> + <el-table-column label="字典名称" align="center" prop="name" show-overflow-tooltip /> + <el-table-column label="字典类型" align="center" show-overflow-tooltip> + <template #default="scope"> + <div> + <router-link :to="'/dict/type/data/' + scope.row.type"> + <span>{{ scope.row.type }}</span> + </router-link> + </div> </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:编辑类型 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['system:dict:update']" - @click="handleTypeUpdate(row.id)" - /> - <!-- 操作:删除类型 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.del')" - v-hasPermi="['system:dict:delete']" - @click="typeDeleteData(row.id)" - /> + </el-table-column> + <el-table-column label="状态" align="center" prop="status"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> </template> - </XTable> - <!-- @星语:分页和列表重叠在一起了 --> - </el-card> - <!-- ====== 字典数据 ====== --> - <el-card class="w-1/2 dict ml-3" :gutter="12" shadow="hover"> - <template #header> - <div class="card-header"> - <span>字典数据</span> - </div> - </template> - <!-- 列表 --> - <div v-if="!tableTypeSelect"> - <span>请从左侧选择</span> - </div> - <div v-if="tableTypeSelect"> - <!-- 列表 --> - <XTable @register="registerData"> - <!-- 操作:新增数据 --> - <template #toolbar_buttons> - <XButton - type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" - v-hasPermi="['system:dict:create']" - @click="handleDataCreate()" - /> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:修改数据 --> - <XTextButton - v-hasPermi="['system:dict:update']" - preIcon="ep:edit" - :title="t('action.edit')" - @click="handleDataUpdate(row.id)" - /> - <!-- 操作:删除数据 --> - <XTextButton - v-hasPermi="['system:dict:delete']" - preIcon="ep:delete" - :title="t('action.del')" - @click="dataDeleteData(row.id)" - /> - </template> - </XTable> - </div> - </el-card> - <XModal id="dictModel" v-model="dialogVisible" :title="dialogTitle"> - <Form - v-if="['typeCreate', 'typeUpdate'].includes(actionType)" - :schema="DictTypeSchemas.allSchemas.formSchema" - :rules="DictTypeSchemas.dictTypeRules" - ref="typeFormRef" - > - <template #type> - <template v-if="actionType == 'typeUpdate'"> - <el-tag>{{ dictTypeValue }}</el-tag> - </template> - <template v-else><el-input v-model="dictTypeValue" /> </template> - </template> - </Form> - <Form - v-if="['dataCreate', 'dataUpdate'].includes(actionType)" - :schema="DictDataSchemas.allSchemas.formSchema" - :rules="DictDataSchemas.dictDataRules" - ref="dataFormRef" + </el-table-column> + <el-table-column label="备注" align="center" prop="remark" /> + <el-table-column + label="创建时间" + :formatter="dateFormatter" + align="center" + prop="createTime" + width="180" /> - <!-- 操作按钮 --> - <template #footer> - <XButton - v-if="['typeCreate', 'typeUpdate'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitTypeForm" - /> - <XButton - v-if="['dataCreate', 'dataUpdate'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitDataForm" - /> - <XButton :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> - </div> + + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + @click="openModal('update', scope.row.id)" + v-hasPermi="['system:dict:update']" + ><Icon icon="ic:outline-mode" class="mr-5px" />修改</el-button + > + <el-button link @click="handleDelete(scope.row.id)" v-hasPermi="['system:dict:delete']" + ><Icon icon="material-symbols:delete-forever-sharp" class="mr-5px" />删除</el-button + > + </template> + </el-table-column> + </el-table> + + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + <!-- 表单弹窗:添加/修改 --> + <dict-type-form ref="modalRef" @success="getList" /> </template> + <script setup lang="ts" name="Dict"> -import { VxeTableEvents } from 'vxe-table' -import type { FormExpose } from '@/components/Form' -import * as DictTypeSchemas from './dict.type' -import * as DictDataSchemas from './dict.data' import * as DictTypeApi from '@/api/system/dict/dict.type' -import * as DictDataApi from '@/api/system/dict/dict.data' -import { DictDataVO, DictTypeVO } from '@/api/system/dict/types' - -const { t } = useI18n() // 国际化 +import { getDictOptions, DICT_TYPE } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' +import DictTypeForm from './form.vue' +import { DictTypePageReqVO } from '@/api/system/dict/types' +import download from '@/utils/download' const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 -const [registerType, { reload: typeGetList, deleteData: typeDeleteData }] = useXTable({ - allSchemas: DictTypeSchemas.allSchemas, - getListApi: DictTypeApi.getDictTypePageApi, - deleteApi: DictTypeApi.deleteDictTypeApi +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 + +const list = ref([]) // 字典表格数据 +const queryParams = reactive<DictTypePageReqVO>({ + pageNo: 1, + pageSize: 10, + name: '', + type: '', + status: undefined, + createTime: [] }) +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 -const queryParams = reactive({ - dictType: null +/** 查询字典类型列表 */ +const getList = async () => { + loading.value = true + try { + const data = await DictTypeApi.getDictTypePageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ +const modalRef = ref() +const openModal = (type: string, id?: number) => { + modalRef.value.openModal(type, id) +} + +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await DictTypeApi.deleteDictTypeApi(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} +} + +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await DictTypeApi.exportDictTypeApi(queryParams) + download.excel(data, '字典类型.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +/** 初始化 **/ +onMounted(() => { + getList() }) -const [registerData, { reload: dataGetList, deleteData: dataDeleteData }] = useXTable({ - allSchemas: DictDataSchemas.allSchemas, - params: queryParams, - getListApi: DictDataApi.getDictDataPageApi, - deleteApi: DictDataApi.deleteDictDataApi -}) -// ========== 字典分类列表相关 ========== -const dictTypeValue = ref('') -// 字典分类修改操作 -const handleTypeCreate = () => { - dictTypeValue.value = '' - setDialogTile('typeCreate') -} -const handleTypeUpdate = async (rowId: number) => { - setDialogTile('typeUpdate') - // 设置数据 - const res = await DictTypeApi.getDictTypeApi(rowId) - dictTypeValue.value = res.type - unref(typeFormRef)?.setValues(res) -} - -// 字典数据修改操作 -const handleDataCreate = () => { - setDialogTile('dataCreate') -} -const handleDataUpdate = async (rowId: number) => { - setDialogTile('dataUpdate') - // 设置数据 - const res = await DictDataApi.getDictDataApi(rowId) - unref(dataFormRef)?.setValues(res) -} -// 字典分类点击行事件 -const parentType = ref('') -const tableTypeSelect = ref(false) -const cellClickEvent: VxeTableEvents.CellClick = async ({ row }) => { - tableTypeSelect.value = true - queryParams.dictType = row['type'] - await nextTick() - await dataGetList() - parentType.value = row['type'] -} -// 弹出框 -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('edit') // 弹出层标题 -const actionLoading = ref(false) // 遮罩层 -const typeFormRef = ref<FormExpose>() // 分类表单 Ref -const dataFormRef = ref<FormExpose>() // 数据表单 Ref -const actionType = ref('') // 操作按钮的类型 - -// 设置标题 -const setDialogTile = (type: string) => { - dialogTitle.value = t('action.' + type) - actionType.value = type - dialogVisible.value = true -} - -// 同步dictTypeValue到form 否则导致表单验证不通过 -watch(dictTypeValue, (val) => { - unref(typeFormRef)?.setValues({ type: val }) -}) - -// 提交按钮 -const submitTypeForm = async () => { - const elForm = unref(typeFormRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid && dictTypeValue.value != '') { - actionLoading.value = true - // 提交请求 - try { - const data = unref(typeFormRef)?.formModel as DictTypeVO - if (actionType.value === 'typeCreate') { - data.type = dictTypeValue.value - await DictTypeApi.createDictTypeApi(data) - message.success(t('common.createSuccess')) - } else if (actionType.value === 'typeUpdate') { - await DictTypeApi.updateDictTypeApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - typeGetList() - } - } - }) -} -const submitDataForm = async () => { - const elForm = unref(dataFormRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid) { - actionLoading.value = true - // 提交请求 - try { - const data = unref(dataFormRef)?.formModel as DictDataVO - if (actionType.value === 'dataCreate') { - data.dictType = parentType.value - await DictDataApi.createDictDataApi(data) - message.success(t('common.createSuccess')) - } else if (actionType.value === 'dataUpdate') { - await DictDataApi.updateDictDataApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - dataGetList() - } - } - }) -} </script> From 188329355353db8a3925089cc8a385eb4f67e812 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sun, 19 Mar 2023 20:56:11 +0800 Subject: [PATCH 03/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9A?= =?UTF-8?q?=E4=BB=A4=E7=89=8C=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/oauth2/token.ts | 10 +- src/views/system/oauth2/token/index.vue | 188 ++++++++++++++------ src/views/system/oauth2/token/token.data.ts | 48 ----- 3 files changed, 137 insertions(+), 109 deletions(-) delete mode 100644 src/views/system/oauth2/token/token.data.ts diff --git a/src/api/system/oauth2/token.ts b/src/api/system/oauth2/token.ts index dc7c44f5..8e9dca1e 100644 --- a/src/api/system/oauth2/token.ts +++ b/src/api/system/oauth2/token.ts @@ -11,18 +11,12 @@ export interface OAuth2TokenVO { expiresTime: Date } -export interface OAuth2TokenPageReqVO extends PageParam { - userId?: number - userType?: number - clientId?: string -} - // 查询 token列表 -export const getAccessTokenPageApi = (params: OAuth2TokenPageReqVO) => { +export const getAccessTokenPage = (params: PageParam) => { return request.get({ url: '/system/oauth2-token/page', params }) } // 删除 token -export const deleteAccessTokenApi = (accessToken: number) => { +export const deleteAccessToken = (accessToken: number) => { return request.delete({ url: '/system/oauth2-token/delete?accessToken=' + accessToken }) } diff --git a/src/views/system/oauth2/token/index.vue b/src/views/system/oauth2/token/index.vue index f0dfbd9c..e8c730e0 100644 --- a/src/views/system/oauth2/token/index.vue +++ b/src/views/system/oauth2/token/index.vue @@ -1,64 +1,146 @@ <template> - <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <template #actionbtns_default="{ row }"> - <!-- 操作:详情 --> - <XTextButton preIcon="ep:view" :title="t('action.detail')" @click="handleDetail(row)" /> - <!-- 操作:登出 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.logout')" - v-hasPermi="['system:oauth2-token:delete']" - @click="handleForceLogout(row.id)" + <content-wrap> + <!-- 搜索工作栏 --> + <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form-item label="用户编号" prop="userId"> + <el-input + v-model="queryParams.userId" + placeholder="请输入用户编号" + clearable + @keyup.enter="handleQuery" /> - </template> - </XTable> - </ContentWrap> - <XModal v-model="dialogVisible" :title="dialogTitle"> - <!-- 对话框(详情) --> - <Descriptions :schema="allSchemas.detailSchema" :data="detailData" /> - <!-- 操作按钮 --> - <template #footer> - <XButton :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> + </el-form-item> + <el-form-item label="用户类型" prop="userType"> + <el-select v-model="queryParams.userType" placeholder="请选择用户类型" clearable> + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.USER_TYPE)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="客户端编号" prop="clientId"> + <el-input + v-model="queryParams.clientId" + placeholder="请输入客户端编号" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + </el-form-item> + </el-form> + </content-wrap> + + <!-- 列表 --> + <content-wrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="访问令牌" align="center" prop="accessToken" width="300" /> + <el-table-column label="刷新令牌" align="center" prop="refreshToken" width="300" /> + <el-table-column label="用户编号" align="center" prop="userId" /> + <el-table-column label="用户类型" align="center" prop="userType"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" /> + </template> + </el-table-column> + <el-table-column + label="过期时间" + align="center" + prop="expiresTime" + :formatter="dateFormatter" + width="180" + /> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + :formatter="dateFormatter" + width="180" + /> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="danger" + @click="handleForceLogout(scope.row.id)" + v-hasPermi="['system:oauth2-token:delete']" + > + 强退 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> </template> -<script setup lang="ts" name="Token"> -import { allSchemas } from './token.data' -import * as TokenApi from '@/api/system/oauth2/token' -const { t } = useI18n() // 国际化 +<script setup lang="ts" name="Oauth2AccessToken"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' +import * as OAuth2AccessTokenApi from '@/api/system/oauth2/token' const message = useMessage() // 消息弹窗 -// 列表相关的变量 -const [registerTable, { reload }] = useXTable({ - allSchemas: allSchemas, - topActionSlots: false, - getListApi: TokenApi.getAccessTokenPageApi +const { t } = useI18n() // 国际化 + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + userId: null, + userType: null, + clientId: null }) +const queryFormRef = ref() // 搜索的表单 -// ========== 详情相关 ========== -const detailData = ref() // 详情 Ref -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref(t('action.detail')) // 弹出层标题 -// 详情 -const handleDetail = async (row: TokenApi.OAuth2TokenVO) => { - // 设置数据 - detailData.value = row - dialogVisible.value = true +/** 查询参数列表 */ +const getList = async () => { + loading.value = true + try { + const data = await OAuth2AccessTokenApi.getAccessTokenPage(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } } -// 强退操作 -const handleForceLogout = (rowId: number) => { - message - .confirm('是否要强制退出用户') - .then(async () => { - await TokenApi.deleteAccessTokenApi(rowId) - message.success(t('common.success')) - }) - .finally(async () => { - // 刷新列表 - await reload() - }) +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() } + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 强制退出操作 */ +const handleForceLogout = async (id: number) => { + try { + // 删除的二次确认 + await message.confirm('是否要强制退出用户') + // 发起删除 + await OAuth2AccessTokenApi.deleteAccessToken(id) + message.success(t('common.success')) + // 刷新列表 + await getList() + } catch {} +} + +/** 初始化 **/ +onMounted(() => { + getList() +}) </script> diff --git a/src/views/system/oauth2/token/token.data.ts b/src/views/system/oauth2/token/token.data.ts deleted file mode 100644 index 8a0e8486..00000000 --- a/src/views/system/oauth2/token/token.data.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -const { t } = useI18n() // 国际化 -// CrudSchema -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: null, - action: true, - columns: [ - { - title: '用户编号', - field: 'userId', - isSearch: true - }, - { - title: '访问令牌', - field: 'accessToken' - }, - { - title: '刷新令牌', - field: 'refreshToken' - }, - { - title: '客户端编号', - field: 'clientId', - isSearch: true - }, - { - title: '用户类型', - field: 'userType', - dictType: DICT_TYPE.USER_TYPE, - dictClass: 'number', - isSearch: true - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false - }, - { - title: '过期时间', - field: 'expiresTime', - formatter: 'formatDate', - isForm: false - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) From cf959599c6425b4f821394cbe3d16b4abb4ae59d Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sun, 19 Mar 2023 21:30:53 +0800 Subject: [PATCH 04/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9AReview?= =?UTF-8?q?=20=E6=95=8F=E6=84=9F=E8=AF=8D=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/sensitiveWord/form.vue | 11 ++++++----- src/views/system/sensitiveWord/index.vue | 24 +++++++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/views/system/sensitiveWord/form.vue b/src/views/system/sensitiveWord/form.vue index a0ed7a21..1dccd656 100644 --- a/src/views/system/sensitiveWord/form.vue +++ b/src/views/system/sensitiveWord/form.vue @@ -48,6 +48,7 @@ <script setup lang="ts"> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as SensitiveWordApi from '@/api/system/sensitiveWord' +import { CommonStatusEnum } from '@/utils/constants' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -56,11 +57,10 @@ const modelVisible = ref(false) // 弹窗的是否展示 const modelTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 -const tags = ref([]) const formData = ref({ id: undefined, name: '', - status: true, + status: CommonStatusEnum.ENABLE, description: '', tags: [] }) @@ -69,6 +69,7 @@ const formRules = reactive({ tags: [{ required: true, message: '标签不能为空', trigger: 'blur' }] }) const formRef = ref() // 表单 Ref +const tags = ref([]) // todo @blue-syd:在 openModal 里加载下 /** 打开弹窗 */ const openModal = async (type: string, id?: number) => { @@ -101,10 +102,10 @@ const submitForm = async () => { try { const data = formData.value as unknown as SensitiveWordApi.SensitiveWordVO if (formType.value === 'create') { - await SensitiveWordApi.createSensitiveWordApi(data) + await SensitiveWordApi.createSensitiveWordApi(data) // TODO @blue-syd:去掉 API 后缀 message.success(t('common.createSuccess')) } else { - await SensitiveWordApi.updateSensitiveWordApi(data) + await SensitiveWordApi.updateSensitiveWordApi(data) // TODO @blue-syd:去掉 API 后缀 message.success(t('common.updateSuccess')) } modelVisible.value = false @@ -120,7 +121,7 @@ const resetForm = () => { formData.value = { id: undefined, name: '', - status: true, + status: CommonStatusEnum.ENABLE, description: '', tags: [] } diff --git a/src/views/system/sensitiveWord/index.vue b/src/views/system/sensitiveWord/index.vue index 0eb8287d..93ea29f1 100644 --- a/src/views/system/sensitiveWord/index.vue +++ b/src/views/system/sensitiveWord/index.vue @@ -40,7 +40,6 @@ :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" /> </el-form-item> - <el-form-item> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> @@ -82,9 +81,11 @@ :key="index" v-for="(tag, index) in scope.row.tags" :index="index" + class="mr-5px" > {{ tag }} </el-tag> + </template> </el-table-column> <el-table-column @@ -132,14 +133,13 @@ import { DICT_TYPE, getDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' import * as SensitiveWordApi from '@/api/system/sensitiveWord' -import ConfigForm from './form.vue' +import ConfigForm from './form.vue' // TODO @blue-syd:组件名不对 const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 -const tags = ref([]) const queryParams = reactive({ pageNo: 1, pageSize: 10, @@ -150,12 +150,13 @@ const queryParams = reactive({ }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 +const tags = ref([]) /** 查询参数列表 */ const getList = async () => { loading.value = true try { - const data = await SensitiveWordApi.getSensitiveWordPageApi(queryParams) + const data = await SensitiveWordApi.getSensitiveWordPageApi(queryParams) // TODO @blue-syd:去掉 API 后缀哈 list.value = data.list total.value = data.total } finally { @@ -163,12 +164,6 @@ const getList = async () => { } } -/** 初始化标签select*/ -const getTags = async () => { - const data = await SensitiveWordApi.getSensitiveWordTagsApi() - tags.value = data -} - /** 搜索按钮操作 */ const handleQuery = () => { queryParams.pageNo = 1 @@ -187,6 +182,8 @@ const openModal = (type: string, id?: number) => { modalRef.value.openModal(type, id) } +// TODO @blue-syd:还少一个【测试】按钮的功能,参见 http://dashboard.yudao.iocoder.cn/system/sensitive-word + /** 删除按钮操作 */ const handleDelete = async (id: number) => { try { @@ -207,7 +204,7 @@ const handleExport = async () => { await message.exportConfirm() // 发起导出 exportLoading.value = true - const data = await SensitiveWordApi.exportSensitiveWordApi(queryParams) + const data = await SensitiveWordApi.exportSensitiveWordApi(queryParams) // TODO @blue-syd:去掉 API 后缀哈 download.excel(data, '敏感词.xls') } catch { } finally { @@ -215,6 +212,11 @@ const handleExport = async () => { } } +/** 获得 Tag 标签列表 */ +const getTags = async () => { + tags.value = await SensitiveWordApi.getSensitiveWordTagsApi() // TODO @blue-syd:去掉 API 后缀哈 +} + /** 初始化 **/ onMounted(() => { getTags() From 40bd2c57f8088962a968a13c891e7e5ea5b87632 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sun, 19 Mar 2023 22:14:55 +0800 Subject: [PATCH 05/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9AReview?= =?UTF-8?q?=20=E5=AD=97=E5=85=B8=E6=95=B0=E6=8D=AE=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/dict/dict.data.ts | 29 +++++--- src/api/system/dict/dict.type.ts | 24 ++++--- src/api/system/dict/types.ts | 50 -------------- src/store/modules/dict.ts | 6 +- .../codegen/components/CloumInfoForm.vue | 4 +- src/views/system/dict/data.form.vue | 25 +++---- src/views/system/dict/data.vue | 67 ++++++++++--------- src/views/system/dict/form.vue | 15 +++-- src/views/system/dict/index.vue | 55 ++++++++------- 9 files changed, 128 insertions(+), 147 deletions(-) delete mode 100644 src/api/system/dict/types.ts diff --git a/src/api/system/dict/dict.data.ts b/src/api/system/dict/dict.data.ts index fd97a2dc..6d981326 100644 --- a/src/api/system/dict/dict.data.ts +++ b/src/api/system/dict/dict.data.ts @@ -1,36 +1,49 @@ import request from '@/config/axios' -import type { DictDataVO, DictDataPageReqVO, DictDataExportReqVO } from './types' + +export type DictDataVO = { + id: number | undefined + sort: number | undefined + label: string + value: string + dictType: string + status: number + colorType: string + cssClass: string + remark: string + createTime: Date +} // 查询字典数据(精简)列表 -export const listSimpleDictDataApi = () => { +export const listSimpleDictData = () => { return request.get({ url: '/system/dict-data/list-all-simple' }) } // 查询字典数据列表 -export const getDictDataPageApi = (params: DictDataPageReqVO) => { +export const getDictDataPage = (params: PageParam) => { return request.get({ url: '/system/dict-data/page', params }) } // 查询字典数据详情 -export const getDictDataApi = (id: number) => { +export const getDictData = (id: number) => { return request.get({ url: '/system/dict-data/get?id=' + id }) } // 新增字典数据 -export const createDictDataApi = (data: DictDataVO) => { +export const createDictData = (data: DictDataVO) => { return request.post({ url: '/system/dict-data/create', data }) } // 修改字典数据 -export const updateDictDataApi = (data: DictDataVO) => { +export const updateDictData = (data: DictDataVO) => { return request.put({ url: '/system/dict-data/update', data }) } // 删除字典数据 -export const deleteDictDataApi = (id: number) => { +export const deleteDictData = (id: number) => { return request.delete({ url: '/system/dict-data/delete?id=' + id }) } + // 导出字典类型数据 -export const exportDictDataApi = (params: DictDataExportReqVO) => { +export const exportDictDataApi = (params) => { return request.get({ url: '/system/dict-data/export', params }) } diff --git a/src/api/system/dict/dict.type.ts b/src/api/system/dict/dict.type.ts index 22e6411e..0d9faeb2 100644 --- a/src/api/system/dict/dict.type.ts +++ b/src/api/system/dict/dict.type.ts @@ -1,36 +1,44 @@ import request from '@/config/axios' -import type { DictTypeVO, DictTypePageReqVO, DictTypeExportReqVO } from './types' + +export type DictTypeVO = { + id: number | undefined + name: string + type: string + status: number + remark: string + createTime: Date +} // 查询字典(精简)列表 -export const listSimpleDictTypeApi = () => { +export const listSimpleDictType = () => { return request.get({ url: '/system/dict-type/list-all-simple' }) } // 查询字典列表 -export const getDictTypePageApi = (params: DictTypePageReqVO) => { +export const getDictTypePage = (params: PageParam) => { return request.get({ url: '/system/dict-type/page', params }) } // 查询字典详情 -export const getDictTypeApi = (id: number) => { +export const getDictType = (id: number) => { return request.get({ url: '/system/dict-type/get?id=' + id }) } // 新增字典 -export const createDictTypeApi = (data: DictTypeVO) => { +export const createDictType = (data: DictTypeVO) => { return request.post({ url: '/system/dict-type/create', data }) } // 修改字典 -export const updateDictTypeApi = (data: DictTypeVO) => { +export const updateDictType = (data: DictTypeVO) => { return request.put({ url: '/system/dict-type/update', data }) } // 删除字典 -export const deleteDictTypeApi = (id: number) => { +export const deleteDictType = (id: number) => { return request.delete({ url: '/system/dict-type/delete?id=' + id }) } // 导出字典类型 -export const exportDictTypeApi = (params: DictTypeExportReqVO) => { +export const exportDictType = (params) => { return request.get({ url: '/system/dict-type/export', params }) } diff --git a/src/api/system/dict/types.ts b/src/api/system/dict/types.ts deleted file mode 100644 index 3421cd23..00000000 --- a/src/api/system/dict/types.ts +++ /dev/null @@ -1,50 +0,0 @@ -export type DictTypeVO = { - id: number | undefined - name: string - type: string - status: number | undefined - remark: string - createTime: Date -} - -export type DictTypePageReqVO = { - pageNo: number - pageSize: number - name: string - type: string - status: number | undefined - createTime: Date[] -} - -export type DictTypeExportReqVO = { - name: string - type: string - status: number - createTime: Date[] -} - -export type DictDataVO = { - id: number | undefined - sort: number | undefined - label: string - value: string - dictType: string - status: number - colorType: string - cssClass: string - remark: string - createTime: Date | undefined -} -export type DictDataPageReqVO = { - pageNo: number - pageSize: number - label: string - dictType: string - status: number | undefined -} - -export type DictDataExportReqVO = { - label: string - dictType: string - status: number -} diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts index 4e9ab39c..2d393e43 100644 --- a/src/store/modules/dict.ts +++ b/src/store/modules/dict.ts @@ -3,7 +3,7 @@ import { store } from '../index' import { DictDataVO } from '@/api/system/dict/types' import { CACHE_KEY, useCache } from '@/hooks/web/useCache' const { wsCache } = useCache('sessionStorage') -import { listSimpleDictDataApi } from '@/api/system/dict/dict.data' +import { listSimpleDictData } from '@/api/system/dict/dict.data' export interface DictValueType { value: any @@ -44,7 +44,7 @@ export const useDictStore = defineStore('dict', { this.dictMap = dictMap this.isSetDict = true } else { - const res = await listSimpleDictDataApi() + const res = await listSimpleDictData() // 设置数据 const dictDataMap = new Map<string, any>() res.forEach((dictData: DictDataVO) => { @@ -74,7 +74,7 @@ export const useDictStore = defineStore('dict', { }, async resetDict() { wsCache.delete(CACHE_KEY.DICT_CACHE) - const res = await listSimpleDictDataApi() + const res = await listSimpleDictData() // 设置数据 const dictDataMap = new Map<string, any>() res.forEach((dictData: DictDataVO) => { diff --git a/src/views/infra/codegen/components/CloumInfoForm.vue b/src/views/infra/codegen/components/CloumInfoForm.vue index 0b6ea697..5a60c546 100644 --- a/src/views/infra/codegen/components/CloumInfoForm.vue +++ b/src/views/infra/codegen/components/CloumInfoForm.vue @@ -114,7 +114,7 @@ import { PropType } from 'vue' import { DictTypeVO } from '@/api/system/dict/types' import { CodegenColumnVO } from '@/api/infra/codegen/types' -import { listSimpleDictTypeApi } from '@/api/system/dict/dict.type' +import { listSimpleDictType } from '@/api/system/dict/dict.type' const props = defineProps({ info: { @@ -125,7 +125,7 @@ const props = defineProps({ /** 查询字典下拉列表 */ const dictOptions = ref<DictTypeVO[]>() const getDictOptions = async () => { - const res = await listSimpleDictTypeApi() + const res = await listSimpleDictType() dictOptions.value = res } onMounted(async () => { diff --git a/src/views/system/dict/data.form.vue b/src/views/system/dict/data.form.vue index 5c85b946..c0b70b8e 100644 --- a/src/views/system/dict/data.form.vue +++ b/src/views/system/dict/data.form.vue @@ -17,7 +17,6 @@ <el-form-item label="数据标签" prop="label"> <el-input v-model="formData.label" placeholder="请输入数据标签" /> </el-form-item> - <el-form-item label="数据键值" prop="value"> <el-input v-model="formData.value" placeholder="请输入数据键值" /> </el-form-item> @@ -61,9 +60,8 @@ </template> <script setup lang="ts"> import { DICT_TYPE, getDictOptions } from '@/utils/dict' - import * as DictDataApi from '@/api/system/dict/dict.data' -import { DictDataVO } from '@/api/system/dict/types' +import { CommonStatusEnum } from '@/utils/constants' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -73,15 +71,14 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加 const formType = ref('') // 表单的类型:create - 新增;update - 修改 const formData = ref({ id: undefined, - sort: 0, + sort: undefined, label: '', value: '', dictType: '', - status: 0, + status: CommonStatusEnum.ENABLE, colorType: '', cssClass: '', - remark: '', - createTime: undefined + remark: '' }) const formRules = reactive({ label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], @@ -91,7 +88,6 @@ const formRules = reactive({ const formRef = ref() // 表单 Ref // 数据标签回显样式 - const colorTypeOptions = readonly([ { value: 'default', @@ -129,7 +125,7 @@ const openModal = async (type: string, id?: number) => { if (id) { formLoading.value = true try { - formData.value = await DictDataApi.getDictDataApi(id) + formData.value = await DictDataApi.getDictData(id) } finally { formLoading.value = false } @@ -147,12 +143,12 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - const data = formData.value as DictDataVO + const data = formData.value as DictDataApi.DictDataVO if (formType.value === 'create') { - await DictDataApi.createDictDataApi(data) + await DictDataApi.createDictData(data) message.success(t('common.createSuccess')) } else { - await DictDataApi.updateDictDataApi(data) + await DictDataApi.updateDictData(data) message.success(t('common.updateSuccess')) } modelVisible.value = false @@ -171,11 +167,10 @@ const resetForm = () => { label: '', value: '', dictType: '', - status: 0, + status: CommonStatusEnum.ENABLE, colorType: '', cssClass: '', - remark: '', - createTime: undefined + remark: '' } formRef.value?.resetFields() } diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue index 2c1b373a..e45dcfec 100644 --- a/src/views/system/dict/data.vue +++ b/src/views/system/dict/data.vue @@ -1,6 +1,12 @@ <template> <content-wrap> - <el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" label-width="68px"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="字典名称" prop="dictType"> <el-select v-model="queryParams.dictType"> <el-option @@ -46,7 +52,10 @@ </el-button> </el-form-item> </el-form> - <!-- 列表 --> + </content-wrap> + + <!-- 列表 --> + <content-wrap> <el-table v-loading="loading" :data="list"> <el-table-column label="字典编码" align="center" prop="id" /> <el-table-column label="字典标签" align="center" prop="label" /> @@ -59,12 +68,7 @@ </el-table-column> <el-table-column label="颜色类型" align="center" prop="colorType" /> <el-table-column label="CSS Class" align="center" prop="cssClass" /> - <el-table-column - label="备注" - align="center" - prop="remark" - :show-overflow-tooltip="tableTooltipConfig" - /> + <el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip /> <el-table-column label="创建时间" align="center" @@ -72,21 +76,28 @@ width="180" :formatter="dateFormatter" /> - <el-table-column label="操作" align="center"> <template #default="scope"> <el-button link + type="primary" @click="openModal('update', scope.row.id)" v-hasPermi="['system:dict:update']" - ><Icon icon="ic:outline-mode" class="mr-5px" />修改</el-button > - <el-button link @click="handleDelete(scope.row.id)" v-hasPermi="['system:dict:delete']" - ><Icon icon="material-symbols:delete-forever-sharp" class="mr-5px" />删除</el-button + 修改 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['system:dict:delete']" > + 删除 + </el-button> </template> </el-table-column> </el-table> + <!-- 分页 --> <Pagination :total="total" v-model:page="queryParams.pageNo" @@ -94,30 +105,24 @@ @pagination="getList" /> </content-wrap> + <!-- 表单弹窗:添加/修改 --> <data-form ref="modalRef" @success="getList" /> </template> - <script setup lang="ts" name="Data"> import * as DictDataApi from '@/api/system/dict/dict.data' -import { listSimpleDictTypeApi } from '@/api/system/dict/dict.type' +import * as DictTypeApi from '@/api/system/dict/dict.data' import { getDictOptions, DICT_TYPE } from '@/utils/dict' import download from '@/utils/download' import { dateFormatter } from '@/utils/formatTime' import DataForm from './data.form.vue' -import { DictTypeVO } from '@/api/system/dict/types' -import { useRoute } from 'vue-router' +import type { DictTypeVO } from '@/api/system/dict/dict.type' const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 - -const route = useRoute() +const route = useRoute() // 路由 const simpleDictList = ref<DictTypeVO[]>() -const tableTooltipConfig = readonly({ - appendTo: 'body' -}) - const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 @@ -135,18 +140,13 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - const data = await DictDataApi.getDictDataPageApi(queryParams) + const data = await DictDataApi.getDictDataPage(queryParams) list.value = data.list total.value = data.total } finally { loading.value = false } } -// 查询字典(精简)列表 -const getSimpleDictList = async () => { - const data = await listSimpleDictTypeApi() - simpleDictList.value = data -} /** 搜索按钮操作 */ const handleQuery = () => { @@ -172,7 +172,7 @@ const handleDelete = async (id: number) => { // 删除的二次确认 await message.delConfirm() // 发起删除 - await DictDataApi.deleteDictDataApi(id) + await DictDataApi.deleteDictData(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() @@ -194,10 +194,15 @@ const handleExport = async () => { } } +/** 查询字典(精简)列表 */ +const getSimpleDictList = async () => { + simpleDictList.value = await DictTypeApi.listSimpleDictData() +} + /** 初始化 **/ onMounted(() => { getList() + // 查询字典(精简)列表 + getSimpleDictList() }) -// 查询字典(精简)列表 -getSimpleDictList() </script> diff --git a/src/views/system/dict/form.vue b/src/views/system/dict/form.vue index 28b42c9d..af02c597 100644 --- a/src/views/system/dict/form.vue +++ b/src/views/system/dict/form.vue @@ -43,7 +43,8 @@ <script setup lang="ts"> import { DICT_TYPE, getDictOptions } from '@/utils/dict' import * as DictTypeApi from '@/api/system/dict/dict.type' -import { DictTypeVO } from '@/api/system/dict/types' +import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -55,7 +56,7 @@ const formData = ref({ id: undefined, name: '', type: '', - status: 0, + status: CommonStatusEnum.ENABLE, remark: '' }) const formRules = reactive({ @@ -74,7 +75,7 @@ const openModal = async (type: string, id?: number) => { if (id) { formLoading.value = true try { - formData.value = await DictTypeApi.getDictTypeApi(id) + formData.value = await DictTypeApi.getDictType(id) } finally { formLoading.value = false } @@ -92,12 +93,12 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - const data = formData.value as DictTypeVO + const data = formData.value as DictTypeApi.DictTypeVO if (formType.value === 'create') { - await DictTypeApi.createDictTypeApi(data) + await DictTypeApi.createDictType(data) message.success(t('common.createSuccess')) } else { - await DictTypeApi.updateDictTypeApi(data) + await DictTypeApi.updateDictType(data) message.success(t('common.updateSuccess')) } modelVisible.value = false @@ -114,7 +115,7 @@ const resetForm = () => { id: undefined, type: '', name: '', - status: undefined, + status: CommonStatusEnum.ENABLE, remark: '' } formRef.value?.resetFields() diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue index 367cc9d4..a029d2ee 100644 --- a/src/views/system/dict/index.vue +++ b/src/views/system/dict/index.vue @@ -1,6 +1,13 @@ <template> + <!-- 搜索工作栏 --> <content-wrap> - <el-form :model="queryParams" ref="queryFormRef" size="small" :inline="true" label-width="68px"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="字典名称" prop="name"> <el-input v-model="queryParams.name" @@ -63,20 +70,14 @@ </el-button> </el-form-item> </el-form> + </content-wrap> - <!-- 列表 --> + <!-- 列表 --> + <content-wrap> <el-table v-loading="loading" :data="list"> <el-table-column label="字典编号" align="center" prop="id" /> <el-table-column label="字典名称" align="center" prop="name" show-overflow-tooltip /> - <el-table-column label="字典类型" align="center" show-overflow-tooltip> - <template #default="scope"> - <div> - <router-link :to="'/dict/type/data/' + scope.row.type"> - <span>{{ scope.row.type }}</span> - </router-link> - </div> - </template> - </el-table-column> + <el-table-column label="字典类型" align="center" prop="type" width="300" /> <el-table-column label="状态" align="center" prop="status"> <template #default="scope"> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> @@ -90,22 +91,31 @@ prop="createTime" width="180" /> - <el-table-column label="操作" align="center"> <template #default="scope"> <el-button link + type="primary" @click="openModal('update', scope.row.id)" v-hasPermi="['system:dict:update']" - ><Icon icon="ic:outline-mode" class="mr-5px" />修改</el-button > - <el-button link @click="handleDelete(scope.row.id)" v-hasPermi="['system:dict:delete']" - ><Icon icon="material-symbols:delete-forever-sharp" class="mr-5px" />删除</el-button + 修改 + </el-button> + <router-link :to="'/dict/type/data/' + scope.row.type"> + <el-button link type="primary">数据</el-button> + </router-link> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['system:dict:delete']" > + 删除 + </el-button> </template> </el-table-column> </el-table> - + <!-- 分页 --> <Pagination :total="total" v-model:page="queryParams.pageNo" @@ -113,25 +123,24 @@ @pagination="getList" /> </content-wrap> + <!-- 表单弹窗:添加/修改 --> <dict-type-form ref="modalRef" @success="getList" /> </template> <script setup lang="ts" name="Dict"> -import * as DictTypeApi from '@/api/system/dict/dict.type' import { getDictOptions, DICT_TYPE } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' +import * as DictTypeApi from '@/api/system/dict/dict.type' import DictTypeForm from './form.vue' -import { DictTypePageReqVO } from '@/api/system/dict/types' import download from '@/utils/download' const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 - const list = ref([]) // 字典表格数据 -const queryParams = reactive<DictTypePageReqVO>({ +const queryParams = reactive({ pageNo: 1, pageSize: 10, name: '', @@ -146,7 +155,7 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - const data = await DictTypeApi.getDictTypePageApi(queryParams) + const data = await DictTypeApi.getDictTypePage(queryParams) list.value = data.list total.value = data.total } finally { @@ -178,7 +187,7 @@ const handleDelete = async (id: number) => { // 删除的二次确认 await message.delConfirm() // 发起删除 - await DictTypeApi.deleteDictTypeApi(id) + await DictTypeApi.deleteDictType(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() @@ -192,7 +201,7 @@ const handleExport = async () => { await message.exportConfirm() // 发起导出 exportLoading.value = true - const data = await DictTypeApi.exportDictTypeApi(queryParams) + const data = await DictTypeApi.exportDictType(queryParams) download.excel(data, '字典类型.xls') } catch { } finally { From 030ecd3137f626854e3c4c4fc713e297ccbd5f41 Mon Sep 17 00:00:00 2001 From: zhangjl <zhangjinlong1211@126.com> Date: Sun, 19 Mar 2023 23:20:49 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=9A=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=A0=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/errorCode/index.ts | 4 +- src/views/system/errorCode/errorCode.data.ts | 54 ---- src/views/system/errorCode/form.vue | 114 +++++++ src/views/system/errorCode/index.vue | 321 +++++++++++-------- 4 files changed, 312 insertions(+), 181 deletions(-) delete mode 100644 src/views/system/errorCode/errorCode.data.ts create mode 100644 src/views/system/errorCode/form.vue diff --git a/src/api/system/errorCode/index.ts b/src/api/system/errorCode/index.ts index 0e000794..65eabd3a 100644 --- a/src/api/system/errorCode/index.ts +++ b/src/api/system/errorCode/index.ts @@ -1,10 +1,10 @@ import request from '@/config/axios' export interface ErrorCodeVO { - id: number + id: number | undefined type: number applicationName: string - code: number + code: number | undefined message: string memo: string createTime: Date diff --git a/src/views/system/errorCode/errorCode.data.ts b/src/views/system/errorCode/errorCode.data.ts deleted file mode 100644 index 4736068b..00000000 --- a/src/views/system/errorCode/errorCode.data.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -const { t } = useI18n() // 国际化 - -// 表单校验 -export const rules = reactive({ - applicationName: [required], - code: [required], - message: [required] -}) - -// 新增 + 修改 -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: 'id', - primaryTitle: '编号', - action: true, - columns: [ - { - title: '错误码类型', - field: 'type', - dictType: DICT_TYPE.SYSTEM_ERROR_CODE_TYPE, - dictClass: 'number', - isSearch: true - }, - { - title: '应用名', - field: 'applicationName', - isSearch: true - }, - { - title: '错误码编码', - field: 'code', - isSearch: true - }, - { - title: '错误码错误提示', - field: 'message', - isSearch: true - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false, - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) diff --git a/src/views/system/errorCode/form.vue b/src/views/system/errorCode/form.vue new file mode 100644 index 00000000..5e6a0bc8 --- /dev/null +++ b/src/views/system/errorCode/form.vue @@ -0,0 +1,114 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="100px" + v-loading="formLoading" + > + <el-form-item label="应用名" prop="applicationName"> + <el-input v-model="formData.applicationName" placeholder="请输入应用名" clearable /> + </el-form-item> + <el-form-item label="错误码编码" prop="code"> + <el-input v-model="formData.code" placeholder="请输入错误码编码" clearable /> + </el-form-item> + <el-form-item label="错误码提示" prop="message"> + <el-input v-model="formData.message" placeholder="请输入错误码提示" clearable /> + </el-form-item> + <el-form-item label="备注" prop="memo"> + <el-input v-model="formData.memo" placeholder="请输入备注" clearable /> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import * as ErrorCodeApi from '@/api/system/errorCode' + +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +// 表单参数 +const formData = ref({ + id: undefined, + code: undefined, + applicationName: '', + message: '', + memo: '' +}) +// 表单校验 +const formRules = reactive({ + applicationName: [{ required: true, message: '应用名不能为空', trigger: 'blur' }], + code: [{ required: true, message: '错误码编码不能为空', trigger: 'blur' }], + message: [{ required: true, message: '错误码提示不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 打开弹窗 */ +const openModal = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await ErrorCodeApi.getErrorCodeApi(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 + +/** 提交按钮 */ +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as ErrorCodeApi.ErrorCodeVO + if (formType.value === 'create') { + await ErrorCodeApi.createErrorCodeApi(data) + message.success(t('common.createSuccess')) + } else { + await ErrorCodeApi.updateErrorCodeApi(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 表单重置 */ +const resetForm = () => { + formData.value = { + id: undefined, + applicationName: '', + code: undefined, + message: '', + memo: '' + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/errorCode/index.vue b/src/views/system/errorCode/index.vue index 1ff3d103..8f7dac33 100644 --- a/src/views/system/errorCode/index.vue +++ b/src/views/system/errorCode/index.vue @@ -1,145 +1,216 @@ <template> - <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <!-- 操作:新增 --> - <template #toolbar_buttons> - <XButton + <!-- 搜索工作栏 --> + <content-wrap> + <el-form :model="queryParams" ref="queryFormRef" class="-mb-15px" :inline="true"> + <el-form-item label="错误码类型" prop="type"> + <el-select v-model="queryParams.type" placeholder="请选择错误码类型" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_ERROR_CODE_TYPE)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="应用名" prop="applicationName"> + <el-input + v-model="queryParams.applicationName" + placeholder="请输入应用名" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="错误码编码" prop="code"> + <el-input + v-model="queryParams.code" + placeholder="请输入错误码编码" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="错误码提示" prop="message"> + <el-input + v-model="queryParams.message" + placeholder="请输入错误码提示" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + value-format="YYYY-MM-DD HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" + @click="openModal('create')" v-hasPermi="['system:error-code:create']" - @click="handleCreate()" - /> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:修改 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['system:error-code:update']" - @click="handleUpdate(row.id)" - /> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['system:error-code:query']" - @click="handleDetail(row.id)" - /> - <!-- 操作:删除 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.del')" - v-hasPermi="['system:error-code:delete']" - @click="deleteData(row.id)" - /> - </template> - </XTable> - </ContentWrap> - <!-- 弹窗 --> - <XModal id="errorCodeModel" v-model="dialogVisible" :title="dialogTitle"> - <!-- 对话框(添加 / 修改) --> - <Form - v-if="['create', 'update'].includes(actionType)" - :schema="allSchemas.formSchema" - :rules="rules" - ref="formRef" - /> - <!-- 对话框(详情) --> - <Descriptions - v-if="actionType === 'detail'" - :schema="allSchemas.detailSchema" - :data="detailData" - /> - <template #footer> - <!-- 按钮:保存 --> - <XButton - v-if="['create', 'update'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitForm()" + > + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['system:error-code:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + </content-wrap> + <!-- 列表 --> + <content-wrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="编号" align="center" prop="id" /> + <el-table-column label="类型" align="center" prop="type" width="80"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.SYSTEM_ERROR_CODE_TYPE" :value="scope.row.type" /> + </template> + </el-table-column> + <el-table-column label="应用名" align="center" prop="applicationName" width="200" /> + <el-table-column label="错误码编码" align="center" prop="code" width="120" /> + <el-table-column label="错误码提示" align="center" prop="message" width="300" /> + <el-table-column label="备注" align="center" prop="memo" width="200" /> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + :formatter="dateFormatter" /> - <!-- 按钮:关闭 --> - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openModal('update', scope.row.id)" + v-hasPermi="['system:error-code:update']" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['system:error-code:delete']" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页组件 --> + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + <!-- 表单弹窗:添加/修改 --> + <error-code-form ref="modalRef" @success="getList" /> </template> + <script setup lang="ts" name="ErrorCode"> -import type { FormExpose } from '@/components/Form' -// 业务相关的 import -import { rules, allSchemas } from './errorCode.data' import * as ErrorCodeApi from '@/api/system/errorCode' - -const { t } = useI18n() // 国际化 +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' +import ErrorCodeForm from './form.vue' +import download from '@/utils/download' const message = useMessage() // 消息弹窗 -// 列表相关的变量 -const [registerTable, { reload, deleteData }] = useXTable({ - allSchemas: allSchemas, - getListApi: ErrorCodeApi.getErrorCodePageApi, - deleteApi: ErrorCodeApi.deleteErrorCodeApi +const { t } = useI18n() // 国际化 + +// 遮罩层 +const loading = ref(true) +// 导出遮罩层 +const exportLoading = ref(false) +// 总条数 +const total = ref(0) +// 错误码列表 +const list = ref([]) +// 查询参数 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + type: undefined, + applicationName: undefined, + code: undefined, + message: undefined, + createTime: [] }) -// 弹窗相关的变量 -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('edit') // 弹出层标题 -const actionType = ref('') // 操作按钮的类型 -const actionLoading = ref(false) // 按钮 Loading -const formRef = ref<FormExpose>() // 表单 Ref -const detailData = ref() // 详情 Ref +// 搜索的表单 +const queryFormRef = ref() -// 设置标题 -const setDialogTile = (type: string) => { - dialogTitle.value = t('action.' + type) - actionType.value = type - dialogVisible.value = true +/** 查询列表 */ +const getList = async () => { + loading.value = true + // 执行查询 + try { + const data = await ErrorCodeApi.getErrorCodePageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } } -// 新增操作 -const handleCreate = () => { - setDialogTile('create') +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() } -// 修改操作 -const handleUpdate = async (rowId: number) => { - setDialogTile('update') - // 设置数据 - const res = await ErrorCodeApi.getErrorCodeApi(rowId) - unref(formRef)?.setValues(res) +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() } -// 详情操作 -const handleDetail = async (rowId: number) => { - setDialogTile('detail') - // 设置数据 - const res = await ErrorCodeApi.getErrorCodeApi(rowId) - detailData.value = res +/** 添加/修改操作 */ +const modalRef = ref() +const openModal = (type: string, id?: number) => { + modalRef.value.openModal(type, id) } -// 提交新增/修改的表单 -const submitForm = async () => { - const elForm = unref(formRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid) { - actionLoading.value = true - // 提交请求 - try { - const data = unref(formRef)?.formModel as ErrorCodeApi.ErrorCodeVO - if (actionType.value === 'create') { - await ErrorCodeApi.createErrorCodeApi(data) - message.success(t('common.createSuccess')) - } else { - await ErrorCodeApi.updateErrorCodeApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - // 刷新列表 - await reload() - } - } - }) +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + await ErrorCodeApi.deleteErrorCodeApi(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} } +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await ErrorCodeApi.excelErrorCodeApi(queryParams) + download.excel(data, '参数配置.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +/** 初始化 **/ +onMounted(() => { + getList() +}) </script> From c40de0330225e1ef81c6c9644c57499773258eda Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Mon, 20 Mar 2023 00:20:24 +0800 Subject: [PATCH 07/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9A?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=20form=20=E7=9A=84=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/infra/config/index.vue | 18 +++++++++++++-- src/views/system/dict/data.vue | 24 ++++++++------------ src/views/system/dict/index.vue | 13 ++++------- src/views/system/notice/index.vue | 16 ++++++++++++-- src/views/system/oauth2/token/index.vue | 17 +++++++++++++-- src/views/system/operatelog/index.vue | 29 ++++++++++++++++++++----- 6 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/views/infra/config/index.vue b/src/views/infra/config/index.vue index 11fc8fe0..fcc3c12c 100644 --- a/src/views/infra/config/index.vue +++ b/src/views/infra/config/index.vue @@ -1,13 +1,20 @@ <template> <!-- 搜索 --> <content-wrap> - <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="参数名称" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入参数名称" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="参数键名" prop="key"> @@ -16,10 +23,16 @@ placeholder="请输入参数键名" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="系统内置" prop="type"> - <el-select v-model="queryParams.type" placeholder="请选择系统内置" clearable> + <el-select + v-model="queryParams.type" + placeholder="请选择系统内置" + clearable + class="!w-240px" + > <el-option v-for="dict in getDictOptions(DICT_TYPE.INFRA_CONFIG_TYPE)" :key="parseInt(dict.value)" @@ -36,6 +49,7 @@ start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" /> </el-form-item> <el-form-item> diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue index e45dcfec..7b159481 100644 --- a/src/views/system/dict/data.vue +++ b/src/views/system/dict/data.vue @@ -8,13 +8,8 @@ label-width="68px" > <el-form-item label="字典名称" prop="dictType"> - <el-select v-model="queryParams.dictType"> - <el-option - v-for="item in simpleDictList" - :key="item.id" - :label="item.name" - :value="item.type" - /> + <el-select v-model="queryParams.dictType" class="!w-240px"> + <el-option v-for="item in dicts" :key="item.type" :label="item.name" :value="item.type" /> </el-select> </el-form-item> <el-form-item label="字典标签" prop="label"> @@ -23,10 +18,11 @@ placeholder="请输入字典标签" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="queryParams.status" placeholder="数据状态" clearable> + <el-select v-model="queryParams.status" placeholder="数据状态" clearable class="!w-240px"> <el-option v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -111,18 +107,15 @@ </template> <script setup lang="ts" name="Data"> import * as DictDataApi from '@/api/system/dict/dict.data' -import * as DictTypeApi from '@/api/system/dict/dict.data' +import * as DictTypeApi from '@/api/system/dict/dict.type' import { getDictOptions, DICT_TYPE } from '@/utils/dict' import download from '@/utils/download' import { dateFormatter } from '@/utils/formatTime' import DataForm from './data.form.vue' -import type { DictTypeVO } from '@/api/system/dict/dict.type' const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const route = useRoute() // 路由 -const simpleDictList = ref<DictTypeVO[]>() - const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 @@ -135,6 +128,7 @@ const queryParams = reactive({ }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 +const dicts = ref<DictTypeApi.DictTypeVO[]>() // 字典类型的列表 /** 查询参数列表 */ const getList = async () => { @@ -195,14 +189,14 @@ const handleExport = async () => { } /** 查询字典(精简)列表 */ -const getSimpleDictList = async () => { - simpleDictList.value = await DictTypeApi.listSimpleDictData() +const getDictList = async () => { + dicts.value = await DictTypeApi.listSimpleDictType() } /** 初始化 **/ onMounted(() => { getList() // 查询字典(精简)列表 - getSimpleDictList() + getDictList() }) </script> diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue index a029d2ee..4e304bf5 100644 --- a/src/views/system/dict/index.vue +++ b/src/views/system/dict/index.vue @@ -13,8 +13,8 @@ v-model="queryParams.name" placeholder="请输入字典名称" clearable - style="width: 240px" @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="字典类型" prop="type"> @@ -22,17 +22,12 @@ v-model="queryParams.type" placeholder="请输入字典类型" clearable - style="width: 240px" @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select - v-model="queryParams.status" - placeholder="字典状态" - clearable - style="width: 240px" - > + <el-select v-model="queryParams.status" placeholder="字典状态" clearable class="!w-240px"> <el-option v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" @@ -44,13 +39,13 @@ <el-form-item label="创建时间" prop="createTime"> <el-date-picker v-model="queryParams.createTime" - style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" /> </el-form-item> <el-form-item> diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue index e36f3aac..65076f9f 100644 --- a/src/views/system/notice/index.vue +++ b/src/views/system/notice/index.vue @@ -1,17 +1,29 @@ <template> <content-wrap> <!-- 搜索工作栏 --> - <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="公告标题" prop="title"> <el-input v-model="queryParams.title" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="公告状态" prop="status"> - <el-select v-model="queryParams.status" placeholder="请选择公告状态" clearable> + <el-select + v-model="queryParams.status" + placeholder="请选择公告状态" + clearable + class="!w-240px" + > <el-option v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" diff --git a/src/views/system/oauth2/token/index.vue b/src/views/system/oauth2/token/index.vue index e8c730e0..7e8aca22 100644 --- a/src/views/system/oauth2/token/index.vue +++ b/src/views/system/oauth2/token/index.vue @@ -1,17 +1,29 @@ <template> <content-wrap> <!-- 搜索工作栏 --> - <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="90px" + > <el-form-item label="用户编号" prop="userId"> <el-input v-model="queryParams.userId" placeholder="请输入用户编号" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="用户类型" prop="userType"> - <el-select v-model="queryParams.userType" placeholder="请选择用户类型" clearable> + <el-select + v-model="queryParams.userType" + placeholder="请选择用户类型" + clearable + class="!w-240px" + > <el-option v-for="dict in getIntDictOptions(DICT_TYPE.USER_TYPE)" :key="dict.value" @@ -26,6 +38,7 @@ placeholder="请输入客户端编号" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item> diff --git a/src/views/system/operatelog/index.vue b/src/views/system/operatelog/index.vue index f9667912..d7490ba8 100644 --- a/src/views/system/operatelog/index.vue +++ b/src/views/system/operatelog/index.vue @@ -1,13 +1,20 @@ <template> <content-wrap> <!-- 搜索工作栏 --> - <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="系统模块" prop="module"> <el-input v-model="queryParams.module" placeholder="请输入系统模块" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="操作人员" prop="userNickname"> @@ -16,10 +23,16 @@ placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> - <el-form-item label="类型" prop="type"> - <el-select v-model="queryParams.type" placeholder="操作类型" clearable> + <el-form-item label="操作类型" prop="type"> + <el-select + v-model="queryParams.type" + placeholder="请选择操作类型" + clearable + class="!w-240px" + > <el-option v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_OPERATE_TYPE)" :key="parseInt(dict.value)" @@ -28,8 +41,13 @@ /> </el-select> </el-form-item> - <el-form-item label="状态" prop="success"> - <el-select v-model="queryParams.success" placeholder="操作状态" clearable> + <el-form-item label="操作状态" prop="success"> + <el-select + v-model="queryParams.success" + placeholder="请选择操作状态" + clearable + class="!w-240px" + > <el-option :key="true" label="成功" :value="true" /> <el-option :key="false" label="失败" :value="false" /> </el-select> @@ -42,6 +60,7 @@ start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" /> </el-form-item> <el-form-item> From 812300cc04050ee0357a0ceea11ec7d5e377909f Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Mon, 20 Mar 2023 08:53:28 +0800 Subject: [PATCH 08/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9AREVIEW?= =?UTF-8?q?=20=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/errorCode/form.vue | 2 -- src/views/system/errorCode/index.vue | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/views/system/errorCode/form.vue b/src/views/system/errorCode/form.vue index 5e6a0bc8..9544c6ab 100644 --- a/src/views/system/errorCode/form.vue +++ b/src/views/system/errorCode/form.vue @@ -74,8 +74,6 @@ defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 - -/** 提交按钮 */ const submitForm = async () => { // 校验表单 if (!formRef) return diff --git a/src/views/system/errorCode/index.vue b/src/views/system/errorCode/index.vue index 8f7dac33..fc152903 100644 --- a/src/views/system/errorCode/index.vue +++ b/src/views/system/errorCode/index.vue @@ -1,7 +1,13 @@ <template> <!-- 搜索工作栏 --> <content-wrap> - <el-form :model="queryParams" ref="queryFormRef" class="-mb-15px" :inline="true"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="90px" + > <el-form-item label="错误码类型" prop="type"> <el-select v-model="queryParams.type" placeholder="请选择错误码类型" clearable> <el-option @@ -9,6 +15,7 @@ :key="dict.value" :label="dict.label" :value="dict.value" + class="!w-240px" /> </el-select> </el-form-item> @@ -18,6 +25,7 @@ placeholder="请输入应用名" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="错误码编码" prop="code"> @@ -34,6 +42,7 @@ placeholder="请输入错误码提示" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="创建时间" prop="createTime"> @@ -44,6 +53,7 @@ start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" /> </el-form-item> <el-form-item> @@ -68,6 +78,7 @@ </el-form-item> </el-form> </content-wrap> + <!-- 列表 --> <content-wrap> <el-table v-loading="loading" :data="list"> @@ -118,6 +129,7 @@ @pagination="getList" /> </content-wrap> + <!-- 表单弹窗:添加/修改 --> <error-code-form ref="modalRef" @success="getList" /> </template> @@ -194,6 +206,7 @@ const handleDelete = async (id: number) => { await getList() } catch {} } + /** 导出按钮操作 */ const handleExport = async () => { try { @@ -202,7 +215,7 @@ const handleExport = async () => { // 发起导出 exportLoading.value = true const data = await ErrorCodeApi.excelErrorCodeApi(queryParams) - download.excel(data, '参数配置.xls') + download.excel(data, '错误码.xls') } catch { } finally { exportLoading.value = false From 7d1d87a1ac5943ff6b27be738f191ae82e95895b Mon Sep 17 00:00:00 2001 From: dtsz <314942997@qq.com> Date: Tue, 21 Mar 2023 20:18:07 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/infra/apiErrorLog/index.ts | 4 +- .../infra/apiErrorLog/apiErrorLog.data.ts | 76 ----- src/views/infra/apiErrorLog/detail.vue | 76 +++++ src/views/infra/apiErrorLog/index.vue | 311 +++++++++++++----- 4 files changed, 305 insertions(+), 162 deletions(-) delete mode 100644 src/views/infra/apiErrorLog/apiErrorLog.data.ts create mode 100644 src/views/infra/apiErrorLog/detail.vue diff --git a/src/api/infra/apiErrorLog/index.ts b/src/api/infra/apiErrorLog/index.ts index 06515c36..779cfd61 100644 --- a/src/api/infra/apiErrorLog/index.ts +++ b/src/api/infra/apiErrorLog/index.ts @@ -46,7 +46,7 @@ export interface ApiErrorLogExportReqVO { } // 查询列表API 访问日志 -export const getApiErrorLogPageApi = (params: ApiErrorLogPageReqVO) => { +export const getApiErrorLogPageApi = (params: PageParam) => { return request.get({ url: '/infra/api-error-log/page', params }) } @@ -58,7 +58,7 @@ export const updateApiErrorLogPageApi = (id: number, processStatus: number) => { } // 导出API 访问日志 -export const exportApiErrorLogApi = (params: ApiErrorLogExportReqVO) => { +export const exportApiErrorLogApi = (params) => { return request.download({ url: '/infra/api-error-log/export-excel', params diff --git a/src/views/infra/apiErrorLog/apiErrorLog.data.ts b/src/views/infra/apiErrorLog/apiErrorLog.data.ts deleted file mode 100644 index a539c167..00000000 --- a/src/views/infra/apiErrorLog/apiErrorLog.data.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' - -// CrudSchema -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: 'id', - primaryTitle: '日志编号', - action: true, - actionWidth: '300', - columns: [ - { - title: '链路追踪', - field: 'traceId', - isTable: false - }, - { - title: '用户编号', - field: 'userId', - isSearch: true - }, - { - title: '用户类型', - field: 'userType', - dictType: DICT_TYPE.USER_TYPE, - isSearch: true - }, - { - title: '应用名', - field: 'applicationName', - isSearch: true - }, - { - title: '请求方法名', - field: 'requestMethod' - }, - { - title: '请求地址', - field: 'requestUrl', - isSearch: true - }, - { - title: '异常发生时间', - field: 'exceptionTime', - formatter: 'formatDate', - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - } - }, - { - title: '异常名', - field: 'exceptionName' - }, - { - title: '处理状态', - field: 'processStatus', - dictType: DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, - dictClass: 'number', - isSearch: true - }, - { - title: '处理人', - field: 'processUserId', - isTable: false - }, - { - title: '处理时间', - field: 'processTime', - formatter: 'formatDate', - isTable: false - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) diff --git a/src/views/infra/apiErrorLog/detail.vue b/src/views/infra/apiErrorLog/detail.vue new file mode 100644 index 00000000..9ede0f1b --- /dev/null +++ b/src/views/infra/apiErrorLog/detail.vue @@ -0,0 +1,76 @@ +<template> + <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="500" width="800"> + <el-descriptions border :column="1"> + <el-descriptions-item label="日志主键" min-width="120"> + {{ detailData.id }} + </el-descriptions-item> + <el-descriptions-item label="链路追踪"> + {{ detailData.traceId }} + </el-descriptions-item> + <el-descriptions-item label="应用名"> + {{ detailData.applicationName }} + </el-descriptions-item> + <el-descriptions-item label="用户信息"> + {{ detailData.userId }} | + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="detailData.userType" /> + | {{ detailData.userIp }} | {{ detailData.userAgent }} + </el-descriptions-item> + <el-descriptions-item label="请求信息"> + {{ detailData.requestMethod }} | {{ detailData.requestUrl }} + </el-descriptions-item> + <el-descriptions-item label="请求参数"> + {{ detailData.requestParams }} + </el-descriptions-item> + <el-descriptions-item label="异常时间"> + {{ formatDate(detailData.exceptionTime, 'YYYY-MM-DD HH:mm:ss') }} + </el-descriptions-item> + <el-descriptions-item label="异常名"> + {{ detailData.exceptionName }} + </el-descriptions-item> + <el-descriptions-item label="异常名" v-if="detailData.exceptionStackTrace"> + <el-input + type="textarea" + :readonly="true" + :autosize="{ maxRows: 20 }" + v-model="detailData.exceptionStackTrace" + /> + </el-descriptions-item> + <el-descriptions-item label="处理状态"> + <dict-tag + :type="DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS" + :value="detailData.processStatus" + /> + </el-descriptions-item> + <el-descriptions-item label="处理人" v-if="detailData.processUserId"> + {{ detailData.processUserId }} + </el-descriptions-item> + <el-descriptions-item label="处理时间" v-if="detailData.processTime"> + {{ formatDate(detailData.processTime, 'YYYY-MM-DD HH:mm:ss') }} + </el-descriptions-item> + </el-descriptions> + </Dialog> +</template> + +<script setup lang="ts"> +import { DICT_TYPE } from '@/utils/dict' +import { formatDate } from '@/utils/formatTime' +import * as ApiErrorLog from '@/api/infra/apiErrorLog' + +const modelVisible = ref(false) // 弹窗的是否展示 +const detailLoading = ref(false) // 表单的加载中 +const detailData = ref() // 详情数据 + +/** 打开弹窗 */ +const openModal = async (data: ApiErrorLog.ApiErrorLogVO) => { + modelVisible.value = true + // 设置数据 + detailLoading.value = true + try { + detailData.value = data + } finally { + detailLoading.value = false + } +} + +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 +</script> diff --git a/src/views/infra/apiErrorLog/index.vue b/src/views/infra/apiErrorLog/index.vue index 4193351a..664546cb 100644 --- a/src/views/infra/apiErrorLog/index.vue +++ b/src/views/infra/apiErrorLog/index.vue @@ -1,99 +1,242 @@ <template> - <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <!-- 操作:导出 --> - <template #toolbar_buttons> - <XButton - type="warning" - preIcon="ep:download" - :title="t('action.export')" - @click="exportList('错误数据.xls')" + <content-wrap> + <!-- 搜索工作栏 --> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > + <el-form-item label="用户编号" prop="userId"> + <el-input + v-model="queryParams.userId" + placeholder="请输入用户编号" + clearable + @keyup.enter="handleQuery" + class="!w-240px" /> - </template> - <template #duration_default="{ row }"> - <span>{{ row.duration + 'ms' }}</span> - </template> - <template #resultCode_default="{ row }"> - <span>{{ row.resultCode === 0 ? '成功' : '失败(' + row.resultMsg + ')' }}</span> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['infra:api-access-log:query']" - @click="handleDetail(row)" + </el-form-item> + <el-form-item label="用户类型" prop="userType"> + <el-select + v-model="queryParams.userType" + placeholder="请选择用户类型" + clearable + class="!w-240px" + > + <el-option + v-for="dict in getDictOptions(DICT_TYPE.USER_TYPE)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item label="应用名" prop="applicationName"> + <el-input + v-model="queryParams.applicationName" + placeholder="请输入应用名" + clearable + @keyup.enter="handleQuery" + class="!w-240px" /> - <XTextButton - preIcon="ep:cpu" - title="已处理" - v-if="row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT" - v-hasPermi="['infra:api-error-log:update-status']" - @click="handleProcessClick(row, InfraApiErrorLogProcessStatusEnum.DONE, '已处理')" + </el-form-item> + <el-form-item label="异常时间" prop="exceptionTime"> + <el-date-picker + v-model="queryParams.exceptionTime" + value-format="yyyy-MM-dd HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" /> - <XTextButton - preIcon="ep:mute-notification" - title="已忽略" - v-if="row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT" - v-hasPermi="['infra:api-error-log:update-status']" - @click="handleProcessClick(row, InfraApiErrorLogProcessStatusEnum.IGNORE, '已忽略')" - /> - </template> - </XTable> - </ContentWrap> - <XModal v-model="dialogVisible" :title="dialogTitle"> - <!-- 对话框(详情) --> - <Descriptions :schema="allSchemas.detailSchema" :data="detailData" /> - <!-- 操作按钮 --> - <template #footer> - <XButton :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> + </el-form-item> + <el-form-item label="处理状态" prop="processStatus"> + <el-select v-model="queryParams.processStatus" placeholder="请选择处理状态" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['infra:api-error-log:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + </content-wrap> + <!-- 列表 --> + <content-wrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="日志编号" align="center" prop="id" /> + <el-table-column label="用户编号" align="center" prop="userId" /> + <el-table-column label="用户类型" align="center" prop="userType"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" /> + </template> + </el-table-column> + <el-table-column label="应用名" align="center" prop="applicationName" /> + <el-table-column label="请求方法名" align="center" prop="requestMethod" /> + <el-table-column label="请求地址" align="center" prop="requestUrl" width="250" /> + <el-table-column label="异常发生时间" align="center" prop="exceptionTime" width="180"> + <template #default="scope"> + <span>{{ scope.row.exceptionTime }}</span> + </template> + </el-table-column> + <el-table-column label="异常名" align="center" prop="exceptionName" width="250" /> + <el-table-column label="处理状态" align="center" prop="processStatus"> + <template #default="scope"> + <dict-tag + :type="DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS" + :value="scope.row.processStatus" + /> + </template> + </el-table-column> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openModal(scope.row)" + v-hasPermi="['infra:api-access-log:query']" + > + 详细 + </el-button> + <el-button + link + type="primary" + v-if="scope.row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT" + @click=" + handleProcessClick(InfraApiErrorLogProcessStatusEnum.DONE, '已处理', scope.row.id) + " + v-hasPermi="['infra:api-error-log:update-status']" + > + 已处理 + </el-button> + <el-button + link + type="primary" + icon="el-icon-check" + v-if="scope.row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT" + @click=" + handleProcessClick(InfraApiErrorLogProcessStatusEnum.IGNORE, '已忽略', scope.row.id) + " + v-hasPermi="['infra:api-error-log:update-status']" + > + 已忽略 + </el-button> + </template> + </el-table-column> + </el-table> + + <!-- 分页组件 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + + <!-- 表单弹窗:详情 --> + <api-error-log-detail ref="modalRef" /> </template> + <script setup lang="ts" name="ApiErrorLog"> -import { allSchemas } from './apiErrorLog.data' +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import download from '@/utils/download' import * as ApiErrorLogApi from '@/api/infra/apiErrorLog' +import ApiErrorLogDetail from './detail.vue' import { InfraApiErrorLogProcessStatusEnum } from '@/utils/constants' +const message = useMessage() // 消息弹窗 -const { t } = useI18n() // 国际化 -const message = useMessage() - -// ========== 列表相关 ========== -const [registerTable, { reload, exportList }] = useXTable({ - allSchemas: allSchemas, - getListApi: ApiErrorLogApi.getApiErrorLogPageApi, - exportListApi: ApiErrorLogApi.exportApiErrorLogApi +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + userId: null, + userType: null, + applicationName: null, + requestUrl: null, + processStatus: null, + exceptionTime: [] }) -// ========== 详情相关 ========== -const detailData = ref() // 详情 Ref -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('') // 弹出层标题 +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 -// 详情操作 -const handleDetail = (row: ApiErrorLogApi.ApiErrorLogVO) => { - // 设置数据 - detailData.value = row - dialogTitle.value = t('action.detail') - dialogVisible.value = true +/** 查询参数列表 */ +const getList = async () => { + loading.value = true + try { + const data = await ApiErrorLogApi.getApiErrorLogPageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() } -// 异常处理操作 -const handleProcessClick = ( - row: ApiErrorLogApi.ApiErrorLogVO, - processSttatus: number, - type: string -) => { - message - .confirm('确认标记为' + type + '?', t('common.reminder')) - .then(async () => { - await ApiErrorLogApi.updateApiErrorLogPageApi(row.id, processSttatus) - message.success(t('common.updateSuccess')) - }) - .finally(async () => { - // 刷新列表 - await reload() - }) - .catch(() => {}) +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() } + +/** 详情操作 */ +const modalRef = ref() +const openModal = (data: ApiErrorLogApi.ApiErrorLogVO) => { + modalRef.value.openModal(data) +} + +/** 处理已处理 / 已忽略的操作 **/ +const handleProcessClick = async (processStatus: number, type: string, id: number) => { + try { + // 操作的二次确认 + await message.confirm('确认标记为' + type + '?') + // 执行操作 + await ApiErrorLogApi.updateApiErrorLogPageApi(id, processStatus) + await message.success(type) + // 刷新列表 + await getList() + } catch {} +} + +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await ApiErrorLogApi.exportApiErrorLogApi(queryParams) + download.excel(data, '操作日志.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +/** 初始化 **/ +onMounted(() => { + getList() +}) </script> From 7cda6f554be6d13cfc6320eb593ecc0f8ac7a6e9 Mon Sep 17 00:00:00 2001 From: Chika <wbs_2018@sina.com> Date: Wed, 22 Mar 2023 16:47:45 +0800 Subject: [PATCH 10/12] =?UTF-8?q?[=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86=20-?= =?UTF-8?q?>=20=E5=B2=97=E4=BD=8D=E7=AE=A1=E7=90=86]=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20Element=20Plus=20=E5=8E=9F=E7=94=9F=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/post/form.vue | 135 ++++++++++------- src/views/system/post/index.vue | 231 ++++++++++++++++++++++------- src/views/system/post/post.data.ts | 58 -------- 3 files changed, 258 insertions(+), 166 deletions(-) delete mode 100644 src/views/system/post/post.data.ts diff --git a/src/views/system/post/form.vue b/src/views/system/post/form.vue index 065aecaf..d5d65dd1 100644 --- a/src/views/system/post/form.vue +++ b/src/views/system/post/form.vue @@ -1,81 +1,96 @@ <template> - <!-- 弹窗 --> - <XModal :title="modelTitle" :loading="modelLoading" v-model="modelVisible"> - <!-- 表单:添加/修改 --> - <Form + <Dialog :title="modelTitle" v-model="modelVisible" width="800"> + <el-form ref="formRef" - v-if="['create', 'update'].includes(actionType)" - :schema="allSchemas.formSchema" - :rules="rules" - /> - <!-- 表单:详情 --> - <Descriptions - v-if="actionType === 'detail'" - :schema="allSchemas.detailSchema" - :data="detailData" - /> + :model="formData" + :rules="formRules" + label-width="80px" + v-loading="formLoading" + > + <el-form-item label="岗位标题" prop="name"> + <el-input v-model="formData.name" placeholder="请输入岗位标题" /> + </el-form-item> + <el-form-item label="岗位编码" prop="code"> + <el-input :model-value="formData.code" placeholder="请输入岗位编码" height="150px" /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" type="textarea" placeholder="请输备注" /> + </el-form-item> + </el-form> <template #footer> - <!-- 按钮:保存 --> - <XButton - v-if="['create', 'update'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitForm()" - /> - <!-- 按钮:关闭 --> - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" /> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> </template> - </XModal> + </Dialog> </template> <script setup lang="ts"> -import type { FormExpose } from '@/components/Form' +import { DICT_TYPE, getDictOptions } from '@/utils/dict' import * as PostApi from '@/api/system/post' -import { rules, allSchemas } from './post.data' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 -// 弹窗相关的变量 -const modelVisible = ref(false) // 是否显示弹出层 -const modelTitle = ref('') // 弹出层标题 -const modelLoading = ref(false) // 弹出层loading -const actionType = ref('') // 操作按钮的类型 -const actionLoading = ref(false) // 按钮 Loading -const formRef = ref<FormExpose>() // 表单 Ref -const detailData = ref() // 详情 Ref +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const formData = ref({ + id: undefined, + name: '', + code: '', + status: undefined, + remark: '' +}) +const formRules = reactive({ + name: [{ required: true, message: '岗位标题不能为空', trigger: 'blur' }], + code: [{ required: true, message: '岗位编码不能为空', trigger: 'change' }], + status: [{ required: true, message: '岗位状态不能为空', trigger: 'change' }], + remark: [{ required: false, message: '岗位内容不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref -// 打开弹窗 +/** 打开弹窗 */ const openModal = async (type: string, id?: number) => { modelVisible.value = true - modelLoading.value = true modelTitle.value = t('action.' + type) - actionType.value = type - // 设置数据 + formType.value = type + resetForm() + // 修改时,设置数据 if (id) { - const res = await PostApi.getPostApi(id) - if (type === 'update') { - unref(formRef)?.setValues(res) - } else if (type === 'detail') { - detailData.value = res + formLoading.value = true + try { + formData.value = await PostApi.getPostApi(id) + } finally { + formLoading.value = false } } - modelLoading.value = false } defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 -// 提交新增/修改的表单 +/** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { // 校验表单 - const elForm = unref(formRef)?.getElFormRef() - if (!elForm) return - const valid = await elForm.validate() + if (!formRef) return + const valid = await formRef.value.validate() if (!valid) return // 提交请求 - actionLoading.value = true + formLoading.value = true try { - const data = unref(formRef)?.formModel as PostApi.PostVO - if (actionType.value === 'create') { + const data = formData.value as unknown as PostApi.PostVO + if (formType.value === 'create') { await PostApi.createPostApi(data) message.success(t('common.createSuccess')) } else { @@ -83,9 +98,23 @@ const submitForm = async () => { message.success(t('common.updateSuccess')) } modelVisible.value = false + // 发送操作成功的事件 emit('success') } finally { - actionLoading.value = false + formLoading.value = false } } + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + title: '', + type: undefined, + content: '', + status: undefined, + remark: '' + } + formRef.value?.resetFields() +} </script> diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue index c5a13e1e..321b5ae3 100644 --- a/src/views/system/post/index.vue +++ b/src/views/system/post/index.vue @@ -1,71 +1,192 @@ <template> - <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <template #toolbar_buttons> - <!-- 操作:新增 --> - <XButton + <content-wrap> + <!-- 搜索工作栏 --> + <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> + <el-form-item label="岗位名称" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入岗位名称" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="岗位编码" prop="code"> + <el-input + v-model="queryParams.code" + placeholder="请输入岗位编码" + clearable + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select v-model="queryParams.status" placeholder="请选择状态" clearable> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="parseInt(dict.value)" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" - v-hasPermi="['system:post:create']" @click="openModal('create')" - /> - <!-- 操作:导出 --> - <XButton - type="primary" + v-hasPermi="['system:notice:create']" + > + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + <el-button + type="success" plain - preIcon="ep:download" - :title="t('action.export')" - v-hasPermi="['system:post:export']" - @click="exportList('岗位列表.xls')" - /> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:修改 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['system:post:update']" - @click="openModal('update', row?.id)" - /> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['system:post:query']" - @click="openModal('detail', row?.id)" - /> - <!-- 操作:删除 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.delete')" - v-hasPermi="['system:post:delete']" - @click="deleteData(row?.id)" - /> - </template> - </XTable> - </ContentWrap> - <!-- 表单弹窗:添加/修改/详情 --> - <PostForm ref="modalRef" @success="reload()" /> + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['infra:config:export']" + > + <Icon icon="ep:download" class="mr-5px" /> 导出 + </el-button> + </el-form-item> + </el-form> + + <!-- 列表 --> + <el-table v-loading="loading" :data="list" align="center"> + <el-table-column label="岗位编号" align="center" prop="id" /> + <el-table-column label="岗位名称" align="center" prop="name" /> + <el-table-column label="岗位编码" align="center" prop="code" /> + <el-table-column label="岗位顺序" align="center" prop="sort" /> + <el-table-column label="岗位备注" align="center" prop="remark" /> + + <el-table-column label="状态" align="center" prop="status"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + :formatter="dateFormatter" + /> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openModal('update', scope.row.id)" + v-hasPermi="['system:post:update']" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['system:post:delete']" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + + <!-- 表单弹窗:添加/修改 --> + <post-form ref="modalRef" @success="getList" /> </template> -<script setup lang="ts" name="Post"> +<script setup lang="tsx"> import * as PostApi from '@/api/system/post' -import { allSchemas } from './post.data' import PostForm from './form.vue' +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' +import download from '@/utils/download' +import { DictTag } from '@/components/DictTag' + +const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 -// 列表相关的变量 -const [registerTable, { reload, deleteData, exportList }] = useXTable({ - allSchemas: allSchemas, // 列表配置 - getListApi: PostApi.getPostPageApi, // 加载列表的 API - deleteApi: PostApi.deletePostApi, // 删除数据的 API - exportListApi: PostApi.exportPostApi // 导出数据的 API +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryParams = reactive({ + code: '', + name: '', + status: undefined, + pageNo: 1, + pageSize: 100 }) +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 +/** 查询岗位列表 */ +const getList = async () => { + loading.value = true + try { + const data = await PostApi.getPostPageApi(queryParams) -// 表单相关的变量 + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} + +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await PostApi.exportPostApi(queryParams) + download.excel(data, '岗位列表.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ const modalRef = ref() const openModal = (type: string, id?: number) => { modalRef.value.openModal(type, id) } + +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await PostApi.deletePostApi(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} +} + +/** 初始化 **/ +onMounted(() => { + getList() +}) </script> diff --git a/src/views/system/post/post.data.ts b/src/views/system/post/post.data.ts deleted file mode 100644 index 4926bcc6..00000000 --- a/src/views/system/post/post.data.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' -const { t } = useI18n() // 国际化 - -// 表单校验 -export const rules = reactive({ - name: [required], - code: [required], - sort: [required] -}) - -// 增删改查 CrudSchema 配置 -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: 'id', - primaryTitle: '岗位编号', - action: true, - columns: [ - { - title: '岗位名称', - field: 'name', - isSearch: true - }, - { - title: '岗位编码', - field: 'code', - isSearch: true - }, - { - title: '岗位顺序', - field: 'sort', - form: { - component: 'InputNumber' - } - }, - { - title: t('common.status'), - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number', - isSearch: true - }, - { - title: '备注', - field: 'remark', - isTable: false - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false, - table: { - width: 180 - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) From 67de9fc5676f6a980ab5f9eaccfb5ebfde98ceaf Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Wed, 22 Mar 2023 21:50:44 +0800 Subject: [PATCH 11/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9A?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bpm/userGroup/index.ts | 12 +- src/api/system/user/index.ts | 2 +- src/types/auto-components.d.ts | 1 + src/views/bpm/group/UserGroupForm.vue | 132 +++++++++ src/views/bpm/group/group.data.ts | 64 ----- src/views/bpm/group/index.vue | 314 +++++++++++---------- src/views/bpm/processInstance/detail.vue | 2 +- src/views/bpm/taskAssignRule/index.vue | 8 +- src/views/system/dept/index.vue | 4 +- src/views/system/notify/template/index.vue | 4 +- 10 files changed, 307 insertions(+), 236 deletions(-) create mode 100644 src/views/bpm/group/UserGroupForm.vue delete mode 100644 src/views/bpm/group/group.data.ts diff --git a/src/api/bpm/userGroup/index.ts b/src/api/bpm/userGroup/index.ts index 88ee9619..c3399f27 100644 --- a/src/api/bpm/userGroup/index.ts +++ b/src/api/bpm/userGroup/index.ts @@ -11,7 +11,7 @@ export type UserGroupVO = { } // 创建用户组 -export const createUserGroupApi = async (data: UserGroupVO) => { +export const createUserGroup = async (data: UserGroupVO) => { return await request.post({ url: '/bpm/user-group/create', data: data @@ -19,7 +19,7 @@ export const createUserGroupApi = async (data: UserGroupVO) => { } // 更新用户组 -export const updateUserGroupApi = async (data: UserGroupVO) => { +export const updateUserGroup = async (data: UserGroupVO) => { return await request.put({ url: '/bpm/user-group/update', data: data @@ -27,21 +27,21 @@ export const updateUserGroupApi = async (data: UserGroupVO) => { } // 删除用户组 -export const deleteUserGroupApi = async (id: number) => { +export const deleteUserGroup = async (id: number) => { return await request.delete({ url: '/bpm/user-group/delete?id=' + id }) } // 获得用户组 -export const getUserGroupApi = async (id: number) => { +export const getUserGroup = async (id: number) => { return await request.get({ url: '/bpm/user-group/get?id=' + id }) } // 获得用户组分页 -export const getUserGroupPageApi = async (params) => { +export const getUserGroupPage = async (params) => { return await request.get({ url: '/bpm/user-group/page', params }) } // 获取用户组精简信息列表 -export const listSimpleUserGroupsApi = async () => { +export const listSimpleUserGroup = async () => { return await request.get({ url: '/bpm/user-group/list-all-simple' }) } diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts index e505921d..3cc0a84d 100644 --- a/src/api/system/user/index.ts +++ b/src/api/system/user/index.ts @@ -86,6 +86,6 @@ export const updateUserStatusApi = (id: number, status: number) => { } // 获取用户精简信息列表 -export const getListSimpleUsersApi = () => { +export const getSimpleUserList = () => { return request.get({ url: '/system/user/list-all-simple' }) } diff --git a/src/types/auto-components.d.ts b/src/types/auto-components.d.ts index be71517c..6284d4dc 100644 --- a/src/types/auto-components.d.ts +++ b/src/types/auto-components.d.ts @@ -30,6 +30,7 @@ declare module '@vue/runtime-core' { ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCard: typeof import('element-plus/es')['ElCard'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCol: typeof import('element-plus/es')['ElCol'] ElCollapse: typeof import('element-plus/es')['ElCollapse'] ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] diff --git a/src/views/bpm/group/UserGroupForm.vue b/src/views/bpm/group/UserGroupForm.vue new file mode 100644 index 00000000..05d646d2 --- /dev/null +++ b/src/views/bpm/group/UserGroupForm.vue @@ -0,0 +1,132 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="100px" + v-loading="formLoading" + > + <el-form-item label="组名" prop="name"> + <el-input v-model="formData.name" placeholder="请输入组名" /> + </el-form-item> + <el-form-item label="描述"> + <el-input type="textarea" v-model="formData.name" placeholder="请输入描述" /> + </el-form-item> + <el-form-item label="成员" prop="memberUserIds"> + <el-select v-model="formData.memberUserIds" multiple placeholder="请选择成员"> + <el-option + v-for="user in userList" + :key="user.id" + :label="user.nickname" + :value="user.id" + /> + </el-select> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="dict.value" + > + {{ dict.label }} + </el-radio> + </el-radio-group> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { CommonStatusEnum } from '@/utils/constants' +import * as UserGroupApi from '@/api/bpm/userGroup' +import * as UserApi from '@/api/system/user' + +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const formData = ref({ + id: undefined, + name: undefined, + description: undefined, + memberUserIds: undefined, + status: CommonStatusEnum.ENABLE +}) +const formRules = reactive({ + name: [{ required: true, message: '组名不能为空', trigger: 'blur' }], + description: [{ required: true, message: '描述不能为空', trigger: 'blur' }], + memberUserIds: [{ required: true, message: '成员不能为空', trigger: 'blur' }], + status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref +const userList = ref([]) // 用户列表 + +/** 打开弹窗 */ +const open = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await UserGroupApi.getUserGroup(id) + } finally { + formLoading.value = false + } + } + // 加载用户列表 + userList.value = await UserApi.getSimpleUserList() +} +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as unknown as UserGroupApi.UserGroupVO + if (formType.value === 'create') { + await UserGroupApi.createUserGroup(data) + message.success(t('common.createSuccess')) + } else { + await UserGroupApi.updateUserGroup(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + name: undefined, + description: undefined, + memberUserIds: undefined, + status: CommonStatusEnum.ENABLE + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/bpm/group/group.data.ts b/src/views/bpm/group/group.data.ts deleted file mode 100644 index 613a7290..00000000 --- a/src/views/bpm/group/group.data.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' - -const { t } = useI18n() // 国际化 - -// 表单校验 -export const rules = reactive({ - name: [required], - description: [required], - memberUserIds: [required], - status: [required] -}) - -// CrudSchema -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryType: 'id', - primaryTitle: '编号', - action: true, - searchSpan: 8, - columns: [ - { - title: '组名', - field: 'name', - isSearch: true - }, - { - title: '成员', - field: 'memberUserIds', - table: { - slots: { - default: 'memberUserIds_default' - } - } - }, - { - title: '描述', - field: 'description' - }, - { - title: t('common.status'), - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number', - isSearch: true - }, - { - title: t('common.createTime'), - field: 'createTime', - formatter: 'formatDate', - isForm: false, - isSearch: true, - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - }, - table: { - width: 180 - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) diff --git a/src/views/bpm/group/index.vue b/src/views/bpm/group/index.vue index b0f08516..5829ebad 100644 --- a/src/views/bpm/group/index.vue +++ b/src/views/bpm/group/index.vue @@ -1,182 +1,184 @@ <template> <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <template #toolbar_buttons> - <!-- 操作:新增 --> - <XButton + <!-- 搜索工作栏 --> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > + <el-form-item label="组名" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入组名" + clearable + @keyup.enter="handleQuery" + class="!w-240px" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px"> + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + value-format="yyyy-MM-dd HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" + @click="openForm('create')" v-hasPermi="['bpm:user-group:create']" - @click="handleCreate()" - /> - </template> - <template #memberUserIds_default="{ row }"> - <span v-for="userId in row.memberUserIds" :key="userId"> - {{ getUserNickname(userId) }} - </span> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:修改 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['bpm:user-group:update']" - @click="handleUpdate(row.id)" - /> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['bpm:user-group:query']" - @click="handleDetail(row.id)" - /> - <!-- 操作:删除 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.del')" - v-hasPermi="['bpm:user-group:delete']" - @click="deleteData(row.id)" - /> - </template> - </XTable> + > + <Icon icon="ep:plus" class="mr-5px" /> 新增 + </el-button> + </el-form-item> + </el-form> </ContentWrap> - <XModal v-model="dialogVisible" :title="dialogTitle" :mask-closable="false"> - <!-- 对话框(添加 / 修改) --> - <Form - v-if="['create', 'update'].includes(actionType)" - :schema="allSchemas.formSchema" - :rules="rules" - ref="formRef" - > - <template #memberUserIds="form"> - <el-select v-model="form.memberUserIds" multiple> - <el-option v-for="item in users" :key="item.id" :label="item.nickname" :value="item.id" /> - </el-select> - </template> - </Form> - <!-- 对话框(详情) --> - <Descriptions - v-if="actionType === 'detail'" - :schema="allSchemas.detailSchema" - :data="detailData" - > - <template #memberUserIds="{ row }"> - <span v-for="userId in row.memberUserIds" :key="userId"> - {{ getUserNickname(userId) }} - </span> - </template> - </Descriptions> - <!-- 操作按钮 --> - <template #footer> - <!-- 按钮:保存 --> - <XButton - v-if="['create', 'update'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitForm" + <!-- 列表 --> + <ContentWrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="编号" align="center" prop="id" /> + <el-table-column label="组名" align="center" prop="name" /> + <el-table-column label="描述" align="center" prop="description" /> + <el-table-column label="成员" align="center"> + <template #default="scope"> + <span v-for="userId in scope.row.memberUserIds" :key="userId" class="pr-5px"> + {{ userList.find((user) => user.id === userId)?.nickname }} + </span> + </template> + </el-table-column> + <el-table-column label="状态" align="center" prop="status"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + :formatter="dateFormatter" /> - <!-- 按钮:关闭 --> - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </XModal> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openForm('update', scope.row.id)" + v-hasPermi="['bpm:user-group:update']" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['bpm:user-group:delete']" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </ContentWrap> + + <!-- 表单弹窗:添加/修改 --> + <UserGroupForm ref="formRef" @success="getList" /> </template> -<script setup lang="ts"> -// 业务相关的 import +<script setup lang="ts" name="UserGroup"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' import * as UserGroupApi from '@/api/bpm/userGroup' -import { getListSimpleUsersApi, UserVO } from '@/api/system/user' -import { allSchemas, rules } from './group.data' -import { FormExpose } from '@/components/Form' - -const { t } = useI18n() // 国际化 +import * as UserApi from '@/api/system/user' +import UserGroupForm from './UserGroupForm.vue' const message = useMessage() // 消息弹窗 -// 列表相关的变量 -const [registerTable, { reload, deleteData }] = useXTable({ - allSchemas: allSchemas, - getListApi: UserGroupApi.getUserGroupPageApi, - deleteApi: UserGroupApi.deleteUserGroupApi +const { t } = useI18n() // 国际化 + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + name: null, + status: null, + createTime: [] }) -// 用户列表 -const users = ref<UserVO[]>([]) +const queryFormRef = ref() // 搜索的表单 +const userList = ref([]) // 用户列表 -const getUserNickname = (userId) => { - for (const user of users.value) { - if (user.id === userId) { - return user.nickname - } +/** 查询参数列表 */ +const getList = async () => { + loading.value = true + try { + const data = await UserGroupApi.getUserGroupPage(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false } - return '未知(' + userId + ')' } -// ========== CRUD 相关 ========== -const actionLoading = ref(false) // 遮罩层 -const actionType = ref('') // 操作按钮的类型 -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('edit') // 弹出层标题 -const formRef = ref<FormExpose>() // 表单 Ref -const detailData = ref() // 详情 Ref - -// 设置标题 -const setDialogTile = (type: string) => { - dialogTitle.value = t('action.' + type) - actionType.value = type - dialogVisible.value = true +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() } -// 新增操作 -const handleCreate = () => { - setDialogTile('create') +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() } -// 修改操作 -const handleUpdate = async (rowId: number) => { - setDialogTile('update') - // 设置数据 - const res = await UserGroupApi.getUserGroupApi(rowId) - unref(formRef)?.setValues(res) +/** 添加/修改操作 */ +const formRef = ref() +const openForm = (type: string, id?: number) => { + formRef.value.open(type, id) } -// 详情操作 -const handleDetail = async (rowId: number) => { - setDialogTile('detail') - detailData.value = await UserGroupApi.getUserGroupApi(rowId) +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await UserGroupApi.deleteUserGroup(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} } -// 提交按钮 -const submitForm = async () => { - const elForm = unref(formRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid) { - actionLoading.value = true - // 提交请求 - try { - const data = unref(formRef)?.formModel as UserGroupApi.UserGroupVO - if (actionType.value === 'create') { - await UserGroupApi.createUserGroupApi(data) - message.success(t('common.createSuccess')) - } else { - await UserGroupApi.updateUserGroupApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - // 刷新列表 - await reload() - } - } - }) -} - -// ========== 初始化 ========== -onMounted(() => { - getListSimpleUsersApi().then((data) => { - users.value = data - }) +/** 初始化 **/ +onMounted(async () => { + await getList() + // 加载用户列表 + userList.value = await UserApi.getSimpleUserList() }) </script> diff --git a/src/views/bpm/processInstance/detail.vue b/src/views/bpm/processInstance/detail.vue index b6d52a4c..7d159673 100644 --- a/src/views/bpm/processInstance/detail.vue +++ b/src/views/bpm/processInstance/detail.vue @@ -378,7 +378,7 @@ onMounted(() => { // 加载详情 getDetail() // 加载用户的列表 - UserApi.getListSimpleUsersApi().then((data) => { + UserApi.getSimpleUserList().then((data) => { userOptions.value.push(...data) }) }) diff --git a/src/views/bpm/taskAssignRule/index.vue b/src/views/bpm/taskAssignRule/index.vue index 012e6f68..6e1432b6 100644 --- a/src/views/bpm/taskAssignRule/index.vue +++ b/src/views/bpm/taskAssignRule/index.vue @@ -140,8 +140,8 @@ import { FormInstance } from 'element-plus' import * as TaskAssignRuleApi from '@/api/bpm/taskAssignRule' import { listSimpleRolesApi } from '@/api/system/role' import { listSimplePostsApi } from '@/api/system/post' -import { getListSimpleUsersApi } from '@/api/system/user' -import { listSimpleUserGroupsApi } from '@/api/bpm/userGroup' +import { getSimpleUserList } from '@/api/system/user' +import { listSimpleUserGroup } from '@/api/bpm/userGroup' import { listSimpleDeptApi } from '@/api/system/dept' import { DICT_TYPE, getDictOptions } from '@/utils/dict' import { handleTree, defaultProps } from '@/utils/tree' @@ -341,12 +341,12 @@ onMounted(() => { }) // 获得用户列表 userOptions.value = [] - getListSimpleUsersApi().then((data) => { + getSimpleUserList().then((data) => { userOptions.value.push(...data) }) // 获得用户组列表 userGroupOptions.value = [] - listSimpleUserGroupsApi().then((data) => { + listSimpleUserGroup().then((data) => { userGroupOptions.value.push(...data) }) if (!isShow) { diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue index 3b182e2a..4e70070f 100644 --- a/src/views/system/dept/index.vue +++ b/src/views/system/dept/index.vue @@ -79,7 +79,7 @@ import { handleTree, defaultProps } from '@/utils/tree' import type { FormExpose } from '@/components/Form' import { allSchemas, rules } from './dept.data' import * as DeptApi from '@/api/system/dept' -import { getListSimpleUsersApi, UserVO } from '@/api/system/user' +import { getSimpleUserList, UserVO } from '@/api/system/user' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -102,7 +102,7 @@ const deptOptions = ref() // 树形结构 const userOption = ref<UserVO[]>([]) const getUserList = async () => { - const res = await getListSimpleUsersApi() + const res = await getSimpleUserList() userOption.value = res } // 获取下拉框[上级]的数据 diff --git a/src/views/system/notify/template/index.vue b/src/views/system/notify/template/index.vue index 4ec16a0a..c4113924 100644 --- a/src/views/system/notify/template/index.vue +++ b/src/views/system/notify/template/index.vue @@ -119,7 +119,7 @@ import { FormExpose } from '@/components/Form' // 业务相关的 import import { rules, allSchemas } from './template.data' import * as NotifyTemplateApi from '@/api/system/notify/template' -import { getListSimpleUsersApi, UserVO } from '@/api/system/user' +import { getSimpleUserList, UserVO } from '@/api/system/user' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -244,7 +244,7 @@ const sendTest = async () => { // ========== 初始化 ========== onMounted(() => { - getListSimpleUsersApi().then((data) => { + getSimpleUserList().then((data) => { userOption.value = data }) }) From c424ee76e4e5145292cb86619899e65fe27ab1ba Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Wed, 22 Mar 2023 22:11:03 +0800 Subject: [PATCH 12/12] =?UTF-8?q?Vue3=20=E9=87=8D=E6=9E=84=EF=BC=9AREVIEW?= =?UTF-8?q?=20=E5=B2=97=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/post/index.ts | 26 ++----- src/views/bpm/taskAssignRule/index.vue | 4 +- .../system/post/{form.vue => PostForm.vue} | 18 +++-- src/views/system/post/index.vue | 78 ++++++++++--------- src/views/system/user/index.vue | 4 +- 5 files changed, 63 insertions(+), 67 deletions(-) rename src/views/system/post/{form.vue => PostForm.vue} (91%) diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts index 9e2540f0..98df227f 100644 --- a/src/api/system/post/index.ts +++ b/src/api/system/post/index.ts @@ -10,49 +10,37 @@ export interface PostVO { createTime?: Date } -export interface PostPageReqVO extends PageParam { - code?: string - name?: string - status?: number -} - -export interface PostExportReqVO { - code?: string - name?: string - status?: number -} - // 查询岗位列表 -export const getPostPageApi = async (params: PostPageReqVO) => { +export const getPostPage = async (params: PageParam) => { return await request.get({ url: '/system/post/page', params }) } // 获取岗位精简信息列表 -export const listSimplePostsApi = async () => { +export const getSimplePostList = async () => { return await request.get({ url: '/system/post/list-all-simple' }) } // 查询岗位详情 -export const getPostApi = async (id: number) => { +export const getPost = async (id: number) => { return await request.get({ url: '/system/post/get?id=' + id }) } // 新增岗位 -export const createPostApi = async (data: PostVO) => { +export const createPost = async (data: PostVO) => { return await request.post({ url: '/system/post/create', data }) } // 修改岗位 -export const updatePostApi = async (data: PostVO) => { +export const updatePost = async (data: PostVO) => { return await request.put({ url: '/system/post/update', data }) } // 删除岗位 -export const deletePostApi = async (id: number) => { +export const deletePost = async (id: number) => { return await request.delete({ url: '/system/post/delete?id=' + id }) } // 导出岗位 -export const exportPostApi = async (params: PostExportReqVO) => { +export const exportPost = async (params) => { return await request.download({ url: '/system/post/export', params }) } diff --git a/src/views/bpm/taskAssignRule/index.vue b/src/views/bpm/taskAssignRule/index.vue index 6e1432b6..8db7b578 100644 --- a/src/views/bpm/taskAssignRule/index.vue +++ b/src/views/bpm/taskAssignRule/index.vue @@ -139,7 +139,7 @@ import { FormInstance } from 'element-plus' // 业务相关的 import import * as TaskAssignRuleApi from '@/api/bpm/taskAssignRule' import { listSimpleRolesApi } from '@/api/system/role' -import { listSimplePostsApi } from '@/api/system/post' +import { getSimplePostList } from '@/api/system/post' import { getSimpleUserList } from '@/api/system/user' import { listSimpleUserGroup } from '@/api/bpm/userGroup' import { listSimpleDeptApi } from '@/api/system/dept' @@ -336,7 +336,7 @@ onMounted(() => { }) // 获得岗位列表 postOptions.value = [] - listSimplePostsApi().then((data) => { + getSimplePostList().then((data) => { postOptions.value.push(...data) }) // 获得用户列表 diff --git a/src/views/system/post/form.vue b/src/views/system/post/PostForm.vue similarity index 91% rename from src/views/system/post/form.vue rename to src/views/system/post/PostForm.vue index d5d65dd1..14aa9651 100644 --- a/src/views/system/post/form.vue +++ b/src/views/system/post/PostForm.vue @@ -37,6 +37,7 @@ </template> <script setup lang="ts"> import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { CommonStatusEnum } from '@/utils/constants' import * as PostApi from '@/api/system/post' const { t } = useI18n() // 国际化 @@ -50,7 +51,8 @@ const formData = ref({ id: undefined, name: '', code: '', - status: undefined, + sort: undefined, + status: CommonStatusEnum.ENABLE, remark: '' }) const formRules = reactive({ @@ -71,7 +73,7 @@ const openModal = async (type: string, id?: number) => { if (id) { formLoading.value = true try { - formData.value = await PostApi.getPostApi(id) + formData.value = await PostApi.getPost(id) } finally { formLoading.value = false } @@ -91,10 +93,10 @@ const submitForm = async () => { try { const data = formData.value as unknown as PostApi.PostVO if (formType.value === 'create') { - await PostApi.createPostApi(data) + await PostApi.createPost(data) message.success(t('common.createSuccess')) } else { - await PostApi.updatePostApi(data) + await PostApi.updatePost(data) message.success(t('common.updateSuccess')) } modelVisible.value = false @@ -109,10 +111,10 @@ const submitForm = async () => { const resetForm = () => { formData.value = { id: undefined, - title: '', - type: undefined, - content: '', - status: undefined, + name: '', + code: '', + sort: undefined, + status: CommonStatusEnum.ENABLE, remark: '' } formRef.value?.resetFields() diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue index 321b5ae3..03e491d0 100644 --- a/src/views/system/post/index.vue +++ b/src/views/system/post/index.vue @@ -1,7 +1,13 @@ <template> - <content-wrap> + <ContentWrap> <!-- 搜索工作栏 --> - <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > <el-form-item label="岗位名称" prop="name"> <el-input v-model="queryParams.name" @@ -21,10 +27,10 @@ <el-form-item label="状态" prop="status"> <el-select v-model="queryParams.status" placeholder="请选择状态" clearable> <el-option - v-for="dict in getDictOptions(DICT_TYPE.COMMON_STATUS)" - :key="parseInt(dict.value)" + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" :label="dict.label" - :value="parseInt(dict.value)" + :value="dict.value" /> </el-select> </el-form-item> @@ -49,15 +55,16 @@ </el-button> </el-form-item> </el-form> + </ContentWrap> - <!-- 列表 --> + <!-- 列表 --> + <ContentWrap> <el-table v-loading="loading" :data="list" align="center"> <el-table-column label="岗位编号" align="center" prop="id" /> <el-table-column label="岗位名称" align="center" prop="name" /> <el-table-column label="岗位编码" align="center" prop="code" /> <el-table-column label="岗位顺序" align="center" prop="sort" /> <el-table-column label="岗位备注" align="center" prop="remark" /> - <el-table-column label="状态" align="center" prop="status"> <template #default="scope"> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> @@ -98,18 +105,17 @@ v-model:limit="queryParams.pageSize" @pagination="getList" /> - </content-wrap> + </ContentWrap> <!-- 表单弹窗:添加/修改 --> - <post-form ref="modalRef" @success="getList" /> + <PostForm ref="formRef" @success="getList" /> </template> <script setup lang="tsx"> -import * as PostApi from '@/api/system/post' -import PostForm from './form.vue' -import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' -import { DictTag } from '@/components/DictTag' +import * as PostApi from '@/api/system/post' +import PostForm from './PostForm.vue' const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 @@ -118,20 +124,20 @@ const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 const queryParams = reactive({ + pageNo: 1, + pageSize: 10, code: '', name: '', - status: undefined, - pageNo: 1, - pageSize: 100 + status: undefined }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 + /** 查询岗位列表 */ const getList = async () => { loading.value = true try { - const data = await PostApi.getPostPageApi(queryParams) - + const data = await PostApi.getPostPage(queryParams) list.value = data.list total.value = data.total } finally { @@ -139,21 +145,6 @@ const getList = async () => { } } -/** 导出按钮操作 */ -const handleExport = async () => { - try { - // 导出的二次确认 - await message.exportConfirm() - // 发起导出 - exportLoading.value = true - const data = await PostApi.exportPostApi(queryParams) - download.excel(data, '岗位列表.xls') - } catch { - } finally { - exportLoading.value = false - } -} - /** 搜索按钮操作 */ const handleQuery = () => { queryParams.pageNo = 1 @@ -167,9 +158,9 @@ const resetQuery = () => { } /** 添加/修改操作 */ -const modalRef = ref() +const formRef = ref() const openModal = (type: string, id?: number) => { - modalRef.value.openModal(type, id) + formRef.value.openModal(type, id) } /** 删除按钮操作 */ @@ -178,13 +169,28 @@ const handleDelete = async (id: number) => { // 删除的二次确认 await message.delConfirm() // 发起删除 - await PostApi.deletePostApi(id) + await PostApi.deletePost(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() } catch {} } +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await PostApi.exportPost(queryParams) + download.excel(data, '岗位列表.xls') + } catch { + } finally { + exportLoading.value = false + } +} + /** 初始化 **/ onMounted(() => { getList() diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 2f9ba9b0..9bb50930 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -273,7 +273,7 @@ import { rules, allSchemas } from './user.data' import * as UserApi from '@/api/system/user' import { listSimpleDeptApi } from '@/api/system/dept' import { listSimpleRolesApi } from '@/api/system/role' -import { listSimplePostsApi, PostVO } from '@/api/system/post' +import { getSimplePostList, PostVO } from '@/api/system/post' import { aassignUserRoleApi, listUserRolesApi, @@ -329,7 +329,7 @@ const postOptions = ref<PostVO[]>([]) //岗位列表 // 获取岗位列表 const getPostOptions = async () => { - const res = await listSimplePostsApi() + const res = await getSimplePostList() postOptions.value.push(...res) } const dataFormater = (val) => {