项目相关功能完善
This commit is contained in:
@@ -27,6 +27,6 @@
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.2",
|
||||
"sass": "^1.71.0",
|
||||
"vite": "^6.3.1"
|
||||
"vite": "6.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -16,7 +16,7 @@ importers:
|
||||
version: 7.0.1(vue@3.5.13)
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.4
|
||||
version: 4.1.4(vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))
|
||||
version: 4.1.4(vite@6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))
|
||||
'@vueuse/head':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(vue@3.5.13)
|
||||
@@ -53,13 +53,13 @@ importers:
|
||||
devDependencies:
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.3(vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))(vue@3.5.13)
|
||||
version: 5.2.3(vite@6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))(vue@3.5.13)
|
||||
sass:
|
||||
specifier: ^1.71.0
|
||||
version: 1.87.0
|
||||
vite:
|
||||
specifier: ^6.3.1
|
||||
version: 6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
specifier: 6.3.4
|
||||
version: 6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1231,8 +1231,8 @@ packages:
|
||||
unhead@1.11.20:
|
||||
resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==}
|
||||
|
||||
vite@6.3.3:
|
||||
resolution: {integrity: sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==}
|
||||
vite@6.3.4:
|
||||
resolution: {integrity: sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -1959,12 +1959,12 @@ snapshots:
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.4
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.1.4
|
||||
|
||||
'@tailwindcss/vite@4.1.4(vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))':
|
||||
'@tailwindcss/vite@4.1.4(vite@6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.1.4
|
||||
'@tailwindcss/oxide': 4.1.4
|
||||
tailwindcss: 4.1.4
|
||||
vite: 6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
vite: 6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
|
||||
'@types/estree@1.0.7': {}
|
||||
|
||||
@@ -2009,9 +2009,9 @@ snapshots:
|
||||
|
||||
'@vavt/util@2.1.0': {}
|
||||
|
||||
'@vitejs/plugin-vue@5.2.3(vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))(vue@3.5.13)':
|
||||
'@vitejs/plugin-vue@5.2.3(vite@6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0))(vue@3.5.13)':
|
||||
dependencies:
|
||||
vite: 6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
vite: 6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)
|
||||
vue: 3.5.13
|
||||
|
||||
'@vue/compiler-core@3.5.13':
|
||||
@@ -2558,7 +2558,7 @@ snapshots:
|
||||
'@unhead/shared': 1.11.20
|
||||
hookable: 5.5.3
|
||||
|
||||
vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0):
|
||||
vite@6.3.4(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.3
|
||||
fdir: 6.4.4(picomatch@4.0.2)
|
||||
|
||||
@@ -22,4 +22,7 @@ export function deleteProjectApi(credentials) {
|
||||
}
|
||||
export function changeContentProjectApi(credentials) {
|
||||
return post(`${prefix}/change-content`, credentials)
|
||||
}
|
||||
export function changeTypeProjectApi(credentials) {
|
||||
return post(`${prefix}/change-type`, credentials)
|
||||
}
|
||||
@@ -196,7 +196,7 @@ const navigateTo = (path) => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
/* 自定义样式 */
|
||||
.admin-layout {
|
||||
min-width: 100vh;
|
||||
@@ -207,4 +207,26 @@ const navigateTo = (path) => {
|
||||
button, a, [role="button"], .cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(156, 163, 175, 0.5);
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(156, 163, 175, 0.7);
|
||||
}
|
||||
|
||||
/* 暗黑模式滚动条 */
|
||||
.dark ::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(75, 85, 99, 0.5);
|
||||
}
|
||||
|
||||
.dark ::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(75, 85, 99, 0.7);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@ import {message, Upload, Select} from "ant-design-vue"
|
||||
import {labelOptionApi} from "@/api/request/label.js";
|
||||
import {categoryOptionApi} from "@/api/request/category.js";
|
||||
import {
|
||||
changeContentProjectApi,
|
||||
changeContentProjectApi, changeTypeProjectApi,
|
||||
createProjectApi,
|
||||
deleteProjectApi,
|
||||
projectDetailApi,
|
||||
@@ -562,6 +562,17 @@ const handleMdImageUpload = async (
|
||||
|
||||
callback(urls);
|
||||
};
|
||||
|
||||
const changeTypeProject = (id, type, index, feild) => {
|
||||
changeTypeProjectApi({
|
||||
id: id,
|
||||
type: type
|
||||
}).then((res) => {
|
||||
message.success("操作成功")
|
||||
console.log(paginatedData.value[index][feild])
|
||||
paginatedData.value[index][feild] = paginatedData.value[index][feild] === 1 ? 0 : 1
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -604,6 +615,18 @@ const handleMdImageUpload = async (
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||
价格
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||
出售
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||
精选
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||
轮播图
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
|
||||
状态
|
||||
@@ -625,7 +648,7 @@ const handleMdImageUpload = async (
|
||||
|
||||
<!-- 表格内容 -->
|
||||
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tr v-for="item in paginatedData" :key="item.id"
|
||||
<tr v-for="(item, index) in paginatedData" :key="item.id"
|
||||
class="hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
|
||||
<div class="flex items-center space-x-3">
|
||||
@@ -654,6 +677,45 @@ const handleMdImageUpload = async (
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
|
||||
{{ formatPrice(item.price) }}
|
||||
</td>
|
||||
<!-- 是否出售 -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span
|
||||
@click="changeTypeProject(item.id, 1, index, 'is_sold')"
|
||||
:class="`px-2 py-1 text-xs font-medium rounded-full ${
|
||||
item.is_sold === 1
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'
|
||||
: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'
|
||||
} cursor-pointer`"
|
||||
>
|
||||
{{ item.is_sold === 0 ? '非卖品' : '出售' }}
|
||||
</span>
|
||||
</td>
|
||||
<!-- 是否精选 -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span
|
||||
@click="changeTypeProject(item.id, 2, index, 'is_selected')"
|
||||
:class="`px-2 py-1 text-xs font-medium rounded-full ${
|
||||
item.is_selected === 1
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'
|
||||
: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'
|
||||
} cursor-pointer`"
|
||||
>
|
||||
{{ item.is_selected === 0 ? '否' : '是' }}
|
||||
</span>
|
||||
</td>
|
||||
<!-- 是否为轮播图 -->
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span
|
||||
@click="changeTypeProject(item.id, 3, index, 'is_carousel')"
|
||||
:class="`px-2 py-1 text-xs font-medium rounded-full ${
|
||||
item.is_carousel === 1
|
||||
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'
|
||||
: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'
|
||||
} cursor-pointer`"
|
||||
>
|
||||
{{ item.is_carousel === 0 ? '否' : '是' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span
|
||||
:class="`px-2 py-1 text-xs font-medium rounded-full ${
|
||||
@@ -662,7 +724,7 @@ const handleMdImageUpload = async (
|
||||
: item.status === 2
|
||||
? 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'
|
||||
: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
|
||||
}`"
|
||||
} cursor-pointer`"
|
||||
>
|
||||
{{ item.status_text }}
|
||||
</span>
|
||||
@@ -1251,6 +1313,7 @@ const handleMdImageUpload = async (
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目表单模态框 -->
|
||||
<div v-if="showContentModal" class="fixed inset-0 z-50 overflow-y-scroll" aria-labelledby="modal-title" role="dialog"
|
||||
aria-modal="true">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup>
|
||||
import { ref, onMounted,reactive, nextTick, inject } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue'
|
||||
import { Autoplay, Pagination, Navigation, EffectFade } from 'swiper/modules'
|
||||
import {ref, onMounted, reactive, nextTick, inject} from 'vue'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {Swiper, SwiperSlide} from 'swiper/vue'
|
||||
import {Autoplay, Pagination, Navigation, EffectFade} from 'swiper/modules'
|
||||
import AOS from 'aos'
|
||||
import 'aos/dist/aos.css'
|
||||
import 'swiper/css'
|
||||
@@ -14,7 +14,7 @@ import {DollarSign, User, X} from "lucide-vue-next";
|
||||
import {createCollectionApi, unCollectionApi} from "@/api/request/collection.js";
|
||||
import {message, Image} from "ant-design-vue";
|
||||
import {useUserStore} from "@/stores/user.js";
|
||||
import { MdPreview } from 'md-editor-v3';
|
||||
import {MdPreview} from 'md-editor-v3';
|
||||
import 'md-editor-v3/lib/style.css';
|
||||
|
||||
const route = useRoute()
|
||||
@@ -32,19 +32,19 @@ onMounted(() => {
|
||||
|
||||
// 分类数据
|
||||
const categories = [
|
||||
{ id: 1, name: 'Web应用', value: 'Web应用' },
|
||||
{ id: 2, name: '移动端', value: '移动端' },
|
||||
{ id: 3, name: '小程序', value: '小程序' },
|
||||
{ id: 4, name: '企业系统', value: '企业系统' }
|
||||
{id: 1, name: 'Web应用', value: 'Web应用'},
|
||||
{id: 2, name: '移动端', value: '移动端'},
|
||||
{id: 3, name: '小程序', value: '小程序'},
|
||||
{id: 4, name: '企业系统', value: '企业系统'}
|
||||
]
|
||||
|
||||
// 标签数据
|
||||
const allTags = [
|
||||
{ id: 1, name: 'Vue3' },
|
||||
{ id: 2, name: 'Node.js' },
|
||||
{ id: 3, name: 'TypeScript' },
|
||||
{ id: 4, name: 'MongoDB' },
|
||||
{ id: 5, name: 'Docker' }
|
||||
{id: 1, name: 'Vue3'},
|
||||
{id: 2, name: 'Node.js'},
|
||||
{id: 3, name: 'TypeScript'},
|
||||
{id: 4, name: 'MongoDB'},
|
||||
{id: 5, name: 'Docker'}
|
||||
]
|
||||
|
||||
const project = ref()
|
||||
@@ -97,7 +97,7 @@ const swiperOptions = {
|
||||
}
|
||||
|
||||
const formatPrice = (price) => {
|
||||
return '¥ ' + price.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
return '¥ ' + price.toLocaleString('zh-CN', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||
}
|
||||
|
||||
getDetail();
|
||||
@@ -165,7 +165,6 @@ const unCollection = () => {
|
||||
</h1>
|
||||
|
||||
|
||||
|
||||
<div class="max-w-3xl">
|
||||
<div class="flex flex-wrap gap-2 mb-3" data-aos="fade-up" data-aos-delay="200">
|
||||
<span
|
||||
@@ -250,9 +249,12 @@ const unCollection = () => {
|
||||
|
||||
<div>
|
||||
<h3 class="text-xl font-bold mb-4 text-gray-900 dark:text-white flex items-center">
|
||||
<span class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
|
||||
<span
|
||||
class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
|
||||
</svg>
|
||||
</span>
|
||||
技术栈
|
||||
@@ -273,9 +275,11 @@ const unCollection = () => {
|
||||
<li
|
||||
class="flex items-center bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3"
|
||||
>
|
||||
<div class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<div
|
||||
class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">前端技术栈: {{ project.front }}</span>
|
||||
@@ -283,9 +287,11 @@ const unCollection = () => {
|
||||
<li
|
||||
class="flex items-center bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3"
|
||||
>
|
||||
<div class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<div
|
||||
class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">后端技术栈: {{ project.service }}</span>
|
||||
@@ -293,9 +299,11 @@ const unCollection = () => {
|
||||
<li
|
||||
class="flex items-center bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3"
|
||||
>
|
||||
<div class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<div
|
||||
class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">部署架构: {{ project.deploy }}</span>
|
||||
@@ -305,9 +313,11 @@ const unCollection = () => {
|
||||
|
||||
<div>
|
||||
<h3 class="text-xl font-bold mb-4 text-gray-900 dark:text-white flex items-center">
|
||||
<span class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<span
|
||||
class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</span>
|
||||
核心功能
|
||||
@@ -318,9 +328,11 @@ const unCollection = () => {
|
||||
:key="index"
|
||||
class="flex items-start"
|
||||
>
|
||||
<div class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3 mt-0.5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||
<div
|
||||
class="flex-shrink-0 w-5 h-5 rounded-full bg-rose-100 dark:bg-rose-900/30 flex items-center justify-center text-rose-600 dark:text-rose-400 mr-3 mt-0.5">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ feature.name }}</span>
|
||||
@@ -330,14 +342,18 @@ const unCollection = () => {
|
||||
|
||||
<div>
|
||||
<h3 class="text-xl font-bold mb-4 text-gray-900 dark:text-white flex items-center">
|
||||
<span class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<span
|
||||
class="w-8 h-8 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-600 dark:text-rose-400 flex items-center justify-center mr-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
</span>
|
||||
项目描述
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 leading-relaxed" style="text-indent: 2em">{{ project.description }}</p>
|
||||
<p class="text-gray-600 dark:text-gray-300 leading-relaxed" style="text-indent: 2em">
|
||||
{{ project.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -389,18 +405,21 @@ const unCollection = () => {
|
||||
class="relative group rounded-xl overflow-hidden cursor-pointer"
|
||||
>
|
||||
|
||||
<div class=" text-center text-gray-500 dark:text-gray-400 items-center" style="margin: 200px auto;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
作者没有上传
|
||||
</div>
|
||||
<div class=" text-center text-gray-500 dark:text-gray-400 items-center" style="margin: 200px auto;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
作者没有上传
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="relative group rounded-xl overflow-hidden cursor-pointer"
|
||||
>
|
||||
<Image :src="project.module_image" class="w-full h-full object-cover transition-transform duration-300" />
|
||||
<Image :src="project.module_image"
|
||||
class="w-full h-full object-cover transition-transform duration-300"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="activeTab === '5'">
|
||||
@@ -410,8 +429,10 @@ const unCollection = () => {
|
||||
>
|
||||
|
||||
<div class=" text-center text-gray-500 dark:text-gray-400 items-center" style="margin: 200px auto;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
作者没有上传
|
||||
</div>
|
||||
@@ -420,7 +441,7 @@ const unCollection = () => {
|
||||
v-else
|
||||
class="relative group rounded-xl overflow-hidden cursor-pointer"
|
||||
>
|
||||
<Image :src="project.flowchart" class="w-full h-full object-cover transition-transform duration-300" />
|
||||
<Image :src="project.flowchart" class="w-full h-full object-cover transition-transform duration-300"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="activeTab === '6'">
|
||||
@@ -429,8 +450,10 @@ const unCollection = () => {
|
||||
class="relative group rounded-xl overflow-hidden cursor-pointer"
|
||||
>
|
||||
<div class=" text-center text-gray-500 dark:text-gray-400 items-center" style="margin: 200px auto;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-4 text-gray-400" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
作者没有上传
|
||||
</div>
|
||||
@@ -450,22 +473,33 @@ const unCollection = () => {
|
||||
<div>
|
||||
<div class="bg-white dark:bg-gray-800 rounded-3xl shadow-xl p-8 sticky top-8">
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-semibold text-white flex items-center">
|
||||
<DollarSign class="w-5 h-5 mr-1.5 text-rose-500"/>
|
||||
项目价格
|
||||
</h3>
|
||||
<!-- <p class="text-3xl font-bold text-rose-600 dark:text-rose-400">{{ formatPrice(project.price) }}</p>-->
|
||||
<div v-if="project.preferential_price" class="flex items-center text-3xl font-bold text-rose-600 dark:text-rose-400">
|
||||
<!-- <p class="text-3xl font-bold text-rose-600 dark:text-rose-400">{{ formatPrice(project.price) }}</p>-->
|
||||
<div v-if="project.is_sold === 1">
|
||||
|
||||
<h3 class="text-lg font-semibold text-white flex items-center">
|
||||
<DollarSign class="w-5 h-5 mr-1.5 text-rose-500"/>
|
||||
项目价格
|
||||
</h3>
|
||||
<div v-if="project.preferential_price"
|
||||
class="flex items-center text-3xl font-bold text-rose-600 dark:text-rose-400">
|
||||
<span class="text-2xl font-bold text-rose-400">
|
||||
{{ formatPrice(project.preferential_price) }}
|
||||
</span>
|
||||
<span v-if="project.preferential_price !== project.price" class="ml-2 text-sm text-gray-400 line-through">
|
||||
<span v-if="project.preferential_price !== project.price"
|
||||
class="ml-2 text-sm text-gray-400 line-through">
|
||||
{{ formatPrice(project.price) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-else class="text-2xl font-bold text-white">
|
||||
{{ formatPrice(project.price) }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h3 class="text-lg font-semibold text-gray-600 flex items-center line-through">
|
||||
<DollarSign class="w-5 h-5 mr-1.5 text-rose-500"/>
|
||||
非卖品
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
@@ -489,19 +523,30 @@ const unCollection = () => {
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<button class="w-full py-3 bg-rose-600 hover:bg-rose-700 text-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<button v-if="project.is_sold === 1" :disabled="true"
|
||||
class="w-full py-3 bg-rose-600 hover:bg-rose-700 text-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<span>立即咨询</span>
|
||||
</button>
|
||||
<button v-else
|
||||
class="w-full py-3 bg-rose-600 hover:bg-rose-700 text-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<span>立即咨询</span>
|
||||
</button>
|
||||
|
||||
<button v-if="project.is_collection === false" @click="collection" class="w-full py-3 bg-white dark:bg-gray-700 text-rose-600 dark:text-rose-400 border border-rose-200 dark:border-rose-800/30 rounded-xl shadow-md hover:shadow-lg transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||
<button v-if="project.is_collection === false" @click="collection"
|
||||
class="w-full py-3 bg-white dark:bg-gray-700 text-rose-600 dark:text-rose-400 border border-rose-200 dark:border-rose-800/30 rounded-xl shadow-md hover:shadow-lg transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"/>
|
||||
</svg>
|
||||
<span>收藏项目</span>
|
||||
</button>
|
||||
<button v-else @click="unCollection" class="w-full py-3 bg-rose-600 hover:bg-rose-700 text-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="gold" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||
<button v-else @click="unCollection"
|
||||
class="w-full py-3 bg-rose-600 hover:bg-rose-700 text-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 flex items-center justify-center cursor-pointer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="gold" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"/>
|
||||
</svg>
|
||||
<span>取消收藏</span>
|
||||
</button>
|
||||
@@ -526,7 +571,8 @@ const unCollection = () => {
|
||||
<h2 class="text-2xl md:text-3xl font-bold mb-8 text-gray-900 dark:text-white">
|
||||
<span class="relative">
|
||||
相关项目
|
||||
<span class="absolute -bottom-2 left-0 w-1/4 h-1 bg-gradient-to-r from-rose-400 to-rose-600 rounded-full"></span>
|
||||
<span
|
||||
class="absolute -bottom-2 left-0 w-1/4 h-1 bg-gradient-to-r from-rose-400 to-rose-600 rounded-full"></span>
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
@@ -543,7 +589,8 @@ const unCollection = () => {
|
||||
class="w-full h-full object-cover transform transition-transform duration-700 group-hover:scale-110"
|
||||
:alt="related.title"
|
||||
/>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
||||
<div
|
||||
class="absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
@@ -564,8 +611,9 @@ const unCollection = () => {
|
||||
<div class="flex justify-between items-center">
|
||||
<p class="font-bold text-rose-600 dark:text-rose-400">{{ formatPrice(related.price) }}</p>
|
||||
<button class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -629,6 +677,7 @@ const unCollection = () => {
|
||||
background: linear-gradient(135deg, #1a1d23 0%, #111827 100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* 自定义样式 */
|
||||
.cursor-grab {
|
||||
cursor: grab;
|
||||
|
||||
Reference in New Issue
Block a user