小说网站前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

303 lines
9.9 KiB

<template>
<div class="create-work-container">
<div class="create-work-content">
<h2 class="page-title">创建新作品</h2>
<div class="form-container">
<el-form :model="workForm" :rules="rules" ref="workFormRef" label-position="top">
<el-form-item label="作品名称" prop="title">
<el-input v-model="workForm.title" placeholder="请输入作品名称"></el-input>
</el-form-item>
<el-form-item label="作品分类" prop="category">
<el-select v-model="workForm.category" placeholder="请选择分类">
<el-option v-for="item in categories" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="作品标签" prop="tags">
<el-select
v-model="workForm.tags"
multiple
placeholder="请选择标签(最多选择3个)"
:multiple-limit="3"
>
<el-option v-for="item in tags" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="简介" prop="description">
<el-input
v-model="workForm.description"
type="textarea"
:rows="5"
placeholder="请输入作品简介"
maxlength="500"
show-word-limit
></el-input>
</el-form-item>
<el-form-item label="封面图片">
<el-upload
class="cover-uploader"
action="#"
:http-request="uploadCover"
:show-file-list="false"
:before-upload="beforeUpload"
>
<img v-if="workForm.cover" :src="workForm.cover" class="cover-image" />
<div v-else class="cover-placeholder">
<el-icon><Plus /></el-icon>
<div class="upload-text">点击上传封面</div>
</div>
</el-upload>
<div class="upload-tip">建议尺寸:300x400像素,JPG/PNG格式</div>
</el-form-item>
<div class="form-actions">
<el-button @click="goBack">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading">创建作品</el-button>
</div>
</el-form>
</div>
</div>
</div>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
export default defineComponent({
name: 'CreateWork',
components: {
Plus
},
setup() {
const router = useRouter();
const workFormRef = ref(null);
const loading = ref(false);
// 表单数据
const workForm = reactive({
title: '',
category: '',
tags: [],
description: '',
cover: ''
});
// 表单验证规则
const rules = {
title: [
{ required: true, message: '请输入作品名称', trigger: 'blur' },
{ min: 2, max: 30, message: '长度应为2-30个字符', trigger: 'blur' }
],
category: [
{ required: true, message: '请选择作品分类', trigger: 'change' }
],
description: [
{ required: true, message: '请输入作品简介', trigger: 'blur' },
{ min: 10, max: 500, message: '简介长度应为10-500个字符', trigger: 'blur' }
]
};
// 分类和标签数据,实际应用中应该从API获取
const categories = ref([
{ id: 1, name: '玄幻' },
{ id: 2, name: '奇幻' },
{ id: 3, name: '武侠' },
{ id: 4, name: '仙侠' },
{ id: 5, name: '都市' },
{ id: 6, name: '历史' },
{ id: 7, name: '军事' },
{ id: 8, name: '科幻' }
]);
const tags = ref([
{ id: 1, name: '热血' },
{ id: 2, name: '爽文' },
{ id: 3, name: '冒险' },
{ id: 4, name: '复仇' },
{ id: 5, name: '种田' },
{ id: 6, name: '经商' },
{ id: 7, name: '争霸' },
{ id: 8, name: '升级' },
{ id: 9, name: '穿越' },
{ id: 10, name: '重生' }
]);
// 上传前校验
const beforeUpload = (file) => {
const isImage = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isImage) {
ElMessage.error('封面图片只能是JPG或PNG格式!');
return false;
}
if (!isLt2M) {
ElMessage.error('封面图片大小不能超过2MB!');
return false;
}
return true;
};
// 上传封面
const uploadCover = (options) => {
const { file } = options;
// 实际应用中应该上传到服务器,这里模拟上传成功
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (e) => {
workForm.cover = e.target.result;
};
};
// 提交表单
const submitForm = () => {
workFormRef.value.validate(async (valid) => {
if (valid) {
try {
loading.value = true;
// 模拟API调用,实际项目中应调用真实的后端API
await new Promise(resolve => setTimeout(resolve, 1000));
ElMessage.success('作品创建成功!');
router.push({ name: 'authorCenter' });
} catch (error) {
ElMessage.error('创建失败,请稍后重试');
} finally {
loading.value = false;
}
} else {
ElMessage.warning('请正确填写表单信息');
return false;
}
});
};
// 返回上一页
const goBack = () => {
router.back();
};
return {
workFormRef,
workForm,
rules,
categories,
tags,
loading,
beforeUpload,
uploadCover,
submitForm,
goBack
};
}
});
</script>
<style lang="scss" scoped>
.create-work-container {
background-color: #f5f5f9;
min-height: calc(100vh - 60px);
padding: 30px 0;
.create-work-content {
max-width: 800px;
margin: 0 auto;
padding: 30px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
.page-title {
font-size: 24px;
color: #333;
margin: 0 0 30px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.form-container {
:deep(.el-form-item__label) {
font-weight: 500;
color: #333;
}
:deep(.el-input__wrapper) {
padding: 0 15px;
height: 44px;
}
.cover-uploader {
.cover-image {
width: 150px;
height: 200px;
object-fit: cover;
border-radius: 4px;
}
.cover-placeholder {
width: 150px;
height: 200px;
background-color: #f7f9fc;
border: 1px dashed #d9d9d9;
border-radius: 4px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
&:hover {
border-color: #0A2463;
color: #0A2463;
}
.el-icon {
font-size: 28px;
color: #8c939d;
margin-bottom: 8px;
}
.upload-text {
font-size: 14px;
color: #8c939d;
}
}
}
.upload-tip {
font-size: 12px;
color: #aaa;
margin-top: 8px;
}
.form-actions {
margin-top: 40px;
display: flex;
justify-content: center;
gap: 20px;
.el-button {
width: 120px;
}
.el-button--primary {
background-color: #0A2463;
border-color: #0A2463;
&:hover, &:focus {
background-color: #1a3473;
border-color: #1a3473;
}
}
}
}
}
}
</style>