Browse Source

feat: ✨ 角色权限金刚区,补课课表等等

zhangtao 2 months ago
parent
commit
0617f543ad

+ 12 - 0
.vscode/extensions.json

@@ -0,0 +1,12 @@
+{
+  "recommendations": [
+    "antfu.vite",
+    "antfu.iconify",
+    "antfu.unocss",
+    "vue.volar",
+    "dbaeumer.vscode-eslint",
+    "editorConfig.editorConfig",
+    "uni-helper.uni-helper-vscode",
+    "alova.alova-vscode-extension"
+  ]
+}

+ 56 - 0
.vscode/settings.json

@@ -0,0 +1,56 @@
+{
+  // Disable the default formatter, use eslint instead
+  "prettier.enable": true,
+  "editor.formatOnSave": true,
+
+  // Auto fix
+  "editor.codeActionsOnSave": {
+    "source.fixAll.eslint": "explicit",
+    "source.organizeImports": "never"
+  },
+
+  // Silent the stylistic rules in you IDE, but still auto fix them
+  "eslint.rules.customizations": [
+    { "rule": "style/*", "severity": "off", "fixable": true },
+    { "rule": "format/*", "severity": "off", "fixable": true },
+    { "rule": "*-indent", "severity": "off", "fixable": true },
+    { "rule": "*-spacing", "severity": "off", "fixable": true },
+    { "rule": "*-spaces", "severity": "off", "fixable": true },
+    { "rule": "*-order", "severity": "off", "fixable": true },
+    { "rule": "*-dangle", "severity": "off", "fixable": true },
+    { "rule": "*-newline", "severity": "off", "fixable": true },
+    { "rule": "*quotes", "severity": "off", "fixable": true },
+    { "rule": "*semi", "severity": "off", "fixable": true }
+  ],
+
+  // Enable eslint for all supported languages
+  "eslint.validate": [
+    "javascript",
+    "javascriptreact",
+    "typescript",
+    "typescriptreact",
+    "vue",
+    "html",
+    "markdown",
+    "json",
+    "jsonc",
+    "yaml",
+    "toml",
+    "xml",
+    "gql",
+    "graphql",
+    "astro",
+    "svelte",
+    "css",
+    "less",
+    "scss",
+    "pcss",
+    "postcss"
+  ],
+
+  // Enable file nesting
+  "explorer.fileNesting.enabled": true,
+  "explorer.fileNesting.patterns": {
+    "vite.config.*": "pages.config.*, manifest.config.*, uno.config.*, volar.config.*, *.env, .env.*, alova.config.*"
+  }
+}

+ 16 - 0
.vscode/tasks.json

@@ -0,0 +1,16 @@
+{
+  "version": "2.0.0",
+  "tasks": [
+    {
+      "label": "uni:h5",
+      "type": "npm",
+      "script": "dev --devtools",
+      "isBackground": true,
+      "problemMatcher": "$vite",
+      "group": {
+        "kind": "build",
+        "isDefault": true
+      }
+    }
+  ]
+}

+ 41 - 0
src/api/apiDefinitions.ts

@@ -1,4 +1,44 @@
+/// <reference types='./globals.d.ts' />
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Swagger Petstore - OpenAPI 3.0 - version 1.0.27
+ *
+ * This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
+Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we&#x27;ve switched to the design first approach!
+You can now help us improve the API whether it&#x27;s by making changes to the definition itself or to the code.
+That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
+
+Some useful links:
+- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
+- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
+ *
+ * OpenAPI version: 3.0.4
+ *
+ * Contact:
+ *
+ * NOTE: This file is auto generated by the alova's vscode plugin.
+ *
+ * https://alova.js.org/devtools/vscode
+ *
+ * **Do not edit the file manually.**
+ */
 export default {
+  "app.queryKongfuZone": ["GET", "/app/user/queryKongfuZone"],
+  "app.getMsgInfo": ["GET", "/app/home/getMsgInfo"],
+  "app.getMsg": ["GET", "/app/home/getMsg"],
+  "app.editPriceRules": ["POST", "/app/appCoursesPriceRules/editPriceRules"],
+  "app.queryListByCoursesId": [
+    "GET",
+    "/app/appCoursesPriceRules/queryListByCoursesId",
+  ],
+  "app.evaluateEdit": ["POST", "/evaluate/evaluate/edit"],
+  "app.evaluateList": ["GET", "/evaluate/evaluate/list"],
+  "app.scanCodeVerification": ["PUT", "/app/course/scanCodeVerification"],
+  "app.scanCodeQueryOrder": ["GET", "/app/course/scanCodeQueryOrder"],
+  "app.queryMakeUpClassTable": ["GET", "/app/course/queryMakeUpClassTable"],
+  "app.getCourseInfo": ["GET", "//app/course/getCourseInfo/{courseId}"],
+  "app.getPageCourse": ["GET", "/app/course/getPageCourse"],
   "app.appCategory": ["GET", "/app/appCategory/list"],
   "user.loginUser": ["POST", "/sys/loginApp"],
   "courses.list": ["GET", "/app/appCourese/list"],
@@ -11,4 +51,5 @@ export default {
   "sys.userEdit": ["POST", "/staff/staff/edit"],
   "sys.userDel": ["delete", "/staff/staff/delete"],
   "sys.queryById": ["GET", "/staff/staff/queryById"],
+  "sys.getCurrentUserDeparts": ["GET", "/sys/user/getCurrentUserDeparts"],
 };

+ 0 - 105
src/api/createApi.ts

@@ -1,105 +0,0 @@
-import type {
-  Alova,
-  MethodType,
-  AlovaGenerics,
-  AlovaMethodCreateConfig,
-} from "alova";
-import { Method } from "alova";
-import apiDefinitions from "./apiDefinitions";
-
-const createFunctionalProxy = (
-  array: (string | symbol)[],
-  alovaInstance: Alova<AlovaGenerics>,
-  configMap: any,
-) => {
-  // create a new proxy instance
-  return new Proxy(function () {}, {
-    get(_, property) {
-      // record the target property, so that it can get the completed accessing paths
-      const newArray = [...array, property];
-      // always return a new proxy to continue recording accessing paths.
-      return createFunctionalProxy(newArray, alovaInstance, configMap);
-    },
-    apply(_, __, [config]) {
-      const apiPathKey = array.join(".") as keyof typeof apiDefinitions;
-      const apiItem = apiDefinitions[apiPathKey];
-      if (!apiItem) {
-        throw new Error(`the api path of \`${apiPathKey}\` is not found`);
-      }
-      const mergedConfig = {
-        ...configMap[apiPathKey],
-        ...config,
-      };
-      const [method, url] = apiItem;
-      const pathParams = mergedConfig.pathParams;
-      const urlReplaced = url.replace(/\{([^}]+)\}/g, (_, key) => {
-        const pathParam = pathParams[key];
-        return pathParam;
-      });
-      delete mergedConfig.pathParams;
-      let data = mergedConfig.data;
-      if (
-        Object.prototype.toString.call(data) === "[object Object]" &&
-        typeof FormData !== "undefined"
-      ) {
-        let hasBlobData = false;
-        const formData = new FormData();
-        for (const key in data) {
-          formData.append(key, data[key]);
-          if (data[key] instanceof Blob) {
-            hasBlobData = true;
-          }
-        }
-        data = hasBlobData ? formData : data;
-      }
-      return new Method(
-        method.toUpperCase() as MethodType,
-        alovaInstance,
-        urlReplaced,
-        mergedConfig,
-        data,
-      );
-    },
-  });
-};
-
-export const createApis = (
-  alovaInstance: Alova<AlovaGenerics>,
-  configMap: any,
-) => {
-  const Apis = new Proxy({} as Apis, {
-    get(_, property) {
-      return createFunctionalProxy([property], alovaInstance, configMap);
-    },
-  });
-  // define global variable `Apis`
-  (globalThis as any).Apis = Apis;
-  return Apis;
-};
-type MethodConfig<T> = AlovaMethodCreateConfig<
-  (typeof import("./index"))["alovaInstance"] extends Alova<infer AG>
-    ? AG
-    : any,
-  any,
-  T
->;
-type APISofParameters<
-  Tag extends string,
-  Url extends string,
-> = Tag extends keyof Apis
-  ? Url extends keyof Apis[Tag]
-    ? Apis[Tag][Url] extends (...args: any) => any
-      ? Parameters<Apis[Tag][Url]>
-      : any
-    : any
-  : any;
-type MethodsConfigMap = {
-  [P in keyof typeof import("./apiDefinitions").default]?: MethodConfig<
-    P extends `${infer Tag}.${infer Url}`
-      ? Parameters<APISofParameters<Tag, Url>[0]["transform"]>[0]
-      : any
-  >;
-};
-export const withConfigType = <Config extends MethodsConfigMap>(
-  config: Config,
-) => config;

+ 99 - 0
src/api/createApis.ts

@@ -0,0 +1,99 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Swagger Petstore - OpenAPI 3.0 - version 1.0.27
+ *
+ * This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
+Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we&#x27;ve switched to the design first approach!
+You can now help us improve the API whether it&#x27;s by making changes to the definition itself or to the code.
+That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
+
+Some useful links:
+- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
+- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
+ *
+ * OpenAPI version: 3.0.4
+ *
+ * Contact: 
+ *
+ * NOTE: This file is auto generated by the alova's vscode plugin.
+ *
+ * https://alova.js.org/devtools/vscode
+ *
+ * **Do not edit the file manually.**
+ */
+import type { Alova, MethodType, AlovaGenerics, AlovaMethodCreateConfig } from 'alova';
+import { Method } from 'alova';
+import apiDefinitions from './apiDefinitions';
+
+const createFunctionalProxy = (array: (string | symbol)[], alovaInstance: Alova<AlovaGenerics>, configMap: any) => {
+  // create a new proxy instance
+  return new Proxy(function () {}, {
+    get(_, property) {
+      // record the target property, so that it can get the completed accessing paths
+      const newArray = [...array, property];
+      // always return a new proxy to continue recording accessing paths.
+      return createFunctionalProxy(newArray, alovaInstance, configMap);
+    },
+    apply(_, __, [config]) {
+      const apiPathKey = array.join('.') as keyof typeof apiDefinitions;
+      const apiItem = apiDefinitions[apiPathKey];
+      if (!apiItem) {
+        throw new Error(`the api path of \`${apiPathKey}\` is not found`);
+      }
+      const mergedConfig = {
+        ...configMap[apiPathKey],
+        ...config
+      };
+      const [method, url] = apiItem;
+      const pathParams = mergedConfig.pathParams;
+      const urlReplaced = url.replace(/\{([^}]+)\}/g, (_, key) => {
+        const pathParam = pathParams[key];
+        return pathParam;
+      });
+      delete mergedConfig.pathParams;
+      let data = mergedConfig.data;
+      if (Object.prototype.toString.call(data) === '[object Object]' && typeof FormData !== 'undefined') {
+        let hasBlobData = false;
+        const formData = new FormData();
+        for (const key in data) {
+          formData.append(key, data[key]);
+          if (data[key] instanceof Blob) {
+            hasBlobData = true;
+          }
+        }
+        data = hasBlobData ? formData : data;
+      }
+      return new Method(method.toUpperCase() as MethodType, alovaInstance, urlReplaced, mergedConfig, data);
+    }
+  });
+};
+
+export const createApis = (alovaInstance: Alova<AlovaGenerics>, configMap: any) => {
+  const Apis = new Proxy({} as Apis, {
+    get(_, property) {
+      return createFunctionalProxy([property], alovaInstance, configMap);
+    }
+  });
+  // define global variable `Apis`
+  (globalThis as any).Apis = Apis;
+  return Apis;
+};
+type MethodConfig<T> = AlovaMethodCreateConfig<
+  (typeof import('./index'))['alovaInstance'] extends Alova<infer AG> ? AG : any,
+  any,
+  T
+>;
+type APISofParameters<Tag extends string, Url extends string> = Tag extends keyof Apis
+  ? Url extends keyof Apis[Tag]
+    ? Apis[Tag][Url] extends (...args: any) => any
+      ? Parameters<Apis[Tag][Url]>
+      : any
+    : any
+  : any;
+type MethodsConfigMap = {
+  [P in keyof typeof import('./apiDefinitions').default]?: MethodConfig<
+    P extends `${infer Tag}.${infer Url}` ? Parameters<APISofParameters<Tag, Url>[0]['transform']>[0] : any
+  >;
+};
+export const withConfigType = <Config extends MethodsConfigMap>(config: Config) => config;

+ 625 - 890
src/api/globals.d.ts

