Browse Source

文章发布页面

master
maziyang 2 weeks ago
parent
commit
2c4ea5582b
  1. 280
      package-lock.json
  2. 1
      package.json
  3. 2
      src/apis/article.js
  4. 0
      src/apis/user.js
  5. 2
      src/components/home/AsideMenu.vue
  6. 11
      src/stores/article.js
  7. 8
      src/stores/user.js
  8. 212
      src/views/Article/Article.vue

280
package-lock.json

@ -8,6 +8,7 @@
"name": "practice-articlevote-vue",
"version": "0.0.0",
"dependencies": {
"axios": "^1.10.0",
"element-plus": "^2.10.2",
"pinia": "^3.0.1",
"vue": "^3.5.13",
@ -1708,6 +1709,23 @@
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
"license": "MIT"
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
"integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/birpc": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.4.0.tgz",
@ -1766,6 +1784,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001723",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
@ -1787,6 +1818,18 @@
],
"license": "CC-BY-4.0"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -1897,6 +1940,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.169",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.169.tgz",
@ -1952,6 +2018,51 @@
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
@ -2073,6 +2184,42 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/follow-redirects": {
"version": "1.15.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
"integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs-extra": {
"version": "11.3.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
@ -2103,6 +2250,15 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@ -2113,6 +2269,43 @@
"node": ">=6.9.0"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-stream": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
@ -2140,6 +2333,18 @@
"node": ">=4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@ -2147,6 +2352,45 @@
"dev": true,
"license": "ISC"
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@ -2367,12 +2611,42 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT"
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
@ -2596,6 +2870,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",

1
package.json

@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.10.0",
"element-plus": "^2.10.2",
"pinia": "^3.0.1",
"vue": "^3.5.13",

2
src/apis/article.js

@ -1,3 +1,3 @@
import { request } from "@/utils/request";
export const apiAddArticle = async (article) =>request.post(`/addArticle`,article);
export const apiAddArticle = async (articleForm) =>request.post(`/addArticle`,articleForm);

0
src/apis/user.js

2
src/components/home/AsideMenu.vue

@ -11,7 +11,7 @@
<el-menu
router
:default-active="post"
:default-active="article"
background-color="#1a3058"
text-color="rgba(255,255,255,0.8)"
active-text-color="#ffd04b"

11
src/stores/article.js

@ -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
}
})

8
src/stores/user.js

@ -0,0 +1,8 @@
import { defineStore } from "pinia";
import { ref } from "vue";
export const useUserStore = defineStore('User',()=>{
let userId = ref(1)
return{
userId
}
})

212
src/views/Article/Article.vue

@ -1,5 +1,213 @@
<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>
<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>
Loading…
Cancel
Save