Просмотр исходного кода

添加数据资源前端页面和api接口

kenny 4 лет назад
Родитель
Сommit
e60807fc2a

+ 19 - 0
Vben2/src/api/sys/admin.ts

@@ -124,6 +124,12 @@ enum Api {
   GrantTenantMenu = '/sysTenant/GrantMenu',
   TenantOwnMenuList = '/sysTenant/ownMenu',
   ResetTenantPwd = '/sysTenant/resetPwd',
+
+  // 数据资源接口
+  DataResourceList = '/sysDataResource/list',
+  AddDataResource = '/sysDataResource/add',
+  DeleteDataResource = '/sysDataResource/delete',
+  UpdateDataResource = '/sysDataResource/update',
 }
 
 ////////// 账号管理接口 //////////
@@ -427,3 +433,16 @@ export const tenantOwnMenuList = (id: number) =>
 export function resetTenantPwd(id: number) {
   return defHttp.post<any>({ url: Api.ResetTenantPwd, params: { id } });
 }
+
+////////// 数据资源管理接口 //////////
+// 获取数据资源列表
+export const getDataResourceList = (params?: any) =>
+  defHttp.get<any>({ url: Api.DataResourceList, params });
+// 增加数据资源
+export const addDataResource = (params: any) => defHttp.post({ url: Api.AddDataResource, params });
+// 删除数据资源
+export const deleteDataResource = (id: number) =>
+  defHttp.post({ url: Api.DeleteDataResource, params: { id } });
+// 更新数据资源
+export const updateDataResource = (params: any) =>
+  defHttp.post({ url: Api.UpdateDataResource, params });

+ 94 - 0
Vben2/src/views/sys/admin/dataResource/DataResourceModal.vue

@@ -0,0 +1,94 @@
+<!--
+ * @Author: kenny 362270511@qq.com
+ * @Date: 2022-05-30 11:36:19
+ * @LastEditors: kenny 362270511@qq.com
+ * @LastEditTime: 2022-05-30 16:00:49
+ * @FilePath: \frontend\src\views\sys\admin\dataResource\org\DataResourceModal.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
+    <BasicForm @register="registerForm" />
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, computed, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+
+  import { formSchema } from './dataResource.data';
+  import { getDataResourceList, addDataResource, updateDataResource } from '/@/api/sys/admin';
+
+  export default defineComponent({
+    name: 'DataResourceModal',
+    components: { BasicModal, BasicForm },
+    emits: ['success', 'register'],
+    setup(_, { emit }) {
+      const isUpdate = ref(true);
+      let rowId: number;
+
+      const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
+        labelWidth: 100,
+        schemas: formSchema,
+        showActionButtonGroup: false,
+      });
+
+      const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
+        resetFields();
+        setModalProps({ confirmLoading: false });
+        isUpdate.value = !!data?.isUpdate;
+
+        const treeData = await getDataResourceList({ id: data.parentId || 0 });
+        debugger;
+        if (!data.parentId) {
+          treeData.push({
+            id: 0,
+            name: '根节点',
+            pid: 0,
+            remark: '根节点',
+            children: [],
+          });
+        }
+        updateSchema({
+          field: 'pid',
+          componentProps: { treeData },
+        });
+
+        if (unref(isUpdate)) {
+          rowId = data.record.id;
+          setFieldsValue({
+            ...data.record,
+          });
+        } else {
+          setFieldsValue({ pid: data.parentId });
+        }
+      });
+
+      const getTitle = computed(() => (!unref(isUpdate) ? '新增数据资源' : '编辑数据资源'));
+
+      async function handleSubmit() {
+        try {
+          const values = await validate();
+          setModalProps({ confirmLoading: true });
+
+          if (unref(isUpdate)) {
+            values.id = rowId;
+            await updateDataResource(values);
+          } else {
+            rowId = await addDataResource(values);
+          }
+
+          closeModal();
+          emit('success', {
+            isUpdate: unref(isUpdate),
+            values: { ...values, id: rowId },
+          });
+        } finally {
+          setModalProps({ confirmLoading: false });
+        }
+      }
+
+      return { registerModal, registerForm, getTitle, handleSubmit };
+    },
+  });
+</script>

+ 82 - 0
Vben2/src/views/sys/admin/dataResource/DataResourceTree.vue

