add notify ai

This commit is contained in:
Chuck1sn
2025-06-13 11:43:35 +08:00
parent 81b02e68e7
commit a00c3e129f
21 changed files with 397 additions and 233 deletions

View File

@@ -30,5 +30,18 @@
"formatter": { "formatter": {
"quoteStyle": "double" "quoteStyle": "double"
} }
} },
"overrides": [
{
"include": ["*.vue"],
"linter": {
"rules": {
"style": {
"useConst": "off",
"useImportType": "off"
}
}
}
}
]
} }

View File

@@ -87,6 +87,7 @@ import LoadingIcon from "@/components/icons/LoadingIcon.vue";
import { useAiAction } from "@/composables/ai/useAiAction"; import { useAiAction } from "@/composables/ai/useAiAction";
import { useDepartmentQuery } from "@/composables/department/useDepartmentQuery"; import { useDepartmentQuery } from "@/composables/department/useDepartmentQuery";
import { useDepartmentUpsert } from "@/composables/department/useDepartmentUpsert"; import { useDepartmentUpsert } from "@/composables/department/useDepartmentUpsert";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
import useAlertStore from "@/composables/store/useAlertStore"; import useAlertStore from "@/composables/store/useAlertStore";
import type { DepartmentUpsertModel } from "@/types/department"; import type { DepartmentUpsertModel } from "@/types/department";
import DOMPurify from "dompurify"; import DOMPurify from "dompurify";
@@ -118,7 +119,7 @@ const { deleteUserByUsername, deleteDepartmentByName } = useAiAction();
const departmentDeleteModal = ref<ModalInterface>(); const departmentDeleteModal = ref<ModalInterface>();
const currentDeleteUsername = ref<string>(); const currentDeleteUsername = ref<string>();
const currentDeleteDepartmentName = ref<string>(); const currentDeleteDepartmentName = ref<string>();
const actionExcStore = useActionExcStore();
const { availableDepartments, fetchAvailableDepartments } = const { availableDepartments, fetchAvailableDepartments } =
useDepartmentQuery(); useDepartmentQuery();
@@ -194,6 +195,7 @@ const handleUpsertUserSubmit = async (data: UserUpsertSubmitModel) => {
content: "操作成功", content: "操作成功",
level: "success", level: "success",
}); });
actionExcStore.notify(true);
}; };
const handleUpsertDepartmentSubmit = async ( const handleUpsertDepartmentSubmit = async (
@@ -205,6 +207,7 @@ const handleUpsertDepartmentSubmit = async (
content: "操作成功", content: "操作成功",
level: "success", level: "success",
}); });
actionExcStore.notify(true);
}; };
const handleDeleteUserSubmit = async () => { const handleDeleteUserSubmit = async () => {
@@ -214,6 +217,7 @@ const handleDeleteUserSubmit = async () => {
content: "操作成功", content: "操作成功",
level: "success", level: "success",
}); });
actionExcStore.notify(true);
}; };
const handleDeleteDepartmentSubmit = async () => { const handleDeleteDepartmentSubmit = async () => {
@@ -223,6 +227,7 @@ const handleDeleteDepartmentSubmit = async () => {
content: "操作成功", content: "操作成功",
level: "success", level: "success",
}); });
actionExcStore.notify(true);
}; };
watch( watch(
@@ -261,6 +266,7 @@ const chatByMode = async (
await searchAction(message); await searchAction(message);
} else if (mode === "execute") { } else if (mode === "execute") {
await executeAction(message); await executeAction(message);
actionExcStore.notify(true);
} else { } else {
await chat(message); await chat(message);
} }

View File

@@ -35,21 +35,21 @@ import { computed } from "vue";
import type { RouteLocationRaw } from "vue-router"; import type { RouteLocationRaw } from "vue-router";
interface BreadcrumbItem { interface BreadcrumbItem {
name: string; name: string;
route?: RouteLocationRaw; route?: RouteLocationRaw;
} }
const props = defineProps<{ const props = defineProps<{
names: string[]; names: string[];
routes?: RouteLocationRaw[]; routes?: RouteLocationRaw[];
}>(); }>();
const breadcrumbs = computed<BreadcrumbItem[]>(() => { const breadcrumbs = computed<BreadcrumbItem[]>(() => {
return props.names.map((name, index) => { return props.names.map((name, index) => {
return { return {
name, name,
route: props.routes?.[index] route: props.routes?.[index],
}; };
}); });
}); });
</script> </script>

View File

@@ -0,0 +1,35 @@
<template>
<div id="date-range-picker" date-rangepicker class="flex items-center">
<div class="relative">
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z" />
</svg>
</div>
<input id="datepicker-range-start" name="start" type="text"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Select date start">
</div>
<span class="mx-4 text-gray-500">to</span>
<div class="relative">
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z" />
</svg>
</div>
<input id="datepicker-range-end" name="end" type="text"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Select date end">
</div>
</div>
</template>
<script setup>
</script>
<style scoped></style>

View File

@@ -4,7 +4,7 @@
<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 type="button" @click="handleSidebarToggle" <button type="button" @click="handleSidebarToggle"
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">
<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"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
@@ -13,7 +13,7 @@
</path> </path>
</svg> </svg>
</button> </button>
<a href="https://github.com/ccmjga/zhilu-admin" target="_blank" class="flex items-center ms-2 md:me-24"> <a href="https://github.com/ccmjga/zhilu-admin" target="_blank" class="flex items-center ms-2 md:me-24 ">
<img class="me-3" src="/logo.svg" alt="logo"> <img class="me-3" src="/logo.svg" alt="logo">
<span class="self-center text-lg sm:text-xl md:text-2xl font-semibold whitespace-nowrap">知路后台管理</span> <span class="self-center text-lg sm:text-xl md:text-2xl font-semibold whitespace-nowrap">知路后台管理</span>
</a> </a>
@@ -36,8 +36,7 @@
</button> </button>
<div class="flex items-center ms-2 sm:ms-3"> <div class="flex items-center ms-2 sm:ms-3">
<div> <div>
<button type="button" id="dropdown-button" <button type="button" id="dropdown-button" class="flex text-sm bg-gray-800 rounded-full cursor-pointer"
class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 cursor-pointer"
aria-expanded="false" data-dropdown-toggle="dropdown-user"> aria-expanded="false" data-dropdown-toggle="dropdown-user">
<span class="sr-only">打开用户菜单</span> <span class="sr-only">打开用户菜单</span>
<img class="w-8 h-8 rounded-full" src="/java.svg" alt="user photo"> <img class="w-8 h-8 rounded-full" src="/java.svg" alt="user photo">

View File

@@ -32,18 +32,18 @@
</template> </template>
<script setup generic="T" lang="ts"> <script setup generic="T" lang="ts">
import { ref } from 'vue'; import { ref } from "vue";
/** 通用对象类型 */ /** 通用对象类型 */
type ItemRecord = Record<string, unknown>; type ItemRecord = Record<string, unknown>;
const props = defineProps<{ const props = defineProps<{
/** 数据项数组 */ /** 数据项数组 */
items: T[] | undefined; items: T[] | undefined;
/** 数据项ID字段名 */ /** 数据项ID字段名 */
idField?: string; idField?: string;
/** 数据项唯一键字段名 */ /** 数据项唯一键字段名 */
keyField?: string; keyField?: string;
}>(); }>();
/** /**
@@ -53,17 +53,17 @@ const props = defineProps<{
* @returns 唯一键 * @returns 唯一键
*/ */
const getItemKey = (item: T, index: number): string | number => { const getItemKey = (item: T, index: number): string | number => {
if (props.keyField) { if (props.keyField) {
const key = (item as ItemRecord)[props.keyField]; const key = (item as ItemRecord)[props.keyField];
if (key !== undefined) return String(key); if (key !== undefined) return String(key);
} }
if (props.idField) { if (props.idField) {
const id = (item as ItemRecord)[props.idField]; const id = (item as ItemRecord)[props.idField];
if (id !== undefined) return String(id); if (id !== undefined) return String(id);
} }
const id = (item as ItemRecord).id; const id = (item as ItemRecord).id;
return id !== undefined ? String(id) : index; return id !== undefined ? String(id) : index;
}; };
</script> </script>

View File

@@ -37,24 +37,24 @@
</template> </template>
<script setup generic="T" lang="ts"> <script setup generic="T" lang="ts">
import { ref, watch } from 'vue'; import { ref, watch } from "vue";
/** 通用对象类型 */ /** 通用对象类型 */
type ItemRecord = Record<string, unknown>; type ItemRecord = Record<string, unknown>;
const props = defineProps<{ const props = defineProps<{
/** 数据项数组 */ /** 数据项数组 */
items: T[] | undefined; items: T[] | undefined;
/** 数据项ID字段名 */ /** 数据项ID字段名 */
idField?: string; idField?: string;
/** 数据项唯一键字段名 */ /** 数据项唯一键字段名 */
keyField?: string; keyField?: string;
/** 选中项的值数组 */ /** 选中项的值数组 */
modelValue?: (string | number)[]; modelValue?: (string | number)[];
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
'update:modelValue': [checkedItems: (string | number)[]]; "update:modelValue": [checkedItems: (string | number)[]];
}>(); }>();
const checkedItems = ref<(string | number)[]>(props.modelValue || []); const checkedItems = ref<(string | number)[]>(props.modelValue || []);
@@ -66,13 +66,13 @@ const checkedItems = ref<(string | number)[]>(props.modelValue || []);
* @returns 唯一键 * @returns 唯一键
*/ */
const getItemKey = (item: T, index: number): string | number => { const getItemKey = (item: T, index: number): string | number => {
if (props.keyField) { if (props.keyField) {
const key = (item as ItemRecord)[props.keyField]; const key = (item as ItemRecord)[props.keyField];
if (key !== undefined) return String(key); if (key !== undefined) return String(key);
} }
const id = getItemId(item); const id = getItemId(item);
return id !== undefined ? id : index; return id !== undefined ? id : index;
}; };
/** /**
@@ -81,21 +81,28 @@ const getItemKey = (item: T, index: number): string | number => {
* @returns ID值 * @returns ID值
*/ */
const getItemId = (item: T): string | number => { const getItemId = (item: T): string | number => {
if (props.idField) { if (props.idField) {
return (item as ItemRecord)[props.idField] as string | number; return (item as ItemRecord)[props.idField] as string | number;
} }
return (item as ItemRecord).id as string | number || item as unknown as string | number; return (
((item as ItemRecord).id as string | number) ||
(item as unknown as string | number)
);
}; };
// 监听选中项变化 // 监听选中项变化
watch(checkedItems, (newVal) => { watch(checkedItems, (newVal) => {
emit('update:modelValue', newVal); emit("update:modelValue", newVal);
}); });
// 监听modelValue变化 // 监听modelValue变化
watch(() => props.modelValue, (newVal) => { watch(
if (newVal) { () => props.modelValue,
checkedItems.value = newVal; (newVal) => {
} if (newVal) {
}, { deep: true }); checkedItems.value = newVal;
}
},
{ deep: true },
);
</script> </script>

View File

@@ -14,70 +14,78 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from "vue";
export type ButtonVariant = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info'; export type ButtonVariant =
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg'; | "primary"
| "secondary"
| "success"
| "danger"
| "warning"
| "info";
export type ButtonSize = "xs" | "sm" | "md" | "lg";
const props = defineProps<{ const props = defineProps<{
/** 按钮变体类型 */ /** 按钮变体类型 */
variant?: ButtonVariant; variant?: ButtonVariant;
/** 按钮尺寸 */ /** 按钮尺寸 */
size?: ButtonSize; size?: ButtonSize;
/** 是否禁用 */ /** 是否禁用 */
disabled?: boolean; disabled?: boolean;
/** 自定义CSS类名 */ /** 自定义CSS类名 */
className?: string; className?: string;
/** 是否为移动端尺寸 */ /** 是否为移动端尺寸 */
isMobile?: boolean; isMobile?: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
'click': [event: MouseEvent]; click: [event: MouseEvent];
}>(); }>();
/** 按钮颜色样式映射 */ /** 按钮颜色样式映射 */
const colorClasses = computed(() => { const colorClasses = computed(() => {
const variants: Record<ButtonVariant, string> = { const variants: Record<ButtonVariant, string> = {
primary: 'text-white bg-blue-700 hover:bg-blue-800 focus:ring-blue-300', primary: "text-white bg-blue-700 hover:bg-blue-800 focus:ring-blue-300",
secondary: 'text-gray-900 bg-white border border-gray-300 hover:bg-gray-100 focus:ring-gray-100', secondary:
success: 'text-white bg-green-700 hover:bg-green-800 focus:ring-green-300', "text-gray-900 bg-white border border-gray-300 hover:bg-gray-100 focus:ring-gray-100",
danger: 'text-white bg-red-700 hover:bg-red-800 focus:ring-red-300', success: "text-white bg-green-700 hover:bg-green-800 focus:ring-green-300",
warning: 'text-gray-900 bg-yellow-400 hover:bg-yellow-500 focus:ring-yellow-300', danger: "text-white bg-red-700 hover:bg-red-800 focus:ring-red-300",
info: 'text-white bg-cyan-700 hover:bg-cyan-800 focus:ring-cyan-300' warning:
}; "text-gray-900 bg-yellow-400 hover:bg-yellow-500 focus:ring-yellow-300",
info: "text-white bg-cyan-700 hover:bg-cyan-800 focus:ring-cyan-300",
return variants[props.variant || 'primary']; };
return variants[props.variant || "primary"];
}); });
/** 按钮尺寸样式映射 */ /** 按钮尺寸样式映射 */
const sizeClasses = computed(() => { const sizeClasses = computed(() => {
// 移动端尺寸 // 移动端尺寸
if (props.isMobile) { if (props.isMobile) {
const sizes: Record<ButtonSize, string> = { const sizes: Record<ButtonSize, string> = {
xs: 'text-xs px-2 py-1', xs: "text-xs px-2 py-1",
sm: 'text-xs px-3 py-1.5', sm: "text-xs px-3 py-1.5",
md: 'text-sm px-3 py-2', md: "text-sm px-3 py-2",
lg: 'text-sm px-4 py-2.5' lg: "text-sm px-4 py-2.5",
}; };
return sizes[props.size || 'sm']; return sizes[props.size || "sm"];
} }
// PC端尺寸 // PC端尺寸
const sizes: Record<ButtonSize, string> = { const sizes: Record<ButtonSize, string> = {
xs: 'text-xs px-3 py-1.5', xs: "text-xs px-3 py-1.5",
sm: 'text-sm px-3 py-2', sm: "text-sm px-3 py-2",
md: 'text-sm px-4 py-2.5', md: "text-sm px-4 py-2.5",
lg: 'text-base px-5 py-3' lg: "text-base px-5 py-3",
}; };
return sizes[props.size || 'md']; return sizes[props.size || "md"];
}); });
/** 处理点击事件 */ /** 处理点击事件 */
const handleClick = (event: MouseEvent) => { const handleClick = (event: MouseEvent) => {
if (!props.disabled) { if (!props.disabled) {
emit('click', event); emit("click", event);
} }
}; };
</script> </script>

View File

@@ -51,44 +51,44 @@
</template> </template>
<script setup generic="T" lang="ts"> <script setup generic="T" lang="ts">
import { defineEmits, ref, watch } from 'vue'; import { defineEmits, ref, watch } from "vue";
/** /**
* 表格列配置接口 * 表格列配置接口
*/ */
export interface Column { export interface Column {
/** 列标题 */ /** 列标题 */
title: string; title: string;
/** 数据字段名 */ /** 数据字段名 */
field: string; field: string;
/** 是否可排序 */ /** 是否可排序 */
sortable?: boolean; sortable?: boolean;
/** 自定义CSS类名 */ /** 自定义CSS类名 */
class?: string; class?: string;
} }
/** 通用对象类型 */ /** 通用对象类型 */
type ItemRecord = Record<string, unknown>; type ItemRecord = Record<string, unknown>;
const props = defineProps<{ const props = defineProps<{
/** 数据项数组 */ /** 数据项数组 */
items: T[]; items: T[];
/** 列配置数组 */ /** 列配置数组 */
columns: Column[]; columns: Column[];
/** 是否显示复选框 */ /** 是否显示复选框 */
hasCheckbox?: boolean; hasCheckbox?: boolean;
/** 数据项ID字段名 */ /** 数据项ID字段名 */
idField?: string; idField?: string;
/** 数据项唯一键字段名 */ /** 数据项唯一键字段名 */
keyField?: string; keyField?: string;
/** 选中项的值数组用于v-model绑定 */ /** 选中项的值数组用于v-model绑定 */
modelValue?: (string | number)[]; modelValue?: (string | number)[];
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
'update:modelValue': [checkedItems: (string | number)[]]; "update:modelValue": [checkedItems: (string | number)[]];
'sort': [field: string]; sort: [field: string];
'all-checked-change': [checked: boolean]; "all-checked-change": [checked: boolean];
}>(); }>();
const checkedItems = ref<(string | number)[]>(props.modelValue || []); const checkedItems = ref<(string | number)[]>(props.modelValue || []);
@@ -101,13 +101,13 @@ const allChecked = ref(false);
* @returns 唯一键 * @returns 唯一键
*/ */
const getItemKey = (item: T, index: number): string | number => { const getItemKey = (item: T, index: number): string | number => {
if (props.keyField) { if (props.keyField) {
const key = (item as ItemRecord)[props.keyField]; const key = (item as ItemRecord)[props.keyField];
if (key !== undefined) return String(key); if (key !== undefined) return String(key);
} }
const id = getItemId(item); const id = getItemId(item);
return id !== undefined ? id : index; return id !== undefined ? id : index;
}; };
/** /**
@@ -116,10 +116,13 @@ const getItemKey = (item: T, index: number): string | number => {
* @returns ID值 * @returns ID值
*/ */
const getItemId = (item: T): string | number => { const getItemId = (item: T): string | number => {
if (props.idField) { if (props.idField) {
return (item as ItemRecord)[props.idField] as string | number; return (item as ItemRecord)[props.idField] as string | number;
} }
return (item as ItemRecord).id as string | number || item as unknown as string | number; return (
((item as ItemRecord).id as string | number) ||
(item as unknown as string | number)
);
}; };
/** /**
@@ -129,26 +132,34 @@ const getItemId = (item: T): string | number => {
* @returns 字段值 * @returns 字段值
*/ */
const getItemValue = (item: T, field: string): string => { const getItemValue = (item: T, field: string): string => {
if (!field) return ''; if (!field) return "";
return String(field.split('.').reduce<unknown>((obj, key) => return String(
obj && typeof obj === 'object' && key in (obj as Record<string, unknown>) field
? (obj as Record<string, unknown>)[key] .split(".")
: '', .reduce<unknown>(
item as ItemRecord)); (obj, key) =>
obj &&
typeof obj === "object" &&
key in (obj as Record<string, unknown>)
? (obj as Record<string, unknown>)[key]
: "",
item as ItemRecord,
),
);
}; };
/** /**
* 处理全选/取消全选 * 处理全选/取消全选
*/ */
const handleAllCheckedChange = () => { const handleAllCheckedChange = () => {
if (allChecked.value) { if (allChecked.value) {
checkedItems.value = props.items.map(getItemId); checkedItems.value = props.items.map(getItemId);
} else { } else {
checkedItems.value = []; checkedItems.value = [];
} }
emit('all-checked-change', allChecked.value); emit("all-checked-change", allChecked.value);
emit('update:modelValue', checkedItems.value); emit("update:modelValue", checkedItems.value);
}; };
/** /**
@@ -156,32 +167,40 @@ const handleAllCheckedChange = () => {
* @param field 排序字段 * @param field 排序字段
*/ */
const handleSortClick = (field: string) => { const handleSortClick = (field: string) => {
emit('sort', field); emit("sort", field);
}; };
// 监听选中项变化 // 监听选中项变化
watch(checkedItems, (newVal) => { watch(checkedItems, (newVal) => {
emit('update:modelValue', newVal); emit("update:modelValue", newVal);
// 更新全选状态 // 更新全选状态
if (props.items.length > 0) { if (props.items.length > 0) {
allChecked.value = newVal.length === props.items.length; allChecked.value = newVal.length === props.items.length;
} else { } else {
allChecked.value = false; allChecked.value = false;
} }
}); });
// 监听modelValue变化 // 监听modelValue变化
watch(() => props.modelValue, (newVal) => { watch(
if (newVal) { () => props.modelValue,
checkedItems.value = newVal; (newVal) => {
} if (newVal) {
}, { deep: true }); checkedItems.value = newVal;
}
},
{ deep: true },
);
// 监听items变化重置选中状态 // 监听items变化重置选中状态
watch(() => props.items, () => { watch(
if (allChecked.value) { () => props.items,
checkedItems.value = props.items.map(getItemId); () => {
emit('update:modelValue', checkedItems.value); if (allChecked.value) {
} checkedItems.value = props.items.map(getItemId);
}, { deep: true }); emit("update:modelValue", checkedItems.value);
}
},
{ deep: true },
);
</script> </script>

View File

@@ -0,0 +1,19 @@
import { defineStore } from "pinia";
export const useActionExcStore = defineStore("refresh", {
state: () => {
return {
callback: (result: boolean) => {
console.debug("callback", result);
},
};
},
actions: {
notify(result: boolean) {
this.callback(result);
},
setCallback(callback: (result: boolean) => void) {
this.callback = callback;
},
},
});

View File

@@ -123,6 +123,7 @@ import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useDepartmentBind } from "../composables/department/useDepartmentBind"; import { useDepartmentBind } from "../composables/department/useDepartmentBind";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const departmentName = ref<string>(""); const departmentName = ref<string>("");
const checkedDepartmentIds = ref<number[]>([]); const checkedDepartmentIds = ref<number[]>([]);
@@ -133,16 +134,16 @@ const $route = useRoute();
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL"); const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
const { total, departments, fetchDepartmentWith } = useDepartmentQuery(); const { total, departments, fetchDepartmentWith } = useDepartmentQuery();
const { bindDepartment, unbindDepartment } = useDepartmentBind(); const { bindDepartment, unbindDepartment } = useDepartmentBind();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '上级部门', field: 'parentName' }, { title: "上级部门", field: "parentName" },
{ title: '部门名称', field: 'name' }, { title: "部门名称", field: "name" },
{ title: '绑定状态', field: 'bindState' } { title: "绑定状态", field: "bindState" },
]; ];
const handleBindDepartmentSubmit = async () => { const handleBindDepartmentSubmit = async () => {
@@ -200,6 +201,11 @@ onMounted(async () => {
"#department-unbind-modal", "#department-unbind-modal",
); );
departmentUnbindModal.value = new Modal($unbindModalElement, {}); departmentUnbindModal.value = new Modal($unbindModalElement, {});
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleSearch = async () => { const handleSearch = async () => {

View File

@@ -125,6 +125,7 @@ import { useRoute } from "vue-router";
import { usePermissionBind } from "../composables/permission/usePermissionBind"; import { usePermissionBind } from "../composables/permission/usePermissionBind";
import usePermissionsQuery from "../composables/permission/usePermissionQuery"; import usePermissionsQuery from "../composables/permission/usePermissionQuery";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const permissionName = ref<string>(""); const permissionName = ref<string>("");
const checkedPermissionIds = ref<number[]>([]); const checkedPermissionIds = ref<number[]>([]);
@@ -135,14 +136,15 @@ const $route = useRoute();
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL"); const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
const { total, permissions, fetchPermissionsWith } = usePermissionsQuery(); const { total, permissions, fetchPermissionsWith } = usePermissionsQuery();
const { bindPermission, unbindPermission } = usePermissionBind(); const { bindPermission, unbindPermission } = usePermissionBind();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '权限编码', field: 'code' }, { title: "权限编码", field: "code" },
{ title: '权限名称', field: 'name' }, { title: "权限名称", field: "name" },
{ title: '绑定状态', field: 'bindState' } { title: "绑定状态", field: "bindState" },
]; ];
const handleBindPermissionSubmit = async () => { const handleBindPermissionSubmit = async () => {
@@ -204,6 +206,11 @@ onMounted(async () => {
{}, {},
{ id: "permission-unbind-modal" }, { id: "permission-unbind-modal" },
); );
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleSearch = async () => { const handleSearch = async () => {

View File

@@ -117,6 +117,7 @@ import { Modal, type ModalInterface, initFlowbite } from "flowbite";
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const positionName = ref<string>(""); const positionName = ref<string>("");
const checkedPositionIds = ref<number[]>([]); const checkedPositionIds = ref<number[]>([]);
@@ -127,15 +128,15 @@ const $route = useRoute();
const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL"); const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
const { total, positions, fetchPositionWith } = usePositionQuery(); const { total, positions, fetchPositionWith } = usePositionQuery();
const { bindPosition, unbindPosition } = usePositionBind(); const { bindPosition, unbindPosition } = usePositionBind();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '岗位名称', field: 'name' }, { title: "岗位名称", field: "name" },
{ title: '绑定状态', field: 'bindState' } { title: "绑定状态", field: "bindState" },
]; ];
const handleBindPositionSubmit = async () => { const handleBindPositionSubmit = async () => {
@@ -191,6 +192,11 @@ onMounted(async () => {
{}, {},
{ id: "position-unbind-modal" }, { id: "position-unbind-modal" },
); );
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleSearch = async () => { const handleSearch = async () => {

View File

@@ -126,6 +126,7 @@ import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useRoleBind } from "../composables/role/useRoleBind"; import { useRoleBind } from "../composables/role/useRoleBind";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const roleName = ref<string>(""); const roleName = ref<string>("");
const checkedRoleIds = ref<number[]>([]); const checkedRoleIds = ref<number[]>([]);
@@ -138,12 +139,12 @@ const bindState = ref<"BIND" | "ALL" | "UNBIND">("ALL");
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const { total, roles, fetchRolesWith } = useRolesQuery(); const { total, roles, fetchRolesWith } = useRolesQuery();
const { bindRole, unbindRole } = useRoleBind(); const { bindRole, unbindRole } = useRoleBind();
const actionExcStore = useActionExcStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '角色编码', field: 'code' }, { title: "角色编码", field: "code" },
{ title: '角色名称', field: 'name' }, { title: "角色名称", field: "name" },
{ title: '绑定状态', field: 'bindState' } { title: "绑定状态", field: "bindState" },
]; ];
const handleBindRoleSubmit = async () => { const handleBindRoleSubmit = async () => {
@@ -200,6 +201,11 @@ onMounted(async () => {
{}, {},
{ id: "role-unbind-modal" }, { id: "role-unbind-modal" },
); );
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleSearch = async () => { const handleSearch = async () => {

View File

@@ -141,6 +141,7 @@ import useDepartmentDelete from "../composables/department/useDepartmentDelete";
import { useDepartmentQuery } from "../composables/department/useDepartmentQuery"; import { useDepartmentQuery } from "../composables/department/useDepartmentQuery";
import { useDepartmentUpsert } from "../composables/department/useDepartmentUpsert"; import { useDepartmentUpsert } from "../composables/department/useDepartmentUpsert";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const name = ref<string>(""); const name = ref<string>("");
const selectedDepartment = ref<components["schemas"]["Department"]>(); const selectedDepartment = ref<components["schemas"]["Department"]>();
@@ -159,12 +160,12 @@ const { deleteDepartment } = useDepartmentDelete();
const { upsertDepartment } = useDepartmentUpsert(); const { upsertDepartment } = useDepartmentUpsert();
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '上级部门', field: 'parentName' }, { title: "上级部门", field: "parentName" },
{ title: '部门名称', field: 'name' }, { title: "部门名称", field: "name" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
onMounted(async () => { onMounted(async () => {
@@ -184,6 +185,11 @@ onMounted(async () => {
if ($deleteModalElement) { if ($deleteModalElement) {
departmentDeleteModal.value = new Modal($deleteModalElement, {}); departmentDeleteModal.value = new Modal($deleteModalElement, {});
} }
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleUpsertDepartmentSubmit = async ( const handleUpsertDepartmentSubmit = async (

View File

@@ -154,14 +154,14 @@ const alertStore = useAlertStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '名称', field: 'name' }, { title: "名称", field: "name" },
{ title: '模型名称', field: 'modelName' }, { title: "模型名称", field: "modelName" },
{ title: '类型', field: 'type' }, { title: "类型", field: "type" },
{ title: 'apiKey', field: 'apiKey', class: 'hidden lg:table-cell' }, { title: "apiKey", field: "apiKey", class: "hidden lg:table-cell" },
{ title: 'url', field: 'url', class: 'hidden lg:table-cell' }, { title: "url", field: "url", class: "hidden lg:table-cell" },
{ title: '状态', field: 'status' }, { title: "状态", field: "status" },
{ title: '优先级', field: 'priority' }, { title: "优先级", field: "priority" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
const handleUpdateModalSubmit = async (llm: components["schemas"]["LlmVm"]) => { const handleUpdateModalSubmit = async (llm: components["schemas"]["LlmVm"]) => {

View File

@@ -142,6 +142,7 @@ import usePermissionsQuery from "../composables/permission/usePermissionQuery";
import usePermissionUpsert from "../composables/permission/usePermissionUpsert"; import usePermissionUpsert from "../composables/permission/usePermissionUpsert";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import type { PermissionUpsertModel } from "../types/permission"; import type { PermissionUpsertModel } from "../types/permission";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const permissionName = ref<string>(""); const permissionName = ref<string>("");
const selectedPermission = ref<components["schemas"]["PermissionRespDto"]>(); const selectedPermission = ref<components["schemas"]["PermissionRespDto"]>();
@@ -153,12 +154,12 @@ const { total, permissions, fetchPermissionsWith } = usePermissionsQuery();
const { deletePermission } = usePermissionDelete(); const { deletePermission } = usePermissionDelete();
const permissionUpsert = usePermissionUpsert(); const permissionUpsert = usePermissionUpsert();
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '权限名称', field: 'name' }, { title: "权限名称", field: "name" },
{ title: '权限编码', field: 'code' }, { title: "权限编码", field: "code" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
onMounted(async () => { onMounted(async () => {
@@ -178,6 +179,11 @@ onMounted(async () => {
if ($deleteModalElement) { if ($deleteModalElement) {
permissionDeleteModal.value = new Modal($deleteModalElement, {}); permissionDeleteModal.value = new Modal($deleteModalElement, {});
} }
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => { const handleUpsertModalSubmit = async (data: PermissionUpsertModel) => {

View File

@@ -126,11 +126,11 @@ import TablePagination from "@/components/TablePagination.vue";
import usePositionDelete from "@/composables/position/usePositionDelete"; import usePositionDelete from "@/composables/position/usePositionDelete";
import { usePositionQuery } from "@/composables/position/usePositionQuery"; import { usePositionQuery } from "@/composables/position/usePositionQuery";
import { usePositionUpsert } from "@/composables/position/usePositionUpsert"; import { usePositionUpsert } from "@/composables/position/usePositionUpsert";
import { useMobileStyles } from "@/composables/useMobileStyles";
import { Modal, type ModalInterface, initFlowbite } from "flowbite"; import { Modal, type ModalInterface, initFlowbite } from "flowbite";
import { nextTick, onMounted, ref } from "vue"; import { nextTick, onMounted, ref } from "vue";
import type { components } from "../api/types/schema"; import type { components } from "../api/types/schema";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const name = ref<string>(""); const name = ref<string>("");
const selectedPosition = ref<components["schemas"]["Position"]>(); const selectedPosition = ref<components["schemas"]["Position"]>();
@@ -144,11 +144,11 @@ const { deletePosition } = usePositionDelete();
const { upsertPosition } = usePositionUpsert(); const { upsertPosition } = usePositionUpsert();
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '岗位名称', field: 'name' }, { title: "岗位名称", field: "name" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
onMounted(async () => { onMounted(async () => {
@@ -169,6 +169,11 @@ onMounted(async () => {
if ($deleteModalElement) { if ($deleteModalElement) {
positionDeleteModal.value = new Modal($deleteModalElement, {}); positionDeleteModal.value = new Modal($deleteModalElement, {});
} }
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleUpsertPositionSubmit = async ( const handleUpsertPositionSubmit = async (

View File

@@ -157,12 +157,13 @@ import { useRouter } from "vue-router";
import type { components } from "../api/types/schema"; import type { components } from "../api/types/schema";
import { useRoleUpsert } from "../composables/role/useRoleUpsert"; import { useRoleUpsert } from "../composables/role/useRoleUpsert";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const roleName = ref<string>(""); const roleName = ref<string>("");
const selectedRole = ref<components["schemas"]["RoleDto"]>(); const selectedRole = ref<components["schemas"]["RoleDto"]>();
const roleUpsertModal = ref<ModalInterface>(); const roleUpsertModal = ref<ModalInterface>();
const roleDeleteModal = ref<ModalInterface>(); const roleDeleteModal = ref<ModalInterface>();
const actionExcStore = useActionExcStore();
const { total, roles, fetchRolesWith } = useRolesQuery(); const { total, roles, fetchRolesWith } = useRolesQuery();
const { deleteRole } = useRoleDelete(); const { deleteRole } = useRoleDelete();
@@ -172,10 +173,10 @@ const upsertRole = useRoleUpsert();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '角色名称', field: 'name' }, { title: "角色名称", field: "name" },
{ title: '角色编码', field: 'code' }, { title: "角色编码", field: "code" },
{ title: '分配', field: 'assign' }, { title: "分配", field: "assign" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
onMounted(async () => { onMounted(async () => {
@@ -193,6 +194,11 @@ onMounted(async () => {
if ($deleteModalElement) { if ($deleteModalElement) {
roleDeleteModal.value = new Modal($deleteModalElement, {}); roleDeleteModal.value = new Modal($deleteModalElement, {});
} }
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleUpsertModalSubmit = async (data: RoleUpsertModel) => { const handleUpsertModalSubmit = async (data: RoleUpsertModel) => {

View File

@@ -195,17 +195,21 @@ const { updateCron } = useJobUpdate();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '任务', field: 'name' }, { title: "任务", field: "name" },
{ title: '触发器', field: 'trigger', class: 'hidden lg:table-cell' }, { title: "触发器", field: "trigger", class: "hidden lg:table-cell" },
{ title: '开始', field: 'startTime', class: 'hidden lg:table-cell' }, { title: "开始", field: "startTime", class: "hidden lg:table-cell" },
{ title: '结束', field: 'endTime', class: 'hidden lg:table-cell' }, { title: "结束", field: "endTime", class: "hidden lg:table-cell" },
{ title: '下次执行', field: 'nextFireTime', class: 'hidden md:table-cell' }, { title: "下次执行", field: "nextFireTime", class: "hidden md:table-cell" },
{ title: '上次执行', field: 'previousFireTime', class: 'hidden lg:table-cell' }, {
{ title: '类型', field: 'schedulerType', class: 'hidden md:table-cell' }, title: "上次执行",
{ title: 'Cron', field: 'cronExpression', class: 'hidden md:table-cell' }, field: "previousFireTime",
{ title: '状态', field: 'triggerState' }, class: "hidden lg:table-cell",
{ title: '编辑', field: 'edit', class: 'hidden sm:table-cell' }, },
{ title: '操作', field: 'actions' } { title: "类型", field: "schedulerType", class: "hidden md:table-cell" },
{ title: "Cron", field: "cronExpression", class: "hidden md:table-cell" },
{ title: "状态", field: "triggerState" },
{ title: "编辑", field: "edit", class: "hidden sm:table-cell" },
{ title: "操作", field: "actions" },
]; ];
const handleResumeJobClick = async ( const handleResumeJobClick = async (

View File

@@ -189,6 +189,7 @@ import { useRouter } from "vue-router";
import type { components } from "../api/types/schema"; import type { components } from "../api/types/schema";
import useAlertStore from "../composables/store/useAlertStore"; import useAlertStore from "../composables/store/useAlertStore";
import { useUserUpsert } from "../composables/user/useUserUpsert"; import { useUserUpsert } from "../composables/user/useUserUpsert";
import { useActionExcStore } from "@/composables/store/useActionExcStore";
const username = ref<string>(""); const username = ref<string>("");
const selectedUser = ref<components["schemas"]["UserRolePermissionDto"]>(); const selectedUser = ref<components["schemas"]["UserRolePermissionDto"]>();
@@ -200,14 +201,14 @@ const { deleteUser } = useUserDelete();
const userUpsert = useUserUpsert(); const userUpsert = useUserUpsert();
const { sortBy, handleSort, getSortField } = useSort(); const { sortBy, handleSort, getSortField } = useSort();
const alertStore = useAlertStore(); const alertStore = useAlertStore();
const actionExcStore = useActionExcStore();
// 定义表格列配置 // 定义表格列配置
const columns = [ const columns = [
{ title: '用户名', field: 'username', sortable: true }, { title: "用户名", field: "username", sortable: true },
{ title: '创建时间', field: 'createTime', sortable: true }, { title: "创建时间", field: "createTime", sortable: true },
{ title: '状态', field: 'status' }, { title: "状态", field: "status" },
{ title: '分配', field: 'assign' }, { title: "分配", field: "assign" },
{ title: '操作', field: 'actions' } { title: "操作", field: "actions" },
]; ];
onMounted(async () => { onMounted(async () => {
@@ -225,6 +226,11 @@ onMounted(async () => {
if ($deleteModalElement) { if ($deleteModalElement) {
userDeleteModal.value = new Modal($deleteModalElement, {}); userDeleteModal.value = new Modal($deleteModalElement, {});
} }
actionExcStore.setCallback((result) => {
if (result) {
handleSearch();
}
});
}); });
const handleUpsertUserSubmit = async (data: UserUpsertSubmitModel) => { const handleUpsertUserSubmit = async (data: UserUpsertSubmitModel) => {