Jelajahi Sumber

feat: 修改提示

DESKTOP-USV654P\pc 9 bulan lalu
induk
melakukan
33c3d0a9aa
38 mengubah file dengan 448 tambahan dan 148 penghapusan
  1. 1 0
      apps/baicai-cms/package.json
  2. 1 0
      apps/baicai-cms/src/api/model/index.ts
  3. 2 0
      apps/baicai-cms/src/bootstrap.ts
  4. 1 0
      apps/baicai-cms/src/components/article/index.ts
  5. 1 0
      apps/baicai-cms/src/components/article/list-page/index.ts
  6. 118 0
      apps/baicai-cms/src/components/article/list-page/list-page.vue
  7. 133 0
      apps/baicai-cms/src/views/default/hardware/components/menu.vue
  8. 6 0
      apps/baicai-cms/src/views/default/hardware/detail/index.vue
  9. 66 0
      apps/baicai-cms/src/views/default/hardware/list/index.vue
  10. 8 14
      apps/baicai-cms/src/views/default/software/components/menu.vue
  11. 4 1
      apps/baicai-cms/src/views/default/software/detail/index.vue
  12. 14 31
      apps/baicai-cms/src/views/default/software/list/index.vue
  13. 3 3
      apps/web-baicai/src/views/cms/article/list/index.vue
  14. 3 3
      apps/web-baicai/src/views/cms/article/type/index.vue
  15. 3 3
      apps/web-baicai/src/views/cms/site/channel/index.vue
  16. 3 3
      apps/web-baicai/src/views/cms/site/channelField/index.vue
  17. 3 3
      apps/web-baicai/src/views/cms/site/domain/index.vue
  18. 3 3
      apps/web-baicai/src/views/cms/site/info/index.vue
  19. 1 0
      apps/web-baicai/src/views/cms/site/menu/components/edit.vue
  20. 3 3
      apps/web-baicai/src/views/cms/site/menu/index.vue
  21. 3 3
      apps/web-baicai/src/views/plugins/template/index.vue
  22. 3 3
      apps/web-baicai/src/views/system/config/index.vue
  23. 3 3
      apps/web-baicai/src/views/system/department/index.vue
  24. 4 34
      apps/web-baicai/src/views/system/design/database/index.vue
  25. 3 3
      apps/web-baicai/src/views/system/design/query/index.vue
  26. 3 3
      apps/web-baicai/src/views/system/design/table/index.vue
  27. 2 2
      apps/web-baicai/src/views/system/dict/item/index.vue
  28. 3 3
      apps/web-baicai/src/views/system/dict/type/index.vue
  29. 3 3
      apps/web-baicai/src/views/system/log/difference/index.vue
  30. 3 3
      apps/web-baicai/src/views/system/log/exception/index.vue
  31. 3 3
      apps/web-baicai/src/views/system/log/operate/index.vue
  32. 3 3
      apps/web-baicai/src/views/system/log/visit/index.vue
  33. 3 3
      apps/web-baicai/src/views/system/menu/index.vue
  34. 3 3
      apps/web-baicai/src/views/system/post/index.vue
  35. 2 2
      apps/web-baicai/src/views/system/role/index.vue
  36. 4 4
      apps/web-baicai/src/views/system/tenant/index.vue
  37. 3 3
      apps/web-baicai/src/views/system/user/index.vue
  38. 20 0
      pnpm-lock.yaml

+ 1 - 0
apps/baicai-cms/package.json

@@ -55,6 +55,7 @@
     "pinia": "catalog:",
     "sm-crypto-v2": "^1.9.2",
     "vue": "catalog:",
+    "vue-dompurify-html": "^5.3.0",
     "vue-router": "catalog:",
     "vuedraggable": "^4.1.0"
   },

+ 1 - 0
apps/baicai-cms/src/api/model/index.ts