@@ -1,7 +1,7 @@
 /* tslint:disable */
 /* eslint-disable */
 /**
- * Swagger Petstore - OpenAPI 3.0 - version 1.0.26
+ * Swagger Petstore - OpenAPI 3.0 - version 1.0.27
  *
  * This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about
 Swagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we&#x27;ve switched to the design first approach!
@@ -111,970 +111,705 @@ type Alova2Method<
         >
       >
     : never;
-
-export type Category = {
-  id?: number;
-  name?: string;
-};
-export type Tag = {
-  id?: number;
-  name?: string;
-};
-export type Pet = {
-  id?: number;
-  /**
-   * [required]
-   */
-  name: string;
-  category?: Category;
-  /**
-   * [required]
-   */
-  photoUrls: string[];
-  tags?: Tag[];
-  /**
-   * pet status in the store
-   */
-  status?: "available" | "pending" | "sold";
-};
-export type ApiResponse = {
-  code?: number;
-  type?: string;
-  message?: string;
-};
-export type Order = {
-  id?: number;
-  petId?: number;
-  quantity?: number;
-  shipDate?: string;
-  /**
-   * Order Status
-   */
-  status?: "placed" | "approved" | "delivered";
-  complete?: boolean;
-};
-export type User = {
-  id?: number;
-  username?: string;
-  firstName?: string;
-  lastName?: string;
-  email?: string;
-  password?: string;
-  phone?: string;
-  /**
-   * User Status
-   */
-  userStatus?: number;
-};
+interface PaginationResponse<T> {
+  orders: any[];
+  pages: number;
+  records: T;
+  searchCount: boolean;
+  size: number;
+  total: number;
+  current?: number; // 如果有当前页码
+}
+interface listData<T> {
+  list: T[];
+}
 declare global {
   interface Apis {
-    pet: {
-      /**
-       * ---
-       *
-       * [PUT] Update an existing pet.
-       *
-       * **path:** /pet
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       */
-      updatePet<
-        Config extends Alova2MethodConfig<Pet> & {
-          data: Pet;
+    user: {
+      loginUser<
+        Config extends Alova2MethodConfig<any> & {
+          params: {
+            username: string;
+            password: string;
+          };
         },
       >(
         config: Config,
-      ): Alova2Method<Pet, "pet.updatePet", Config>;
-      /**
-       * ---
-       *
-       * [POST] Add a new pet to the store.
-       *
-       * **path:** /pet
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       */
-      addPet<
-        Config extends Alova2MethodConfig<Pet> & {
-          data: Pet;
+      ): Alova2Method<any, "user.loginUser", Config>;
+    };
+    sys: {
+      staff<
+        Config extends Alova2MethodConfig<{ records: sysStaff[] }> & {
+          data: {
+            page: number;
+            pageSize: number;
+          };
         },
       >(
         config: Config,
-      ): Alova2Method<Pet, "pet.addPet", Config>;
-      /**
-       * ---
-       *
-       * [GET] Finds Pets by status.
-       *
-       * **path:** /pet/findByStatus
-       *
-       * ---
-       *
-       * **Query Parameters**
-       * ```ts
-       * type QueryParameters = {
-       *   // Status values that need to be considered for filter
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = Array<{
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }>
-       * ```
-       */
-      findPetsByStatus<
-        Config extends Alova2MethodConfig<Pet[]> & {
-          params: {
-            /**
-             * Status values that need to be considered for filter
-             */
-            status?: "available" | "pending" | "sold";
-          };
+      ): Alova2Method<{ records: sysStaff[] }, "sys.staff", Config>;
+
+      updateStatus<
+        Config extends Alova2MethodConfig<any> & {
+          data: { status: number; id: string };
         },
       >(
         config: Config,
-      ): Alova2Method<Pet[], "pet.findPetsByStatus", Config>;
-      /**
-       * ---
-       *
-       * [GET] Finds Pets by tags.
-       *
-       * **path:** /pet/findByTags
-       *
-       * ---
-       *
-       * **Query Parameters**
-       * ```ts
-       * type QueryParameters = {
-       *   // Tags to filter by
-       *   tags?: string[]
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = Array<{
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }>
-       * ```
-       */
-      findPetsByTags<
-        Config extends Alova2MethodConfig<Pet[]> & {
-          params: {
-            /**
-             * Tags to filter by
-             */
-            tags?: string[];
-          };
+      ): Alova2Method<any, "sys.updateStatus", Config>;
+      userDel<
+        Config extends Alova2MethodConfig<any> & {
+          params: { id: string };
         },
       >(
         config: Config,
-      ): Alova2Method<Pet[], "pet.findPetsByTags", Config>;
-      /**
-       * ---
-       *
-       * [GET] Find pet by ID.
-       *
-       * **path:** /pet/{petId}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // ID of pet to return
-       *   // [required]
-       *   petId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       */
-      getPetById<
-        Config extends Alova2MethodConfig<Pet> & {
-          pathParams: {
-            /**
-             * ID of pet to return
-             * [required]
-             */
-            petId: number;
-          };
+      ): Alova2Method<any, "sys.userDel", Config>;
+      findByDeptTree<>(): Alova2Method<any, "sys.findByDeptTree", Config>;
+      rolelist<>(): Alova2Method<any, "sys.rolelist", Config>;
+      userAdd<
+        Config extends Alova2MethodConfig<any> & {
+          data: userAdd;
         },
       >(
         config: Config,
-      ): Alova2Method<Pet, "pet.getPetById", Config>;
-      /**
-       * ---
-       *
-       * [POST] Updates a pet in the store with form data.
-       *
-       * **path:** /pet/{petId}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // ID of pet that needs to be updated
-       *   // [required]
-       *   petId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Query Parameters**
-       * ```ts
-       * type QueryParameters = {
-       *   // Name of pet that needs to be updated
-       *   name?: string
-       *   // Status of pet that needs to be updated
-       *   status?: string
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   // [required]
-       *   name: string
-       *   category?: {
-       *     id?: number
-       *     name?: string
-       *   }
-       *   // [required]
-       *   photoUrls: string[]
-       *   tags?: Array<{
-       *     id?: number
-       *     name?: string
-       *   }>
-       *   // pet status in the store
-       *   status?: 'available' | 'pending' | 'sold'
-       * }
-       * ```
-       */
-      updatePetWithForm<
-        Config extends Alova2MethodConfig<Pet> & {
-          pathParams: {
-            /**
-             * ID of pet that needs to be updated
-             * [required]
-             */
-            petId: number;
-          };
-          params: {
-            /**
-             * Name of pet that needs to be updated
-             */
-            name?: string;
-            /**
-             * Status of pet that needs to be updated
-             */
-            status?: string;
-          };
+      ): Alova2Method<any, "sys.userAdd", Config>;
+      queryById<
+        Config extends Alova2MethodConfig<any> & {
+          data: { id: string };
         },
       >(
         config: Config,
-      ): Alova2Method<Pet, "pet.updatePetWithForm", Config>;
-      /**
-       * ---
-       *
-       * [DELETE] Deletes a pet.
-       *
-       * **path:** /pet/{petId}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // Pet id to delete
-       *   // [required]
-       *   petId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = unknown
-       * ```
-       */
-      deletePet<
-        Config extends Alova2MethodConfig<unknown> & {
-          pathParams: {
-            /**
-             * Pet id to delete
-             * [required]
-             */
-            petId: number;
-          };
+      ): Alova2Method<any, "sys.queryById", Config>;
+      userEdit<
+        Config extends Alova2MethodConfig<any> & {
+          data: userAdd;
         },
       >(
         config: Config,
-      ): Alova2Method<unknown, "pet.deletePet", Config>;
-      /**
-       * ---
-       *
-       * [POST] Uploads an image.
-       *
-       * **path:** /pet/{petId}/uploadImage
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // ID of pet to update
-       *   // [required]
-       *   petId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Query Parameters**
-       * ```ts
-       * type QueryParameters = {
-       *   // Additional Metadata
-       *   additionalMetadata?: string
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = Blob
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   code?: number
-       *   type?: string
-       *   message?: string
-       * }
-       * ```
-       */
-      uploadFile<
-        Config extends Alova2MethodConfig<ApiResponse> & {
-          pathParams: {
-            /**
-             * ID of pet to update
-             * [required]
-             */
-            petId: number;
-          };
-          params: {
-            /**
-             * Additional Metadata
-             */
-            additionalMetadata?: string;
-          };
-          data: Blob;
-        },
+      ): Alova2Method<any, "sys.userEdit", Config>;
+      getCurrentUserDeparts<
+        Config extends Alova2MethodConfig<listData<deptart>> & {},
       >(
         config: Config,
-      ): Alova2Method<ApiResponse, "pet.uploadFile", Config>;
+      ): Alova2Method<listData<deptart>, "sys.getCurrentUserDeparts", Config>;
     };
-    store: {
+    app: {
+      appCategory<Config extends Alova2MethodConfig<any>>(): Alova2Method<
+        any,
+        "app.appCategory",
+        Config
+      >;
       /**
-       * ---
-       *
-       * [GET] Returns pet inventories by status.
-       *
-       * **path:** /store/inventory
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = Record<string, number>
-       * ```
-       */
-      getInventory<Config extends Alova2MethodConfig<Record<string, number>>>(
-        config?: Config,
-      ): Alova2Method<Record<string, number>, "store.getInventory", Config>;
-      /**
-       * ---
-       *
-       * [POST] Place an order for a pet.
-       *
-       * **path:** /store/order
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = {
-       *   id?: number
-       *   petId?: number
-       *   quantity?: number
-       *   shipDate?: string
-       *   // Order Status
-       *   status?: 'placed' | 'approved' | 'delivered'
-       *   complete?: boolean
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   petId?: number
-       *   quantity?: number
-       *   shipDate?: string
-       *   // Order Status
-       *   status?: 'placed' | 'approved' | 'delivered'
-       *   complete?: boolean
-       * }
-       * ```
+       * 拍照验课
+       * @param config
        */
-      placeOrder<
-        Config extends Alova2MethodConfig<Order> & {
-          data: Order;
+      getPageCourse<
+        Config extends Alova2MethodConfig<
+          PaginationResponse<GetPageCourseRes[]>
+        > & {
+          data: { pageNo: number; pageSize: number; orgCode: string };
         },
       >(
         config: Config,
-      ): Alova2Method<Order, "store.placeOrder", Config>;
+      ): Alova2Method<
+        PaginationResponse<GetPageCourseRes[]>,
+        "app.getPageCourse",
+        Config
+      >;
       /**
-       * ---
-       *
-       * [GET] Find purchase order by ID.
-       *
-       * **path:** /store/order/{orderId}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // ID of order that needs to be fetched
-       *   // [required]
-       *   orderId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   petId?: number
-       *   quantity?: number
-       *   shipDate?: string
-       *   // Order Status
-       *   status?: 'placed' | 'approved' | 'delivered'
-       *   complete?: boolean
-       * }
-       * ```
+       * 获取课程详情
+       * @param config
        */
-      getOrderById<
-        Config extends Alova2MethodConfig<Order> & {
-          pathParams: {
-            /**
-             * ID of order that needs to be fetched
-             * [required]
-             */
-            orderId: number;
-          };
+      getCourseInfo<
+        Config extends Alova2MethodConfig<VerifyCourseInfoDTO[]> & {
+          pathParams: { courseId };
         },
       >(
         config: Config,
-      ): Alova2Method<Order, "store.getOrderById", Config>;
+      ): Alova2Method<VerifyCourseInfoDTO[], "app.getCourseInfo", Config>;
       /**
-       * ---
-       *
-       * [DELETE] Delete purchase order by identifier.
-       *
-       * **path:** /store/order/{orderId}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // ID of the order that needs to be deleted
-       *   // [required]
-       *   orderId: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = unknown
-       * ```
+       * 查询补课补课表
        */
-      deleteOrder<
-        Config extends Alova2MethodConfig<unknown> & {
-          pathParams: {
-            /**
-             * ID of the order that needs to be deleted
-             * [required]
-             */
-            orderId: number;
-          };
-        },
+      queryMakeUpClassTable<
+        Config extends Alova2MethodConfig<AppCoursesPriceRules> & {},
       >(
         config: Config,
-      ): Alova2Method<unknown, "store.deleteOrder", Config>;
-    };
-    user: {
+      ): Alova2Method<
+        AppCoursesPriceRules,
+        "app.queryMakeUpClassTable",
+        Config
+      >;
       /**
-       * ---
-       *
-       * [POST] Create user.
-       *
-       * **path:** /user
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = {
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }
-       * ```
+       * 扫码核销详情
+       * @param config
        */
-      createUser<
-        Config extends Alova2MethodConfig<User> & {
-          data: User;
+      scanCodeQueryOrder<
+        Config extends Alova2MethodConfig<ScanCodeQueryOrderVO> & {
+          params: {
+            orderId: string;
+          };
         },
       >(
         config: Config,
-      ): Alova2Method<User, "user.createUser", Config>;
+      ): Alova2Method<ScanCodeQueryOrderVO, "app.scanCodeQueryOrder", Config>;
       /**
-       * ---
-       *
-       * [POST] Creates list of users with given input array.
-       *
-       * **path:** /user/createWithList
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = Array<{
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }>
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }
-       * ```
+       * 确认核销
+       * @param config
        */
-      createUsersWithListInput<
-        Config extends Alova2MethodConfig<User> & {
-          data: User[];
+      scanCodeVerification<
+        Config extends Alova2MethodConfig<any> & {
+          data: string[];
         },
       >(
         config: Config,
-      ): Alova2Method<User, "user.createUsersWithListInput", Config>;
+      ): Alova2Method<any, "app.scanCodeVerification", Config>;
       /**
-       * ---
-       *
-       * [GET] Logs user into the system.
-       *
-       * **path:** /user/login
-       *
-       * ---
-       *
-       * **Query Parameters**
-       * ```ts
-       * type QueryParameters = {
-       *   // The user name for login
-       *   username?: string
-       *   // The password for login in clear text
-       *   password?: string
-       * }
-       * ```
-       *
-       * ---
        *
-       * **Response**
-       * ```ts
-       * type Response = string
-       * ```
+       * @param config
+       * 评价管理
        */
-      loginUser<
-        Config extends Alova2MethodConfig<string> & {
+      evaluateList<
+        Config extends Alova2MethodConfig<PaginationResponse<Evaluate[]>> & {
           params: {
-            /**
-             * The user name for login
-             */
-            username?: string;
-            /**
-             * The password for login in clear text
-             */
-            password?: string;
+            pageNo: number;
+            pageSize: number;
           };
         },
       >(
         config: Config,
-      ): Alova2Method<string, "user.loginUser", Config>;
-      /**
-       * ---
-       *
-       * [GET] Logs out current logged in user session.
-       *
-       * **path:** /user/logout
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = unknown
-       * ```
-       */
-      logoutUser<Config extends Alova2MethodConfig<unknown>>(
-        config?: Config,
-      ): Alova2Method<unknown, "user.logoutUser", Config>;
-      /**
-       * ---
-       *
-       * [GET] Get user by user name.
-       *
-       * **path:** /user/{username}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // The name that needs to be fetched. Use user1 for testing
-       *   // [required]
-       *   username: string
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = {
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }
-       * ```
-       */
-      getUserByName<
-        Config extends Alova2MethodConfig<User> & {
-          pathParams: {
-            /**
-             * The name that needs to be fetched. Use user1 for testing
-             * [required]
-             */
-            username: string;
-          };
+      ): Alova2Method<
+        PaginationResponse<Evaluate[]>,
+        "app.evaluateList",
+        Config
+      >;
+      evaluateEdit<
+        Config extends Alova2MethodConfig<any> & {
+          data: Evaluate;
         },
       >(
         config: Config,
-      ): Alova2Method<User, "user.getUserByName", Config>;
+      ): Alova2Method<any, "app.evaluateEdit", Config>;
       /**
-       * ---
-       *
-       * [PUT] Update user resource.
-       *
-       * **path:** /user/{username}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // name that need to be deleted
-       *   // [required]
-       *   username: string
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **RequestBody**
-       * ```ts
-       * type RequestBody = {
-       *   id?: number
-       *   username?: string
-       *   firstName?: string
-       *   lastName?: string
-       *   email?: string
-       *   password?: string
-       *   phone?: string
-       *   // User Status
-       *   userStatus?: number
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = unknown
-       * ```
+       * 补课课表详情
+       * @param config
        */
-      updateUser<
-        Config extends Alova2MethodConfig<unknown> & {
-          pathParams: {
-            /**
-             * name that need to be deleted
-             * [required]
-             */
-            username: string;
+      queryListByCoursesId<
+        Config extends Alova2MethodConfig<webMakeClass[]> & {
+          params: {
+            coursesType: number;
+            id: string;
           };
-          data: User;
         },
       >(
         config: Config,
-      ): Alova2Method<unknown, "user.updateUser", Config>;
+      ): Alova2Method<webMakeClass[], "app.queryListByCoursesId", Config>;
+      editPriceRules<
+        Config extends Alova2MethodConfig<any> & {
+          data: webMakeClass[];
+        },
+      >(
+        config: Config,
+      ): Alova2Method<any, "app.editPriceRules", Config>;
       /**
-       * ---
-       *
-       * [DELETE] Delete user resource.
-       *
-       * **path:** /user/{username}
-       *
-       * ---
-       *
-       * **Path Parameters**
-       * ```ts
-       * type PathParameters = {
-       *   // The name that needs to be deleted
-       *   // [required]
-       *   username: string
-       * }
-       * ```
-       *
-       * ---
-       *
-       * **Response**
-       * ```ts
-       * type Response = unknown
-       * ```
+       * 消息通知
+       * @param config
        */
-      deleteUser<
-        Config extends Alova2MethodConfig<unknown> & {
-          pathParams: {
-            /**
-             * The name that needs to be deleted
-             * [required]
-             */
-            username: string;
+      getMsg<Config extends Alova2MethodConfig<sysMsg[]> & {}>(
+        config: Config,
+      ): Alova2Method<sysMsg[], "app.getMsg", Config>;
+      getMsgInfo<
+        Config extends Alova2MethodConfig<sysMsg> & {
+          params: {
+            id: string;
           };
         },
       >(
         config: Config,
-      ): Alova2Method<unknown, "user.deleteUser", Config>;
+      ): Alova2Method<sysMsg, "app.getMsgInfo", Config>;
+      queryKongfuZone<Config extends Alova2MethodConfig<sysRole[]> & {}>(
+        config: Config,
+      ): Alova2Method<sysRole[], "app.queryKongfuZone", Config>;
     };
   }
 
   var Apis: Apis;
 }
+export interface sysMsg {
+  id: string;
+  titile: string;
+  imgUrl: string;
+  sender: string;
+  sendTime: string;
+  msgContent: string;
+}
+
+export interface sysRole {
+  id: string;
+  name: string;
+  iconUrl: null;
+  route: string;
+  orderNumber: number;
+  izShow: string;
+  delFlag: number;
+  roleCode: string;
+}
+export interface sysStaff {
+  id: string;
+  username: string;
+  realname: string;
+  status: 0;
+  departName: string;
+  createTime: string;
+}
+
+export interface userAdd {
+  id: string;
+  username: string;
+  backgroundImg: string;
+  realname: string;
+  status: string;
+  password: string;
+  selectedroles: string;
+  selecteddeparts: string;
+  orgCode: string;
+  trainingPrograms: string;
+  teachingPhilosophy: string;
+  excelMsg: string;
+  certificateInnocence: string;
+  healthy: string;
+  honor: string;
+}
+export interface GetPageCourseRes {
+  /**
+   * 课程ID
+   */
+  appCourseId?: string;
+  /**
+   * 课时数
+   */
+  classNum?: number;
+  /**
+   * 封面
+   */
+  cover?: string;
+  /**
+   * 结束时间
+   */
+  endTime?: string;
+  /**
+   * 产品名称
+   */
+  name?: string;
+  /**
+   * 上课地址
+   */
+  siteAddress?: string;
+  /**
+   * 开始时间
+   */
+  startTime?: string;
+  /**
+   * 教练id(关联用户表)
+   */
+  userId?: string;
+  [property: string]: any;
+}
+
+export interface deptart {
+  address?: string;
+  createBy?: string;
+  createTime?: string;
+  delFlag?: string;
+  departName?: string;
+  departNameAbbr?: string;
+  departNameEn?: string;
+  departOrder?: number;
+  description?: string;
+  dingIdentifier?: string;
+  directorUserIds?: string;
+  fax?: string;
+  id: string;
+  izLeaf?: number;
+  memo?: string;
+  mobile?: string;
+  oldDirectorUserIds?: string;
+  orgCategory?: string;
+  orgCode: string;
+  orgType?: string;
+  parentId?: string;
+  qywxIdentifier?: string;
+  status: string;
+  tenantId?: number;
+}
+
+export interface VerifyCourseInfoDTO {
+  coursesId?: string;
+  /**
+   * 课程类型(0-正常 1-补课)
+   */
+  coursesType?: number;
+  /**
+   * 结束时间
+   */
+  endTime?: string;
+  /**
+   * id
+   */
+  id?: string;
+  /**
+   * 名称
+   */
+  name?: string;
+  /**
+   * 是否今日
+   */
+  orToday?: boolean;
+  /**
+   * 延课人数
+   */
+  postponeNum?: number;
+  /**
+   * 开始时间
+   */
+  startTime?: string;
+  /**
+   * 上课人数
+   */
+  totalNum?: number;
+  /**
+   * 未核销人数
+   */
+  unwrittenOffNum?: number;
+  /**
+   * 已核销人数
+   */
+  writtenOffNum?: number;
+  /**
+   * 是否完成
+   */
+  orDone: boolean;
+}
+/**
+ * 课程补课课表
+ */
+export interface AppCoursesPriceRules {
+  /**
+   * 课时状态
+   * 课时状态(0-正常 1-延期)
+   */
+  classStatus?: number;
+  /**
+   * 课程id
+   */
+  coursesId?: string;
+  /**
+   * 结束时间
+   * 课程类型(0-正常 1-补课)
+   */
+  coursesType?: number;
+  /**
+   * 创建人;创建人
+   */
+  createBy?: string;
+  /**
+   * 创建时间;创建时间
+   */
+  createTime?: string;
+  /**
+   * 删除标志;删除状态(0-正常,1-已删除)
+   */
+  delFlag?: number;
+  /**
+   * 结束时间
+   */
+  endTime?: string;
+  /**
+   * id
+   */
+  id?: string;
+  /**
+   * 名称
+   */
+  name?: string;
+  /**
+   * 部门id
+   */
+  orgCode?: string;
+  /**
+   * 乐观锁
+   */
+  revision?: number;
+  /**
+   * 排序
+   */
+  sort?: number;
+  /**
+   * 开始时间
+   */
+  startTime?: string;
+  /**
+   * 系统状态;状态(0-正常,1-冻结)
+   */
+  status?: number;
+  /**
+   * 租户id
+   */
+  tenantId?: string;
+  /**
+   * 更新人;更新人
+   */
+  updateBy?: string;
+  /**
+   * 更新时间;更新时间
+   */
+  updateTime?: string;
+  [property: string]: any;
+}
+
+/**
+ * 扫码核销
+ */
+export interface ScanCodeQueryOrderVO {
+  /**
+   * 商品数量
+   */
+  amount?: number;
+  /**
+   * 子订单信息
+   */
+  appOrderProInfoVerifyVOS?: AppOrderProInfoVerifyVO[];
+  /**
+   * 比赛类型 0-个人 1-团队
+   */
+  gameType?: number;
+  /**
+   * 商品价格
+   */
+  price?: number;
+  /**
+   * 商品图片
+   */
+  productImage?: string;
+  /**
+   * 商品名称
+   */
+  productName?: string;
+  /**
+   * 场馆
+   */
+  siteName?: string;
+  [property: string]: any;
+}
+
+/**
+ * org.jeecg.modules.app.vo.AppOrderProInfoVerifyVO
+ *
+ * AppOrderProInfoVerifyVO
+ */
+export interface AppOrderProInfoVerifyVO {
+  /**
+   * 子订单商品
+   */
+  appOrderProInfo: AppOrderProInfo;
+  /**
+   * 券ID
+   */
+  isinId?: string;
+  /**
+   * 券状态 1、待使用 2、已使用 3、已失效
+   */
+  isinStatus?: number;
+  [property: string]: any;
+}
+
+/**
+ * 子订单商品
+ *
+ * AppOrderProInfo
+ */
+export interface AppOrderProInfo {
+  /**
+   * 地点
+   */
+  address?: string;
+  /**
+   * 售后状态
+   */
+  afterSaleStatus?: number;
+  /**
+   * 创建人;创建人
+   */
+  createBy?: string;
+  /**
+   * 创建时间;创建时间
+   */
+  createTime?: string;
+  /**
+   * 删除标志;删除状态(0-正常,1-已删除)
+   */
+  delFlag?: number;
+  /**
+   * 使用人ID
+   */
+  familyUserId?: string;
+  /**
+   * 时间段
+   */
+  frameTimeStr?: string;
+  /**
+   * 比赛日期
+   */
+  gameTimeStr?: string;
+  /**
+   * id
+   */
+  id?: string;
+  /**
+   * 订单id
+   * 订单编号
+   */
+  orderCode?: string;
+  /**
+   * 订单id
+   */
+  orderId?: string;
+  /**
+   * 订单状态
+   */
+  orderStatus?: number;
+  /**
+   * 是否免费试听课(0-否 1-是)
+   */
+  orFreePro?: number;
+  /**
+   * 原价/元
+   */
+  originalPrice?: number;
+  /**
+   * 实际价格/元
+   */
+  price?: number;
+  /**
+   * 产品id;场地/赛事/课程
+   */
+  productId?: string;
+  /**
+   * 商品图片
+   */
+  productImage?: string;
+  /**
+   * 商品名称
+   */
+  productName?: string;
+  /**
+   * 数量
+   */
+  quantity?: number;
+  /**
+   * 系统状态;状态(0-正常,1-冻结)
+   */
+  status?: number;
+  /**
+   * 券号
+   */
+  ticketNo?: string;
+  /**
+   * 商品类型(1-学校 2-包场 3-无固定场 4-个人赛 5-团队赛 6-课程 7-保险)
+   */
+  type?: number;
+  /**
+   * 更新人;更新人
+   */
+  updateBy?: string;
+  /**
+   * 更新时间;更新时间
+   */
+  updateTime?: string;
+  /**
+   * 日期
+   */
+  useDateStr?: string;
+  /**
+   * 使用人
+   */
+  userName?: string;
+  /**
+   * 手机号
+   */
+  userPhone?: string;
+  [property: string]: any;
+}
+
+export interface Evaluate {
+  id: string;
+  /**
+   * 部门编码
+   */
+  orgCode: string;
+  /**	发布单位名称
+   *
+   */
+  departName: string;
+  /**
+   * 场地/地点
+   */
+  address: string;
+  /**
+   * 	用户
+   */
+  username: string;
+  /**
+   * 用户手机号
+   */
+  phone: string;
+  /**
+   * 头像
+   */
+  avatar: string;
+  /**
+   * 评分
+   */
+  score: number;
+  /**
+   * 评价内容
+   */
+  evaluateContent: string;
+  /**
+   * 图片
+   */
+  images: string;
+  /**
+   * 审核状态;0待审核 1审核通过 2审核不通过
+   */
+  checkStatus: number;
+  /**
+   * 	回复状态 0-未回复 1-已回复
+   */
+  replyStatus: number;
+  /**
+   * 回复内容
+   */
+  replyContent: string;
+  /**
+   * 回复时间
+   */
+  replyTime: string;
+  /**
+   * 业务类型;0场地 1课程
+   */
+  type: number;
+  createTime: string;
+  updateTime: string;
+  /**	图片列表集合
+   *
+   */
+  imageList: string[];
+  isAnonymous: number;
+}
+
+export interface webMakeClass {
+  id?: string;
+  coursesId: string;
+  name: string;
+  startTime: string;
+  endTime: string;
+}

+ 1 - 1
src/api/index.ts

@@ -2,7 +2,7 @@
 import alovaInstance from "./core/instance";
 
 // Export the global Apis object from the generated code
-import { createApis, withConfigType } from "./createApi";
+import { createApis, withConfigType } from "./createApis";
 
 // Export the alova instance for direct use if needed
 export { alovaInstance };

+ 13 - 4
src/auto-imports.d.ts

@@ -9,10 +9,12 @@ declare global {
   const Apis: typeof import('./api/index')['Apis']
   const CommonUtil: typeof import('wot-design-uni')['CommonUtil']
   const EffectScope: typeof import('vue')['EffectScope']
+  const UserCourseStore: typeof import('./store/course')['UserCourseStore']
   const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
   const alovaInstance: typeof import('./api/index')['alovaInstance']
   const api: typeof import('./api/index')['default']
   const apiDefinitions: typeof import('./api/apiDefinitions')['default']
+  const areAllItemsAllFieldsFilled: typeof import('./utils/index')['areAllItemsAllFieldsFilled']
   const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
   const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
   const computed: typeof import('vue')['computed']
@@ -22,7 +24,7 @@ declare global {
   const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
   const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
   const controlledRef: typeof import('@vueuse/core')['controlledRef']
-  const createApis: typeof import('./api/createApi')['createApis']
+  const createApis: typeof import('./api/createApis')['createApis']
   const createApp: typeof import('vue')['createApp']
   const createEventHook: typeof import('@vueuse/core')['createEventHook']
   const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
@@ -47,6 +49,7 @@ declare global {
   const getCurrentInstance: typeof import('vue')['getCurrentInstance']
   const getCurrentPath: typeof import('./utils/index')['getCurrentPath']
   const getCurrentScope: typeof import('vue')['getCurrentScope']
+  const getImageURL: typeof import('./utils/index')['getImageURL']
   const h: typeof import('vue')['h']
   const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
   const inject: typeof import('vue')['inject']
@@ -181,6 +184,7 @@ declare global {
   const useColorMode: typeof import('@vueuse/core')['useColorMode']
   const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
   const useCounter: typeof import('@vueuse/core')['useCounter']
+  const useCourseStore: typeof import('./store/course')['useCourseStore']
   const useCssModule: typeof import('vue')['useCssModule']
   const useCssVar: typeof import('@vueuse/core')['useCssVar']
   const useCssVars: typeof import('vue')['useCssVars']
@@ -322,6 +326,7 @@ declare global {
   const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
   const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
   const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
+  const utils: typeof import('./utils/index')['default']
   const watch: typeof import('vue')['watch']
   const watchArray: typeof import('@vueuse/core')['watchArray']
   const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
@@ -338,7 +343,7 @@ declare global {
   const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
   const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
   const whenever: typeof import('@vueuse/core')['whenever']
-  const withConfigType: typeof import('./api/createApi')['withConfigType']
+  const withConfigType: typeof import('./api/createApis')['withConfigType']
 }
 // for type re-export
 declare global {
@@ -359,6 +364,7 @@ declare module 'vue' {
     readonly alovaInstance: UnwrapRef<typeof import('./api/index')['alovaInstance']>
     readonly api: UnwrapRef<typeof import('./api/index')['default']>
     readonly apiDefinitions: UnwrapRef<typeof import('./api/apiDefinitions')['default']>
+    readonly areAllItemsAllFieldsFilled: UnwrapRef<typeof import('./utils/index')['areAllItemsAllFieldsFilled']>
     readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
     readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
     readonly computed: UnwrapRef<typeof import('vue')['computed']>
@@ -368,7 +374,7 @@ declare module 'vue' {
     readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
     readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
     readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
-    readonly createApis: UnwrapRef<typeof import('./api/createApi')['createApis']>
+    readonly createApis: UnwrapRef<typeof import('./api/createApis')['createApis']>
     readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
     readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
     readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
@@ -393,6 +399,7 @@ declare module 'vue' {
     readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
     readonly getCurrentPath: UnwrapRef<typeof import('./utils/index')['getCurrentPath']>
     readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
+    readonly getImageURL: UnwrapRef<typeof import('./utils/index')['getImageURL']>
     readonly h: UnwrapRef<typeof import('vue')['h']>
     readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
     readonly inject: UnwrapRef<typeof import('vue')['inject']>
@@ -527,6 +534,7 @@ declare module 'vue' {
     readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
     readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
     readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
+    readonly useCourseStore: UnwrapRef<typeof import('./store/course')['useCourseStore']>
     readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
     readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
     readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
@@ -668,6 +676,7 @@ declare module 'vue' {
     readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
     readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
     readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
+    readonly utils: UnwrapRef<typeof import('./utils/index')['default']>
     readonly watch: UnwrapRef<typeof import('vue')['watch']>
     readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
     readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
@@ -684,6 +693,6 @@ declare module 'vue' {
     readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
     readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
     readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
-    readonly withConfigType: UnwrapRef<typeof import('./api/createApi')['withConfigType']>
+    readonly withConfigType: UnwrapRef<typeof import('./api/createApis')['withConfigType']>
   }
 }

+ 1 - 0
src/components.d.ts

@@ -36,6 +36,7 @@ declare module 'vue' {
     WdRate: typeof import('wot-design-uni/components/wd-rate/wd-rate.vue')['default']
     WdSearch: typeof import('wot-design-uni/components/wd-search/wd-search.vue')['default']
     WdSelectPicker: typeof import('wot-design-uni/components/wd-select-picker/wd-select-picker.vue')['default']
+    WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
     WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default']
     WdTab: typeof import('wot-design-uni/components/wd-tab/wd-tab.vue')['default']
     WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']

+ 33 - 10
src/components/classItem/index.vue

@@ -1,53 +1,76 @@
 <template>
-  <view class="bg-white rounded-32rpx p24rpx box-border">
+  <view class="bg-white rounded-32rpx p24rpx box-border" v-if="item">
     <view class="flex items-center">
       <view class="w-8rpx h-28rpx bg-#0074FF"></view>
-      <view class="ml20rpx text-28rpx">05.06 17:00-19:00</view>
+      <view class="ml20rpx text-28rpx">
+        {{ dayjs(item?.startTime).format("MM-DD hh:ss") }}
+        {{ dayjs(item?.endTime).format("hh:ss") }}
+      </view>
     </view>
     <view class="mt20rpx flex items-center justify-between pl20rpx">
-      <view class="text-28rpx">第二节:拍球、握球、传球...</view>
+      <!-- <view class="text-28rpx">{{ item.name }}</view> -->
+      <wd-text :text="item.name" size="28rpx" :lines="1"></wd-text>
       <commonbtn
         bg-color="#0074FF"
         @click="handleGoPath('/subPack/selectClass/index')"
-        v-if="type == 0"
+        v-if="type == 0 && showBtn"
         >拍照核销</commonbtn
       >
       <commonbtn
         bg-color="#0074FF"
         @click="handleGoPath('/subPack/ReservationClass/index')"
-        v-if="type == 1"
+        v-if="type == 1 && showBtn"
         >预约这节</commonbtn
       ><commonbtn
         bg-color="#0074FF"
         @click="handleGoPath('/subPack/ExtensionClass/index')"
-        v-if="type == 2"
+        v-if="type == 2 && showBtn"
         >延期这节</commonbtn
       >
+      <view v-if="!showBtn">
+        <view class="text-gray font-semibold text-28rpx" v-if="item.orDone"
+          >已完成</view
+        >
+        <view v-else class="text-[#0074FF] font-semibold text-28rpx"
+          >未开始</view
+        >
+      </view>
     </view>
     <view
       class="mt20rpx pl20rpx flex items-center text-24rpx"
       @click="handleGoPath('/subPack/PersonnelView/index')"
     >
-      <view class="text-[rgb(0,0,0,0.3)] mr20rpx">共20人</view>
       <view class="text-[rgb(0,0,0,0.3)] mr20rpx"
-        >延课 <text class="text-#0074FF">5</text> 人</view
+        >共{{ item?.totalNum }}人</view
       >
       <view class="text-[rgb(0,0,0,0.3)] mr20rpx"
-        >已核销<text class="text-#0074FF">10</text>人</view
+        >延课
+        <text class="text-#0074FF"> {{ item.postponeNum }} </text> 人</view
+      >
+      <view class="text-[rgb(0,0,0,0.3)] mr20rpx"
+        >已核销<text class="text-#0074FF"> {{ item.writtenOffNum }} </text
+        >人</view
       >
       <view class="text-[rgb(0,0,0,0.3)]"
-        >未核销<text class="text-#0074FF">5</text>人</view
+        >未核销<text class="text-#0074FF"> {{ item.unwrittenOffNum }} </text
+        >人</view
       >
     </view>
   </view>
 </template>
 
 <script setup lang="ts">
+import type { VerifyCourseInfoDTO } from "@/api/globals";
+import dayjs from "dayjs";
+
 interface IProps {
   /**
    * 当前组件在什么地方展示,0为验课,1为约课,2为课程延期
    */
   type: number;
+
+  item?: VerifyCourseInfoDTO;
+  showBtn: boolean;
 }
 const props = defineProps<IProps>();
 function handleGoPath(url: string) {

+ 11 - 21
src/components/course/index.vue

@@ -4,57 +4,47 @@
     @click="handleDetailes"
   >
     <image
-      src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
+      :src="getImageURL(item.cover)"
       class="w-200rpx h-200rpx rounded-32rpx min-w-200rpx"
     />
+
     <view class="ml20rpx">
       <view class="text-#000000 text-32rpx font-semibold">{{ item.name }}</view>
       <view class="text-[rgba(0,0,0,0.3)] text-28rpx mt-24rpx"
-        >上课地点:{{ item.address }}</view
+        >上课地点:{{ item.siteAddress }}</view
       >
       <view class="text-[rgba(0,0,0,0.3)] text-28rpx mt-24rpx"
-        >{{ item.totalNum }}课时 {{ item.startTime }}-{{ item.endTime }}</view
+        >{{ item.classNum }}课时 {{ item.startTime }}-{{ item.endTime }}</view
       >
     </view>
   </view>
 </template>
 
 <script setup lang="ts">
+import type { GetPageCourseRes } from "@/api/globals";
+
 interface props {
   /**
    * 当前组件在什么地方展示,0为验课,1为约课,2为课程延期
    */
   type?: number;
   disabled?: boolean;
-  item: {
-    address: string;
-    categoryId: string;
-    categoryIds: string;
-    coursesStatus: number;
-    cover: string;
-    endTime: string;
-    id: string;
-    name: string;
-    originalPrice: number;
-    priceType: number;
-    rackingStatus: number;
-    sellingPrice: number;
-    startTime: string;
-    totalNum: number;
-  };
+  item: GetPageCourseRes;
 }
 const props = defineProps<props>();
+const useCourese = useCourseStore();
+
 function handleDetailes() {
   if (props.disabled) return;
+  useCourese.setCourseItem(props.item);
   if (props.type == 3) {
     uni.navigateTo({
       url: `/subPack/Makeupclass/index`,
     });
-
     return;
   }
   uni.navigateTo({
-    url: `/subPack/classInspectionDetaile/index?type=${props.type}&id=${props.item.id}`,
+    url: `/subPack/classInspectionDetaile/index?type=${props.type}&id=${props.item.appCourseId}`,
   });
 }
 </script>

+ 34 - 2
src/config/index.ts

@@ -3,8 +3,8 @@ const mapEnvVersion = {
    * 	开发版
    */
   // develop: "http://192.168.1.166:8080/jeecg-boot",
-  // develop: "http://192.168.1.34:8080/jeecg-boot",
-  develop: "http://192.168.0.11:8080/jeecg-boot",
+  develop: "http://192.168.1.34:8080/jeecg-boot",
+  // develop: "http://192.168.0.11:8080/jeecg-boot",
   /**
    * 	体验版
    */
@@ -26,3 +26,35 @@ export const BASE_UPLOADURL =
   "http://192.168.1.166:8080/jeecg-boot/sys/common/upload";
 // export const BASE_UPLOADURL =
 //   "http://192.168.0.11:8080/jeecg-boot/sys/common/upload";
+
+//1-学校 2-包场 3-无固定场 4-个人赛 5-团队赛 6-课程 7-保险
+export enum GoodsType {
+  /**
+   * 学校
+   */
+  school = 1,
+  /**
+   * 包场
+   */
+  package = 2,
+  /**
+   * 无固定场
+   */
+  noFixed = 3,
+  /**
+   * 个人赛
+   */
+  personal = 4,
+  /**
+   * 团队赛
+   */
+  team = 5,
+  /**
+   * 课程
+   */
+  course = 6,
+  /**
+   *  保险
+   */
+  insurance = 7,
+}

+ 14 - 2
src/pages.json

@@ -71,7 +71,8 @@
           "name": "classInspection",
           "style": {
             "navigationBarTitleText": "拍照验课||选择课程",
-            "navigationStyle": "custom"
+            "navigationStyle": "custom",
+            "disableScroll": true
           }
         },
         {
@@ -106,7 +107,8 @@
           "name": "Evaluation",
           "style": {
             "navigationBarTitleText": "评价",
-            "navigationStyle": "custom"
+            "navigationStyle": "custom",
+            "disableScroll": true
           }
         },
         {
@@ -188,6 +190,16 @@
           "style": {
             "navigationBarTitleText": "核销明细"
           }
+        },
+        {
+          "path": "writeOff/error/index",
+          "type": "page",
+          "name": "error",
+          "style": {
+            "navigationBarTitleText": "",
+            "navigationStyle": "custom",
+            "disableScroll": true
+          }
         }
       ]
     }

+ 122 - 81
src/pages/index/index.vue

@@ -1,25 +1,98 @@
 <script setup lang="ts">
 import router from "@/router";
-
+import hxs from "@/subPack/static/hxs.png";
+import hx from "@/static/index/hx.png";
+import bk from "@/static/index/bk.png";
+import pj from "@/static/index/pj.png";
+import ye from "@/static/index/ye.png";
+import yg from "@/static/index/yg.png";
+import pz from "@/static/index/pz.png";
+import ls from "@/static/index/ls.png";
+import nz from "@/static/index/nz.png";
+import sm from "@/static/index/sm.png";
 const { statusBarHeight } = uni.getSystemInfoSync();
-const { token, userInfo } = storeToRefs(useUserStore());
-const option1 = ref<Record<string, any>[]>([
-  { label: "选择场馆", value: 0 },
-  { label: "选择场馆1", value: 1 },
-  { label: "选择场馆1", value: 2 },
-]);
+const { token, userInfo, orgCode, title, isShowLoging, topMenu, StoreMenu } =
+  storeToRefs(useUserStore());
+
+const { data: dept, send: getDeptList } = useRequest(
+  () => Apis.sys.getCurrentUserDeparts({}),
+  {
+    initialData: [],
+    immediate: false,
+  },
+).onSuccess(() => {
+  title.value = String(dept.value.list[0].departName);
+});
+
+const { data: sysMsg, send: getmsgData } = useRequest(
+  () => Apis.app.getMsg({}),
+  { immediate: false },
+);
 function handleCommenPath(url: string) {
-  router.push(url);
+  if (url == "/subPack/writeOff/index") {
+    uni.scanCode({
+      success: function (res) {
+        console.log(res, "扫码信息");
+        if (res.result) {
+          handleCommenPath(`/subPack/writeOff/index?id=${res.result}`);
+        } else {
+          uni.showToast({
+            title: "请检查二维码是否正确",
+            icon: "none",
+          });
+        }
+      },
+    });
+  } else {
+    router.push(url);
+  }
 }
-function handleScanCode() {
-  // uni.scanCode({
-  //   success: function (res) {
-  //     console.log(res, "扫码信息");
-  //   },
-  // });
-  handleCommenPath("/subPack/writeOff/index");
+onMounted(() => {
+  if (token.value) {
+    getDeptList();
+  }
+});
+onShow(() => {
+  if (token.value) {
+    getmsgData();
+    useUserStore().getMenuList();
+  }
+});
+watch(
+  () => isShowLoging.value,
+  () => {
+    if (isShowLoging.value) {
+      uni.showToast({
+        image: hxs,
+        title: "核销成功",
+      });
+    }
+  },
+);
+
+function getIcon(path: string) {
+  const iconMap: Record<string, string> = {
+    "/subPack/classInspection/index?type=0": pz,
+    "/subPack/classInspection/index?type=1": ls,
+    "/subPack/classInspection/index?type=2": nz,
+    "/subPack/writeOffDetaile/index": hx,
+    "/subPack/classInspection/index?type=3": bk,
+    "/subPack/Evaluation/index": pj,
+    "/subPack/Storebalance/index": ye,
+    "/subPack/EmployeeList/index": yg,
+    "/subPack/writeOff/index": sm,
+  };
+  return iconMap[path] || "";
+}
+function getItemClass(path: string) {
+  const classMap: Record<string, string> = {
+    "/subPack/classInspection/index?type=0": "header",
+    "/subPack/classInspection/index?type=1": "ls",
+    "/subPack/writeOff/index": "sm",
+    "/subPack/classInspection/index?type=2": "kc",
+  };
+  return classMap[path] || "";
 }
-const value = ref<number>(0);
 </script>
 
 <template>
@@ -42,9 +115,16 @@ const value = ref<number>(0);
     </view>
     <view class="relative">
       <wd-drop-menu>
-        <wd-drop-menu-item :options="option1" v-model="value" />
+        <wd-drop-menu-item
+          :options="dept.list"
+          v-model:model-value="orgCode"
+          value-key="orgCode"
+          label-key="departName"
+          :title="title"
+          @change="useUserStore().setTitile"
+        />
       </wd-drop-menu>
-      <view class="absolute top-50% -translate-y-50% right-50rpx">
+      <view class="absolute top-50% -translate-y-50% right-50rpx" v-if="token">
         <view class="flex items-center">
           <image src="@/static/index/user.png" class="w-40rpx h-40rpx"></image>
           <view class="text-32rpx font-semibold ml-3">{{
@@ -57,87 +137,45 @@ const value = ref<number>(0);
       <view class="grid grid-cols-2 gap-3">
         <view
           class="flex items-center px-40rpx header rounded-2xl h-162rpx"
-          @click="handleCommenPath('/subPack/classInspection/index?type=0')"
-        >
-          <image src="@/static/index/pz.png" class="w-100rpx h-100rpx"></image>
-          <view class="text-32rpx font-semibold">拍照验课</view>
-        </view>
-        <view
-          class="flex items-center px-40rpx ls rounded-2xl h-162rpx"
-          @click="handleCommenPath('/subPack/classInspection/index?type=1')"
-        >
-          <image src="@/static/index/ls.png" class="w-100rpx h-100rpx"></image>
-          <view class="text-32rpx font-semibold">临时约课</view>
-        </view>
-        <view
-          class="flex items-center px-40rpx kc rounded-2xl h-162rpx"
-          @click="handleCommenPath('/subPack/classInspection/index?type=2')"
-        >
-          <image src="@/static/index/nz.png" class="w-100rpx h-100rpx"></image>
-          <view class="text-32rpx font-semibold">课程延期</view>
-        </view>
-        <view
-          class="flex items-center px-40rpx sm rounded-2xl h-162rpx"
-          @click="handleScanCode"
+          @click="handleCommenPath(item.route)"
+          v-for="item in topMenu"
+          :class="getItemClass(item.route)"
+          :key="item.id"
         >
-          <image src="@/static/index/sm.png" class="w-100rpx h-100rpx"></image>
-          <view class="text-32rpx font-semibold">扫码验券</view>
+          <image :src="getIcon(item.route)" class="w-100rpx h-100rpx"></image>
+          <view class="text-32rpx font-semibold">{{ item.name }}</view>
         </view>
       </view>
-      <view class="mt-3">
+      <view class="mt-3" v-if="sysMsg">
         <wd-notice-bar
-          :text="[
-            '这是一条消息提示信息',
-            '这是一条消息提示信息',
-            '这是一条消息提示信息',
-          ]"
+          :text="sysMsg.map((it) => it.titile)"
           color="#000000"
           background-color="#fff"
+          :delay="3"
           direction="vertical"
           @click="handleCommenPath('/subPack/notification/index')"
         >
           <template #prefix>
-            <image src="@/static/index/msg.png" class="w-30rpx h-30rpx"></image>
+            <image
+              src="@/static/index/msg.png"
+              class="w-30rpx h-30rpx mr2"
+            ></image>
           </template>
         </wd-notice-bar>
       </view>
-      <view class="mt-3 rounded-2xl bg-white p-28rpx">
+      <view class="mt-3 rounded-2xl bg-white p-28rpx" v-if="StoreMenu">
         <view class="font-semibold text-32rpx">门店经营</view>
         <view class="grid grid-cols-4 gap-3 mt-3">
           <view
             class="flex items-center justify-center flex-col"
-            @click="handleCommenPath('/subPack/writeOffDetaile/index')"
-          >
-            <image src="@/static/index/hx.png" class="w-52rpx h-52rpx"></image>
-            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">核销明细</view>
-          </view>
-          <view
-            class="flex items-center justify-center flex-col"
-            @click="handleCommenPath('/subPack/classInspection/index?type=3')"
-          >
-            <image src="@/static/index/bk.png" class="w-52rpx h-52rpx"></image>
-            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">补课课表</view>
-          </view>
-          <view
-            class="flex items-center justify-center flex-col"
-            @click="handleCommenPath('/subPack/Evaluation/index')"
-          >
-            <image src="@/static/index/pj.png" class="w-52rpx h-52rpx"></image>
-            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">评价管理</view>
-          </view>
-          <view
-            class="flex items-center justify-center flex-col"
-            @click="handleCommenPath('/subPack/Storebalance/index')"
-          >
-            <image src="@/static/index/ye.png" class="w-52rpx h-52rpx"></image>
-            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">店铺余额</view>
-          </view>
-          <view
-            class="flex items-center justify-center flex-col"
-            @click="handleCommenPath('/subPack/EmployeeList/index')"
+            @click="handleCommenPath(item.route)"
+            v-for="item in StoreMenu"
+            :key="item.id"
           >
-            <image src="@/static/index/yg.png" class="w-52rpx h-52rpx"></image>
-            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">员工管理</view>
+            <image :src="getIcon(item.route)" class="w-52rpx h-52rpx"></image>
+            <view class="text-24rpx text-[rgb(0,0,0,0.6)] mt-3">{{
+              item.name
+            }}</view>
           </view>
           <view class="flex items-center justify-center flex-col">
             <image src="@/static/index/kf.png" class="w-52rpx h-52rpx"></image>
@@ -165,6 +203,9 @@ const value = ref<number>(0);
   background-color: transparent !important;
   .wd-drop-menu__item {
     text-align: left !important;
+    .wd-drop-menu__item-title {
+      max-width: 300rpx !important;
+    }
   }
 }
 .ls {

+ 18 - 0
src/store/course.ts

@@ -0,0 +1,18 @@
+import type { deptart, GetPageCourseRes } from "@/api/globals";
+import { defineStore } from "pinia";
+
+interface useCourseStore {
+  courseItem: GetPageCourseRes;
+}
+export const useCourseStore = defineStore({
+  id: "app-course",
+  state: (): useCourseStore => ({
+    courseItem: {},
+  }),
+  getters: {},
+  actions: {
+    setCourseItem(course: GetPageCourseRes) {
+      this.courseItem = course;
+    },
+  },
+});

+ 77 - 0
src/store/user.ts

@@ -1,3 +1,4 @@
+import type { deptart, sysRole } from "@/api/globals";
 import { defineStore } from "pinia";
 interface user {
   activitiSync: number;
@@ -36,7 +37,20 @@ interface user {
 interface UserState {
   token: string;
   userInfo: user;
+  orgCode: string;
+  title: string;
+  isShowLoging: boolean;
+  topMenu: sysRole[];
+  StoreMenu: sysRole[];
 }
+
+const { data: menuList, send: getMenu } = useRequest(
+  () => Apis.app.queryKongfuZone({}),
+  {
+    immediate: false,
+  },
+);
+
 export const useUserStore = defineStore({
   id: "app-user",
   state: (): UserState => ({
@@ -75,12 +89,75 @@ export const useUserStore = defineStore({
       workNo: "",
     },
     token: "",
+    orgCode: "",
+    title: "请选择场馆",
+    isShowLoging: false,
+    topMenu: [
+      {
+        delFlag: 0,
+        iconUrl: null,
+        id: "4",
+        izShow: "1",
+        name: "扫码验券",
+        orderNumber: 4,
+        roleCode: "stores_mg,operation_mg,platform_mg,school_mg,admin",
+        route: "/subPack/writeOff/index",
+      },
+      {
+        delFlag: 0,
+        iconUrl: null,
+        id: "3",
+        izShow: "1",
+        name: "课程延期",
+        orderNumber: 3,
+        roleCode: "stores_mg,operation_mg,platform_mg,school_mg,admin",
+        route: "/subPack/classInspection/index?type=2",
+      },
+      {
+        delFlag: 0,
+        iconUrl: null,
+        id: "4",
+        izShow: "1",
+        name: "临时约课",
+        orderNumber: 4,
+        roleCode: "stores_mg,operation_mg,platform_mg,school_mg,admin",
+        route: "/subPack/classInspection/index?type=1",
+      },
+      {
+        delFlag: 0,
+        iconUrl: null,
+        id: "4",
+        izShow: "1",
+        name: "拍照验课",
+        orderNumber: 4,
+        roleCode: "stores_mg,operation_mg,platform_mg,school_mg,admin",
+        route: "/subPack/classInspection/index?type=0",
+      },
+    ],
+    StoreMenu: [],
   }),
   getters: {},
   actions: {
     handleLogin(userInfo: user, token: string) {
       this.userInfo = userInfo;
       this.token = token;
+      this.orgCode = userInfo.orgCode;
+      this.getMenuList();
+    },
+    setTitile(event: { selectedItem: deptart }) {
+      this.title = String(event.selectedItem.departName);
+    },
+    async getMenuList() {
+      const top = [
+        "/subPack/classInspection/index?type=0",
+        "/subPack/classInspection/index?type=1",
+        "/subPack/classInspection/index?type=2",
+        "/subPack/writeOff/index",
+      ];
+      await getMenu();
+      this.topMenu = menuList.value.filter((it) => top.includes(it.route));
+      this.StoreMenu = menuList.value.filter((it) => !top.includes(it.route));
+      console.log(this.StoreMenu);
     },
   },
 });

+ 10 - 8
src/subPack/EmployeeList/index.vue

@@ -40,6 +40,7 @@
         </view>
       </template>
     </wd-card>
+    <wd-status-tip image="content" tip="暂无内容" v-if="!data.length" />
     <view class="h150rpx"></view>
   </view>
   <fixdbtn block size="large" @click="handleAdd(0, '')">新增员工</fixdbtn>
@@ -59,6 +60,7 @@ function handleAdd(type: number, id: string) {
 async function getData() {
   await getList();
 }
+
 onShow(() => getData());
 const {
   loading,
@@ -70,20 +72,20 @@ const {
   refresh,
   send: getList,
 } = usePagination(
-  (page, pageSize) =>
+  (page: number, pageSize: number) =>
     Apis.sys.staff({
       data: { page, pageSize },
     }),
   {
     middleware: createGlobalLoadingMiddleware(),
-    data: (resp) => resp.records,
+    data: (resp: any) => resp.records,
     initialPage: 1, // 初始页码,默认为1
     initialPageSize: 10, // 初始每页数据条数,默认为10
     immediate: false,
   },
-).onError((error) => {});
+);
 const { send: uploadStatus } = useRequest(
-  (status, id) =>
+  (status: number, id: string) =>
     Apis.sys.updateStatus({
       data: { status, id },
     }),
@@ -92,9 +94,9 @@ const { send: uploadStatus } = useRequest(
     middleware: createGlobalLoadingMiddleware(),
     immediate: false,
   },
-).onError((error) => {});
+);
 const { send: del } = useRequest(
-  (id) =>
+  (id: string) =>
     Apis.sys.userDel({
       params: { id },
     }),
@@ -103,9 +105,9 @@ const { send: del } = useRequest(
     middleware: createGlobalLoadingMiddleware(),
     immediate: false,
   },
-).onError((error) => {});
+);
 async function handleChange(e: SwitchBeforeChangeOption, id: string) {
-  await uploadStatus(e.value, id);
+  await uploadStatus(Number(e.value), id);
   refresh();
 }
 async function handleDelete(item: { realname: string; id: string }) {

+ 72 - 21
src/subPack/EmployeeListAdd/index.vue

@@ -90,6 +90,8 @@
                 :value="item.id"
                 v-for="item in rolelist.records"
                 :key="item.id"
+                true-value="sting"
+                false-value="string"
                 >{{ item.roleName }}</wd-radio
               >
             </wd-radio-group>
@@ -219,7 +221,7 @@
             ></upload>
           </wd-cell>
         </customFormItem>
-        <customFormItem label="教学理念" v-if="isShowInstructor">
+        <customFormItem label="教学理念" v-if="isShowInstructor" required>
           <wd-input
             type="text"
             placeholder="请输入教学理念"
@@ -230,7 +232,7 @@
             :rules="[{ required: true, message: '请输入教学理念' }]"
           />
         </customFormItem>
-        <customFormItem label="擅长描述" v-if="isShowInstructor">
+        <customFormItem label="擅长描述" v-if="isShowInstructor" required>
           <wd-input
             type="text"
             placeholder="请输入擅长描述"
@@ -243,7 +245,7 @@
         </customFormItem>
         <customFormItem label="荣誉证书" bg="#fff">
           <upload
-            tip="最多支持2张图片,单张照片不超过5MB"
+            tip="最多支持9张图片,单张照片不超过5MB"
             :max-size="5242880"
             :sourceType="['camera']"
             accept="image"
@@ -255,7 +257,11 @@
     </wd-form>
   </view>
   <view class="h-180rpx"></view>
-  <fixdbtn block size="large" @click="handleSubmit" :loading="isloading"
+  <fixdbtn
+    block
+    size="large"
+    @click="handleSubmit"
+    :loading="isloading || loading"
     >确认</fixdbtn
   >
   <view class="customPopup">
@@ -304,6 +310,7 @@ import tree from "./components/tree/index.vue";
 import upload from "./components/upload/index.vue";
 import { type FormInstance } from "wot-design-uni/components/wd-form/types";
 import { createGlobalLoadingMiddleware } from "@/api/core/middleware";
+import assignFormValues from "@/utils";
 const titleArr = ["新增员工", "编辑员工"];
 const treePicker = ref();
 const form = ref<FormInstance>();
@@ -330,15 +337,20 @@ const id = ref("");
 const { data: deptList } = useRequest(() => Apis.sys.findByDeptTree(), {});
 const { data: rolelist } = useRequest(() => Apis.sys.rolelist(), {});
 const { data: categoryList } = useRequest(() => Apis.app.appCategory(), {});
-const {
-  data,
-  send: handleAdd,
-  loading: isloading,
-} = useRequest((param) => Apis.sys.userAdd({ data: { ...param } }), {
-  immediate: false,
-  middleware: createGlobalLoadingMiddleware(),
-});
-
+const { send: handleAdd, loading: isloading } = useRequest(
+  (param) => Apis.sys.userAdd({ data: { ...param } }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware(),
+  },
+);
+const { send: handleuserEdit, loading: loading } = useRequest(
+  (param) => Apis.sys.userEdit({ data: { ...param } }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware(),
+  },
+);
 const { send: queryById } = useRequest(
   (id) => Apis.sys.queryById({ data: { id } }),
   {
@@ -349,11 +361,47 @@ const { send: queryById } = useRequest(
 onLoad((query: any) => {
   type.value = query.type;
   id.value = query.id;
+});
+watch(
+  () => [rolelist.value, deptList.value],
+  () => {
+    getDetaile();
+  },
+);
+async function getDetaile() {
   if (type.value == 1) {
-    const res = queryById(query.id);
-    console.log(res, "场地");
+    const res = await queryById(id.value);
+    if (res.instructorId) {
+      isShowInstructor.value = true;
+    }
+    assignFormValues(formData, res, {
+      ignoreEmpty: true,
+      transform: {
+        backgroundImg: (value) => {
+          return value ? value.split(",").map((url: string) => ({ url })) : [];
+        },
+        healthy: (value) => {
+          return value ? value.split(",").map((url: string) => ({ url })) : [];
+        },
+        certificateInnocence: (value) =>
+          value ? value.split(",").map((url: string) => ({ url })) : [],
+        honor: (value) => {
+          if (typeof value == "string") {
+            return value.split(",").map((url: string) => ({ url }));
+          }
+          return value;
+        },
+        selectedroles: (value) => {
+          return value ? value.join(",") : "";
+        },
+      },
+    });
+    formData.deptName = findNamesByKeys(
+      formData.selecteddeparts,
+      deptList.value,
+    ).join(",");
   }
-});
+}
 function handleShow() {
   // treePicker.value._show();
   treeFlage.value = true;
@@ -369,17 +417,18 @@ async function handleSubmit() {
       honor: transformImg("honor") || null,
       backgroundImg: transformImg("backgroundImg") || null,
       healthy: transformImg("healthy") || null,
-      trainingPrograms: transformImg("trainingPrograms") || null,
+      trainingPrograms: formData.trainingPrograms.join(",") || null,
       certificateInnocence: transformImg("certificateInnocence") || null,
       selecteddeparts: formData.selecteddeparts.join(","),
     };
     console.log(obj, "提交表单");
-    type.value == 0 ? await handleAdd(obj) : await handleEdit(obj);
+    type.value == 0
+      ? await handleAdd(obj)
+      : await handleuserEdit({ ...obj, id: id.value });
     uni.navigateBack();
   }
-  // console.log(val, "校验", formData);
 }
-function handleEdit(a: any) {}
+
 function handleSubmitDept() {
   const key = treePicker.value.getCheckedKeys();
   if (!key) return uni.showToast({ title: "最少选择一个部门", icon: "none" });
@@ -405,7 +454,9 @@ function handleChangeRole(e: { value: string }) {
   });
 }
 function transformImg(key: keyof typeof formData) {
-  const list = (formData[key] as any[]).map((it) => it.url).join(",");
+  const list = formData[key]
+    ? (formData[key] as any[]).map((it) => it.url).join(",")
+    : null;
   return list;
 }
 

+ 123 - 67
src/subPack/Evaluation/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <view class="h-screen overflow-y-scroll header box-border">
+  <view class="header box-border h-screen">
     <wd-navbar
       title="评价管理"
       fixed
@@ -10,67 +10,102 @@
       leftArrow
       @click-left="handleClickLeft"
     ></wd-navbar>
-    <view class="px-32rpx">
-      <view
-        class="bg-white p-24rpx mb-20rpx rounded-32rpx"
-        v-for="item in data"
-        :key="item.id"
-      >
-        <view class="text-[rgba(0,0,0,0.7)] text-28rpx">评价(23)</view>
-        <wd-divider color="#F0F0F0" custom-class="custom-divider"></wd-divider>
-        <view class="flex items-center justify-between mt-2">
-          <view class="flex items-center text-24rpx">
+    <scroll-view
+      scroll-y
+      :style="{
+        height: `calc(100vh - ${statusBarHeight}px - ${height}px)`,
+        paddingBottom: 'env(safe-area-inset-bottom)',
+      }"
+      @scrolltolower="handleBottom"
+    >
+      <view class="px-32rpx">
+        <view
+          class="bg-white p-24rpx mb-20rpx rounded-32rpx"
+          v-for="(item, idx) in list"
+          :key="item.id"
+        >
+          <template v-if="idx == 0">
+            <view class="text-[rgba(0,0,0,0.7)] text-28rpx"
+              >评价({{ list.length }})</view
+            >
+            <wd-divider
+              color="#F0F0F0"
+              custom-class="custom-divider"
+            ></wd-divider>
+          </template>
+          <view class="flex items-center justify-between mt-2">
+            <view class="flex items-center text-24rpx">
+              <image
+                src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
+                class="w-60rpx h-60rpx rounded-full"
+              ></image>
+              <view class="ml-20rpx text-[rgba(0,0,0,0.9)]">{{
+                item.username
+              }}</view>
+              <view class="ml-20rpx text-[rgba(0,0,0,0.3)]">{{
+                dayjs(item.createTime).format("YYYY-MM-DD")
+              }}</view>
+            </view>
+            <view
+              v-if="item.checkStatus == 0"
+              class="flex items-center justify-center text-white text-28rpx bg-#0074FF px-23rpx py-4rpx rounded-8rpx"
+              >待审核</view
+            >
+          </view>
+          <view class="flex items-center mt-16rpx">
+            <text class="text-[rgba(0,0,0,0.3)] text-24rpx mr-20rpx"
+              >{{ item.score }}.0</text
+            >
+            <wd-rate v-model="item.score" readonly />
+          </view>
+          <view class="mt-20rpx text-[rgba(0,0,0,0.9)] text-28rpx">{{
+            item.evaluateContent
+          }}</view>
+          <view class="mt-20rpx grid grid-cols-3">
             <image
-              src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
-              class="w-60rpx h-60rpx rounded-full"
+              :src="its"
+              :key="its"
+              v-for="its in item.imageList"
+              class="w-202rpx h-200rpx rounded-32rpx"
             ></image>
-            <view class="ml-20rpx text-[rgba(0,0,0,0.9)]">张三</view>
-            <view class="ml-20rpx text-[rgba(0,0,0,0.3)]">2021-01-01</view>
           </view>
           <view
-            class="flex items-center justify-center text-white text-28rpx bg-#0074FF px-23rpx py-4rpx rounded-8rpx"
-            >待审核</view
+            class="mt-24rpx"
+            v-if="item.checkStatus == 1 && item.replyContent"
           >
-        </view>
-        <view class="flex items-center mt-16rpx">
-          <text class="text-[rgba(0,0,0,0.3)] text-24rpx mr-20rpx">4.0</text>
-          <wd-rate v-model="rate" readonly />
-        </view>
-        <view class="mt-20rpx text-[rgba(0,0,0,0.9)] text-28rpx"
-          >詹姆四对孩子很有耐心,也非常照顾小朋友的情绪, 值得推荐!</view
-        >
-        <view class="mt-20rpx flex items-center justify-between">
-          <image
-            src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
-            v-for="item in 3"
-            class="w-202rpx h-200rpx rounded-32rpx"
-          ></image>
-        </view>
-        <view class="mt-24rpx">
-          <view class="bg-#F6F6F6 rounded-16rpx flex p-20rpx">
-            <view class="text-[rgba(0,0,0,0.3)] text-24rpx">商家回复:</view>
-            <view
-              class="text-24rpx w-68%"
-              :class="[currentId == item.id ? '' : 'truncate ']"
-              >谢谢您的评价,我们会越来越好,谢谢额外企鹅王企鹅我去额外企鹅轻微青sadsadasdsadasdasdasdasdasd蛙</view
-            >
-            <view
-              class="text-[rgba(0,0,0,0.3)] text-24rpx flex-1 text-center"
-              @click="handleChange(item.id)"
-              >{{ currentId == item.id ? "折叠" : "展开" }}</view
-            >
+            <view class="bg-#F6F6F6 rounded-16rpx flex p-20rpx">
+              <view class="text-[rgba(0,0,0,0.3)] text-24rpx">商家回复:</view>
+              <view
+                class="text-24rpx w-68%"
+                :class="[currentId == item.id ? '' : 'truncate ']"
+                >{{ item.replyContent }}</view
+              >
+              <view
+                class="text-[rgba(0,0,0,0.3)] text-24rpx flex-1 text-center"
+                @click="handleChange(item.id)"
+                >{{ currentId == item.id ? "折叠" : "展开" }}</view
+              >
+            </view>
           </view>
-        </view>
-        <view class="flex items-center justify-end mt-3">
           <view
-            class="flex items-center justify-center text-white text-28rpx bg-#FDD143 px-23rpx py-4rpx rounded-8rpx"
-            @click="handleHf"
-            >回复</view
+            class="flex items-center justify-end mt-3"
+            v-if="item.checkStatus == 1 && item.replyStatus == 0"
           >
+            <view
+              class="flex items-center justify-center text-white text-28rpx bg-#FDD143 px-23rpx py-4rpx rounded-8rpx"
+              @click="handleHf(item)"
+              >回复</view
+            >
+          </view>
         </view>
+        <view class="h40rpx"></view>
       </view>
-    </view>
+      <view v-if="!list.length" class="h-80% w-full flex items-center">
+        <wd-status-tip image="content" tip="暂无内容" />
+      </view>
+    </scroll-view>
   </view>
+
   <wd-message-box selector="wd-message-box-slot" :closeOnClickModal="false">
     <view class="flex items-center justify-center w-full">
       <view
@@ -89,40 +124,60 @@
 </template>
 
 <script setup lang="ts">
+import { createGlobalLoadingMiddleware } from "@/api/core/middleware";
+import type { Evaluate } from "@/api/globals";
+import dayjs from "dayjs";
 import { useMessage } from "wot-design-uni";
 const message = useMessage("wd-message-box-slot");
+const { statusBarHeight } = uni.getSystemInfoSync();
+const { height } = uni.getMenuButtonBoundingClientRect();
 const msgContent = ref();
-const rate = ref(4);
 const currentId = ref();
-const data = ref([
-  { id: 0 },
-  { id: 1 },
-  { id: 2 },
-  { id: 3 },
-  { id: 4 },
-  { id: 5 },
-  { id: 6 },
-  { id: 7 },
-  { id: 8 },
-]);
-function handleChange(id: number) {
+const {
+  data: list,
+  isLastPage,
+  page,
+  refresh,
+} = usePagination(
+  (page, size) =>
+    Apis.app.evaluateList({ params: { pageNo: page, pageSize: size } }),
+  {
+    data: (res) => res.records,
+  },
+);
+const { send: senMsg } = useRequest(
+  (data) => Apis.app.evaluateEdit({ data: data }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware({ loadingText: "提交中..." }),
+  },
+);
+function handleChange(id: string) {
   currentId.value == id ? (currentId.value = null) : (currentId.value = id);
 }
 function handleClickLeft() {
   uni.navigateBack();
 }
-function handleHf() {
+function handleHf(item: Evaluate) {
   message
     .confirm({
       title: "回复",
       confirmButtonText: "提交",
       closeOnClickModal: false,
     })
-    .then(() => {})
+    .then(async () => {
+      await senMsg({ ...item, replyContent: msgContent.value });
+      refresh();
+    })
     .catch((error) => {
       console.log(error);
     });
 }
+function handleBottom() {
+  if (!isLastPage.value) {
+    page.value++;
+  }
+}
 </script>
 
 <style>
@@ -135,7 +190,8 @@ function handleHf() {
   "name": "Evaluation",
   "style": {
     "navigationBarTitleText": "评价",
-    "navigationStyle": "custom"
+    "navigationStyle": "custom",
+    "disableScroll": true
   }
 }
 </route>

+ 87 - 9
src/subPack/Makeupclass/index.vue

@@ -2,11 +2,17 @@
   <view class="py-20rpx">
     <view class="bg-white px32rpx py28rpx flex items-center">
       <view class="text-[rgba(0,0,0,0.3)]">课程名称:</view>
-      <view class="flex-1">
-        <wd-input type="text" placeholder="请输入课程名称" no-border />
+      <view class="flex-1 flex items-center">
+        <wd-input
+          type="text"
+          placeholder="请输入课程名称"
+          no-border
+          v-model:model-value="courseItem.name"
+          readonly
+        />
       </view>
     </view>
-    <view class="mt20rpx bg-white px32rpx py30rpx">
+    <view class="mt20rpx bg-white px32rpx py30rpx" v-if="data">
       <view class="flex items-center justify-between">
         <view class="flex items-center">
           <view class="bg-#0074FF w8rpx h28rpx rounded-6rpx"></view>
@@ -83,7 +89,7 @@
             <view class="mt20rpx b-white rounded-16rpx overflow-hidden">
               <wd-datetime-picker
                 placeholder="请选择开始时间"
-                v-model="item.startTime"
+                v-model:model-value="item.startTime"
                 :minDate="dayjs().valueOf()"
               />
             </view>
@@ -95,7 +101,7 @@
             <view class="mt20rpx b-white rounded-16rpx overflow-hidden">
               <wd-datetime-picker
                 placeholder="请选择结束时间"
-                v-model="item.endTime"
+                v-model:model-value="item.endTime"
                 :minDate="dayjs().valueOf()"
               />
             </view>
@@ -116,6 +122,15 @@
             </view>
           </view>
         </view>
+        <view class="mt3" v-show="!isActiveItem.includes(idx)">
+          <wd-text
+            :lines="1"
+            size="28rpx"
+            color="#000000"
+            bold
+            :text="`${item.startTime} ${item.name}`"
+          ></wd-text>
+        </view>
       </view>
       <view class="h150rpx"></view>
     </view>
@@ -127,11 +142,54 @@
 import dayjs from "dayjs";
 import img1 from "@/subPack/static/del.png";
 import img2 from "@/subPack/static/success.png";
+import type { webMakeClass } from "@/api/globals";
+import { createGlobalLoadingMiddleware } from "@/api/core/middleware";
 const isAll = ref(true);
 const isActiveItem = ref([0]);
-const makeupClassList = ref([{ startTime: "", endTime: "", name: "" }]);
+const makeupClassList = ref<
+  {
+    startTime: string | number | null;
+    endTime: string | number | null;
+    name: string | null;
+  }[]
+>([{ startTime: null, endTime: null, name: null }]);
+const { courseItem } = storeToRefs(useCourseStore());
+
+const { data, send: getData } = useRequest(
+  (id: string, coursesType: number) =>
+    Apis.app.queryListByCoursesId({
+      params: { coursesType, id },
+    }),
+  {
+    immediate: false,
+  },
+);
+
+const { send: saveData } = useRequest(
+  (fromData: webMakeClass[]) => Apis.app.editPriceRules({ data: fromData }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware({ loadingText: "保存中..." }),
+  },
+);
+watch(
+  () => courseItem.value,
+  async () => {
+    await getData(String(courseItem.value.appCourseId), 1);
+    makeupClassList.value = data.value.map((it) => {
+      return {
+        ...it,
+        startTime: dayjs(it.startTime).valueOf(),
+        endTime: dayjs(it.endTime).valueOf(),
+      };
+    });
+  },
+  {
+    immediate: true,
+  },
+);
 function handleAddClass() {
-  makeupClassList.value.push({ startTime: "", endTime: "", name: "" });
+  makeupClassList.value.push({ startTime: null, endTime: null, name: null });
   isActiveItem.value.push(makeupClassList.value.length - 1);
 }
 function handleItemDown(idx: number) {
@@ -161,8 +219,28 @@ function handleAllUp() {
     }
   });
 }
-function save() {
-  console.log(makeupClassList.value, "asdsadsada");
+async function save() {
+  const form: webMakeClass[] = JSON.parse(
+    JSON.stringify(makeupClassList.value),
+  );
+  console.log(form);
+
+  if (!areAllItemsAllFieldsFilled(form))
+    return uni.showToast({
+      title: "请填写完整",
+      icon: "error",
+      duration: 2000,
+    });
+  const newObj = form.map((it) => {
+    return {
+      ...it,
+      startTime: dayjs(it.startTime).format("YYYY-MM-DD HH:mm:ss"),
+      endTime: dayjs(it.endTime).format("YYYY-MM-DD HH:mm:ss"),
+      coursesId: String(courseItem.value.appCourseId),
+    };
+  });
+  await saveData(newObj);
+  uni.navigateBack();
 }
 function handleDelete(idx: number) {
   console.log("点击");

+ 35 - 30
src/subPack/classInspection/index.vue

@@ -8,62 +8,66 @@
     leftArrow
     @click-left="handleClickLeft"
   ></wd-navbar>
-  <view class="px32rpx py-24rpx">
-    <view v-for="item in data" class="mb24rpx">
-      <course :type="type" :item="item"></course>
+  <scroll-view
+    scroll-y
+    @scrolltolower="handleBottom"
+    :style="{ height: `calc(100vh - ${statusBarHeight}px - ${height}px)` }"
+  >
+    <view class="px32rpx py-24rpx">
+      <view v-for="item in data" class="mb24rpx" :key="item.appCourseId">
+        <course :type="type" :item="item"></course>
+      </view>
     </view>
-  </view>
+    <view class="h80rpx"></view>
+  </scroll-view>
 </template>
 
 <script setup lang="ts">
 const type = ref(0);
 const titleArr = ["拍照验课", "选择课程", "选择课程延期", "选择课程"];
-onLoad((query: any) => {
+const { statusBarHeight } = uni.getSystemInfoSync();
+const { height } = uni.getMenuButtonBoundingClientRect();
+onLoad(async (query: any) => {
   type.value = query.type;
 });
-const {
-  loading,
 
+const {
   // 列表数据
   data,
-
-  // 是否为最后一页
   // 下拉加载时可通过此参数判断是否还需要加载
   isLastPage,
-
   // 当前页码,改变此页码将自动触发请求
   page,
-
-  // 每页数据条数
-  pageSize,
-
-  // 分页页数
-  pageCount,
-
-  // 总数据量
   total,
+  loading,
+  send: getData,
 } = usePagination(
-  (page, pageSize) =>
-    Apis.courses.list({
-      data: { page, pageSize },
+  (pageNo: number, pageSize: number) =>
+    Apis.app.getPageCourse({
+      data: {
+        pageNo,
+        pageSize,
+        orgCode: useUserStore().orgCode,
+      },
     }),
-
   {
-    data: (resp) => resp.result.records,
+    data: (res) => res.records,
     initialPage: 1, // 初始页码,默认为1
     initialPageSize: 10, // 初始每页数据条数,默认为10
   },
-).onError((error) => {});
-
+);
+onShow(async () => {
+  await getData();
+});
 function handleClickLeft() {
   uni.navigateBack();
 }
-onReachBottom(() => {
-  console.log(total.value, "页面触底", data.value.length);
-  if (total.value > data.value.length) {
+
+function handleBottom() {
+  if (isLastPage.value) {
     page.value++;
   }
-});
+}
 </script>
 
 <style scoped></style>
@@ -72,7 +76,8 @@ onReachBottom(() => {
   "name": "classInspection",
   "style": {
     "navigationBarTitleText": "拍照验课||选择课程",
-    "navigationStyle": "custom"
+    "navigationStyle": "custom",
+    "disableScroll": true
   }
 }
 </route>

+ 42 - 19
src/subPack/classInspectionDetaile/index.vue

@@ -8,35 +8,46 @@
     leftArrow
     @click-left="handleClickLeft"
   ></wd-navbar>
-  <view class="px32rpx py-24rpx">
-    <course disabled :item="courses"></course>
+  <view class="px32rpx py-24rpx" v-if="data">
+    <course disabled :item="courseItem"></course>
     <view class="mt24rpx flex items-center">
       <image src="@/subPack/static/nz.png" class="w-30rpx h30rpx"></image>
       <view class="text-32rpx ml-3 font-semibold">今日上课</view>
     </view>
     <view class="mt24rpx">
-      <ClassItem :type="type"></ClassItem>
+      <template v-for="item in todayClass" :key="item.id">
+        <view class="mb24rpx">
+          <ClassItem :type="type" :item="item" showBtn></ClassItem>
+        </view>
+      </template>
     </view>
     <view class="title">
-      <view class="mt24rpx mb24rpx flex text-32rpx items-center">
+      <view
+        class="mt24rpx mb24rpx flex text-32rpx items-center"
+        v-if="NormalClass.length"
+      >
         <view
           class="mr28rpx"
           :class="[tab == 0 ? 'text-#0074FF' : 'text-[rgb(0,0,0,0.3)]']"
           @click="tab = 0"
-          >正常课(6)</view
+          >正常课({{ NormalClass?.length }})</view
         >
         <view
           :class="[tab == 1 ? 'text-#0074FF' : 'text-[rgb(0,0,0,0.3)]']"
           @click="handleGoView"
-          >补课(5)</view
+          >补课({{ MakeUpCasses?.length }})</view
         >
       </view>
-      <view v-for="item in 6" class="mb24rpx">
-        <ClassItem :type="type"></ClassItem>
+      <view v-for="item in NormalClass" class="mb24rpx" :key="item.id">
+        <ClassItem :type="type" :item="item" :showBtn="false"></ClassItem>
       </view>
-      <view class="text-#0074FF mt24rpx mb24rpx view">补课(5)</view>
-      <view v-for="item in 5" class="mb24rpx">
-        <ClassItem :type="type"></ClassItem>
+      <view
+        v-if="MakeUpCasses?.length"
+        class="text-#0074FF mt24rpx mb24rpx view"
+        >补课({{ MakeUpCasses?.length }})</view
+      >
+      <view v-for="item in MakeUpCasses" class="mb24rpx" :key="item.id">
+        <ClassItem :type="type" :item="item" :showBtn="false"></ClassItem>
       </view>
     </view>
   </view>
@@ -48,26 +59,38 @@ import img1 from "@/subPack/static/yq.png";
 const tab = ref(0);
 const type = ref(0);
 const titleArr = ["拍照验课", "选择课程", "选择延期课时"];
-const courses = ref();
+const { courseItem } = storeToRefs(useCourseStore());
 onLoad((query: any) => {
   type.value = query.type;
   getDataDetaile(query.id);
 });
-const { send: getData } = useRequest(
-  (id: string) =>
-    Apis.courses.getCourseDetail({
-      data: {
-        id,
+const NormalClass = computed(() => {
+  return data.value.filter((it) => it.coursesType == 0);
+});
+const MakeUpCasses = computed(() => {
+  return data.value.filter((it) => it.coursesType == 1);
+});
+const todayClass = computed(() => {
+  return data.value.filter((it) => it.orToday);
+});
+const { send: getData, data } = useRequest(
+  (courseId: string) =>
+    Apis.app.getCourseInfo({
+      pathParams: {
+        courseId,
       },
     }),
 
   {
     immediate: false,
   },
-).onError((error) => {});
+);
 async function getDataDetaile(id: string) {
   const res = await getData(id);
-  courses.value = res.result.courses;
+  // console.log(res, "asdsad");
+  console.log(todayClass.value);
+  console.log(NormalClass.value);
+  console.log(MakeUpCasses.value);
 }
 function handleGoView() {
   tab.value = 1;

+ 12 - 9
src/subPack/notification/index.vue

@@ -2,22 +2,23 @@
   <view class="px32rpx py20rpx">
     <view
       class="bg-white rounded-32rpx px24rpx py28rpx box-border flex items-center justify-between mb24rpx"
-      v-for="item in 5"
-      @click="handleDetailes"
+      v-for="item in sysMsg"
+      @click="handleDetailes(item.id)"
     >
       <view>
         <wd-text
           color="rgb(0,0,0,0.9)"
-          text="爱护公共场所,请勿吸烟乱扔垃圾爱护公共场所,请312321312ewerwrwe勿吸..."
+          :text="item.titile"
           :lines="2"
           size="32"
         ></wd-text>
         <view class="text-24rpx text-[rgb(0,0,0,0.3)] mt24rpx"
-          >全龄运动平台 03-14 10:23</view
+          >{{ item.sender }}
+          {{ dayjs(item.sendTime).format("MM-DD ss:mm") }}</view
         >
       </view>
       <image
-        src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
+        :src="item.imgUrl"
         class="w-160rpx h-160rpx rounded-32rpx min-w-160rpx"
       />
     </view>
@@ -25,10 +26,12 @@
 </template>
 
 <script setup lang="ts">
-function handleDetailes() {
-  uni.navigateTo({
-    url: "/subPack/notificationDetailes/index",
-  });
+import router from "@/router";
+import dayjs from "dayjs";
+
+const { data: sysMsg } = useRequest(() => Apis.app.getMsg({}));
+function handleDetailes(id: string) {
+  router.push({ path: "/subPack/notificationDetailes/index", query: { id } });
 }
 </script>
 

+ 25 - 13
src/subPack/notificationDetailes/index.vue

@@ -1,25 +1,37 @@
 <template>
-  <view class="px32rpx py20rpx bg-white h-screen overflow-y-scroll">
-    <view class="text-32rpx"
-      >爱护公共场所,请勿吸烟乱扔垃圾爱护公共场所, 请勿吸烟乱扔</view
-    >
+  <view class="px32rpx py20rpx bg-white h-screen overflow-y-scroll" v-if="data">
+    <view class="text-32rpx">{{ data.titile }}</view>
     <view class="text-[rgb(0,0,0,0.3)] text-24rpx mt24rpx mb24rpx">
-      全龄运动平台 03-14 10:23</view
-    >
-    <view class="text-28rpx"
-      >爱护公共场所,请勿吸烟乱扔垃圾爱护公共场所,请勿
-      吸烟乱扔爱护公共场所,请勿吸烟乱扔垃圾爱护公共场
-      所,请勿吸烟乱扔爱护公共场所,请勿吸烟乱扔垃圾爱
-      护公共场所,请勿吸烟乱扔。</view
+      {{ data.sender }} {{ dayjs(data.sendTime).format("MM-DD ss:mm") }}</view
     >
+    <view class="text-28rpx">
+      <rich-text :nodes="text"></rich-text>
+    </view>
+    <view class="h112rpx"></view>
   </view>
 </template>
 
 <script setup lang="ts">
-function handleDetailes() {}
+import dayjs from "dayjs";
+
+const { data, send: getData } = useRequest(
+  (id) => Apis.app.getMsgInfo({ params: { id } }),
+  { immediate: false },
+);
+const text = computed(() => {
+  if (data.value) {
+    return data.value.msgContent.replace(
+      /\<img/gi,
+      '<img style="max-width:100%;height:auto" ',
+    );
+  }
+});
+onLoad(async (query: any) => {
+  await getData(query.id);
+});
 </script>
 
-<style scoped></style>
+<style scoped lang="scss"></style>
 <route lang="json">
 {
   "name": "notificationDetailes",

BIN
src/subPack/static/err.png


+ 43 - 0
src/subPack/writeOff/error/index.vue

@@ -0,0 +1,43 @@
+<template>
+  <view class="header h-screen px32rpx">
+    <wd-navbar
+      fixed
+      placeholder
+      title=""
+      left-arrow
+      safe-area-inset-top
+      :bordered="false"
+      custom-style="background: transparent !important"
+    ></wd-navbar>
+    <view class="flex items-center justify-center mt96rpx">
+      <view class="flex items-center justify-center flex-col">
+        <image src="@/subPack/static/err.png" class="w148rpx h148rpx" />
+        <view class="font-semibold text-32rpx mt32rpx">核销失败</view>
+        <view class="text-24rpx mt20rpx mb60rpx text-[rgba(0,0,0,0.30)]"
+          >失败原因:校验失败</view
+        >
+      </view>
+    </view>
+    <wd-button block size="large" @click="router.back()">关闭页面</wd-button>
+  </view>
+</template>
+
+<script setup lang="ts">
+import router from "@/router";
+</script>
+
+<style scoped>
+.header {
+  background: linear-gradient(180deg, #e4efff 0%, #f9fcff 45%, #f6f6f6 100%);
+}
+</style>
+<route lang="json">
+{
+  "name": "error",
+  "style": {
+    "navigationBarTitleText": "",
+    "navigationStyle": "custom",
+    "disableScroll": true
+  }
+}
+</route>

+ 94 - 32
src/subPack/writeOff/index.vue

@@ -1,45 +1,50 @@
 <template>
-  <view class="px32rpx py20rpx">
+  <view class="px32rpx py20rpx" v-if="data">
     <view class="flex items-center">
       <image src="@/subPack/static/map.png" class="w30rpx h30rpx mr20rpx">
       </image>
-      <view class="font-semibold text-32rpx">体育馆综合训练馆(观山湖店)</view>
+      <view class="font-semibold text-32rpx">{{ data.siteName }}</view>
     </view>
-    <view class="mt20rpx bg-white px-24rpx py-28rpx rounded-32rpx">
+    {{ type }}
+    <view
+      class="mt20rpx bg-white px-24rpx py-28rpx rounded-32rpx"
+      v-if="data.appOrderProInfoVerifyVOS"
+    >
       <wd-checkbox-group v-model="checkedAll">
         <!-- 无固定场 -->
-        <view class="flex items-center">
-          <image
-            src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
-            class="w200rpx h-200rpx rounded-32rpx min-w-200rpx"
-          />
-          <view class="ml20rpx">
-            <view class="text-32rpx"
-              >一对一篮球30分钟室内精品 课程,一对一篮球30分</view
-            >
+        <template v-if="type > GoodsType.noFixed">
+          <view class="flex items-center">
+            <image
+              src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg"
+              class="w200rpx h-200rpx rounded-32rpx min-w-200rpx"
+            />
+            <view class="ml20rpx flex-1">
+              <view class="text-32rpx">{{ data.productName }}</view>
 
-            <view class="mt26rpx flex items-center justify-between">
-              <view class="text-#FB5B5B">
-                ¥<text class="text-48rpx">25.9</text>
+              <view class="mt26rpx flex items-center justify-between">
+                <view class="text-#FB5B5B">
+                  ¥<text class="text-48rpx">{{ data.price }}</text>
+                </view>
+                <view class="text-[rgb(0,0,0,0.3)]">×{{ data.amount }}</view>
               </view>
-              <view class="text-[rgb(0,0,0,0.3)]">×2</view>
             </view>
           </view>
-        </view>
-        <view
-          class="flex items-center justify-between mb20rpx mt24rpx"
-          v-for="item in 5"
-        >
-          <view>券号:0017 1712 5994</view>
-          <wd-checkbox
-            :model-value="item"
-            checked-color="#fdd143"
-          ></wd-checkbox>
-        </view>
-
+          <view
+            class="flex items-center justify-between mb20rpx mt24rpx"
+            v-for="item in data.appOrderProInfoVerifyVOS"
+            :key="item.appOrderProInfo.id"
+          >
+            <view>券号:{{ item.appOrderProInfo.ticketNo }}</view>
+            <wd-checkbox
+              :model-value="item.isinId"
+              checked-color="#fdd143"
+              v-if="item.isinStatus == 1"
+            >
+            </wd-checkbox>
+          </view>
+        </template>
         <!-- 包场 -->
-
-        <view class="flex justify-between w-full">
+        <view class="flex justify-between w-full" v-else>
           <view>场次</view>
           <view class="flex-1">
             <view
@@ -63,7 +68,7 @@
           >本次核销{{ checkedAll.length }}张</view
         >
       </view>
-      <view class="mt12rpx text-#FB5B5B"> 共4张可用</view>
+      <view class="mt12rpx text-#FB5B5B"> 共{{ data.amount }}张可用</view>
     </view>
     <view class="mt20rpx flex items-center">
       <image src="@/subPack/static/i.png" class="w30rpx h30rpx mr6rpx" />
@@ -71,11 +76,68 @@
     </view>
   </view>
 
-  <fixdbtn block size="large">确认核销(0)</fixdbtn>
+  <fixdbtn
+    block
+    size="large"
+    :disabled="!checkedAll.length"
+    @click="handleSubmit"
+    >确认核销({{ checkedAll.length }})</fixdbtn
+  >
 </template>
 
 <script setup lang="ts">
+import { GoodsType } from "@/config";
+import { createGlobalLoadingMiddleware } from "@/api/core/middleware";
+import router from "@/router";
+const { isShowLoging } = storeToRefs(useUserStore());
 const checkedAll = ref([]);
+const { data, send: getOrder } = useRequest(
+  (id: string) =>
+    Apis.app.scanCodeQueryOrder({
+      params: {
+        orderId: id,
+      },
+    }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware({ loadingText: "加载中..." }),
+  },
+);
+const { send: submit } = useRequest(
+  (orderProInfoIds: string[]) =>
+    Apis.app.scanCodeVerification({
+      data: orderProInfoIds,
+    }),
+  {
+    immediate: false,
+    middleware: createGlobalLoadingMiddleware({ loadingText: "核销中..." }),
+  },
+);
+onLoad(async (query: any) => {
+  getOrder(query.id);
+});
+const type = computed(() => {
+  //如果是-1则找不到
+  // 商品类型(1-学校 2-包场 3-无固定场 4-个人赛 5-团队赛 6-课程 7-保险)
+  if (data.value.appOrderProInfoVerifyVOS) {
+    return data.value.appOrderProInfoVerifyVOS[0].appOrderProInfo?.type || -1;
+  }
+  return -1;
+});
+async function handleSubmit() {
+  console.log(checkedAll.value, "核销");
+  try {
+    await submit(checkedAll.value);
+    uni.navigateBack({
+      success: () => {
+        isShowLoging.value = true;
+      },
+    });
+  } catch (error) {
+    console.log(error);
+    router.push({ name: "error" });
+  }
+}
 </script>
 
 <style scoped></style>

+ 2 - 1
src/uni-pages.d.ts

@@ -21,7 +21,8 @@ interface NavigateToOptions {
        "/subPack/selectClass/index" |
        "/subPack/Storebalance/index" |
        "/subPack/writeOff/index" |
-       "/subPack/writeOffDetaile/index";
+       "/subPack/writeOffDetaile/index" |
+       "/subPack/writeOff/error/index";
 }
 interface RedirectToOptions extends NavigateToOptions {}
 

+ 125 - 0
src/utils/index.ts

@@ -1,3 +1,5 @@
+import { BASE_URL } from "@/config";
+
 /**
  * 获取当前页面路径
  * @returns 当前页面路径
@@ -7,3 +9,126 @@ export function getCurrentPath() {
   const currentPage = pages[pages.length - 1];
   return currentPage.route || "";
 }
+/**
+ * 通用表单赋值方法
+ * @param form 表单数据对象
+ * @param data 需要赋值的数据
+ * @param options 配置选项
+ */
+function assignFormValues<T extends Record<string, any>>(
+  form: T,
+  data: Partial<T>,
+  options?: {
+    /**
+     * 是否忽略空值(null, undefined, '')
+     * @default false
+     */
+    ignoreEmpty?: boolean;
+    /**
+     * 自定义字段映射
+     * @example { 'oldKey': 'newKey' }
+     */
+    fieldMap?: Record<string, string>;
+    /**
+     * 需要特殊处理的字段
+     */
+    transform?: Partial<Record<string, (value: any) => any>>;
+  },
+): void {
+  const { ignoreEmpty = false, fieldMap = {}, transform = {} } = options || {};
+
+  for (const key in data) {
+    if (Object.prototype.hasOwnProperty.call(data, key)) {
+      const targetKey = fieldMap[key] || key;
+
+      // 检查目标表单是否有这个字段
+      if (!(targetKey in form)) {
+        continue;
+      }
+
+      let value = data[key];
+
+      // 处理空值
+      if (
+        ignoreEmpty &&
+        (value === null || value === undefined || value === "")
+      ) {
+        continue;
+      }
+
+      // 处理特殊转换
+      if (targetKey in transform) {
+        value = transform[targetKey]!(value);
+      } else if (typeof value === "string") {
+        // 字符串特殊处理
+        if (
+          key.includes("Img") ||
+          key.includes("image") ||
+          key.includes("photo") ||
+          key.includes("certificate")
+        ) {
+          // 图片字段处理
+          if (value) {
+            value = value.split(",").map((url: string) => ({ url }));
+          } else {
+            value = [] as unknown as T[keyof T];
+          }
+        } else if (key === "selecteddeparts" || key.includes("selected")) {
+          // 选择字段处理
+          value = value ? value.split(",") : [];
+        }
+      }
+
+      // 类数组对象特殊处理
+      if (
+        Array.isArray(form[targetKey]) &&
+        !Array.isArray(value) &&
+        typeof value === "string"
+      ) {
+        try {
+          const parsed = JSON.parse(value);
+          if (Array.isArray(parsed)) {
+            form[targetKey as keyof T] = parsed as T[keyof T];
+            continue;
+          }
+        } catch (e) {
+          // 解析失败,继续使用原值
+        }
+      }
+
+      form[targetKey as keyof T] = value as T[keyof T];
+    }
+  }
+}
+
+export default assignFormValues;
+
+export function getImageURL(url?: string) {
+  return BASE_URL + "/sys/common/static/" + url;
+}
+/**
+ * 判断一个对象的所有字段是否有值(非 null 和 undefined)
+ * @param obj 要检查的对象
+ * @returns 所有字段有值返回 true,否则 false
+ */
+function areAllFieldsFilled(obj: Record<string, any>): boolean {
+  return Object.values(obj).every(
+    (value) => unref(value) !== null && unref(value) !== undefined,
+  );
+}
+
+/**
+ * 判断数组中每个对象是否所有字段都有值
+ * @param arr 要检查的对象数组
+ * @returns 所有对象字段都有值返回 true,否则 false
+ */
+export function areAllItemsAllFieldsFilled(
+  arr: Array<Record<string, any>>,
+): boolean {
+  // return arr.every((item) => areAllFieldsFilled(item));
+  //修复新增的时候id校验
+  return arr.every((item) => {
+    const { coursesId, id, ...rest } = item;
+    return areAllFieldsFilled(rest);
+  });
+}