Browse Source

新增项目管理业务子模块

longping 4 months ago
parent
commit
857af5e836

+ 1 - 1
ruoyi-admin/src/main/resources/application-dev.yml

@@ -102,7 +102,7 @@ spring.data:
     # 数据库索引
     database: 0
     # redis 密码必须配置
-    password: keiven
+    password: 123456
     # 连接超时时间
     timeout: 10s
     # 是否开启ssl

+ 78 - 0
ruoyi-ui/apps/web-antd/src/views/subject/subject/config-modal.vue

@@ -0,0 +1,78 @@
+<script setup lang="ts">
+import { computed, ref } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { $t } from '@vben/locales';
+import { cloneDeep } from '@vben/utils';
+
+import { useVbenForm } from '#/adapter/form';
+import { configAdd, configInfo, configUpdate } from '#/api/system/config';
+
+import { modalSchema } from './data';
+
+const emit = defineEmits<{ reload: [] }>();
+
+const isUpdate = ref(false);
+const title = computed(() => {
+  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
+});
+
+const [BasicForm, formApi] = useVbenForm({
+  commonConfig: {
+    labelWidth: 80,
+  },
+  schema: modalSchema(),
+  showDefaultActions: false,
+});
+
+const [BasicModal, modalApi] = useVbenModal({
+  fullscreenButton: false,
+  onCancel: handleCancel,
+  onConfirm: handleConfirm,
+  onOpenChange: async (isOpen) => {
+    if (!isOpen) {
+      return null;
+    }
+    modalApi.modalLoading(true);
+
+    const { id } = modalApi.getData() as { id?: number | string };
+    isUpdate.value = !!id;
+
+    if (isUpdate.value && id) {
+      const record = await configInfo(id);
+      await formApi.setValues(record);
+    }
+
+    modalApi.modalLoading(false);
+  },
+});
+
+async function handleConfirm() {
+  try {
+    modalApi.modalLoading(true);
+    const { valid } = await formApi.validate();
+    if (!valid) {
+      return;
+    }
+    const data = cloneDeep(await formApi.getValues());
+    await (isUpdate.value ? configUpdate(data) : configAdd(data));
+    emit('reload');
+    await handleCancel();
+  } catch (error) {
+    console.error(error);
+  } finally {
+    modalApi.modalLoading(false);
+  }
+}
+
+async function handleCancel() {
+  modalApi.close();
+  await formApi.resetForm();
+}
+</script>
+
+<template>
+  <BasicModal :close-on-click-modal="false" :title="title" class="w-[550px]">
+    <BasicForm />
+  </BasicModal>
+</template>

+ 125 - 0
ruoyi-ui/apps/web-antd/src/views/subject/subject/data.ts

@@ -0,0 +1,125 @@
+import type { VxeGridProps } from '#/adapter/vxe-table';
+
+import { DictEnum } from '@vben/constants';
+import { getPopupContainer } from '@vben/utils';
+
+import { type FormSchemaGetter } from '#/adapter/form';
+import { getDictOptions } from '#/utils/dict';
+import { renderDict } from '#/utils/render';
+
+export const querySchema: FormSchemaGetter = () => [
+  {
+    component: 'Input',
+    fieldName: 'configName',
+    label: '参数名称',
+  },
+  {
+    component: 'Input',
+    fieldName: 'configKey',
+    label: '参数键名',
+  },
+  {
+    component: 'Select',
+    componentProps: {
+      getPopupContainer,
+      options: getDictOptions(DictEnum.SYS_YES_NO),
+    },
+    fieldName: 'configType',
+    label: '系统内置',
+  },
+  {
+    component: 'RangePicker',
+    fieldName: 'createTime',
+    label: '创建时间',
+  },
+];
+
+export const columns: VxeGridProps['columns'] = [
+  { type: 'checkbox', width: 60 },
+  {
+    title: '参数名称',
+    field: 'configName',
+  },
+  {
+    title: '参数KEY',
+    field: 'configKey',
+  },
+  {
+    title: '参数Value',
+    field: 'configValue',
+  },
+  {
+    title: '系统内置',
+    field: 'configType',
+    width: 120,
+    slots: {
+      default: ({ row }) => {
+        return renderDict(row.configType, DictEnum.SYS_YES_NO);
+      },
+    },
+  },
+  {
+    title: '备注',
+    field: 'remark',
+  },
+  {
+    title: '创建时间',
+    field: 'createTime',
+  },
+  {
+    field: 'action',
+    fixed: 'right',
+    slots: { default: 'action' },
+    title: '操作',
+    width: 180,
+  },
+];
+
+export const modalSchema: FormSchemaGetter = () => [
+  {
+    component: 'Input',
+    dependencies: {
+      show: () => false,
+      triggerFields: [''],
+    },
+    fieldName: 'configId',
+    label: '参数主键',
+  },
+  {
+    component: 'Input',
+    fieldName: 'configName',
+    label: '参数名称',
+    rules: 'required',
+  },
+  {
+    component: 'Input',
+    fieldName: 'configKey',
+    label: '参数键名',
+    rules: 'required',
+  },
+  {
+    component: 'Textarea',
+    formItemClass: 'items-baseline',
+    fieldName: 'configValue',
+    label: '参数键值',
+    rules: 'required',
+  },
+  {
+    component: 'RadioGroup',
+    componentProps: {
+      buttonStyle: 'solid',
+      options: getDictOptions(DictEnum.SYS_YES_NO),
+      optionType: 'button',
+    },
+    defaultValue: 'N',
+    fieldName: 'configType',
+    label: '是否内置',
+    rules: 'required',
+  },
+  {
+    component: 'Textarea',
+    fieldName: 'remark',
+    formItemClass: 'items-baseline',
+    label: '备注',
+  },
+];

