8 changed files with 513 additions and 5 deletions
-
280package-lock.json
-
1package.json
-
2src/apis/article.js
-
0src/apis/user.js
-
2src/components/home/AsideMenu.vue
-
11src/stores/article.js
-
8src/stores/user.js
-
214src/views/Article/Article.vue
@ -1,3 +1,3 @@ |
|||||
import { request } from "@/utils/request"; |
import { request } from "@/utils/request"; |
||||
|
|
||||
export const apiAddArticle = async (article) =>request.post(`/addArticle`,article); |
|
||||
|
export const apiAddArticle = async (articleForm) =>request.post(`/addArticle`,articleForm); |
@ -0,0 +1,11 @@ |
|||||
|
import { apiAddArticle } from "@/apis/article"; |
||||
|
import { defineStore } from "pinia"; |
||||
|
|
||||
|
export const useArticleStore = defineStore('Atricle',()=>{ |
||||
|
const addArticle = async(atricleForm) =>{ |
||||
|
return await apiAddArticle(atricleForm) |
||||
|
} |
||||
|
return{ |
||||
|
addArticle |
||||
|
} |
||||
|
}) |
@ -0,0 +1,8 @@ |
|||||
|
import { defineStore } from "pinia"; |
||||
|
import { ref } from "vue"; |
||||
|
export const useUserStore = defineStore('User',()=>{ |
||||
|
let userId = ref(1) |
||||
|
return{ |
||||
|
userId |
||||
|
} |
||||
|
}) |
@ -1,5 +1,213 @@ |
|||||
<template> |
<template> |
||||
<div> |
|
||||
aaaa |
|
||||
|
<el-form :model="form" label-width="auto" :rules="rules" ref="elFormRef" style="max-width: 600px"> |
||||
|
<el-form-item label="文章标题" prop="articleTitle"> |
||||
|
<el-input v-model="form.articleTitle" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="文章内容" prop="articleContent"> |
||||
|
<el-input v-model="form.articleContent" type="textarea" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="是否发起投票"> |
||||
|
<el-switch v-model="form.voteStatus" style="--el-switch-on-color: red" @change="handleVoteToggle" /> |
||||
|
</el-form-item> |
||||
|
<div class="vote-section" v-show="form.voteStatus"> |
||||
|
<el-form-item label="投票标题" prop="voteTitle"> |
||||
|
<el-input v-model="form.voteTitle" placeholder="请填写投票标题,最多24个字" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="选项" required> |
||||
|
<div class="vote-options-container"> |
||||
|
<div v-for="(option, index) in form.optionList" :key="index" class="vote-option-item"> |
||||
|
<!-- <el-input v-model="option.optionContent" :placeholder="'选项' + (index + 1) + ',最多24个字'" /> --> |
||||
|
<el-form-item :prop="`optionList.${index}.optionContent`" :rules="[ |
||||
|
{ required: true, message: `选项${index + 1}不能为空`, trigger: 'blur' }, |
||||
|
{ max: 24, message: '最多24个字', trigger: 'blur' } |
||||
|
]" style="flex: 1"> |
||||
|
<el-input v-model="option.optionContent" :placeholder="'选项' + (index + 1) + ',最多24个字'" /> |
||||
|
</el-form-item> |
||||
|
<el-button v-show="index > 1" @click="removeOption(index)" class="remove-btn" type="danger" :icon="Delete" |
||||
|
circle /> |
||||
|
</div> |
||||
|
<el-button @click="addOption" type="primary" plain class="add-option-btn"> |
||||
|
<el-icon> |
||||
|
<Plus /> |
||||
|
</el-icon>添加选项 |
||||
|
</el-button> |
||||
|
</div> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="支持多选"> |
||||
|
<el-switch v-model="form.multiOption" style="--el-switch-on-color: red" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="投票截止时间" prop="deadlineTime"> |
||||
|
<el-date-picker v-model="form.deadlineTime" type="datetime" placeholder="选择时间" format="YYYY/MM/DD HH:mm:ss" /> |
||||
|
</el-form-item> |
||||
</div> |
</div> |
||||
</template> |
|
||||
|
<el-form-item> |
||||
|
<div class="publish-article"> |
||||
|
<el-button type="primary" @click="onSubmit">发表</el-button> |
||||
|
</div> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</template> |
||||
|
<script setup> |
||||
|
import { reactive, ref } from 'vue' |
||||
|
import { Delete, Plus } from '@element-plus/icons-vue' |
||||
|
import { ElMessage, ElMessageBox, ElForm } from 'element-plus' |
||||
|
import { useArticleStore } from '@/stores/article' |
||||
|
import { useUserStore } from '@/stores/user' |
||||
|
const elFormRef = ref() |
||||
|
let optionIndex = ref(3) |
||||
|
// 切换投票开关 |
||||
|
const handleVoteToggle = (value) => { |
||||
|
if (value) { |
||||
|
optionIndex.value = 3 |
||||
|
form.voteTitle = ''; |
||||
|
form.optionList = [ |
||||
|
{ index: 1, optionContent: '' }, |
||||
|
{ index: 2, optionContent: '' } |
||||
|
]; |
||||
|
form.deadlineTime = ''; |
||||
|
} else { |
||||
|
form.optionList = [] |
||||
|
} |
||||
|
}; |
||||
|
// 添加选项 |
||||
|
const addOption = () => { |
||||
|
if (form.optionList.length >= 20) { |
||||
|
ElMessageBox.alert('最多添加20个选项', '提示', { |
||||
|
confirmButtonText: '确认', |
||||
|
}); |
||||
|
return |
||||
|
} |
||||
|
form.optionList.push({ index: optionIndex.value++, optionContent: '' }); |
||||
|
}; |
||||
|
// 移除选项 |
||||
|
const removeOption = (index) => { |
||||
|
console.log(index) |
||||
|
if (form.optionList.length > 2) { |
||||
|
form.optionList.splice(index, 1); |
||||
|
} |
||||
|
}; |
||||
|
const form = reactive({ |
||||
|
articleTitle: '', |
||||
|
articleContent: '', |
||||
|
voteStatus: false, |
||||
|
voteTitle: '', |
||||
|
optionList: [], |
||||
|
deadlineTime: '' |
||||
|
}) |
||||
|
const rules = reactive({ |
||||
|
articleTitle: [ |
||||
|
{ required: true, message: '请输入文章标题', trigger: 'blur' }, |
||||
|
{ min: 3, max: 50, message: '标题长度在5~100字范围内', trigger: 'blur' } |
||||
|
], |
||||
|
articleContent: [ |
||||
|
{ required: true, message: '请输入文章内容', trigger: 'change' } |
||||
|
], |
||||
|
voteTitle: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入投票标题', |
||||
|
trigger: 'blur', |
||||
|
validator: (rule, value, callback) => { |
||||
|
if (form.voteStatus && !value) { |
||||
|
callback(new Error('请输入投票标题')) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
{ max: 24, message: '投票标题最多24个字', trigger: 'blur' } |
||||
|
], |
||||
|
deadlineTime: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
trigger: 'blur', |
||||
|
validator: (rule, value, callback) => { |
||||
|
if (form.voteStatus && !value) { |
||||
|
callback(new Error('请选择截止日期')) |
||||
|
} else { |
||||
|
callback() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
] |
||||
|
}) |
||||
|
const onSubmit = async () => { |
||||
|
let valid = false |
||||
|
try { |
||||
|
valid = await elFormRef.value.validate() |
||||
|
} catch (error) { |
||||
|
// 表单验证失败会 throw |
||||
|
console.log('表单验证失败', error) |
||||
|
} |
||||
|
if (valid) { |
||||
|
console.log('表单验证通过') |
||||
|
try { |
||||
|
form.userId = useUserStore().userId |
||||
|
console.log(form) |
||||
|
const submitRes = await useArticleStore().addArticle(form) |
||||
|
console.log('提交成功', submitRes) |
||||
|
} catch (error) { |
||||
|
console.log('请求失败',error) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.vote-section { |
||||
|
background: #e8f4fe; |
||||
|
border-left: 4px solid #3498db; |
||||
|
padding: 20px; |
||||
|
border-radius: 8px; |
||||
|
margin-top: 15px; |
||||
|
margin-bottom: 15px; |
||||
|
transition: all 0.4s ease; |
||||
|
} |
||||
|
|
||||
|
.vote-options-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
width: 60%; |
||||
|
} |
||||
|
|
||||
|
.vote-option-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 15px; |
||||
|
border-radius: 8px; |
||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.vote-option-item:hover { |
||||
|
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.08); |
||||
|
transform: translateY(-2px); |
||||
|
} |
||||
|
|
||||
|
.remove-btn { |
||||
|
margin-left: 5px; |
||||
|
opacity: 0.7; |
||||
|
transition: all 0.2s; |
||||
|
} |
||||
|
|
||||
|
.remove-btn:hover { |
||||
|
color: #e74c3c !important; |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.add-option-btn { |
||||
|
margin-top: 10px; |
||||
|
display: inline-flex; |
||||
|
align-items: center; |
||||
|
transition: all 0.2s; |
||||
|
border-radius: 6px; |
||||
|
background-color: #f5f9ff; |
||||
|
border: 1px dashed #3498db; |
||||
|
} |
||||
|
|
||||
|
.publish-article { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
width: 100%; |
||||
|
} |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue