liuxinyang 1 year ago
parent
commit
21f313ad27

+ 1 - 0
images/crouse.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><path d="M3 21h18v-2H3v2zM3 8v8l4-4l-4-4zm8 9h10v-2H11v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z" fill="currentColor"></path></svg>

+ 1 - 14
mock/api/crud/modules/demo.ts

@@ -7,20 +7,7 @@ const options: BaseMockOptions = {
   name: 'crud/demo',
   idGenerator: 0,
   list: [
-    {
-      select: '1',
-      text: '文本测试',
-      copyable: '文本可复制',
-      avatar: 'http://greper.handsfree.work/extends/avatar.jpg',
-      richtext: '富文本',
-      datetime: '2023-01-30 11:11:11'
-    },
-    {
-      select: '2'
-    },
-    {
-      select: '0'
-    }
+
   ]
 };
 const mockedApis = mockBase.buildMock(options);

+ 5 - 0
pnpm-lock.yaml

@@ -1,5 +1,9 @@
 lockfileVersion: '6.0'
 
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
 patchedDependencies:
   mockjs@1.1.0:
     hash: zljuuegabo7mnbroxnwxab3e2u
@@ -7921,6 +7925,7 @@ packages:
   /iconv-lite@0.6.3:
     resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
     engines: {node: '>=0.10.0'}
+    requiresBuild: true
     dependencies:
       safer-buffer: 2.1.2
     dev: true

+ 11 - 0
src/router/modules/management.ts

@@ -46,6 +46,17 @@ const management: AuthRoute.Route = {
         requiresAuth: true,
         icon: 'material-symbols:route'
       }
+    },
+    {
+      name: 'management_crouse',
+      path: '/management/crouse',
+      component: 'self',
+      meta: {
+        title: '课程管理',
+        i18nTitle: '课程管理',
+        requiresAuth: true,
+        icon: 'zondicons:align-left'
+      }
     }
   ],
   meta: {

+ 171 - 0
src/service/api/crouse.ts

@@ -0,0 +1,171 @@
+import { request } from '../request';
+// 参数接口 根据相关条件进行查询课程
+export interface SelectByConditionParams {
+  id?: number;
+  name?: string;
+  description?: string;
+  categoryId?: string;
+  createTime?: Record<string, unknown>;
+  modifyTime?: Record<string, unknown>;
+  createUid?: number;
+  disabled?: string;
+}
+
+// 响应接口
+export interface SelectByConditionRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+  total: number;
+}
+
+/**
+ * 根据条件进行查询课程
+ * @param {string} pageNum
+ * @param {string} pageSize
+ * @param {object} params EasEduSubjects
+ * @param {number} params.id
+ * @param {string} params.name 学科名称
+ * @param {string} params.description 学科描述
+ * @param {string} params.categoryId 学科分类
+ * @param {object} params.createTime 创建时间
+ * @param {object} params.modifyTime 修改时间
+ * @param {number} params.createUid 创建用户ID
+ * @param {string} params.disabled 状态
+ * @returns
+ */
+export function selectByCondition( pageNum: number | undefined, pageSize: number | undefined, params: SelectByConditionParams) {
+  return request.post(`/subject/selectByCondition?pageNum=${pageNum}&pageSize=${pageSize}`, params);
+}
+
+// 响应接口 查询所有课程
+export interface SelectAllRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+}
+
+/**
+ * 查询所有课程
+ * @returns
+ */
+export function selectAll() {
+  return request.get(`/subject/selectAll`);
+}
+
+// 参数接口 添加接口
+export interface AddSubjectParams {
+  id?: number;
+  name?: string;
+  description?: string;
+  categoryId?: string;
+  createTime?: string;
+  modifyTime?: string;
+  createUid?: number;
+  disabled?: string;
+}
+
+// 响应接口
+export interface AddSubjectRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+}
+
+/**
+ * 添加课程
+ * @param {object} params EasEduSubjects
+ * @param {number} params.id
+ * @param {string} params.name 学科名称
+ * @param {string} params.description 学科描述
+ * @param {string} params.categoryId 学科分类
+ * @param {object} params.createTime 创建时间
+ * @param {object} params.modifyTime 修改时间
+ * @param {number} params.createUid 创建用户ID
+ * @param {string} params.disabled 状态
+ * @returns
+ */
+export function addSubject(params: AddSubjectParams) {
+  return request.post(`/subject/addSubject`, params);
+}
+// 响应接口
+export interface DeleteSubjectsRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+}
+
+/**
+ * 删除课程
+ * @param {string} id
+ * @returns
+ */
+export function deleteSubjects(id: number) {
+  return request.delete(`/subject/deleteSubjects/${id}`);
+}
+
+// 修改课程
+// 参数接口
+export interface UpdateSubjectsParams {
+  id?: number;
+  name?: string;
+  description?: string;
+  categoryId?: string;
+  createTime?: Record<string, unknown>;
+  modifyTime?: Record<string, unknown>;
+  createUid?: number;
+  disabled?: string;
+}
+
+// 响应接口
+export interface UpdateSubjectsRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+}
+
+/**
+ * 修改课程
+ * @param {object} params EasEduSubjects
+ * @param {number} params.id
+ * @param {string} params.name 学科名称
+ * @param {string} params.description 学科描述
+ * @param {string} params.categoryId 学科分类
+ * @param {object} params.createTime 创建时间
+ * @param {object} params.modifyTime 修改时间
+ * @param {number} params.createUid 创建用户ID
+ * @param {string} params.disabled 状态
+ * @returns
+ */
+export function updateSubjects(params: UpdateSubjectsParams) {
+  return request.post(`/subject/updateSubjects`, params);
+}
+
+// 响应接口  根据id寻找课程
+export interface SelectByIdRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+}
+
+/**
+ * id查询课程
+ * @param {string} id
+  * @returns
+ */
+export function selectById(id: number) {
+  return request.get(`/subject/selectById?id=${id}`);
+}
+
+// 参数接口
+export interface SelectByConditionParams {
+  id?: number;
+  name?: string;
+  description?: string;
+  categoryId?: string;
+  createTime?: Record<string, unknown>;
+  modifyTime?: Record<string, unknown>;
+  createUid?: number;
+  disabled?: string;
+}
+

