新增推广横幅组件,并在用户管理页面中集成,展示官方教程链接和相关信息,同时添加新的图片资源。

This commit is contained in:
Chuck1sn
2025-06-25 12:10:53 +08:00
parent 8ffa4324d3
commit 76b77dbf18
3 changed files with 69 additions and 15 deletions

BIN
frontend/public/ai-tdd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

View File

@@ -0,0 +1,45 @@
<template>
<div class="flex justify-center items-center my-4">
<a class="group relative w-full sm:w-2/3 md:w-1/2 lg:w-2/5 xl:w-1/3 max-w-xs overflow-hidden rounded-lg border border-gray-200 shadow-lg transition-all duration-300 hover:shadow-xl hover:scale-[1.02]"
:href="href" target="_blank">
<div class="absolute top-0 right-0 bg-blue-600 text-white text-xs px-2 py-1 rounded-bl-lg z-10">{{ label }}</div>
<img :src="imageSrc" :alt="imageAlt"
class="w-full h-auto transition-transform duration-500 group-hover:scale-105">
<div
class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-3 transform transition-all duration-300">
<span class="text-white text-sm font-medium group-hover:underline flex items-center">
{{ text }}
<svg class="w-4 h-4 ml-1 transition-transform duration-300 group-hover:translate-x-1" fill="none"
stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</span>
</div>
</a>
</div>
</template>
<script setup lang="ts">
defineProps({
href: {
type: String,
required: true
},
imageSrc: {
type: String,
required: true
},
imageAlt: {
type: String,
default: 'promotion'
},
label: {
type: String,
default: '官方教程'
},
text: {
type: String,
required: true
}
});
</script>

View File

@@ -1,5 +1,7 @@
<template> <template>
<div class="px-2 sm:px-4 pt-6 sm:rounded-lg"> <div class="px-2 sm:px-4 pt-6 sm:rounded-lg">
<PromotionBanner href="https://www.bilibili.com/cheese/play/ss198449120" imageSrc="/ai-tdd.png"
imageAlt="ai-tdd-tutorial" label="官方教程" text="无幻觉式 AI 编程方法论" />
<div class="mb-4"> <div class="mb-4">
<Breadcrumbs :names="['用户管理']" /> <Breadcrumbs :names="['用户管理']" />
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">用户管理</h1> <h1 class="text-xl font-semibold text-gray-900 sm:text-2xl">用户管理</h1>
@@ -159,6 +161,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { components } from "@/api/types/schema"; import type { components } from "@/api/types/schema";
import PromotionBanner from "@/components/common/PromotionBanner.vue";
import { PlusIcon } from "@/components/icons"; import { PlusIcon } from "@/components/icons";
import Breadcrumbs from "@/components/layout/Breadcrumbs.vue"; import Breadcrumbs from "@/components/layout/Breadcrumbs.vue";
import ConfirmationDialog from "@/components/modals/ConfirmationDialog.vue"; import ConfirmationDialog from "@/components/modals/ConfirmationDialog.vue";
@@ -290,31 +293,37 @@ const handleUpsertUserClick = async (
const handleBindRoleClick = async ( const handleBindRoleClick = async (
user: components["schemas"]["UserRolePermissionDto"], user: components["schemas"]["UserRolePermissionDto"],
) => { ) => {
router.push( if (user.id) {
Routes.BINDROLEVIEW.withParams({ router.push(
userId: user.id!, Routes.BINDROLEVIEW.withParams({
}), userId: user.id,
); }),
);
}
}; };
const handleBindDepartmentClick = async ( const handleBindDepartmentClick = async (
user: components["schemas"]["UserRolePermissionDto"], user: components["schemas"]["UserRolePermissionDto"],
) => { ) => {
router.push( if (user.id) {
Routes.BINDDEPARTMENTVIEW.withParams({ router.push(
userId: user.id!, Routes.BINDDEPARTMENTVIEW.withParams({
}), userId: user.id,
); }),
);
}
}; };
const handleBindPositionClick = async ( const handleBindPositionClick = async (
user: components["schemas"]["UserRolePermissionDto"], user: components["schemas"]["UserRolePermissionDto"],
) => { ) => {
router.push( if (user.id) {
Routes.BINDPOSITIONVIEW.withParams({ router.push(
userId: user.id!, Routes.BINDPOSITIONVIEW.withParams({
}), userId: user.id,
); }),
);
}
}; };
const handleSortClick = async (field: string) => { const handleSortClick = async (field: string) => {