@@ -0,0 +1,82 @@
+<!--
+ * @Author: kenny 362270511@qq.com
+ * @Date: 2022-05-30 14:35:51
+ * @LastEditors: kenny 362270511@qq.com
+ * @LastEditTime: 2022-05-30 14:41:06
+ * @FilePath: \frontend\src\views\sys\admin\dataResource\DataResourceTree.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="m-4 mr-0 overflow-hidden bg-white">
+    <BasicTree
+      title="数据资源列表"
+      toolbar
+      search
+      :clickRowToExpand="true"
+      :treeData="treeData"
+      :fieldNames="{ key: 'id', title: 'name' }"
+      @select="handleSelect"
+      ref="treeAction"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, onMounted, ref, unref, nextTick } from 'vue';
+  import { BasicTree, TreeActionType, TreeItem } from '/@/components/Tree/index';
+
+  import { getDataResourceList } from '/@/api/sys/admin';
+
+  export default defineComponent({
+    name: 'DataResourceTree',
+    components: { BasicTree },
+
+    emits: ['select'],
+    setup(_, { emit }) {
+      const treeData = ref<TreeItem[]>([]);
+      const treeAction = ref<Nullable<TreeActionType>>(null);
+
+      const appendNodeByKey = (parentKey: string, values) => {
+        unref(treeAction).insertNodeByKey({
+          parentKey: parentKey,
+          node: values,
+          // 往后插入
+          push: 'push',
+          // 往前插入
+          // push:'unshift'
+        });
+      };
+
+      const updateNodeByKey = (key: string, values) => {
+        unref(treeAction).updateNodeByKey(key, values);
+      };
+
+      const deleteNodeByKey = (key: string) => {
+        unref(treeAction).deleteNodeByKey(key);
+      };
+
+      async function fetch() {
+        treeData.value = (await getDataResourceList()) as unknown as TreeItem[];
+        nextTick(() => {
+          unref(treeAction)?.filterByLevel(2);
+        });
+      }
+
+      function handleSelect(keys, obj) {
+        emit('select', keys[0], obj.selectedNodes[0]);
+      }
+
+      onMounted(() => {
+        fetch();
+      });
+      return {
+        treeData,
+        handleSelect,
+        treeAction,
+        appendNodeByKey,
+        updateNodeByKey,
+        deleteNodeByKey,
+        fetch,
+      };
+    },
+  });
+</script>

+ 140 - 0
Vben2/src/views/sys/admin/dataResource/dataResource.data.ts

