From ac6c50ff2847b52f0789ebdefe03787c7a46cde6 Mon Sep 17 00:00:00 2001 From: Chuck1sn Date: Fri, 13 Jun 2025 14:36:47 +0800 Subject: [PATCH] add date picker --- .../com/zl/mjga/dto/urp/UserQueryDto.java | 6 +-- .../zl/mjga/repository/UserRepository.java | 13 ++--- .../db/migration/V1_0_0__init_table.sql | 2 +- frontend/.env | 8 +-- frontend/package-lock.json | 26 ++++++++++ frontend/package.json | 1 + frontend/src/App.vue | 4 +- frontend/src/assets/datepicker.css | 51 +++++++++++++++++++ frontend/src/composables/user/useUserQuery.ts | 2 + frontend/src/main.ts | 4 ++ frontend/src/utils/dateUtil.ts | 7 ++- frontend/src/views/BindRoleView.vue | 2 + frontend/src/views/SchedulerView.vue | 3 +- frontend/src/views/UserView.vue | 47 +++++++++++------ 14 files changed, 138 insertions(+), 38 deletions(-) create mode 100644 frontend/src/assets/datepicker.css diff --git a/backend/src/main/java/com/zl/mjga/dto/urp/UserQueryDto.java b/backend/src/main/java/com/zl/mjga/dto/urp/UserQueryDto.java index f3c9080..130cf50 100644 --- a/backend/src/main/java/com/zl/mjga/dto/urp/UserQueryDto.java +++ b/backend/src/main/java/com/zl/mjga/dto/urp/UserQueryDto.java @@ -1,6 +1,6 @@ package com.zl.mjga.dto.urp; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import lombok.*; @AllArgsConstructor @@ -8,6 +8,6 @@ import lombok.*; @Data public class UserQueryDto { private String username; - private LocalDateTime starDate; - private LocalDateTime endDate; + private OffsetDateTime startDate; + private OffsetDateTime endDate; } diff --git a/backend/src/main/java/com/zl/mjga/repository/UserRepository.java b/backend/src/main/java/com/zl/mjga/repository/UserRepository.java index 2e58159..8769595 100644 --- a/backend/src/main/java/com/zl/mjga/repository/UserRepository.java +++ b/backend/src/main/java/com/zl/mjga/repository/UserRepository.java @@ -1,6 +1,5 @@ package com.zl.mjga.repository; -import static org.jooq.generated.mjga.Tables.*; import static org.jooq.generated.mjga.tables.User.USER; import static org.jooq.impl.DSL.*; @@ -65,8 +64,8 @@ public class UserRepository extends UserDao { ? USER.USERNAME.like("%" + userQueryDto.getUsername() + "%") : noCondition()) .and( - userQueryDto.getStarDate() != null - ? USER.CREATE_TIME.ge(userQueryDto.getStarDate()) + userQueryDto.getStartDate() != null + ? USER.CREATE_TIME.ge(userQueryDto.getStartDate()) : noCondition()) .and( userQueryDto.getEndDate() != null @@ -79,13 +78,7 @@ public class UserRepository extends UserDao { } public Result pageFetchBy(PageRequestDto pageRequestDto, UserQueryDto userQueryDto) { - return ctx() - .select(asterisk(), DSL.count().over().as("total_user")) - .from(USER) - .where( - userQueryDto.getUsername() != null - ? USER.USERNAME.like("%" + userQueryDto.getUsername() + "%") - : noCondition()) + return selectBy(userQueryDto) .orderBy(pageRequestDto.getSortFields()) .limit(pageRequestDto.getSize()) .offset(pageRequestDto.getOffset()) diff --git a/backend/src/main/resources/db/migration/V1_0_0__init_table.sql b/backend/src/main/resources/db/migration/V1_0_0__init_table.sql index f214ef9..da173d8 100644 --- a/backend/src/main/resources/db/migration/V1_0_0__init_table.sql +++ b/backend/src/main/resources/db/migration/V1_0_0__init_table.sql @@ -3,7 +3,7 @@ CREATE SCHEMA IF NOT EXISTS mjga; CREATE TABLE mjga.user ( id BIGSERIAL PRIMARY KEY, username VARCHAR NOT NULL UNIQUE, - create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, password VARCHAR NOT NULL, enable BOOLEAN NOT NULL DEFAULT TRUE ); diff --git a/frontend/.env b/frontend/.env index cbc4b2d..bd687de 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1,11 +1,11 @@ VITE_APP_PORT=5173 VITE_SOURCE_MAP=true # mock -VITE_ENABLE_MOCK=true -VITE_BASE_URL=http://localhost:5173 +#VITE_ENABLE_MOCK=true +#VITE_BASE_URL=http://localhost:5173 # local -#VITE_ENABLE_MOCK=false -#VITE_BASE_URL=http://localhost:8080 +VITE_ENABLE_MOCK=false +VITE_BASE_URL=http://localhost:8080 # dev #VITE_ENABLE_MOCK=false #VITE_BASE_URL=https://localhost/api diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d0b4b2c..2461849 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@microsoft/fetch-event-source": "^2.0.1", "@tailwindcss/vite": "^4.0.14", + "@vuepic/vue-datepicker": "^11.0.2", "@vueuse/core": "^13.0.0", "apexcharts": "^3.46.0", "dayjs": "^1.11.13", @@ -2691,6 +2692,21 @@ } } }, + "node_modules/@vuepic/vue-datepicker": { + "version": "11.0.2", + "resolved": "http://mirrors.tencent.com/npm/@vuepic/vue-datepicker/-/vue-datepicker-11.0.2.tgz", + "integrity": "sha512-uHh78mVBXCEjam1uVfTzZ/HkyDwut/H6b2djSN9YTF+l/EA+XONfdCnOVSi1g+qVGSy65DcQAwyBNidAssnudQ==", + "license": "MIT", + "dependencies": { + "date-fns": "^4.1.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "vue": ">=3.3.0" + } + }, "node_modules/@vueuse/core": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.1.0.tgz", @@ -3237,6 +3253,16 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "http://mirrors.tencent.com/npm/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "http://mirrors.tencent.com/npm/dayjs/-/dayjs-1.11.13.tgz", diff --git a/frontend/package.json b/frontend/package.json index c9fe9a4..aa55f31 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "dependencies": { "@microsoft/fetch-event-source": "^2.0.1", "@tailwindcss/vite": "^4.0.14", + "@vuepic/vue-datepicker": "^11.0.2", "@vueuse/core": "^13.0.0", "apexcharts": "^3.46.0", "dayjs": "^1.11.13", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 58745fb..91e4dd6 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -8,4 +8,6 @@ import Alert from "./components/Alert.vue"; - + diff --git a/frontend/src/assets/datepicker.css b/frontend/src/assets/datepicker.css new file mode 100644 index 0000000..8825029 --- /dev/null +++ b/frontend/src/assets/datepicker.css @@ -0,0 +1,51 @@ +/* 日期选择器亮色主题 - 与 Flowbite 蓝色主题匹配 */ .dp__theme_light { + /* 基础颜色 */ + --dp-background-color: #fff; + --dp-text-color: #1f2937; /* 对应 Flowbite 的 gray-800 */ + + /* 主色调 */ + --dp-primary-color: #2563eb; /* 对应 Flowbite 的 primary-600 */ + --dp-primary-disabled-color: #93c5fd; /* 对应 Flowbite 的 primary-300 */ + --dp-primary-text-color: #fff; + + /* 次要颜色 */ + --dp-secondary-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */ + + /* 边框颜色 */ + --dp-border-color: var(--color-gray-300); /* 对应 Flowbite 的 gray-200 */ + --dp-menu-border-color: #e5e7eb; + + /* 禁用状态 */ + --dp-disabled-color: #f3f4f6; /* 对应 Flowbite 的 gray-100 */ + --dp-disabled-color-text: #9ca3af; /* 对应 Flowbite 的 gray-400 */ + + /* 滚动条 */ + --dp-scroll-bar-background: #f3f4f6; /* 对应 Flowbite 的 gray-100 */ + --dp-scroll-bar-color: #9ca3af; /* 对应 Flowbite 的 gray-400 */ + + /* 成功状态 */ + --dp-success-color: #10b981; /* 对应 Tailwind 的 emerald-500 */ + --dp-success-color-disabled: #6ee7b7; /* 对应 Tailwind 的 emerald-300 */ + + /* 图标颜色 */ + --dp-icon-color: #6b7280; /* 对应 Flowbite 的 gray-500 */ + + /* 危险/错误状态 */ + --dp-danger-color: #ef4444; /* 对应 Tailwind 的 red-500 */ + --dp-marker-color: #ef4444; + + /* 提示颜色 */ + --dp-tooltip-color: #f9fafb; /* 对应 Flowbite 的 gray-50 */ + + /* 高亮颜色 */ + --dp-highlight-color: rgb(37 99 235 / 10%); /* 对应 Flowbite 的 primary-600 透明度 */ + + /* 日期范围相关 */ + --dp-range-between-dates-background-color: var(--dp-hover-color, #eff6ff); + --dp-range-between-dates-text-color: var(--dp-hover-text-color, #1f2937); + --dp-range-between-border-color: var(--dp-hover-color, #eff6ff); + + /* 圆角设置 - 匹配项目中的 rounded-lg */ + --dp-border-radius: 0.5rem; /* 8px,匹配 Tailwind 的 rounded-lg */ + --dp-cell-border-radius: 0.375rem; /* 6px,稍微小一点,更美观 */ +} diff --git a/frontend/src/composables/user/useUserQuery.ts b/frontend/src/composables/user/useUserQuery.ts index edf7d4b..efd84fc 100644 --- a/frontend/src/composables/user/useUserQuery.ts +++ b/frontend/src/composables/user/useUserQuery.ts @@ -21,6 +21,8 @@ export const useUserQuery = () => { const fetchUsersWith = async ( param: { username?: string; + startDate?: string; + endDate?: string; }, page = 1, size = 10, diff --git a/frontend/src/main.ts b/frontend/src/main.ts index cdd9efe..13e78c0 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -8,6 +8,9 @@ import useUserAuth from "./composables/auth/useUserAuth"; import useAlertStore from "./composables/store/useAlertStore"; import router from "./router"; import makeErrorHandler from "./utils/errorHandler"; +import VueDatePicker from "@vuepic/vue-datepicker"; +import "@vuepic/vue-datepicker/dist/main.css"; +import "./assets/datepicker.css"; async function enableMocking() { if (import.meta.env.VITE_ENABLE_MOCK === "false") { @@ -29,5 +32,6 @@ enableMocking().then(() => { app.use(router); const errorHandler = makeErrorHandler(router, signOut, showAlert); app.config.errorHandler = errorHandler; + app.component("VueDatePicker", VueDatePicker); app.mount("#app"); }); diff --git a/frontend/src/utils/dateUtil.ts b/frontend/src/utils/dateUtil.ts index 7e93251..1fc88cf 100644 --- a/frontend/src/utils/dateUtil.ts +++ b/frontend/src/utils/dateUtil.ts @@ -8,4 +8,9 @@ dayjs.locale("zh-cn"); dayjs.extend(timezone); dayjs.tz.setDefault("Asia/Shanghai"); -export default dayjs; +const formatDate = (date?: Date) => { + if (!date) return undefined; + return dayjs(date).format("YYYY-MM-DDTHH:mm:ss.SSSZ"); +}; + +export { dayjs, formatDate }; diff --git a/frontend/src/views/BindRoleView.vue b/frontend/src/views/BindRoleView.vue index c4d0492..8dd8ecb 100644 --- a/frontend/src/views/BindRoleView.vue +++ b/frontend/src/views/BindRoleView.vue @@ -127,6 +127,8 @@ import { useRoute } from "vue-router"; import { useRoleBind } from "../composables/role/useRoleBind"; import useAlertStore from "../composables/store/useAlertStore"; import { useActionExcStore } from "@/composables/store/useActionExcStore"; +import VueDatePicker from "@vuepic/vue-datepicker"; +import "@vuepic/vue-datepicker/dist/main.css"; const roleName = ref(""); const checkedRoleIds = ref([]); diff --git a/frontend/src/views/SchedulerView.vue b/frontend/src/views/SchedulerView.vue index 9713de2..fd6591d 100644 --- a/frontend/src/views/SchedulerView.vue +++ b/frontend/src/views/SchedulerView.vue @@ -173,8 +173,7 @@ import { useJobControl } from "@/composables/job/useJobControl"; import { useJobsPaginationQuery } from "@/composables/job/useJobQuery"; import { useJobUpdate } from "@/composables/job/useJobUpdate"; import useAlertStore from "@/composables/store/useAlertStore"; -import { useMobileStyles } from "@/composables/useMobileStyles"; -import dayjs from "@/utils/dateUtil"; +import { dayjs } from "@/utils/dateUtil"; import { Modal, type ModalInterface, initFlowbite } from "flowbite"; import { nextTick, onMounted, ref } from "vue"; import type { components } from "../api/types/schema"; diff --git a/frontend/src/views/UserView.vue b/frontend/src/views/UserView.vue index 85c9910..0723389 100644 --- a/frontend/src/views/UserView.vue +++ b/frontend/src/views/UserView.vue @@ -5,23 +5,27 @@

用户管理

-
- -
-
- + +
+ +
+
+ +
+
- -
+ + +