fix modal dup id

This commit is contained in:
Chuck1sn
2025-06-04 10:53:33 +08:00
parent 34e0d3d8e7
commit 07e590dc2d
21 changed files with 1881 additions and 1927 deletions

View File

@@ -1,11 +1,11 @@
VITE_APP_PORT=5173 VITE_APP_PORT=5173
VITE_SOURCE_MAP=true VITE_SOURCE_MAP=true
# mock # mock
#VITE_ENABLE_MOCK=true VITE_ENABLE_MOCK=true
#VITE_BASE_URL=http://localhost:5173 VITE_BASE_URL=http://localhost:5173
# local # local
VITE_ENABLE_MOCK=false #VITE_ENABLE_MOCK=false
VITE_BASE_URL=http://localhost:8080 #VITE_BASE_URL=http://localhost:8080
# dev # dev
#VITE_ENABLE_MOCK=false #VITE_ENABLE_MOCK=false
#VITE_BASE_URL=https://localhost/api #VITE_BASE_URL=https://localhost/api

File diff suppressed because it is too large Load Diff

View File

@@ -104,7 +104,8 @@ import useUserStore from "../composables/store/useUserStore";
import { useUserUpsert } from "../composables/user/useUserUpsert"; import { useUserUpsert } from "../composables/user/useUserUpsert";
import type { UserUpsertSubmitModel } from "../types/user"; import type { UserUpsertSubmitModel } from "../types/user";
const { messages, chat, isLoading, cancel, searchAction, executeAction } = useAiChat(); const { messages, chat, isLoading, cancel, searchAction, executeAction } =
useAiChat();
const { user } = useUserStore(); const { user } = useUserStore();
const userUpsertModal = ref<ModalInterface>(); const userUpsertModal = ref<ModalInterface>();
const departmentUpsertModal = ref<ModalInterface>(); const departmentUpsertModal = ref<ModalInterface>();
@@ -249,7 +250,10 @@ const abortChat = () => {
cancel(); cancel();
}; };
const chatByMode = async (message: string, mode: "chat" | "search" | "execute") => { const chatByMode = async (
message: string,
mode: "chat" | "search" | "execute",
) => {
inputMessage.value = ""; inputMessage.value = "";
messages.value.push({ messages.value.push({
content: message, content: message,
@@ -266,7 +270,10 @@ const chatByMode = async (message: string, mode: "chat" | "search" | "execute")
} }
}; };
const handleSendClick = async (message: string, mode: "chat" | "search" | "execute") => { const handleSendClick = async (
message: string,
mode: "chat" | "search" | "execute",
) => {
scrollToBottom(); scrollToBottom();
if (isLoading.value) { if (isLoading.value) {
abortChat(); abortChat();

View File

@@ -36,7 +36,7 @@ const props = defineProps<{
isLoading: boolean; isLoading: boolean;
abortable: boolean; abortable: boolean;
handleClick: (event: Event) => void; handleClick: (event: Event) => void;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; size?: "xs" | "sm" | "md" | "lg" | "xl";
iconOnly?: boolean; iconOnly?: boolean;
}>(); }>();
@@ -45,36 +45,49 @@ const slots = useSlots();
const sizeClasses = computed(() => { const sizeClasses = computed(() => {
if (props.iconOnly && slots.icon) { if (props.iconOnly && slots.icon) {
switch (props.size) { switch (props.size) {
case 'xs': return 'p-1.5'; case "xs":
case 'sm': return 'p-2'; return "p-1.5";
case 'lg': return 'p-3'; case "sm":
case 'xl': return 'p-3.5'; return "p-2";
default: return 'p-2.5'; case "lg":
return "p-3";
case "xl":
return "p-3.5";
default:
return "p-2.5";
} }
} }
switch (props.size) { switch (props.size) {
case 'xs': return 'text-xs px-2.5 py-1.5'; case "xs":
case 'sm': return 'text-xs px-3 py-2'; return "text-xs px-2.5 py-1.5";
case 'lg': return 'text-base px-5 py-3'; case "sm":
case 'xl': return 'text-base px-6 py-3.5'; return "text-xs px-3 py-2";
case "lg":
return "text-base px-5 py-3";
case "xl":
return "text-base px-6 py-3.5";
default: default:
return 'text-sm px-4 py-2.5'; return "text-sm px-4 py-2.5";
} }
}); });
const iconSizeClasses = computed(() => { const iconSizeClasses = computed(() => {
switch (props.size) { switch (props.size) {
case 'xs': return 'w-3 h-3'; case "xs":
case 'sm': return 'w-4 h-4'; return "w-3 h-3";
case 'lg': return 'w-5 h-5'; case "sm":
case 'xl': return 'w-6 h-6'; return "w-4 h-4";
case "lg":
return "w-5 h-5";
case "xl":
return "w-6 h-6";
default: default:
return 'w-5 h-5'; return "w-5 h-5";
} }
}); });
const loadingStyle = computed<string>(() => { const loadingStyle = computed<string>(() => {
return ''; return "";
}); });
const disabled = computed(() => { const disabled = computed(() => {

View File

@@ -42,7 +42,7 @@
</div> </div>
</div> </div>
<button type="submit" @click="handleSubmit" <button type="submit" @click="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</div> </div>

View File

@@ -1,10 +1,10 @@
<template> <template>
<nav class="fixed top-0 z-40 w-full bg-white border-b border-gray-200"> <nav class="fixed top-0 z-1 w-full bg-white border-b border-gray-200">
<div class="px-3 py-3 lg:px-5 lg:pl-3"> <div class="px-3 py-3 lg:px-5 lg:pl-3">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center justify-start rtl:justify-end"> <div class="flex items-center justify-start rtl:justify-end">
<button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar" <button id="sidebar-toggle-btn" data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar"
type="button" aria-controls="logo-sidebar" type="button"
class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200"> class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200">
<span class="sr-only">Open sidebar</span> <span class="sr-only">Open sidebar</span>
<svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" <svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20"
@@ -94,7 +94,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import useUserStore from "@/composables/store/useUserStore"; import useUserStore from "@/composables/store/useUserStore";
import { Dropdown, initFlowbite, type DropdownInterface } from "flowbite"; import { Dropdown, type DropdownInterface, initFlowbite } from "flowbite";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import useUserAuth from "../composables/auth/useUserAuth"; import useUserAuth from "../composables/auth/useUserAuth";

View File

@@ -70,7 +70,7 @@
</div> </div>
</div> </div>
<button type="submit" @click.prevent="handleSubmit" <button type="submit" @click.prevent="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</form> </form>

View File

@@ -32,7 +32,7 @@
</div> </div>
</div> </div>
<button type="submit" @click.prevent="handleSubmit" <button type="submit" @click.prevent="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</div> </div>

View File

@@ -31,7 +31,7 @@
</div> </div>
<button type="submit" @click="handleSubmit" <button type="submit" @click="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</div> </div>

View File

@@ -32,7 +32,7 @@
</div> </div>
</div> </div>
<button type="submit" @click.prevent="handleSubmit" <button type="submit" @click.prevent="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</div> </div>

View File

@@ -1,7 +1,7 @@
<template> <template>
<aside id="logo-sidebar" <aside id="logo-sidebar"
class="fixed top-0 left-0 z-30 px-1 w-44 min-h-screen overflow-y-auto pt-20 transition-transform -translate-x-full bg-white border-r border-gray-200 sm:translate-x-0" class="fixed top-0 left-0 px-1 w-44 min-h-screen overflow-y-auto pt-20 transition-transform -translate-x-full bg-white border-r border-gray-200 sm:translate-x-0"
aria-label="Sidebar" tabindex="-1" data-drawer-backdrop="true"> aria-label="Sidebar" tabindex="-1">
<div class="h-full px-3 pb-4 overflow-y-auto bg-white "> <div class="h-full px-3 pb-4 overflow-y-auto bg-white ">
<ul class="space-y-2 font-medium"> <ul class="space-y-2 font-medium">
<li v-for="item in menuItems" :key="item.path"> <li v-for="item in menuItems" :key="item.path">
@@ -16,22 +16,28 @@
</ul> </ul>
</div> </div>
</aside> </aside>
<!-- 添加遮罩层 -->
<div id="drawer-backdrop" :class="isDrawerVisible ? 'block' : 'hidden'"
class="bg-gray-900 bg-opacity-50 fixed inset-0 z-50 sm:hidden" @click="closeSidebar">
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { RoutePath } from "@/router/constants"; import { RoutePath } from "@/router/constants";
import { initFlowbite } from "flowbite"; import { initFlowbite } from "flowbite";
import { onMounted } from "vue"; import { onMounted, ref } from "vue";
import { RouterLink, useRoute } from "vue-router"; import { RouterLink, useRoute } from "vue-router";
import DepartmentIcon from "./icons/DepartmentIcon.vue"; import DepartmentIcon from "./icons/DepartmentIcon.vue";
import LlmConfigIcon from "./icons/LlmConfigIcon.vue";
import PermissionIcon from "./icons/PermissionIcon.vue"; import PermissionIcon from "./icons/PermissionIcon.vue";
import PositionIcon from "./icons/PositionIcon.vue"; import PositionIcon from "./icons/PositionIcon.vue";
import RoleIcon from "./icons/RoleIcon.vue"; import RoleIcon from "./icons/RoleIcon.vue";
import SchedulerIcon from "./icons/SchedulerIcon.vue"; import SchedulerIcon from "./icons/SchedulerIcon.vue";
import SettingsIcon from "./icons/SettingsIcon.vue"; import SettingsIcon from "./icons/SettingsIcon.vue";
import UsersIcon from "./icons/UsersIcon.vue"; import UsersIcon from "./icons/UsersIcon.vue";
import LlmConfigIcon from "./icons/LlmConfigIcon.vue";
const isDrawerVisible = ref(false);
// 菜单配置 // 菜单配置
const menuItems = [ const menuItems = [
@@ -83,6 +89,10 @@ const isActive = (path: string) => {
return route.path === path; return route.path === path;
}; };
const closeSidebar = () => {
isDrawerVisible.value = false;
};
onMounted(() => { onMounted(() => {
initFlowbite(); initFlowbite();
}); });

View File

@@ -51,7 +51,7 @@
</div> </div>
</div> </div>
<button type="submit" @click.prevent="handleSubmit" <button type="submit" @click.prevent="handleSubmit"
class="w-full sm:w-auto text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-xs sm:text-sm px-4 py-2 sm:px-5 sm:py-2.5 text-center self-start mt-5"> class="w-auto text-sm px-4 py-2 text-white flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-center self-start mt-5">
保存 保存
</button> </button>
</form> </form>

View File

@@ -11,8 +11,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const { size = 'w-6 h-6' } = defineProps<{ const { size = "w-6 h-6" } = defineProps<{
size?: string; size?: string;
}>(); }>();
</script> </script>

View File

@@ -154,20 +154,8 @@ onMounted(async () => {
const $deleteModalElement: HTMLElement | null = document.querySelector( const $deleteModalElement: HTMLElement | null = document.querySelector(
"#department-delete-modal", "#department-delete-modal",
); );
departmentUpsertModal.value = new Modal( departmentUpsertModal.value = new Modal($upsertModalElement, {});
$upsertModalElement, departmentDeleteModal.value = new Modal($deleteModalElement, {});
{},
{
id: "department-upsert-modal",
},
);
departmentDeleteModal.value = new Modal(
$deleteModalElement,
{},
{
id: "department-delete-modal",
},
);
}); });
const handleUpsertDepartmentSubmit = async ( const handleUpsertDepartmentSubmit = async (

View File

@@ -168,13 +168,7 @@ onMounted(async () => {
const $llmUpdateModalElement: HTMLElement | null = const $llmUpdateModalElement: HTMLElement | null =
document.querySelector("#llm-update-modal"); document.querySelector("#llm-update-modal");
llmUpdateModal.value = new Modal( llmUpdateModal.value = new Modal($llmUpdateModalElement, {});
$llmUpdateModalElement,
{},
{
id: "llm-update-modal",
},
);
}); });
</script> </script>

View File

@@ -148,16 +148,8 @@ onMounted(async () => {
const $deleteModalElement: HTMLElement | null = document.querySelector( const $deleteModalElement: HTMLElement | null = document.querySelector(
"#permission-delete-modal", "#permission-delete-modal",
); );
permissionUpsertModal.value = new Modal( permissionUpsertModal.value = new Modal($upsertModalElement, {});
$upsertModalElement, permissionDeleteModal.value = new Modal($deleteModalElement, {});
{},
{ id: "permission-upsert-modal" },
);
permissionDeleteModal.value = new Modal(
$deleteModalElement,
{},
{ id: "permission-delete-modal" },
);
}); });
const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => { const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => {

View File

@@ -147,20 +147,8 @@ onMounted(async () => {
const $deleteModalElement: HTMLElement | null = document.querySelector( const $deleteModalElement: HTMLElement | null = document.querySelector(
"#position-delete-modal", "#position-delete-modal",
); );
positionUpsertModal.value = new Modal( positionUpsertModal.value = new Modal($upsertModalElement, {});
$upsertModalElement, positionDeleteModal.value = new Modal($deleteModalElement, {});
{},
{
id: "position-upsert-modal",
},
);
positionDeleteModal.value = new Modal(
$deleteModalElement,
{},
{
id: "position-delete-modal",
},
);
}); });
const handleUpsertPositionSubmit = async ( const handleUpsertPositionSubmit = async (

View File

@@ -155,16 +155,8 @@ onMounted(async () => {
document.querySelector("#role-upsert-modal"); document.querySelector("#role-upsert-modal");
const $deleteModalElement: HTMLElement | null = const $deleteModalElement: HTMLElement | null =
document.querySelector("#role-delete-modal"); document.querySelector("#role-delete-modal");
roleUpsertModal.value = new Modal( roleUpsertModal.value = new Modal($upsertModalElement, {});
$upsertModalElement, roleDeleteModal.value = new Modal($deleteModalElement, {});
{},
{ id: "role-upsert-modal" },
);
roleDeleteModal.value = new Modal(
$deleteModalElement,
{},
{ id: "role-delete-modal" },
);
}); });
const handleUpsertModalSubmit = async (data: RoleUpsertModel) => { const handleUpsertModalSubmit = async (data: RoleUpsertModel) => {

View File

@@ -275,27 +275,9 @@ onMounted(async () => {
const $jobUpdateModalElement: HTMLElement | null = const $jobUpdateModalElement: HTMLElement | null =
document.querySelector("#job-update-modal"); document.querySelector("#job-update-modal");
jobResumeModal.value = new Modal( jobResumeModal.value = new Modal($jobResumeModalElement, {});
$jobResumeModalElement, jobPauseModal.value = new Modal($jobPauseModalElement, {});
{}, jobUpdateModal.value = new Modal($jobUpdateModalElement, {});
{
id: "job-resume-modal",
},
);
jobPauseModal.value = new Modal(
$jobPauseModalElement,
{},
{
id: "job-pause-modal",
},
);
jobUpdateModal.value = new Modal(
$jobUpdateModalElement,
{},
{
id: "job-update-modal",
},
);
}); });
</script> </script>

View File

@@ -41,7 +41,7 @@
</div> </div>
<div class="col-span-1 sm:col-span-6"> <div class="col-span-1 sm:col-span-6">
<button <button
class="text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center w-full sm:w-auto" class="text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center w-auto"
@click.prevent="handleUpdateClick" type="submit">保存</button> @click.prevent="handleUpdateClick" type="submit">保存</button>
</div> </div>
</div> </div>

View File

@@ -192,20 +192,8 @@ onMounted(async () => {
document.querySelector("#user-upsert-modal"); document.querySelector("#user-upsert-modal");
const $deleteModalElement: HTMLElement | null = const $deleteModalElement: HTMLElement | null =
document.querySelector("#user-delete-modal"); document.querySelector("#user-delete-modal");
userUpsertModal.value = new Modal( userUpsertModal.value = new Modal($upsertModalElement, {});
$upsertModalElement, userDeleteModal.value = new Modal($deleteModalElement, {});
{},
{
id: "user-upsert-modal",
},
);
userDeleteModal.value = new Modal(
$deleteModalElement,
{},
{
id: "user-delete-modal",
},
);
}); });
const handleUpsertUserSubmit = async (data: UserUpsertSubmitModel) => { const handleUpsertUserSubmit = async (data: UserUpsertSubmitModel) => {