200 lines
4.9 KiB
Vue
200 lines
4.9 KiB
Vue
<template>
|
|
<div class="form-container">
|
|
<h1 class="page-title">{{ isEdit ? '编辑合作伙伴' : '新建合作伙伴' }}</h1>
|
|
|
|
<div class="form-card">
|
|
<form @submit.prevent="submitForm">
|
|
<div class="form-group">
|
|
<label class="form-label">名称</label>
|
|
<input type="text" v-model="formData.name" class="form-input" required placeholder="请输入合作伙伴名称">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Logo</label>
|
|
<ImageUpload
|
|
v-model="formData.logo"
|
|
:category-id="1"
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">官网链接</label>
|
|
<input type="text" v-model="formData.url" class="form-input" placeholder="https://...">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">描述</label>
|
|
<textarea v-model="formData.description" class="form-input" rows="4" placeholder="请输入描述"></textarea>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn-secondary" @click="router.back()">取消</button>
|
|
<button type="submit" class="btn-primary">{{ isEdit ? '保存修改' : '创建合作伙伴' }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useToast } from '../../composables/useToast'
|
|
import { createPartner, updatePartner, fetchPartners } from '../../services/api'
|
|
import ImageUpload from '../../components/admin/ImageUpload.vue'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const toast = useToast()
|
|
|
|
const isEdit = computed(() => !!route.params.id)
|
|
|
|
const formData = ref({
|
|
name: '',
|
|
logo: '',
|
|
url: '',
|
|
description: ''
|
|
})
|
|
|
|
const loadData = async () => {
|
|
if (!isEdit.value) return
|
|
|
|
try {
|
|
const id = parseInt(route.params.id as string)
|
|
// Same as testimonials, fetching list to find item
|
|
const list = await fetchPartners()
|
|
const item = list.find(p => p.id === id)
|
|
if (item) {
|
|
formData.value = {
|
|
name: item.name,
|
|
logo: item.logo,
|
|
url: item.url,
|
|
description: item.description
|
|
}
|
|
} else {
|
|
toast.error('未找到该合作伙伴')
|
|
router.push('/admin/partners')
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load partner:', error)
|
|
toast.error('加载数据失败')
|
|
}
|
|
}
|
|
|
|
const submitForm = async () => {
|
|
try {
|
|
if (isEdit.value) {
|
|
await updatePartner(parseInt(route.params.id as string), formData.value)
|
|
toast.success('更新成功')
|
|
} else {
|
|
await createPartner(formData.value)
|
|
toast.success('创建成功')
|
|
}
|
|
router.push('/admin/partners')
|
|
} catch (error: any) {
|
|
console.error('Failed to submit form:', error)
|
|
toast.error(error.message || '操作失败')
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadData()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.form-container {
|
|
width: 100%;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 1.75rem;
|
|
font-weight: 600;
|
|
color: #d4b383;
|
|
margin-bottom: 1.5rem;
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
.form-card {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
border-radius: 0.5rem;
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
padding: 2rem;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
max-width: 600px;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
font-size: 0.95rem;
|
|
font-weight: 500;
|
|
color: #d4b383;
|
|
margin-bottom: 0.5rem;
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
.form-input {
|
|
width: 100%;
|
|
padding: 0.75rem 1rem;
|
|
background: rgba(255, 255, 255, 0.08);
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
border-radius: 0.375rem;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
font-size: 0.95rem;
|
|
font-family: 'Inter', sans-serif;
|
|
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.form-input:focus {
|
|
outline: none;
|
|
border-color: #d4b383;
|
|
box-shadow: 0 0 0 3px rgba(212, 179, 131, 0.1);
|
|
}
|
|
|
|
.form-actions {
|
|
display: flex;
|
|
gap: 1rem;
|
|
justify-content: flex-end;
|
|
margin-top: 2rem;
|
|
}
|
|
|
|
.btn-primary, .btn-secondary {
|
|
padding: 0.625rem 1.25rem;
|
|
border-radius: 0.375rem;
|
|
cursor: pointer;
|
|
font-size: 0.95rem;
|
|
font-weight: 500;
|
|
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: rgba(212, 179, 131, 0.1);
|
|
border: 1px solid #d4b383;
|
|
color: #d4b383;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background: rgba(212, 179, 131, 0.2);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 16px rgba(212, 179, 131, 0.15);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background: rgba(255, 255, 255, 0.15);
|
|
transform: translateY(-2px);
|
|
}
|
|
</style> |