+ 187 - 0
ruoyi-ui/apps/web-antd/src/views/subject/subject/index.vue

@@ -0,0 +1,187 @@
+<script setup lang="ts">
+import type { Recordable } from '@vben/types';
+
+import { ref } from 'vue';
+
+import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
+import { getVxePopupContainer } from '@vben/utils';
+
+import { Modal, Popconfirm, Space } from 'ant-design-vue';
+
+import {
+  tableCheckboxEvent,
+  useVbenVxeGrid,
+  type VxeGridProps,
+} from '#/adapter/vxe-table';
+import {
+  configExport,
+  configList,
+  configRefreshCache,
+  configRemove,
+} from '#/api/system/config';
+import { commonDownloadExcel } from '#/utils/file/download';
+
+import configModal from './config-modal.vue';
+import { columns, querySchema } from './data';
+
+const formOptions: VbenFormProps = {
+  commonConfig: {
+    labelWidth: 80,
+    componentProps: {
+      allowClear: true,
+    },
+  },
+  schema: querySchema(),
+  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
+  // 日期选择格式化
+  fieldMappingTime: [
+    [
+      'createTime',
+      ['params[beginTime]', 'params[endTime]'],
+      ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
+    ],
+  ],
+};
+
+const gridOptions: VxeGridProps = {
+  checkboxConfig: {
+    // 高亮
+    highlight: true,
+    // 翻页时保留选中状态
+    reserve: true,
+  },
+  columns,
+  height: 'auto',
+  keepSource: true,
+  pagerConfig: {},
+  proxyConfig: {
+    ajax: {
+      query: async ({ page }, formValues = {}) => {
+        return await configList({
+          pageNum: page.currentPage,
+          pageSize: page.pageSize,
+          ...formValues,
+        });
+      },
+    },
+  },
+  rowConfig: {
+    isHover: true,
+    keyField: 'configId',
+  },
+  id: 'system-config-index',
+};
+
+const checked = ref(false);
+const [BasicTable, tableApi] = useVbenVxeGrid({
+  formOptions,
+  gridOptions,
+  gridEvents: {
+    checkboxChange: tableCheckboxEvent(checked),
+    checkboxAll: tableCheckboxEvent(checked),
+  },
+});
+const [ConfigModal, modalApi] = useVbenModal({
+  connectedComponent: configModal,
+});
+
+function handleAdd() {
+  modalApi.setData({});
+  modalApi.open();
+}
+
+async function handleEdit(record: Recordable<any>) {
+  modalApi.setData({ id: record.configId });
+  modalApi.open();
+}
+
+async function handleDelete(row: Recordable<any>) {
+  await configRemove(row.configId);
+  await tableApi.query();
+}
+
+function handleMultiDelete() {
+  const rows = tableApi.grid.getCheckboxRecords();
+  const ids = rows.map((row: any) => row.configId);
+  Modal.confirm({
+    title: '提示',
+    okType: 'danger',
+    content: `确认删除选中的${ids.length}条记录吗?`,
+    onOk: async () => {
+      await configRemove(ids);
+      await tableApi.query();
+      checked.value = false;
+    },
+  });
+}
+
+function handleDownloadExcel() {
+  commonDownloadExcel(configExport, '参数配置', tableApi.formApi.form.values, {
+    fieldMappingTime: formOptions.fieldMappingTime,
+  });
+}
+
+async function handleRefreshCache() {
+  await configRefreshCache();
+  await tableApi.query();
+}
+</script>
+
+<template>
+  <Page :auto-content-height="true">
+    <BasicTable table-title="参数列表">
+      <template #toolbar-tools>
+        <Space>
+          <a-button @click="handleRefreshCache"> 刷新缓存 </a-button>
+          <a-button
+            v-access:code="['system:config:export']"
+            @click="handleDownloadExcel"
+          >
+            {{ $t('pages.common.export') }}
+          </a-button>
+          <a-button
+            :disabled="!checked"
+            danger
+            type="primary"
+            v-access:code="['system:config:remove']"
+            @click="handleMultiDelete"
+          >
+            {{ $t('pages.common.delete') }}
+          </a-button>
+          <a-button
+            type="primary"
+            v-access:code="['system:config:add']"
+            @click="handleAdd"
+          >
+            {{ $t('pages.common.add') }}
+          </a-button>
+        </Space>
+      </template>
+      <template #action="{ row }">
+        <Space>
+          <ghost-button
+            v-access:code="['system:config:edit']"
+            @click.stop="handleEdit(row)"
+          >
+            {{ $t('pages.common.edit') }}
+          </ghost-button>
+          <Popconfirm
+            :get-popup-container="getVxePopupContainer"
+            placement="left"
+            title="确认删除?"
+            @confirm="handleDelete(row)"
+          >
+            <ghost-button
+              danger
+              v-access:code="['system:config:remove']"
+              @click.stop=""
+            >
+              {{ $t('pages.common.delete') }}
+            </ghost-button>
+          </Popconfirm>
+        </Space>
+      </template>
+    </BasicTable>
+    <ConfigModal @reload="tableApi.query()" />
+  </Page>
+</template>