@@ -6,6 +6,7 @@ export interface BasicPageParams {
 export interface BasicFetchResult<T> {
   items: T[];
   total: number;
+  totalPages: number;
 }
 
 export interface StatusParams {

+ 2 - 0
apps/baicai-cms/src/bootstrap.ts

@@ -1,4 +1,5 @@
 import { createApp, watchEffect } from 'vue';
+import VueDOMPurifyHTML from 'vue-dompurify-html';
 
 import { registerAccessDirective } from '@vben/access';
 import { registerLoadingDirective } from '@vben/common-ui';
@@ -34,6 +35,7 @@ async function bootstrap(namespace: string) {
 
   const app = createApp(App);
 
+  app.use(VueDOMPurifyHTML);
   // 注册v-loading指令
   registerLoadingDirective(app, {
     loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令

+ 1 - 0
apps/baicai-cms/src/components/article/index.ts

@@ -1,4 +1,5 @@
 export * from './detail-banner';
+export * from './list-page';
 export * from './list-text';
 export * from './type-banner';
 export * from './type-group';

+ 1 - 0
apps/baicai-cms/src/components/article/list-page/index.ts

@@ -0,0 +1 @@
+export { default as ArticleListPage } from './list-page.vue';

+ 118 - 0
apps/baicai-cms/src/components/article/list-page/list-page.vue

@@ -0,0 +1,118 @@
+<script lang="ts" setup>
+import type { PropType } from 'vue';
+
+import { reactive, watch } from 'vue';
+
+import { Loading } from '@vben/common-ui';
+
+import { Pagination } from 'ant-design-vue';
+
+import { ArticleApi } from '#/api';
+import { BcListItem } from '#/components/bc-list';
+import { $t } from '#/locales';
+import { useWebStore } from '#/store';
+/**
+ * Banner
+ */
+defineOptions({
+  name: 'ListPage',
+});
+
+const props = defineProps({
+  channelId: {
+    type: Number as PropType<number>,
+    default: 0,
+  },
+  pageSize: {
+    type: Number as PropType<number>,
+    default: 9,
+  },
+  typeId: {
+    type: Number as PropType<number>,
+    default: 0,
+  },
+  href: {
+    type: String as PropType<string>,
+    default: '',
+  },
+});
+const webSite = useWebStore();
+
+const state = reactive<{
+  listData: ArticleApi.ListItem[];
+  loading: boolean;
+  total: number;
+  totalPages: number;
+}>({
+  listData: [],
+  loading: false,
+  total: 0,
+  totalPages: 0,
+});
+
+const searchInfo = reactive<{
+  pageIndex: number;
+  pageSize: number;
+}>({
+  pageIndex: 1,
+  pageSize: props.pageSize,
+});
+
+const fetch = async () => {
+  try {
+    state.loading = true;
+    const { items, total, totalPages } = await ArticleApi.getPage({
+      ...searchInfo,
+      siteId: webSite.config?.id ?? 0,
+      channelId: props.channelId,
+      typeId: props.typeId,
+    });
+    state.listData = items;
+    state.total = total;
+    state.totalPages = totalPages;
+  } finally {
+    state.loading = false;
+  }
+};
+
+const handelPageChange = async (pageIndex: number) => {
+  searchInfo.pageIndex = pageIndex;
+  await fetch();
+};
+
+watch(
+  () => props.typeId,
+  (val) => {
+    if (val > 0) {
+      searchInfo.pageIndex = 1;
+      fetch();
+    }
+  },
+  { deep: true },
+);
+
+defineExpose({ loadData: fetch });
+</script>
+<template>
+  <Loading
+    class="w-full"
+    :spinning="state.loading"
+    :text="$t('page.common.loading')"
+  >
+    <div class="grid grid-cols-3 gap-4">
+      <BcListItem
+        v-for="item in state.listData"
+        :key="item.id"
+        :href="href"
+        :item="item"
+      />
+    </div>
+    <div class="mt-8 flex justify-center" v-if="state.totalPages > 1">
+      <Pagination
+        v-model:current="searchInfo.pageIndex"
+        :total="state.total"
+        @change="handelPageChange"
+      />
+    </div>
+  </Loading>
+</template>

+ 133 - 0
apps/baicai-cms/src/views/default/hardware/components/menu.vue

@@ -0,0 +1,133 @@
+<script lang="ts" setup>
+import type { PropType } from 'vue';
+
+import type { BasicTreeOptionResult } from '#/api/model';
+
+import { onMounted, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
+
+import { Loading } from '@vben/common-ui';
+
+import { cn } from '@vben-core/shared/utils';
+
+import { ArticleApi, SiteApi } from '#/api';
+import { useLazyLoad } from '#/components/useLazyLoad';
+import { $t } from '#/locales';
+import { useWebStore } from '#/store';
+
+defineProps({
+  channelInfo: {
+    type: Object as PropType<SiteApi.SiteChannelItem>,
+    default: () => ({}),
+  },
+});
+
+const emit = defineEmits(['click']);
+
+const webSite = useWebStore();
+
+const route = useRoute();
+
+const listRef = ref<HTMLDivElement | null>(null);
+const { createObserver } = useLazyLoad<HTMLDivElement>();
+
+const handleClick = (item: BasicTreeOptionResult) => {
+  state.typeId = item.value;
+  emit('click', { ...item });
+};
+
+const state = reactive<{
+  channelId: number;
+  listData: BasicTreeOptionResult[];
+  loading: boolean;
+  typeId: boolean | number | string | undefined;
+}>({
+  listData: [],
+  loading: false,
+  channelId: Number(route.query.channelId ?? 0),
+  typeId: '',
+});
+
+const fetch = async () => {
+  try {
+    state.loading = true;
+    state.listData = await ArticleApi.getTypeOptions({
+      siteId: webSite.config?.id ?? 0,
+      channelId: state.channelId,
+    });
+    if (state.listData.length > 0) {
+      state.typeId = state.listData[0]?.value;
+      emit('click', { ...state.listData[0] });
+    }
+  } finally {
+    state.loading = false;
+  }
+};
+
+onMounted(async () => {
+  if (listRef.value) {
+    createObserver(listRef.value, () => fetch());
+  }
+});
+</script>
+
+<template>
+  <Loading :spinning="state.loading" :text="$t('page.common.loading')">
+    <div
+      class="bg-background shadow-primary-200 dark:shadow-heavy max-w-full rounded shadow-md"
+    >
+      <ul class="divide-primary-100 dark:divide-border divide-y" ref="listRef">
+        <li
+          class="bg-primary-400 items-content dark:bg-primary/50 flex gap-4 px-4 py-3 font-bold"
+        >
+          <div class="flex items-center text-white">
+            <svg
+              xmlns="http://www.w3.org/2000/svg"
+              fill="none"
+              viewBox="0 0 24 24"
+              stroke-width="1.5"
+              stroke="currentColor"
+              class="h-6 w-6"
+              aria-label="Dashboard icon"
+              role="graphics-symbol"
+            >
+              <path
+                stroke-linecap="round"
+                stroke-linejoin="round"
+                d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75"
+              />
+            </svg>
+          </div>
+          <div
+            class="flex min-h-[2rem] w-full min-w-0 flex-col items-start justify-center gap-0"
+          >
+            <h4 class="text-base text-white">{{ channelInfo.title }}</h4>
+          </div>
+        </li>
+        <li
+          class="flex cursor-pointer items-start gap-4 px-4 py-3"
+          v-for="(item, index) in state.listData"
+          :key="index"
+          :class="
+            cn(
+              state.typeId === item.value
+                ? 'bg-primary/30 text-primary-700 dark:text-primary'
+                : 'dark:text-foreground text-slate-700',
+              'hover:bg-primary/10 hover:text-primary-600',
+            )
+          "
+          @click="handleClick(item)"
+        >
+          <a
+            class="flex min-h-[2rem] w-full min-w-0 flex-col items-start justify-center gap-0"
+            href="#"
+          >
+            <h4 class="text-base">
+              {{ item.label }}
+            </h4>
+          </a>
+        </li>
+      </ul>
+    </div>
+  </Loading>
+</template>

+ 6 - 0
apps/baicai-cms/src/views/default/hardware/detail/index.vue

@@ -0,0 +1,6 @@
+<script lang="ts" setup>
+import DetailIndex from '../../software/detail/index.vue';
+</script>
+<template>
+  <DetailIndex />
+</template>

+ 66 - 0
apps/baicai-cms/src/views/default/hardware/list/index.vue

@@ -0,0 +1,66 @@
+<script setup lang="ts">
+import type { BasicTreeOptionResult } from '#/api/model';
+
+import { onMounted, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
+
+import { ArticleApi, SiteApi } from '#/api';
+import { ArticleListPage, DetailBanner } from '#/components/article';
+import { BcWrap } from '#/components/bc-wrap';
+
+import LeftMenu from '../components/menu.vue';
+
+const route = useRoute();
+
+const state = reactive<{
+  channelId: number;
+  channelInfo: SiteApi.SiteChannelItem;
+  dataList: ArticleApi.ListItem[];
+  loading: boolean;
+  typeId: number;
+}>({
+  channelId: Number(route.query.channelId ?? 0),
+  channelInfo: {} as SiteApi.SiteChannelItem,
+  dataList: [],
+  loading: false,
+  typeId: 0,
+});
+
+const listPageRef = ref<any | null>(null);
+
+const handleClick = (item: BasicTreeOptionResult) => {
+  state.typeId = Number(item.value);
+};
+
+onMounted(async () => {
+  try {
+    state.loading = true;
+    state.channelInfo = await SiteApi.getChannel({ id: state.channelId });
+  } finally {
+    state.loading = false;
+  }
+});
+</script>
+
+<template>
+  <BcWrap :full="true">
+    <DetailBanner channel-code="other" article-code="software-banner" />
+    <BcWrap :full="false" class="my-12 w-full">
+      <div class="flex w-full">
+        <LeftMenu
+          :channel-info="state.channelInfo"
+          class="w-80"
+          @click="handleClick"
+        />
+        <div class="ml-8 flex-1">
+          <ArticleListPage
+            ref="listPageRef"
+            :channel-id="state.channelId"
+            :type-id="state.typeId"
+            href="/hardware/detail"
+          />
+        </div>
+      </div>
+    </BcWrap>
+  </BcWrap>
+</template>

+ 8 - 14
apps/baicai-cms/src/views/default/software/components/menu.vue

@@ -18,10 +18,12 @@ defineProps({
     type: Object as PropType<SiteApi.SiteChannelItem>,
     default: () => ({}),
   },
+  href: {
+    type: String as PropType<string>,
+    default: '',
+  },
 });
 
-const emit = defineEmits(['click']);
-
 const webSite = useWebStore();
 
 const route = useRoute();
@@ -29,11 +31,6 @@ const route = useRoute();
 const listRef = ref<HTMLDivElement | null>(null);
 const { createObserver } = useLazyLoad<HTMLDivElement>();
 
-const handleClick = (item: ArticleApi.ListItem) => {
-  state.typeId = item.id;
-  emit('click', { ...item });
-};
-
 const state = reactive<{
   channelId: number;
   listData: ArticleApi.ListItem[];
@@ -55,10 +52,6 @@ const fetch = async () => {
       typeId: 0,
       top: 0,
     });
-    if (state.listData.length > 0) {
-      state.typeId = state.listData[0]?.id;
-      emit('click', { ...state.listData[0] });
-    }
   } finally {
     state.loading = false;
   }
@@ -116,15 +109,16 @@ onMounted(async () => {
               'hover:bg-primary/10 hover:text-primary-600',
             )
           "
-          @click="handleClick(item)"
         >
-          <div
+          <a
             class="flex min-h-[2rem] w-full min-w-0 flex-col items-start justify-center gap-0"
+            :href="`${href}?id=${item.id}`"
+            target="_blank"
           >
             <h4 class="text-base">
               {{ item.title }}
             </h4>
-          </div>
+          </a>
         </li>
       </ul>
     </div>

+ 4 - 1
apps/baicai-cms/src/views/default/software/detail/index.vue

@@ -47,7 +47,10 @@ onMounted(async () => {
           :spinning="state.loading"
           :text="$t('page.common.loading')"
         >
-          <div v-if="state.dataInfo.content"></div>
+          <div
+            v-if="state.dataInfo.content"
+            v-dompurify-html="state.dataInfo.content"
+          ></div>
           <div v-else>
             <Fallback status="coming-soon" />
           </div>

+ 14 - 31
apps/baicai-cms/src/views/default/software/list/index.vue

@@ -1,19 +1,14 @@
 <script setup lang="ts">
-import { onMounted, reactive } from 'vue';
+import { onMounted, reactive, ref } from 'vue';
 import { useRoute } from 'vue-router';
 
-import { Loading } from '@vben/common-ui';
-
 import { ArticleApi, SiteApi } from '#/api';
-import { DetailBanner } from '#/components/article';
-import { BcListItem } from '#/components/bc-list';
+import { ArticleListPage, DetailBanner } from '#/components/article';
 import { BcWrap } from '#/components/bc-wrap';
-import { useWebStore } from '#/store';
 
 import LeftMenu from '../components/menu.vue';
 
 const route = useRoute();
-const webSite = useWebStore();
 
 const state = reactive<{
   channelId: number;
@@ -27,21 +22,14 @@ const state = reactive<{
   loading: false,
 });
 
-// const handleClick = (item: ArticleApi.ListItem) => {};
+const listPageRef = ref<any | null>(null);
 
 onMounted(async () => {
   try {
     state.loading = true;
     state.channelInfo = await SiteApi.getChannel({ id: state.channelId });
-    const data = await ArticleApi.getPage({
-      pageIndex: 1,
-      pageSize: 10,
-      siteId: webSite.config?.id ?? 0,
-      channelId: state.channelId,
-      typeId: 0,
-    });
 
-    state.dataList = data.items;
+    listPageRef.value?.loadData();
   } finally {
     state.loading = false;
   }
@@ -53,22 +41,17 @@ onMounted(async () => {
     <DetailBanner channel-code="other" article-code="software-banner" />
     <BcWrap :full="false" class="my-12 w-full">
       <div class="flex w-full">
-        <LeftMenu :channel-info="state.channelInfo" class="w-80" />
+        <LeftMenu
+          :channel-info="state.channelInfo"
+          class="w-80"
+          href="/software/detail"
+        />
         <div class="ml-8 flex-1">
-          <Loading
-            class="w-full"
-            :spinning="state.loading"
-            :text="$t('page.common.loading')"
-          >
-            <div class="grid grid-cols-3 gap-4">
-              <BcListItem
-                v-for="item in state.dataList"
-                :key="item.id"
-                href="/software/detail"
-                :item="item"
-              />
-            </div>
-          </Loading>
+          <ArticleListPage
+            ref="listPageRef"
+            :channel-id="state.channelId"
+            href="/software/detail"
+          />
         </div>
       </div>
     </BcWrap>

+ 3 - 3
apps/web-baicai/src/views/cms/article/list/index.vue

@@ -5,9 +5,9 @@ import { onMounted, reactive, ref, unref } from 'vue';
 import { useRoute } from 'vue-router';
 
 import { AccessControl } from '@vben/access';
-import { alert, Fallback, Page, useVbenModal } from '@vben/common-ui';
+import { Fallback, Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsArticleApi, CmsSiteChannelApi } from '#/api';
@@ -40,7 +40,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsArticleApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/cms/article/type/index.vue

@@ -5,9 +5,9 @@ import { onMounted, reactive, ref, unref } from 'vue';
 import { useRoute } from 'vue-router';
 
 import { AccessControl } from '@vben/access';
-import { alert, Fallback, Page, useVbenModal } from '@vben/common-ui';
+import { Fallback, Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsArticleTypeApi, CmsSiteChannelApi } from '#/api';
@@ -40,7 +40,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsArticleTypeApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/cms/site/channel/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsSiteChannelApi } from '#/api';
@@ -25,7 +25,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsSiteChannelApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/cms/site/channelField/index.vue

@@ -3,9 +3,9 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
 import { computed, nextTick, reactive, ref, unref } from 'vue';
 
-import { alert, useVbenModal } from '@vben/common-ui';
+import { useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsSiteChannelFieldApi } from '#/api';
@@ -29,7 +29,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsSiteChannelFieldApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/cms/site/domain/index.vue

@@ -3,9 +3,9 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
 import { computed, nextTick, reactive, ref, unref } from 'vue';
 
-import { alert, useVbenModal } from '@vben/common-ui';
+import { useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsSiteDomainApi } from '#/api';
@@ -29,7 +29,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsSiteDomainApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/cms/site/info/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsSiteApi } from '#/api';
@@ -29,7 +29,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await CmsSiteApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 1 - 0
apps/web-baicai/src/views/cms/site/menu/components/edit.vue

@@ -28,6 +28,7 @@ const [Form, formApi] = useVbenForm(
 
 const [Drawer, { close, getData, lock, unlock }] = useVbenDrawer({
   closeOnClickModal: false,
+  destroyOnClose: true,
   onCancel() {
     close();
   },

+ 3 - 3
apps/web-baicai/src/views/cms/site/menu/index.vue

@@ -3,10 +3,10 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/';
 
 import { computed, nextTick, reactive, ref, unref } from 'vue';
 
-import { alert, useVbenDrawer, useVbenModal } from '@vben/common-ui';
+import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
 import { IconifyIcon } from '@vben/icons';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { CmsSiteMenuApi } from '#/api';
@@ -27,7 +27,7 @@ const handelSuccess = () => {
 
 const handleDelete = async (id: number) => {
   await CmsSiteMenuApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/plugins/template/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { PluginsTemplateApi } from '#/api';
@@ -21,7 +21,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await PluginsTemplateApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/config/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { ConfigApi } from '#/api';
@@ -21,7 +21,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await ConfigApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/department/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { DepartmentApi } from '#/api';
@@ -20,7 +20,7 @@ const handelSuccess = () => {
 
 const handleDelete = async (id: number) => {
   await DepartmentApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 4 - 34
apps/web-baicai/src/views/system/design/database/index.vue

@@ -1,33 +1,29 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { useAccess } from '@vben/access';
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { DatabaseApi } from '#/api';
-import { TableAction } from '#/components/table-action';
 
 import FormEdit from './components/edit.vue';
 import { useColumns, useSearchSchema } from './data.config';
 
-const { hasAccessByCodes } = useAccess();
-
 const [FormEditModal, formEditApi] = useVbenModal({
   connectedComponent: FormEdit,
 });
 
 const handleDelete = async (id: number) => {
   await DatabaseApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 
 const handelCreate = async (id: number) => {
   await DatabaseApi.getCreate(id);
-  alert('创建表成功');
+  message.success('创建表成功');
   reload();
 };
 
@@ -101,32 +97,6 @@ const [Grid, { reload }] = useVbenVxeGrid(
           新增表
         </Button>
       </template>
-      <template #action="{ row }">
-        <TableAction
-          :actions="[
-            {
-              label: '编辑',
-              type: 'text',
-              disabled: !hasAccessByCodes(['table:edit']),
-              onClick: handleEdit.bind(null, row, true),
-            },
-            {
-              label: '创建表',
-              type: 'text',
-              disabled: !hasAccessByCodes(['table:create']),
-              onClick: handelCreate.bind(null, row.id),
-            },
-          ]"
-          :drop-down-actions="[
-            {
-              label: '删除',
-              type: 'link',
-              disabled: !hasAccessByCodes(['table:delete']),
-              onClick: handleDelete.bind(null, row.id),
-            },
-          ]"
-        />
-      </template>
     </Grid>
   </Page>
 </template>

+ 3 - 3
apps/web-baicai/src/views/system/design/query/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { QueryApi } from '#/api';
@@ -21,7 +21,7 @@ const [FormViewModal, formViewApi] = useVbenModal({
 });
 const handleDelete = async (id: number) => {
   await QueryApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/design/table/index.vue

@@ -3,9 +3,9 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
 import { useRouter } from 'vue-router';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { TableApi } from '#/api';
@@ -31,7 +31,7 @@ const [FormPreviewModal, formPreviewApi] = useVbenModal({
 
 const handleDelete = async (id: number) => {
   await TableApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 2 - 2
apps/web-baicai/src/views/system/dict/item/index.vue

@@ -7,7 +7,7 @@ import { watch } from 'vue';
 
 import { alert, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { DictionaryApi } from '#/api';
@@ -36,7 +36,7 @@ const handelSuccess = () => {
 
 const handleDelete = async (id: number) => {
   await DictionaryApi.deleteItemDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/dict/type/index.vue

@@ -5,9 +5,9 @@ import type {
   VxeTableGridOptions,
 } from '#/adapter';
 
-import { alert, useVbenModal } from '@vben/common-ui';
+import { useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { DictionaryApi } from '#/api';
@@ -30,7 +30,7 @@ const handelSuccess = () => {
 
 const handleDelete = async (id: number) => {
   await DictionaryApi.deleteTypeDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/log/difference/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { VxeTableGridOptions } from '#/adapter';
 
-import { alert, confirm, Page } from '@vben/common-ui';
+import { confirm, Page } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { LogApi } from '#/api';
@@ -41,7 +41,7 @@ const handelClear = () => {
     beforeClose: async ({ isConfirm }: { isConfirm: boolean }) => {
       if (isConfirm) {
         await LogApi.clearLog('logdifference');
-        alert('数据删除成功');
+        message.success('数据删除成功');
         reload();
         return true;
       } else return false;

+ 3 - 3
apps/web-baicai/src/views/system/log/exception/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, confirm, Page, useVbenModal } from '@vben/common-ui';
+import { confirm, Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { LogApi } from '#/api';
@@ -67,7 +67,7 @@ const handelClear = () => {
     beforeClose: async ({ isConfirm }: { isConfirm: boolean }) => {
       if (isConfirm) {
         await LogApi.clearLog('logException');
-        alert('数据删除成功');
+        message.success('数据删除成功');
         reload();
         return true;
       } else return false;

+ 3 - 3
apps/web-baicai/src/views/system/log/operate/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, confirm, Page, useVbenModal } from '@vben/common-ui';
+import { confirm, Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { LogApi } from '#/api';
@@ -64,7 +64,7 @@ const handelClear = () => {
     beforeClose: async ({ isConfirm }: { isConfirm: boolean }) => {
       if (isConfirm) {
         await LogApi.clearLog('logOperate');
-        alert('数据删除成功');
+        message.success('数据删除成功');
         reload();
         return true;
       } else return false;

+ 3 - 3
apps/web-baicai/src/views/system/log/visit/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { VxeTableGridOptions } from '#/adapter';
 
-import { alert, confirm, Page } from '@vben/common-ui';
+import { confirm, Page } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { LogApi } from '#/api';
@@ -42,7 +42,7 @@ const handelClear = () => {
     beforeClose: async ({ isConfirm }: { isConfirm: boolean }) => {
       if (isConfirm) {
         await LogApi.clearLog('logVisit');
-        alert('数据删除成功');
+        message.success('数据删除成功');
         reload();
         return true;
       } else return false;

+ 3 - 3
apps/web-baicai/src/views/system/menu/index.vue

@@ -1,10 +1,10 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/';
 
-import { alert, Page, useVbenDrawer } from '@vben/common-ui';
+import { Page, useVbenDrawer } from '@vben/common-ui';
 import { IconifyIcon } from '@vben/icons';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { MenuApi } from '#/api';
@@ -22,7 +22,7 @@ const handelSuccess = () => {
 
 const handleDelete = async (id: number) => {
   await MenuApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/post/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { PostApi } from '#/api';
@@ -20,7 +20,7 @@ const handelSuccess = () => {
 };
 const handleDelete = async (id: number) => {
   await PostApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   handelSuccess();
 };
 

+ 2 - 2
apps/web-baicai/src/views/system/role/index.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
 
 import { Button, message } from 'ant-design-vue';
 
@@ -15,7 +15,7 @@ import { useColumns, useSearchSchema } from './data.config';
 
 const handleDelete = async (id: number) => {
   await RoleApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 const handleActionClick = async ({

+ 4 - 4
apps/web-baicai/src/views/system/tenant/index.vue

@@ -1,9 +1,9 @@
 <script lang="ts" setup>
 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
-import { alert, Page, useVbenModal } from '@vben/common-ui';
+import { Page, useVbenModal } from '@vben/common-ui';
 
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
 
 import { useTableGridOptions, useVbenVxeGrid } from '#/adapter';
 import { TenantApi } from '#/api';
@@ -17,12 +17,12 @@ const [FormEditModal, formEditApi] = useVbenModal({
 
 const handleCreateDb = async (id: number) => {
   await TenantApi.createDb(id);
-  alert('创建/更新租户数据库成功');
+  message.success('创建/更新租户数据库成功');
 };
 
 const handleDelete = async (id: number) => {
   await TenantApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 3 - 3
apps/web-baicai/src/views/system/user/index.vue

@@ -3,7 +3,7 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter';
 
 import { reactive } from 'vue';
 
-import { alert, BcPage, confirm, useVbenModal } from '@vben/common-ui';
+import { BcPage, confirm, useVbenModal } from '@vben/common-ui';
 
 import { useClipboard } from '@vueuse/core';
 import { Button, message } from 'ant-design-vue';
@@ -36,7 +36,7 @@ const handelResetPassword = async (id: number) => {
     beforeClose: ({ isConfirm }: { isConfirm: boolean }) => {
       if (isConfirm) {
         copy(data);
-        alert('密码复制成功!');
+        message.success('密码复制成功!');
       }
       return true;
     },
@@ -45,7 +45,7 @@ const handelResetPassword = async (id: number) => {
 
 const handleDelete = async (id: number) => {
   await UserApi.deleteDetail(id);
-  alert('数据删除成功');
+  message.success('数据删除成功');
   reload();
 };
 

+ 20 - 0
pnpm-lock.yaml

@@ -731,6 +731,9 @@ importers:
       vue:
         specifier: ^3.5.13
         version: 3.5.13(typescript@5.8.3)
+      vue-dompurify-html:
+        specifier: ^5.3.0
+        version: 5.3.0(vue@3.5.13(typescript@5.8.3))
       vue-router:
         specifier: 'catalog:'
         version: 4.5.1(vue@3.5.13(typescript@5.8.3))
@@ -6617,6 +6620,9 @@ packages:
     resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
     engines: {node: '>= 4'}
 
+  dompurify@3.2.6:
+    resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==}
+
   domutils@2.8.0:
     resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
 
@@ -11449,6 +11455,11 @@ packages:
       '@vue/composition-api':
         optional: true
 
+  vue-dompurify-html@5.3.0:
+    resolution: {integrity: sha512-HJQGBHbfSPcb6Mu97McdKbX7TqRHZa6Ji8OCpCNyuHca5QvQZ8IiuwghFPSO8OkSQfqXPNPKFMZdCOrnGGmOSQ==}
+    peerDependencies:
+      vue: ^3.5.13
+
   vue-eslint-parser@10.1.3:
     resolution: {integrity: sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -16959,6 +16970,10 @@ snapshots:
     dependencies:
       domelementtype: 2.3.0
 
+  dompurify@3.2.6:
+    optionalDependencies:
+      '@types/trusted-types': 2.0.7
+
   domutils@2.8.0:
     dependencies:
       dom-serializer: 1.4.1
@@ -22328,6 +22343,11 @@ snapshots:
     dependencies:
       vue: 3.5.13(typescript@5.8.3)
 
+  vue-dompurify-html@5.3.0(vue@3.5.13(typescript@5.8.3)):
+    dependencies:
+      dompurify: 3.2.6
+      vue: 3.5.13(typescript@5.8.3)
+
   vue-eslint-parser@10.1.3(eslint@9.26.0(jiti@2.4.2)):
     dependencies:
       debug: 4.4.0