+ 3 - 2
src/service/api/management.ts

@@ -1,9 +1,10 @@
 import { adapter } from '@/utils';
-import { mockRequest } from '../request';
+// import { mockRequest } from '../request';
+import { request } from '../request';
 import { adapterOfFetchUserList } from './management.adapter';
 
 /** 获取用户列表 */
 export const fetchUserList = async () => {
-  const data = await mockRequest.post<ApiUserManagement.User[] | null>('/getAllUserList');
+  const data = await request.get<ApiUserManagement1.User[] | any>('/subject/selectAll');
   return adapter(adapterOfFetchUserList, data);
 };

+ 6 - 4
src/service/request/instance.ts

@@ -1,5 +1,6 @@
 import axios from 'axios';
 import type { AxiosResponse, AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
+// eslint-disable-next-line import/no-unresolved
 import { REFRESH_TOKEN_CODE } from '@/config';
 import {
   localStg,
@@ -8,6 +9,7 @@ import {
   handleResponseError,
   handleServiceResult,
   transformRequestData
+  // eslint-disable-next-line import/no-unresolved
 } from '@/utils';
 import { handleRefreshToken } from './helpers';
 
@@ -28,10 +30,10 @@ export default class CustomAxiosInstance {
   constructor(
     axiosConfig: AxiosRequestConfig,
     backendConfig: Service.BackendResultConfig = {
-      codeKey: 'status',
+      codeKey: 'code',
       dataKey: 'data',
-      msgKey: 'code',
-      successCode: true
+      msgKey: 'message',
+      successCode: 200
     }
   ) {
     this.backendConfig = backendConfig;
@@ -65,7 +67,7 @@ export default class CustomAxiosInstance {
           const backend = response.data;
           const { codeKey, dataKey, successCode } = this.backendConfig;
           // 请求成功
-          if (backend[codeKey] === successCode) {
+          if (backend[codeKey] === successCode || response.status === 200) {
             return handleServiceResult(null, backend[dataKey]);
           }
 

+ 1 - 1
src/typings/api.d.ts

@@ -25,7 +25,7 @@ declare namespace ApiRoute {
 declare namespace ApiUserManagement {
   interface User {
     /** 用户id */
-    id: string;
+    id: number;
     /** 用户名 */
     userName: string | null;
     /** 用户年龄 */

+ 61 - 0
src/typings/api1.d.ts

@@ -0,0 +1,61 @@
+// 后端接口返回的数据类型
+
+/** 后端返回的用户权益相关类型 */
+declare namespace ApiAuth {
+  /** 返回的token和刷新token */
+  interface Token {
+    token: string;
+    refreshToken: string;
+  }
+  /** 返回的用户信息 */
+  type UserInfo1 = Auth.UserInfo;
+}
+
+/** 后端返回的路由相关类型 */
+declare namespace ApiRoute {
+  /** 后端返回的路由数据类型 */
+  interface Route {
+    /** 动态路由 */
+    routes: AuthRoute.Route[];
+    /** 路由首页对应的key */
+    home: AuthRoute.AllRouteKey;
+  }
+}
+
+declare namespace ApiUserManagement1 {
+  interface User {
+    // /** 用户id */
+    // id: string;
+    // /** 用户名 */
+    // userName: string | null;
+    // /** 用户年龄 */
+    // age: number | null;
+    // /**
+    //  * 用户性别
+    //  * - 0: 女
+    //  * - 1: 男
+    //  */
+    // gender: '0' | '1' | null;
+    // /** 用户手机号码 */
+    // phone: string;
+    // /** 用户邮箱 */
+    // email: string | null;
+    // /**
+    //  * 用户状态
+    //  * - 1: 启用
+    //  * - 2: 禁用
+    //  * - 3: 冻结
+    //  * - 4: 软删除
+    //  */
+    // userStatus: '1' | '2' | '3' | '4' | null;
+		id: number;
+    name: string;
+		description: string;
+		categoryId:string;
+		createTime: string;
+		modifyTime:string;
+		createUid:number;
+		disabled:string;
+		inputValue:string;
+  }
+}

+ 45 - 0
src/typings/business1.d.ts

@@ -0,0 +1,45 @@
+/** 用户相关模块 */
+declare namespace Auth {
+  /**
+   * 用户角色类型(前端静态路由用角色类型进行路由权限的控制)
+   * - super: 超级管理员(该权限具有所有路由数据)
+   * - admin: 管理员
+   * - user: 用户
+   */
+  type RoleType1 = 'super' | 'admin' | 'user';
+
+  /** 用户信息 */
+  interface UserInfo {
+    /** 用户id */
+    userId: string;
+    /** 用户名 */
+    userName: string;
+    /** 用户角色类型 */
+    userRole: RoleType;
+  }
+}
+
+declare namespace UserManagement1 {
+  interface User extends ApiUserManagement1.User {
+    /** 序号 */
+    index: number;
+    /** 表格的key(id) */
+    key: string;
+  }
+
+  /**
+   * 用户性别
+   * - 0: 女
+   * - 1: 男
+   */
+  // type GenderKey = NonNullable<User['gender']>;
+
+  /**
+   * 用户状态
+   * - 1: 启用
+   * - 2: 禁用
+   * - 3: 冻结
+   * - 4: 软删除
+   */
+  // type UserStatusKey = NonNullable<User['userStatus']>;
+}

+ 2 - 0
src/typings/page-route.d.ts

@@ -55,6 +55,7 @@ declare namespace PageRoute {
     | 'function_tab'
     | 'management'
     | 'management_auth'
+    | 'management_crouse'
     | 'management_role'
     | 'management_route'
     | 'management_user'
@@ -113,6 +114,7 @@ declare namespace PageRoute {
     | 'function_tab-multi-detail'
     | 'function_tab'
     | 'management_auth'
+    | 'management_crouse'
     | 'management_role'
     | 'management_route'
     | 'management_user'

+ 1 - 2
src/views/crud/demo/api.ts

@@ -1,6 +1,5 @@
 import type { UserPageQuery } from '@fast-crud/fast-crud';
 import { mockRequest } from '@/service/request';
-
 const request = mockRequest;
 const apiPrefix = '/crud/demo';
 
@@ -13,7 +12,7 @@ function resHandle(res: any) {
   return res.data;
 }
 export async function GetList(query: UserPageQuery) {
-  const res = await request.post(`${apiPrefix}/page`, query);
+  const res = await request.post(`${apiPrefix}/get`, query);
   return resHandle(res);
 }
 

+ 87 - 43
src/views/crud/demo/crud.tsx

@@ -44,8 +44,78 @@ export default function createCrudOptions(): CreateCrudOptionsRet {
             show: false
           }
         },
-        datetime: {
-          title: '时间',
+        // datetime: {
+        //   title: '时间',
+        //   type: 'datetime',
+        //   // naive 默认仅支持数字类型时间戳作为日期输入与输出
+        //   // 字符串类型的时间需要转换格式
+        //   valueBuilder(context) {
+        //     const { value, row, key } = context;
+        //     if (value) {
+        //       // naive 默认仅支持时间戳作为日期输入与输出
+        //       row[key] = dayjs(value).valueOf();
+        //     }
+        //   },
+        //   valueResolve(context) {
+        //     const { value, form, key } = context;
+        //     if (value) {
+        //       form[key] = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
+        //     }
+        //   }
+        // },
+        select: {
+          title: '状态',
+          search: { show: true },
+          type: 'dict-select',
+          dict: dict({
+            url: '/mock/crud/demo/dict'
+          })
+        },
+        text2: {
+          title: '学科名称',
+          type: 'text',
+          search: { show: true }
+        },
+        // copyable: {
+        //   title: '可复制',
+        //   type: ['text', 'copyable'],
+        //   search: { show: true }
+        // },
+        // upload: {
+        //   title: '文件上传',
+        //   type: 'file-uploader'
+        // },
+        // richtext: {
+        //   title: '富文本',
+        //   type: 'editor-wang5',
+        //   column: {
+        //     // cell中不显示
+        //     show: false
+        //   },
+        //   form: {
+        //     col: {
+        //       // 横跨两列
+        //       span: 24
+        //     },
+        //     component: {
+        //       style: {
+        //         height: '300px'
+        //       }
+        //     }
+        //   }
+        // }
+				text: {
+          title: '学科描述',
+          type: 'text',
+          search: { show: true }
+        },
+				text1: {
+          title: '学科分类',
+          type: 'text',
+          search: { show: true }
+        },
+				datetime: {
+          title: '创建时间',
           type: 'datetime',
           // naive 默认仅支持数字类型时间戳作为日期输入与输出
           // 字符串类型的时间需要转换格式
@@ -63,48 +133,22 @@ export default function createCrudOptions(): CreateCrudOptionsRet {
             }
           }
         },
-        select: {
-          title: '状态',
-          search: { show: true },
-          type: 'dict-select',
-          dict: dict({
-            url: '/mock/crud/demo/dict'
-          })
-        },
-        text: {
-          title: '文本',
-          type: 'text',
-          search: { show: true }
-        },
-        copyable: {
-          title: '可复制',
-          type: ['text', 'copyable'],
-          search: { show: true }
-        },
-        avatar: {
-          title: '头像裁剪',
-          type: 'cropper-uploader'
-        },
-        upload: {
-          title: '文件上传',
-          type: 'file-uploader'
-        },
-        richtext: {
-          title: '富文本',
-          type: 'editor-wang5',
-          column: {
-            // cell中不显示
-            show: false
+				datetime1: {
+          title: '修改时间',
+          type: 'datetime',
+          // naive 默认仅支持数字类型时间戳作为日期输入与输出
+          // 字符串类型的时间需要转换格式
+          valueBuilder(context) {
+            const { value, row, key } = context;
+            if (value) {
+              // naive 默认仅支持时间戳作为日期输入与输出
+              row[key] = dayjs(value).valueOf();
+            }
           },
-          form: {
-            col: {
-              // 横跨两列
-              span: 24
-            },
-            component: {
-              style: {
-                height: '300px'
-              }
+          valueResolve(context) {
+            const { value, form, key } = context;
+            if (value) {
+              form[key] = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
             }
           }
         }

+ 2 - 2
src/views/crud/header_group/api.ts

@@ -12,8 +12,8 @@ export type HeaderGroupRecord = {
 function resHandle(res: any) {
   return res.data;
 }
-export async function GetList(query: UserPageQuery) {
-  const res = await request.post(`${apiPrefix}/page`, query);
+export async function GetList() {
+  const res = await request.get(`${apiPrefix}/get`);
   return resHandle(res);
 }
 

+ 1 - 0
src/views/index.ts

@@ -34,6 +34,7 @@ export const views: Record<
   'function_tab-multi-detail': () => import('./function/tab-multi-detail/index.vue'),
   function_tab: () => import('./function/tab/index.vue'),
   management_auth: () => import('./management/auth/index.vue'),
+  management_crouse: () => import('./management/crouse/index.vue'),
   management_role: () => import('./management/role/index.vue'),
   management_route: () => import('./management/route/index.vue'),
   management_user: () => import('./management/user/index.vue'),

+ 39 - 0
src/views/management/crouse/component/AddView.vue

@@ -0,0 +1,39 @@
+<template>
+  <n-button @click="showModal = true">添加</n-button>
+  <n-modal v-model:show="showModal">
+    <n-card style="width: 600px" title="模态框" :bordered="false" size="huge" role="dialog" aria-modal="true">
+      <template #header-extra>请输入要添加的信息...</template>
+      内容
+      <template #footer>
+        <n-button @click="showModal = false">确定</n-button>
+      </template>
+    </n-card>
+  </n-modal>
+</template>
+
+<script lang="ts">
+import { defineComponent, ref } from 'vue';
+import { addSubject } from '~/src/service/api/crouse';
+import type { AddSubjectParams } from '~/src/service/api/crouse';
+const useAdd: AddSubjectParams = {
+  id: 2,
+  name: '物理',
+  description: '很难',
+  categoryId: '理学',
+  createTime: '',
+  modifyTime: '',
+  createUid: 2,
+  disabled: '1'
+} as any;
+
+export default defineComponent({
+  setup() {
+    return {
+      showModal: ref(false)
+    };
+  }
+});
+addSubject(useAdd).then(r => {
+  console.log(r, 'jdiap');
+});
+</script>

+ 26 - 0
src/views/management/crouse/component/Pagination.vue

@@ -0,0 +1,26 @@
+<template>
+	<n-pagination v-model:page="page" v-model:page-size="pageSize" :page-count="100" show-size-picker
+		:page-sizes="[10, 20, 30, 40]" />
+</template>
+
+<script lang="tsx">
+import { defineComponent, ref } from 'vue'
+import type { SelectByConditionParams } from '~/src/service/api/crouse'
+import { selectByCondition } from '~/src/service/api/crouse';
+import { inputPageNum1, inputPageNum2 } from '../index.vue'
+const conditionParams: SelectByConditionParams = {};
+// import  selectByCondition  from '../index.vue'
+export default defineComponent({
+	setup() {
+		return {
+			selectByCondition,
+			conditionParams,
+			inputPageNum1,
+			inputPageNum2,
+			page: ref(2),
+			pageSize: ref(20)
+    }
+  }
+})
+
+</script>

+ 185 - 0
src/views/management/crouse/component/table-action-modal.vue

@@ -0,0 +1,185 @@
+<template>
+	<n-modal v-model:show="modalVisible" preset="card" :title="title" class="w-700px">
+		<n-form ref="formRef" label-placement="left" :label-width="80" :model="formModel" :rules="rules">
+			<n-grid :cols="24" :x-gap="18">
+				<!-- <n-form-item-grid-item :span="12" label="id" path="createUid">
+          <n-input-number v-model:value="formModel.createUid"  />
+        </n-form-item-grid-item> -->
+				<n-form-item-grid-item :span="12" label="学科名称" path="name">
+					<n-input v-model:value="formModel.name" />
+				</n-form-item-grid-item>
+				<n-form-item-grid-item :span="12" label="学科描述" path="description">
+					<n-input v-model:value="formModel.description" clearable />
+				</n-form-item-grid-item>
+				<n-form-item-grid-item :span="12" label="学科分类" path="categoryId">
+					<n-input v-model:value="formModel.categoryId" />
+				</n-form-item-grid-item>
+				<!-- <n-form-item-grid-item :span="12" label="创建时间" path="createTime">
+          <n-input v-model:value="formModel.createTime" :options="userStatusOptions"/>
+        </n-form-item-grid-item> -->
+				<!-- <n-form-item-grid-item :span="12" label="修改时间" path="modifyTime">
+          <n-input v-model:value="formModel.modifyTime" :options="userStatusOptions"/>
+        </n-form-item-grid-item> -->
+				<n-form-item-grid-item :span="12" label="创建用户ID" path="createUid">
+					<n-input-number v-model:value="formModel.createUid" />
+				</n-form-item-grid-item>
+				<n-form-item-grid-item :span="12" label="状态" path="disabled">
+					<n-input v-model:value="formModel.disabled" :options="userStatusOptions" />
+				</n-form-item-grid-item>
+			</n-grid>
+			<n-space class="w-full pt-16px" :size="24" justify="end">
+				<n-button class="w-72px" @click="closeModal">取消</n-button>
+				<n-button class="w-72px" type="primary" v-if="props.type === 'add'" @click="handleSubmit">添加</n-button>
+				<n-button class="w-72px" type="primary" v-if="props.type === 'edit'" @click="handleupdate">修改</n-button>
+			</n-space>
+		</n-form>
+	</n-modal>
+</template>
+
+<script setup lang="ts">
+import { ref, computed, reactive, watch } from 'vue';
+import type { FormInst, FormItemRule } from 'naive-ui';
+import { addSubject , updateSubjects } from '~/src/service/api/crouse';
+import { userStatusOptions } from '@/constants';
+// import type { UpdateSubjectsParams } from '~/src/service/api/crouse';
+import { createRequiredFormRule } from '@/utils';
+import { init } from '../index.vue'
+// import { number } from 'echarts';
+import dayjs from 'dayjs';
+
+export interface Props {
+	/** 弹窗可见性 */
+	visible: boolean;
+	/**
+	 * 弹窗类型
+	 * add: 新增
+	 * edit: 编辑
+	 */
+	type?: 'add' | 'edit';
+	/** 编辑的表格行数据 */
+	editData?: UserManagement1.User | null;
+}
+
+export type ModalType = NonNullable<Props['type']>;
+
+defineOptions({ name: 'TableActionModal' });
+
+const props = withDefaults(defineProps<Props>(), {
+	type: 'add' || 'edit',
+	editData: null
+});
+
+interface Emits {
+	(e: 'update:visible', visible: boolean): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const modalVisible = computed({
+	get() {
+		return props.visible;
+	},
+	set(visible) {
+		emit('update:visible', visible);
+	}
+});
+const closeModal = () => {
+	modalVisible.value = false;
+};
+
+const title = computed(() => {
+	const titles: Record<ModalType, string> = {
+		add: '添加用户',
+		edit: '编辑用户'
+	};
+	return titles[props.type];
+});
+
+const formRef = ref<HTMLElement & FormInst>();
+
+type FormModel = Pick<UserManagement1.User, 'inputValue' | 'id' | 'name' | 'description' | 'categoryId' | 'createTime' | 'modifyTime' | 'createUid' | 'disabled'>;
+
+const formModel = reactive<FormModel>(createDefaultFormModel());
+
+const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
+	id: createRequiredFormRule('请输入id'),
+	name: createRequiredFormRule('请输入用户名'),
+	description: createRequiredFormRule('请输入年龄'),
+	categoryId: createRequiredFormRule('请选择性别'),
+	createTime: createRequiredFormRule('请选择用户状态'),
+	modifyTime: createRequiredFormRule('请选择用户状态'),
+	createUid: createRequiredFormRule('请选择用户状态'),
+	disabled: createRequiredFormRule('请选择用户状态'),
+	inputValue:createRequiredFormRule('请选择用户状态')
+};
+
+function createDefaultFormModel(): FormModel {
+	return {
+		id: 0,
+		name: '',
+		description: '',
+		categoryId: '',
+		createTime: '',
+		modifyTime: '',
+		createUid: 0,
+		disabled: '',
+		inputValue:'',
+	};
+}
+
+function handleUpdateFormModel(model: Partial<FormModel>) {
+	Object.assign(formModel, model);
+}
+
+function handleUpdateFormModelByModalType() {
+	const handlers: Record<ModalType, () => void> = {
+		add: () => {
+			const defaultFormModel = createDefaultFormModel();
+			handleUpdateFormModel(defaultFormModel);
+		},
+		edit: () => {
+			if (props.editData) {
+				handleUpdateFormModel(props.editData);
+			}
+		}
+	};
+
+	handlers[props.type]();
+}
+
+async function handleSubmit() {
+	await formRef.value?.validate();
+	window.$message?.success('新增成功!');
+	addSubject(formModel).then(() => {
+		// location.reload()
+		init();
+	})
+	closeModal();
+
+}
+
+async function handleupdate() {
+	await formRef.value?.validate();
+	window.$message?.success('修改成功!');
+	// formModel.modifyTime = Date()
+	const timer = dayjs().format('YYYY-MM-DD HH:mm:ss')
+	handleUpdateFormModel({ modifyTime: timer });
+	updateSubjects(formModel).then(() => {
+
+		// location.reload()
+		init();
+	})
+	closeModal();
+
+}
+watch(
+	() => props.visible,
+	newValue => {
+		if (newValue) {
+			handleUpdateFormModelByModalType();
+		}
+	}
+);
+</script>
+
+<style scoped></style>

+ 377 - 0
src/views/management/crouse/index.vue

@@ -0,0 +1,377 @@
+<template>
+	<div class="h-full overflow-hidden">
+		<n-card title="课程管理" :bordered="false" class="rounded-16px shadow-sm">
+			<n-space class="pb-12px" justify="space-between">
+				<n-space>
+					<n-button type="primary" @click="handleAddTable">
+						<icon-ic-round-plus class="mr-4px text-20px" />
+						新增
+					</n-button>
+					<n-button type="error" @click="deleteSubjectsList">
+						<icon-ic-round-delete class="mr-4px text-20px" />
+						删除
+					</n-button>
+					<n-input-group>
+
+						<n-input :style="{ width: '50%' }" @keyup="serchForm" @change="handleChange" placeholder="输入id查询..." />
+						<n-button type="primary" ghost @click="serchForm()">
+							搜索
+						</n-button>
+					</n-input-group>
+					<n-input-group>
+						<n-input-number :style="{ width: '33%' }"  @input="handleInput1" />
+						<n-input-number :style="{ width: '33%' }"  @input="handleInput2" />
+						<n-button type="primary" @click="serchCondition()">
+							搜索
+						</n-button>
+					</n-input-group>
+				</n-space>
+			</n-space>
+			<n-data-table v-if="serchFormEr.length > 0 && inputValue !== 0" :columns="columns" :data="serchFormEr"
+				:loading="loading" :pagination="pagination" :row-key="rowKey" @update:checked-row-keys="handleCheck" />
+			<n-data-table v-if="serchFormEr.length <= 0 || inputValue === 0" :columns="columns" :data="pageDate"
+				:loading="loading" :pagination="pagination" :row-key="rowKey" @update:checked-row-keys="handleCheck" />
+			<table-action-modal v-model:visible="visible" :type="modalType" :edit-data="editData" />
+		</n-card>
+	</div>
+</template>
+
+<script lang="tsx">
+import { reactive, ref, defineComponent } from 'vue';
+import type { Ref } from 'vue';
+import { useBoolean, useLoading } from '@/hooks';
+import TableActionModal from './component/table-action-modal.vue';
+import type { ModalType } from './component/table-action-modal.vue';
+import { selectAll, deleteSubjects, selectById, selectByCondition } from '~/src/service/api/crouse';
+import type { SelectByConditionParams } from '~/src/service/api/crouse'
+import { PaginationProps, DataTableColumns, DataTableRowKey, NButton, NPopconfirm, NSpace } from 'naive-ui';
+import { fetchUserList } from '@/service';
+import { number } from 'echarts';
+
+// import { selectByCondition } from '../../../service/api/crouse.ts';
+// import AddView from '~/src/views/management/crouse/component/AddView.vue';
+// const useSelect: SelectByConditionParams = {};
+// const { loading } = useLoading(false);
+const conditionParams: SelectByConditionParams = {};
+const { loading, startLoading, endLoading } = useLoading(false);
+const { bool: visible, setTrue: openModal } = useBoolean();
+// input的值
+const inputValue = ref(0);
+// 接收查询返回的数组
+const serchInput = ref([]) as any;
+const serchFormEr = ref([]);
+// 根据条件查询
+const inputPageNum1 = ref(0);
+const inputPageNum2 = ref(0);
+console.log(inputValue.value)
+const pagination: PaginationProps = reactive({
+	page: 1 || number,
+	pageSize: 10 || number,
+	showSizePicker: true,
+	pageSizes: [10, 15, 20, 25, 30] || number,
+	// onChange: (page: number) => {
+	// 	pagination.page = page;
+	// },
+	onUpdatePageSize: (pageSize: number) => {
+		pagination.pageSize = pageSize;
+	},
+	onUpdatePage: (page: number) =>{
+		pagination.page = page;
+	}
+});
+
+const pageDate = ref([]);
+type RowData = {
+	key: number;
+	id: number;
+	select: string;
+	name: string;
+	description: string;
+	categoryId: string;
+	createTime: string;
+	modifyTime: string;
+	createUid: number;
+	disabled: string;
+};
+const columns: Ref<DataTableColumns<UserManagement1.User>> = ref([
+	{
+		type: 'selection',
+		align: 'center'
+	},
+	{
+		key: 'id',
+		title: 'id',
+		align: 'center'
+	},
+	{
+		key: 'name',
+		title: '学科名称',
+		align: 'center'
+	},
+	{
+		key: 'description',
+		title: '学科描述',
+		align: 'center'
+	},
+	{
+		key: 'categoryId',
+		title: '学科分类',
+		align: 'center'
+	},
+	{
+		key: 'createTime',
+		title: '创建时间',
+		align: 'center'
+	},
+	{
+		key: 'modifyTime',
+		title: '修改时间',
+		align: 'center'
+	},
+	{
+		key: 'createUid',
+		title: '创建用户ID',
+		align: 'center'
+	},
+	{
+		key: 'disabled',
+		title: '状态',
+		align: 'center'
+	},
+	{
+		key: 'actions',
+		title: '操作',
+		align: 'center',
+		render: row => {
+			function handleDeleteTable(value: never[]): any {
+				throw new Error('Function not implemented.');
+			}
+
+			return (
+				<NSpace justify={'center'}>
+					<NButton size={'small'} onClick={() => handleEditTable(row.id)}>
+						编辑
+					</NButton>
+					<NPopconfirm onPositiveClick={() => handleDeleteTable(pageDate.value)}>
+						{{
+							default: () => '确认删除',
+							trigger: () => <NButton size={'small'}>删除</NButton>
+						}}
+					</NPopconfirm>
+				</NSpace>
+			);
+		}
+	}
+]) as Ref<DataTableColumns<UserManagement1.User>>;
+// selectByCondition(pagination.page, pagination.pageSize, useSelect).then(r => {
+//   console.log(r);
+// });
+// eslint-disable-next-line import/no-duplicates
+// import { selectAll } from '../../../service/api/crouse.ts';
+// selectAll().then(r => {
+//   console.log(r);
+// });
+// const useAdd: AddSubjectParams = {
+//   id: 2,
+//   name: '物理',
+//   description: '很难',
+//   categoryId: '理学',
+//   createTime: '',
+//   modifyTime: '',
+//   createUid: 2,
+//   disabled: '1'
+// } as any;
+// 重新加载
+// function handleRefresh() {
+// 	const isCached = routeStore.cacheRoutes.includes(String(route.name));
+// 	if (isCached) {
+// 		routeStore.removeCacheRoute(route.name as AuthRoute.AllRouteKey);
+// 	}
+// 	startLoading();
+// 	app.reloadPage();
+// 	setTimeout(() => {
+// 		if (isCached) {
+// 			routeStore.addCacheRoute(route.name as AuthRoute.AllRouteKey);
+// 		}
+// 		endLoading();
+// 	}, 1000);
+// }
+function handleAddTable() {
+	openModal();
+	setModalType('add');
+	init();
+}
+// 编辑
+const editData = ref<UserManagement1.User | null>(null);
+function setEditData(data: UserManagement1.User | null) {
+	editData.value = data;
+	console.log(editData.value)
+}
+function handleEditTable(rowId: number) {
+	console.log(rowId)
+	// 	selectAll().then(r => {
+	// 	pageDate.value = r.data as [];
+	// });
+	const findItem = pageDate.value.find(item => item.id === rowId);
+	console.log(findItem, pageDate.value)
+	if (findItem) {
+		setEditData(findItem);
+	}
+	setModalType('edit');
+	openModal();
+}
+
+const modalType = ref<ModalType>('add' || 'edit');
+function setModalType(type: ModalType) {
+	modalType.value = type;
+	console.log(modalType.value)
+}
+
+selectAll().then(r => {
+	console.log(r)
+	pageDate.value = r.data as [];
+});
+// addSubject(useAdd).then(() => {
+//   selectAll();
+// });
+// const tableData = ref<RowData[]>([]);
+// function setTableData(data: RowData[]) {
+//   tableData.value = data;
+// }
+// 删除
+const s = ref([]) as any;
+const d = ref([]) as any
+function deleteSubjectsList() {
+	if (s.value.length !== 0) {
+		for (let i = 0; i < s.value.length; i++) {
+			deleteSubjects(s.value[i]).then((r) => {
+				// handleRefresh();
+				console.log(r)
+				console.log(s.value.length)
+				d.value.id = s.value[i].id
+				// for(let j = 0;j<d.value.length;j++){
+				// 	if(d.value[j].id === s.value[j].id){
+				// 		s.value.length = 0
+				// 	}
+				// }
+				console.log(s.value[i].id)
+			});
+		}
+
+	}
+	s.value = [];
+	console.log(s.value.length)
+	if (s.value.length == 0) {
+		console.log(s.value.length)
+		window.$message?.success('删除成功!');
+	}
+
+
+	init();
+}
+// function handleDeleteTable(rowId) {
+//   window.$message?.info(`点击了删除,rowId为${rowId}`);
+// }
+
+async function getTableData() {
+	startLoading();
+	const { data } = await fetchUserList();
+	if (data) {
+		setTimeout(() => {
+			// setTableData(data);
+			selectAll().then((r) => [
+				pageDate.value = r.data as []
+			]);
+			endLoading();
+		}, 1000);
+	}
+}
+
+// deleteSubjects(r: RowData)
+export default defineComponent({
+	components: { TableActionModal },
+	setup() {
+		// console.log(pageDate.value)
+		const checkedRowKeysRef = ref<DataTableRowKey[]>([]);
+		return {
+			columns,
+			inputPageNum1,
+			inputPageNum2,
+			loading,
+			inputValue,
+			NButton,
+			NPopconfirm,
+			NSpace,
+			conditionParams,
+			serchInput,
+			pageDate,
+			checkedRowKeys: checkedRowKeysRef,
+			pagination,
+			deleteSubjects,
+			deleteSubjectsList,
+			handleEditTable,
+			// handleRefresh,
+			visible,
+			serchFormEr,
+			editData,
+			modalType,
+			handleAddTable,
+			openModal,
+			setModalType,
+			useBoolean, useLoading,
+			rowKey: (row: RowData) => row.id,
+			handleCheck(rowKeys: DataTableRowKey[]) {
+				checkedRowKeysRef.value = rowKeys;
+				// rowKeys.splice(0);
+				// console.log(rowKeys)
+				s.value = checkedRowKeysRef.value
+				// rowKeys = []
+				// d.length = 0
+				// rowKeys.length = 0
+			},
+			// 根据条件查询
+			handleInput1(v: number) {
+				inputPageNum1.value = v;
+				// pagination.page = inputPageNum1.value.data;
+
+			},
+			handleInput2(v: number) {
+				inputPageNum2.value = v;
+				// pagination.pageSize = inputPageNum2.value.data;
+			},
+			// 根据id查询
+			handleChange(v: string) {
+				inputValue.value = Number(v)
+			},
+			async serchForm() {
+				await selectById(inputValue.value).then(r => {
+					console.log(inputValue.value)
+					serchInput.value = r.data as [];
+					const filteredItems = Object.values(pageDate.value.filter(item => item.id === serchInput.value.id))
+					// console.log(filteredItems,Array.isArray(filteredItems))
+					serchFormEr.value = filteredItems;
+					console.log(serchFormEr.value)
+				})
+			},
+			async serchCondition() {
+				await selectByCondition(inputPageNum1.value.data, inputPageNum2.value.data, conditionParams).then(r => {
+					console.log(r)
+					pageDate.value = r.data as [];
+					pagination.page = inputPageNum1.value.data;
+					pagination.pageSize = inputPageNum2.value.data;
+					// console.log(inputPageNum1.value.data, pagination.page)
+				})
+				// console.log(inputPageNum1.value.data, inputPageNum2.value.data)
+			}
+		};
+	}
+});
+export function init() {
+	getTableData();
+}
+
+// 初始化
+init();
+</script>
+
+<style scoped></style>

+ 72 - 2
src/views/management/role/index.vue

@@ -1,7 +1,77 @@
 <template>
-  <div>角色管理</div>
+  <div class="h-full overflow-hidden">
+    <n-card title="用户管理" :bordered="false" class="rounded-16px shadow-sm">
+      <n-space class="pb-12px" justify="space-between"></n-space>
+      <n-data-table :columns="columns" :data="pageDate" :pagination="pagination" />
+    </n-card>
+  </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { reactive, ref } from 'vue';
+import type { Ref } from 'vue';
+import { query } from '~/src/service/api/user';
+import type { QueryParams } from '~/src/service/api/user';
+import type { DataTableColumns, PaginationProps } from 'naive-ui';
+const UserQuery: QueryParams = {};
+const pagination: PaginationProps = reactive({
+  page: 1,
+  pageSize: 10,
+  showSizePicker: true,
+  pageSizes: [10, 15, 20, 25, 30],
+  onChange: (page: number) => {
+    pagination.page = page;
+  },
+  onUpdatePageSize: (pageSize: number) => {
+    pagination.pageSize = pageSize;
+    pagination.page = 1;
+  }
+});
+const pageDate = ref<QueryParams[]>([]);
+const columns: Ref<DataTableColumns<QueryParams>> = ref([
+  {
+    type: 'selection',
+    align: 'center'
+  },
+  {
+    key: 'name',
+    title: '权限名称',
+    align: 'center'
+  },
+  {
+    key: 'description',
+    title: '权限描述',
+    align: 'center'
+  },
+  {
+    key: 'isActive',
+    title: '是否激活',
+    align: 'center'
+  },
+  {
+    key: 'createTime',
+    title: '创建时间',
+    align: 'center'
+  },
+  {
+    key: 'modifyTime',
+    title: '修改时间',
+    align: 'center'
+  },
+  {
+    key: 'createUid',
+    title: '创建用户ID',
+    align: 'center'
+  },
+  {
+    key: 'disabled',
+    title: '状态',
+    align: 'center'
+  }
+]) as Ref<DataTableColumns<QueryParams>>;
+query(pagination.page, pagination.pageSize, UserQuery).then(result => {
+  pageDate.value = result.data as [];
+});
+</script>
 
 <style scoped></style>

+ 1 - 1
src/views/management/user/index.vue

@@ -165,7 +165,7 @@ function handleAddTable() {
   setModalType('add');
 }
 
-function handleEditTable(rowId: string) {
+function handleEditTable(rowId: number) {
   const findItem = tableData.value.find(item => item.id === rowId);
   if (findItem) {
     setEditData(findItem);