@@ -0,0 +1,140 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { h } from 'vue';
+import { Tag } from 'ant-design-vue';
+
+export const columns: BasicColumn[] = [
+  {
+    title: '资源名称',
+    dataIndex: 'name',
+    width: 200,
+    align: 'left',
+  },
+  {
+    title: '资源值',
+    dataIndex: 'value',
+    width: 200,
+    align: 'left',
+  },
+  {
+    title: '编码',
+    dataIndex: 'code',
+    width: 200,
+    align: 'left',
+  },
+  {
+    title: '状态',
+    dataIndex: 'status',
+    width: 80,
+    customRender: ({ record }) => {
+      const status = record.status;
+      const enable = ~~status === 1;
+      const color = enable ? 'green' : 'red';
+      const text = enable ? '启用' : '停用';
+      return h(Tag, { color: color }, () => text);
+    },
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'createTime',
+    width: 180,
+  },
+  {
+    title: '排序',
+    dataIndex: 'order',
+    width: 50,
+  },
+  {
+    title: '备注',
+    dataIndex: 'remark',
+  },
+];
+
+export const searchFormSchema: FormSchema[] = [
+  {
+    field: 'name',
+    label: '资源名称',
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'value',
+    label: '资源值',
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'code',
+    label: '资源编码',
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+];
+
+export const formSchema: FormSchema[] = [
+  {
+    field: 'pid',
+    label: '上级资源',
+    component: 'TreeSelect',
+    defaultValue: 0,
+    componentProps: {
+      fieldNames: {
+        label: 'name',
+        key: 'id',
+        value: 'id',
+      },
+      getPopupContainer: () => document.body,
+    },
+    required: true,
+    colProps: { span: 24 },
+  },
+  {
+    field: 'name',
+    label: '资源名称',
+    component: 'Input',
+    required: true,
+    colProps: { span: 24 },
+  },
+  {
+    field: 'value',
+    label: '资源值',
+    component: 'Input',
+    required: true,
+    colProps: { span: 24 },
+  },
+  // {
+  //   field: 'code',
+  //   label: '编码',
+  //   component: 'Input',
+  //   colProps: { span: 24 },
+  // },
+  {
+    field: 'order',
+    label: '排序',
+    component: 'InputNumber',
+    defaultValue: 0,
+    required: true,
+    componentProps: { style: { width: '100%' } },
+    colProps: { span: 24 },
+  },
+  {
+    field: 'status',
+    label: '状态',
+    component: 'RadioButtonGroup',
+    defaultValue: 1,
+    componentProps: {
+      options: [
+        { label: '启用', value: 1 },
+        { label: '停用', value: 2 },
+      ],
+    },
+    required: true,
+    colProps: { span: 24 },
+  },
+  {
+    label: '备注',
+    field: 'remark',
+    component: 'InputTextArea',
+    colProps: { span: 24 },
+  },
+];

+ 189 - 0
Vben2/src/views/sys/admin/dataResource/index.vue

@@ -0,0 +1,189 @@
+<template>
+  <PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
+    <DataResourceTree
+      class="w-1/4 xl:w-1/5"
+      style="overflow: auto"
+      @select="handleSelect"
+      ref="DataResourceTreeChild"
+    />
+    <BasicTable @register="registerTable" class="w-3/4 xl:w-4/5" :searchInfo="searchInfo">
+      <template #toolbar>
+        <a-button
+          type="primary"
+          @click="handleCreatebrother"
+          :disabled="!hasPermission('sysDataResource:add')"
+        >
+          添加同级资源
+        </a-button>
+        <a-button
+          type="primary"
+          @click="handleCreatechild()"
+          :disabled="!hasPermission('sysDataResource:add')"
+        >
+          添加下级资源
+        </a-button>
+      </template>
+      <template #action="{ record }">
+        <TableAction
+          :actions="[
+            {
+              icon: 'clarity:note-edit-line',
+              label: '编辑',
+              disabled: !hasPermission('sysDataResource:update'),
+              onClick: handleEdit.bind(null, record),
+            },
+            {
+              icon: 'ant-design:delete-outlined',
+              label: '删除',
+              color: 'error',
+              ifShow: hasPermission('sysDataResource:delete'),
+              popConfirm: {
+                title: '是否确认删除',
+                confirm: handleDelete.bind(null, record),
+              },
+            },
+          ]"
+        />
+      </template>
+    </BasicTable>
+    <DataResourceModal @register="registerModal" @success="handleSuccess" />
+  </PageWrapper>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, ref, unref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/Table';
+  import { useModal } from '/@/components/Modal';
+  import { usePermission } from '/@/hooks/web/usePermission';
+
+  import { PageWrapper } from '/@/components/Page';
+  import DataResourceTree from './DataResourceTree.vue';
+
+  import DataResourceModal from './DataResourceModal.vue';
+
+  import { columns, searchFormSchema } from './dataResource.data';
+  import { getDataResourceList, deleteDataResource } from '/@/api/sys/admin';
+
+  export default defineComponent({
+    name: 'DataResourceManagement',
+    components: { BasicTable, DataResourceModal, TableAction, PageWrapper, DataResourceTree },
+    setup() {
+      const { hasPermission } = usePermission();
+      const DataResourceTreeChild = ref(null);
+      const [registerModal, { openModal }] = useModal();
+      const searchInfo = reactive<Recordable>({});
+      const [registerTable, { reload, updateTableDataRecord }] = useTable({
+        title: '数据资源列表',
+        api: getDataResourceList,
+        columns,
+        formConfig: {
+          labelWidth: 120,
+          schemas: searchFormSchema,
+        },
+        rowKey: 'id',
+        pagination: false,
+        striped: false,
+        useSearchForm: true,
+        showTableSetting: true,
+        bordered: true,
+        showIndexColumn: false,
+        canResize: true,
+        actionColumn: {
+          width: 150,
+          title: '操作',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+          fixed: undefined,
+        },
+      });
+
+      function getTree() {
+        const tree = unref(DataResourceTreeChild);
+        if (!tree) {
+          throw new Error('Tree is null!');
+        }
+        return tree;
+      }
+
+      function appendNodeByKey(parentKey, values) {
+        getTree().appendNodeByKey(parentKey, values);
+      }
+
+      function updateNodeByKey(key, values) {
+        getTree().updateNodeByKey(key, values); // 子组件里的方法
+      }
+
+      function deleteNodeByKey(key) {
+        getTree().deleteNodeByKey(key);
+      }
+
+      function handleCreate() {
+        openModal(true, {
+          isUpdate: false,
+        });
+      }
+
+      function handleCreatechild() {
+        openModal(true, {
+          isUpdate: false,
+          parentId: searchInfo.Id,
+        });
+      }
+
+      function handleCreatebrother() {
+        openModal(true, {
+          isUpdate: false,
+          parentId: searchInfo.pId,
+        });
+      }
+
+      function handleEdit(record: Recordable) {
+        openModal(true, {
+          record,
+          isUpdate: true,
+        });
+      }
+
+      async function handleDelete(record: Recordable) {
+        await deleteDataResource(record.id);
+        deleteNodeByKey(record.id);
+        searchInfo.Id = record.pid;
+        reload();
+      }
+
+      function handleSelect(orgId: number, obj) {
+        searchInfo.Id = orgId;
+        searchInfo.pId = obj.pid ? obj.pid : 0;
+        reload();
+      }
+
+      function handleSuccess({ isUpdate, values }) {
+        if (isUpdate) {
+          updateTableDataRecord(values.id, values);
+          updateNodeByKey(values.id, values);
+        } else {
+          reload();
+          appendNodeByKey(values.pid, values);
+        }
+        // getTree().fetch();
+      }
+
+      return {
+        registerTable,
+        registerModal,
+        searchInfo,
+        DataResourceTreeChild,
+        handleSelect,
+        updateNodeByKey,
+        appendNodeByKey,
+        deleteNodeByKey,
+        handleCreate,
+        handleCreatebrother,
+        handleCreatechild,
+        handleEdit,
+        handleDelete,
+        handleSuccess,
+        hasPermission,
+      };
+    },
+  });
+</script>