This commit is contained in:
aa
2024-10-16 22:11:24 +08:00
parent 91cccb62b9
commit 16d1ae126c
28 changed files with 14435 additions and 92 deletions

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -1,92 +1,3 @@
# kangkang
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin http://gitlab.yidooplanet.com/gitlab-instance-0a899031/kangkang.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](http://gitlab.yidooplanet.com/gitlab-instance-0a899031/kangkang/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
node v20.9.0
@vue/cli 5.0.8 https://cli.vuejs.org/zh/
vue2

5
babel.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

19
jsconfig.json Normal file
View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

12014
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

53
package.json Normal file
View File

@@ -0,0 +1,53 @@
{
"name": "activites-admin",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^1.7.4",
"core-js": "^3.8.3",
"element-ui": "^2.15.14",
"lodash": "^4.17.21",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"less": "^4.0.0",
"less-loader": "^8.0.0",
"mockjs": "^1.1.0",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

17
public/index.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

4
public/xx.json Normal file
View File

@@ -0,0 +1,4 @@
{
"a": 1,
"b": 2
}

18
src/App.vue Normal file
View File

@@ -0,0 +1,18 @@
<template>
<div id="app">
<!-- <el-button type="primary">主要按钮</el-button> -->
<router-view class="content"></router-view>
</div>
</template>
<style lang="less">
#app {
width: 100vw;
height: 100vh;
// text-align: center;
background-color: #f5f5f5;
}
* {
margin: 0;
}
</style>

19
src/api/activity/index.js Normal file
View File

@@ -0,0 +1,19 @@
export const activityApi = {
lists: {
url: '/activity/lists',
method: 'GET'
},
add: {
url: '/activity/add',
method: 'POST'
},
update: {
url: '/activity/update',
method: 'POST'
},
delete: {
url: '/activity/delete',
method: 'POST'
},
}

10
src/api/category/index.js Normal file
View File

@@ -0,0 +1,10 @@
export const categoryApi = {
details: {
url: '/category/details',
method: 'GET'
},
lists: {
url: '/category/lists',
method: 'GET'
}
}

10
src/api/index.js Normal file
View File

@@ -0,0 +1,10 @@
import { userApi } from './user'
import { activityApi } from './activity'
import { categoryApi } from './category'
export const apis = {
user: userApi,
activity: activityApi,
category: categoryApi,
}

49
src/api/request.js Normal file
View File

@@ -0,0 +1,49 @@
import axios from 'axios'
import "../mock/mockData"
//定义一个请求实例
export let requests = axios.create({
//定义URL
baseURL: '/api',
//超时时间
timeout: 5000,
})
// 添加请求拦截器
requests.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// console.log('请求拦截', config)
return config;
}, function (error) {
// 对请求错误做些什么
console.log(response.data)
return Promise.reject(error);
});
// 添加响应拦截器
requests.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
// console.log('响应拦截', response)
if (response.data.code == 200) {
return response;
}
else {
return Promise.reject(response.data)
}
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
console.log(response.data)
return Promise.reject(error);
});
// // 发起一个post请求
// console.log('发起登录请求')
// requests({
// method: 'post',
// url: "http://192.168.31.61:8086/user/login",
// data: {
// username: 'Fred',
// password: 'Flintstone'
// }
// });

10
src/api/user/index.js Normal file
View File

@@ -0,0 +1,10 @@
export const userApi = {
login: {
url: '/user/login',
method: 'POST'
},
userInfo: {
url: '/user/userInfo',
method: 'GET'
}
}

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,130 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex"
target="_blank"
rel="noopener"
>vuex</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

17
src/main.js Normal file
View File

@@ -0,0 +1,17 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import { requests } from './api/request.js'
Vue.config.productionTip = false
Vue.use(ElementUI);
Vue.prototype.$http = requests
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

73
src/mock/mockData.js Normal file
View File

@@ -0,0 +1,73 @@
import Mock from 'mockjs';
const Random = Mock.Random;
// 定义活动列表的 mock 数据
Mock.mock('/api/activities', 'get', {
code: 200,
data: {
'list|10': [
{
'id|+1': 1,
title: () => Random.ctitle(5, 10),
description: () => Random.cparagraph(1, 3),
date: () => Random.date(),
},
],
},
});
// 定义登录接口的 mock 数据
Mock.mock('/api/login', 'post', (options) => {
// 解析请求体中的 JSON 数据
const body = JSON.parse(options.body);
// 模拟的用户信息
const userInfo = {
username: 'dsx2016',
password: '123456',
};
// 根据请求数据判断登录是否成功
if (body.username === userInfo.username && body.password === userInfo.password) {
return {
code: 200,
message: '登录成功',
data: 'fake-token', // 假token
};
} else {
return {
code: 401,
message: '用户名或密码错误',
};
}
});
const userInfo = {
id: 1,
username: "dsx2016",
email: "admin@example.com",
role: "administrator",
avatar: "https://example.com/avatar.png",
};
// 定义 Mock 登录和用户信息接口
Mock.mock("/api/userInfo", "get", (req) => {
// 从请求头中获取 Authorization
const authorizationHeader = req.headers.Authorization;
// 假设令牌为 'fake-token' 时,视为已登录
if (authorizationHeader === "fake-token") {
return {
code: 200,
message: "获取用户信息成功",
data: userInfo,
};
} else {
// 如果没有 token 或 token 错误,返回错误信息
return {
code: 401,
message: "未登录,请先登录",
};
}
});

47
src/router/index.js Normal file
View File

@@ -0,0 +1,47 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import LoginPage from '../views/login'
import HomePage from '../views/home'
import helloPage from '../views/hello'
import actlistPage from '../views/actlist'
Vue.use(VueRouter)
const routes = [
{
path: '/login',
name: 'login',
component: LoginPage
},
{
path: '/',
name: 'home',
component: HomePage,
children: [
{
path: '/hello',
name: 'hello',
component: helloPage
},
{
path: '/actlist',
name: 'actlist',
component: actlistPage
}
]
}
// {
// path: '/about',
// name: 'about',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
// }
]
const router = new VueRouter({
routes
})
export default router

51
src/store/index.js Normal file
View File

@@ -0,0 +1,51 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: '',
userInfo: {},
activities: {},
categories: {}
},
getters: {
getToken(state) {
return state.token || ""
},
getUserInfo(state) {
return state.userInfo || {}
},
getActivities(state) {
return state.activities.items || {}
},
getTotalActivities(state) {
return state.activities.total || 0
},
getCategories(state) {
return state.categories || {}
}
},
mutations: {
setToken(state, token) {
state.token = token
},
delToken(state) {
state.token = ''
},
setUserInfo(state, userInfo) {
state.userInfo = userInfo
},
setActivities(state, activities) {
state.activities = activities
},
setCategories(state, categories) {
state.categories = categories
}
},
actions: {
},
modules: {
}
})

View File

@@ -0,0 +1,140 @@
<template>
<el-form
:model="ruleForm"
ref="ruleForm"
label-width="150px"
class="demo-ruleForm"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动标题"
prop="activityTitle"
:rules="[
{
required: true,
message: '活动标题不能为空',
trigger: 'blur',
},
]"
>
<el-input v-model="ruleForm.activityTitle"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="活动副标题"
prop="activitySubTitle"
label-width="150px"
>
<el-input v-model="ruleForm.activitySubTitle"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动开始时间"
label-width="150px"
prop="activityStartTime"
:rules="[
{
required: true,
message: '活动开始时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="ruleForm.activityStartTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="活动结束时间"
label-width="150px"
prop="activityEndTime"
:rules="[
{
required: true,
message: '活动结束时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="ruleForm.activityEndTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<!-- 其余部分保留 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动封面图"
prop="avatarImgUrl"
label-width="150px"
>
<el-input v-model="ruleForm.avatarImgUrl"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动简介" prop="activityInfo" label-width="150px">
<el-input v-model="ruleForm.activityInfo"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 其他代码按原样继续 -->
<!-- 底部 -->
<el-col :span="24">
<el-form-item label="活动详情" prop="activityDetails">
<el-input type="textarea" v-model="ruleForm.activityDetails"></el-input>
</el-form-item>
</el-col>
</el-form>
</template>
<script>
export default {
name: "NewActivityForm",
props: {
ruleForm: {
type: Object,
required: true,
},
isPriceDisabled: {
type: Boolean,
default: false,
},
},
methods: {
handlePayTypeChange(value) {
this.$emit("pay-type-change", value); // 触发父组件的事件
},
},
};
</script>
<style scoped>
.demo-ruleForm {
padding: 20px;
}
</style>

997
src/views/actlist/index.vue Normal file
View File

@@ -0,0 +1,997 @@
<template>
<el-container>
<el-header height="100px">
<el-row :gutter="20">
<el-form
:inline="true"
:model="formInline"
class="demo-form-inline"
ref="formInline"
>
<el-col :span="6">
<el-form-item prop="activityName">
<el-input
v-model="formInline.activityName"
placeholder="请输入活动名"
></el-input>
</el-form-item>
</el-col>
<el-col :span="6" :offset="12">
<el-form-item class="buttons">
<el-button type="primary" @click="onSubmit(1)">查询</el-button>
<el-button @click="resetSearchForm('formInline')">重置</el-button>
</el-form-item>
</el-col>
</el-form>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<el-button type="primary" @click="newDialogFormVisible = true"
>新建</el-button
>
<el-dialog
title="新建活动"
:visible.sync="newDialogFormVisible"
width="70%"
>
<!-- <el-form
:model="ruleForm"
ref="ruleForm"
label-width="150px"
class="demo-ruleForm"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动标题"
prop="activityTitle"
:rules="[
{
required: true,
message: '活动标题不能为空',
trigger: 'blur',
},
]"
>
<el-input v-model="ruleForm.activityTitle"></el-input>
</el-form-item>
</el-col>
<el-col :span="12"
><el-form-item
label="活动副标题"
prop="activitySubTitle"
label-width="150px"
>
<el-input
v-model="ruleForm.activitySubTitle"
></el-input> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动开始时间"
label-width="150px"
prop="activityStartTime"
:rules="[
{
required: true,
message: '活动开始时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="ruleForm.activityStartTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="活动结束时间"
label-width="150px"
prop="activityEndTime"
:rules="[
{
required: true,
message: '活动结束时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="ruleForm.activityEndTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"
><el-form-item
label="活动封面图"
prop="avatarImgUrl"
label-width="150px"
>
<el-input
v-model="ruleForm.avatarImgUrl"
></el-input> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item
label="活动简介"
prop="activityInfo"
label-width="150px"
>
<el-input
v-model="ruleForm.activityInfo"
></el-input> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动分类"
label-width="150px"
prop="activityCategoryId"
:rules="[
{
required: true,
message: '活动分类不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="ruleForm.activityCategoryId"
placeholder="请选择活动分类"
style="width: 100%"
>
<el-option label="徒步" :value="1"></el-option>
<el-option label="读书会" :value="2"></el-option>
<el-option label="脱口秀" :value="3"></el-option>
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动线下线上分类"
prop="activityLineType"
label-width="150px"
:rules="[
{
required: true,
message: '活动线上线下分类不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="ruleForm.activityLineType"
placeholder="请选择线下分类"
style="width: 100%"
>
<el-option label="线上" value="1"></el-option>
<el-option label="线下" value="2"></el-option>
</el-select> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
prop="activityPayType"
label="活动付费类型"
label-width="150px"
:rules="[
{
required: true,
message: '活动付费类型不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="ruleForm.activityPayType"
placeholder="请选择活动付费类型"
style="width: 100%"
@change="handlePayTypeChange"
>
<el-option label="免费" value="1"></el-option>
<el-option label="付费" value="2"></el-option>
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动价格"
prop="activityPrice"
:rules="[
{
required: true,
message: '活动价格不能为空',
trigger: 'blur',
},
]"
>
<el-input
v-model="ruleForm.activityPrice"
type="number"
step="1"
min="0"
:disabled="isPriceDisabled"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"
><el-form-item
label="活动地址"
prop="activityAddress"
label-width="150px"
>
<el-input
v-model="ruleForm.activityAddress"
></el-input> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动人数限制"
prop="activityPeopleLimit"
:rules="[
{
required: true,
message: '活动人数不能为空',
trigger: 'blur',
},
]"
>
<el-input
v-model="ruleForm.activityPeopleLimit"
type="number"
min="0"
step="1"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
prop="activityStatus"
label="活动状态"
label-width="150px"
:rules="[
{
required: true,
message: '活动状态不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="ruleForm.activityStatus"
placeholder="请选择活动状态"
style="width: 100%"
>
<el-option label="草稿" :value="1"></el-option>
<el-option label="已发布" :value="2"></el-option>
<el-option label="已下线" :value="3"></el-option>
<el-option label="已终止" :value="4"></el-option>
</el-select> </el-form-item
></el-col>
</el-row>
<el-col :span="24">
<el-form-item label="活动详情" prop="activityDetails">
<el-input
type="textarea"
v-model="ruleForm.activityDetails"
></el-input>
</el-form-item>
</el-col>
</el-form> -->
<new-activity-form
:rule-form="ruleForm"
:isPriceDisabled="isPriceDisabled"
@pay-type-change="handlePayTypeChange"
></new-activity-form>
<div slot="footer" class="dialog-footer">
<el-row :gutter="20" type="flex" justify="center">
<el-col :span="24" style="text-align: center">
<el-button @click="closeForm('ruleForm')"> </el-button>
<el-button type="primary" @click="submitAddForm('ruleForm')"
> </el-button
>
</el-col>
</el-row>
</div>
</el-dialog>
</el-col>
</el-row>
</el-header>
<el-main style="height: 632px">
<el-row :gutter="20" type="flex" justify="center">
<el-col :span="24" style="text-align: center"
><el-table
:data="tableData"
:border="true"
style="width: 100%"
:fit="true"
resizable
>
<el-table-column prop="activityTitle" label="活动名">
</el-table-column>
<el-table-column :formatter="formatCategoryName" label="分类">
</el-table-column>
<el-table-column prop="activityStartTime" label="活动日期">
</el-table-column>
<el-table-column prop="activityPeopleLimit" label="活动限制人数">
</el-table-column>
<el-table-column prop="address" label="操作">
<template slot-scope="scope">
<el-button
@click="detailDialog(scope.row)"
type="primary"
size="small"
style="margin-right: 10px"
>查看</el-button
>
<el-dialog
title="编辑活动"
:visible.sync="detailsDialogFormVisible"
width="70%"
>
<el-form
:model="detailsForm"
ref="detailsForm"
label-width="150px"
class="demo-ruleForm"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动标题"
prop="activityTitle"
:rules="[
{
required: true,
message: '活动标题不能为空',
trigger: 'blur',
},
]"
>
<el-input
v-model="detailsForm.activityTitle"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12"
><el-form-item
label="活动副标题"
prop="activitySubTitle"
label-width="150px"
>
<el-input
v-model="detailsForm.activitySubTitle"
></el-input> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动开始时间"
label-width="150px"
prop="activityStartTime"
:rules="[
{
required: true,
message: '活动开始时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="detailsForm.activityStartTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="活动结束时间"
label-width="150px"
prop="activityEndTime"
:rules="[
{
required: true,
message: '活动结束时间不能为空',
trigger: 'blur',
},
]"
>
<el-date-picker
v-model="detailsForm.activityEndTime"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
placeholder="选择结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"
><el-form-item
label="活动封面图"
prop="avatarImgUrl"
label-width="150px"
>
<el-input
v-model="detailsForm.avatarImgUrl"
></el-input> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item
label="活动简介"
prop="activityInfo"
label-width="150px"
>
<el-input
v-model="detailsForm.activityInfo"
></el-input> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="活动分类"
label-width="150px"
prop="activityCategoryId"
:rules="[
{
required: true,
message: '活动分类不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="detailsForm.activityCategoryId"
placeholder="请选择活动分类"
style="width: 100%"
>
<el-option label="徒步" :value="1"></el-option>
<el-option label="读书会" :value="2"></el-option>
<el-option label="脱口秀" :value="3"></el-option>
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动线下线上分类"
prop="activityLineType"
label-width="150px"
:rules="[
{
required: true,
message: '活动线上线下分类不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="detailsForm.activityLineType"
placeholder="请选择线下分类"
style="width: 100%"
>
<el-option label="线上" value="1"></el-option>
<el-option label="线下" value="2"></el-option>
</el-select> </el-form-item
></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
prop="activityPayType"
label="活动付费类型"
label-width="150px"
:rules="[
{
required: true,
message: '活动付费类型不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="detailsForm.activityPayType"
placeholder="请选择活动付费类型"
style="width: 100%"
@blur="handleDetailsPayTypeChange"
@change="handleDetailsPayTypeChange"
>
<el-option label="免费" value="1"></el-option>
<el-option label="付费" value="2"></el-option>
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动价格"
prop="activityPrice"
:rules="[
{
required: true,
message: '活动价格不能为空',
trigger: 'blur',
},
]"
>
<el-input
v-model="detailsForm.activityPrice"
type="number"
step="1"
min="0"
:disabled="isPriceDisabled"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"
><el-form-item
label="活动地址"
prop="activityAddress"
label-width="150px"
>
<el-input
v-model="detailsForm.activityAddress"
></el-input> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item
label="活动人数限制"
prop="activityPeopleLimit"
:rules="[
{
required: true,
message: '活动人数不能为空',
trigger: 'blur',
},
]"
>
<el-input
v-model="detailsForm.activityPeopleLimit"
type="number"
min="0"
step="1"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
prop="activityStatus"
label="活动状态"
label-width="150px"
:rules="[
{
required: true,
message: '活动状态不能为空',
trigger: 'blur',
},
]"
>
<el-select
v-model="detailsForm.activityStatus"
placeholder="请选择活动状态"
style="width: 100%"
>
<el-option label="草稿" :value="1"></el-option>
<el-option label="已发布" :value="2"></el-option>
<el-option label="已下线" :value="3"></el-option>
<el-option label="已终止" :value="4"></el-option>
</el-select> </el-form-item
></el-col>
</el-row>
<el-col :span="24">
<el-form-item label="活动详情" prop="activityDetails">
<el-input
type="textarea"
v-model="detailsForm.activityDetails"
></el-input>
</el-form-item>
</el-col>
</el-form>
<div slot="footer" class="dialog-footer">
<el-row :gutter="20" type="flex" justify="center">
<el-col :span="24" style="text-align: center">
<el-button @click="closeDetailForm('detailsForm')"
> </el-button
>
<el-button
type="primary"
@click="submitDetailsForm('detailsForm')"
> </el-button
>
</el-col>
</el-row>
</div>
</el-dialog>
<el-button
type="danger"
@click="openDeleteDialog(scope.row)"
size="small"
>删除</el-button
>
<el-dialog
title="提示"
:visible.sync="deleteDialogVisible"
width="30%"
>
<span>是否确认删除</span>
<span slot="footer" class="dialog-footer">
<el-button @click="deleteDialogVisible = false"
> </el-button
>
<el-button
type="primary"
@click="submitDeleteItem(deleteItem.id)"
> </el-button
>
</span>
</el-dialog>
</template>
</el-table-column>
</el-table></el-col
>
</el-row>
</el-main>
<el-footer>
<el-row :gutter="20" type="flex" justify="center">
<el-col :span="24" style="text-align: center">
<el-pagination
background
layout="prev, pager, next"
:total="total"
:current-page.sync="paginationCurrentPage"
@current-change="handleCurrentChange"
:page-size="10"
>
</el-pagination>
</el-col>
</el-row>
</el-footer>
</el-container>
</template>
<script>
import { apis } from "../../api/index";
import NewActivityForm from "./NewActivityForm.vue";
export default {
name: "actlist",
data() {
return {
tableData: {},
formInline: {
activityName: "",
},
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
formLabelWidth: "120px",
categories: {},
total: 0,
newDialogFormVisible: false,
detailsDialogFormVisible: false,
deleteDialogVisible: false,
ruleForm: {
activityAddress: "",
activityCategoryId: null,
activityCreateUser: 0,
activityDetails: "",
activityEndTime: "",
activityInfo: "",
activityLineType: "",
activityPayType: "",
activityPeopleLimit: 0,
activityPrice: 0,
activityStartTime: "",
activityStatus: "",
activitySubTitle: "",
activityTitle: "",
activityViewNum: 0,
avatarImgUrl: "",
},
detailsForm: {
activityAddress: "",
activityCategoryId: null,
activityCreateUser: 0,
activityDetails: "",
activityEndTime: "",
activityInfo: "",
activityLineType: "",
activityPayType: "",
activityPeopleLimit: 0,
activityPrice: 0,
activityStartTime: "",
activityStatus: "",
activitySubTitle: "",
activityTitle: "",
activityViewNum: 0,
avatarImgUrl: "",
},
deleteItem: {},
isPriceDisabled: false,
paginationCurrentPage: 1,
};
},
comments: { NewActivityForm },
computed: {
// activities() {
// return this.;
// },
},
mounted() {
this.fetchCategories();
// this.onSubmit(1);
},
methods: {
addActivity(activity) {
let that = this;
that
.$http({
method: apis.activity.add.method,
url: apis.activity.add.url,
headers: {
Authorization: that.$store.getters.getToken,
},
data: activity,
})
.then((response) => {
that.onSubmit(1);
that.$message.closeAll();
that.$message({
message: "添加成功",
type: "success",
});
this.newDialogFormVisible = false;
})
.catch((error) => {
console.log("error", error.message);
that.$message.error(error.message);
});
},
async submitAddForm(formName) {
const that = this;
// this.newDialogFormVisible = false;
this.$refs[formName].validate((valid) => {
if (valid) {
// this.newDialogFormVisible = false;
that.addActivity(that.ruleForm);
that.$nextTick(() => {
this.resetForm(formName);
});
} else {
console.log("error submit!!");
return false;
}
});
},
closeAddForm(formName) {
this.resetForm(formName);
this.newDialogFormVisible = false;
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
fetchCategories() {
this.$http({
method: apis.category.lists.method,
url: apis.category.lists.url,
headers: {
Authorization: this.$store.getters.getToken,
},
})
.then((response) => {
this.$store.commit("setCategories", response.data.data);
this.categories = this.$store.getters.getCategories;
})
.catch((error) => {
console.log("error", error.message);
this.$message.error(error.message);
});
},
onSubmit(pageNumber) {
const that = this;
const loadingInstance = this.$loading({
lock: true,
text: "加载中...",
// spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
that
.$http({
method: apis.activity.lists.method,
url: apis.activity.lists.url,
headers: {
Authorization: that.$store.getters.getToken,
},
params: {
pageNum: pageNumber,
pageSize: 10,
activityTitle: this.formInline.activityName,
},
})
.then((response) => {
that.$message.closeAll();
that.$message({
message: "查询完毕",
type: "success",
});
that.$store.commit("setActivities", response.data.data);
that.tableData = this.$store.getters.getActivities;
this.resetToFirstPage(pageNumber);
})
.catch((error) => {
console.log("error", error.message);
that.$message.error(error.message);
})
.finally(() => {
loadingInstance.close();
});
this.tableData = that.$store.getters.getActivities;
that.categories = this.$store.getters.getCategories;
(that.total = this.$store.getters.getTotalActivities),
console.log(
"this.categories",
that.categories,
this.$store.getters.getCategories
);
},
handleCurrentChange(val) {
this.onSubmit(val);
},
resetSearchForm(formName) {
this.$refs[formName].resetFields();
this.onSubmit(1);
},
detailDialog(row) {
this.detailsDialogFormVisible = true;
this.detailsForm = _.cloneDeep(row);
this.handleDetailsPayTypeChange(this.detailsForm.activityPayType);
},
updateDetails(detailsForm) {
let that = this;
that
.$http({
method: apis.activity.update.method,
url: apis.activity.update.url,
headers: {
Authorization: that.$store.getters.getToken,
},
data: detailsForm,
})
.then((response) => {
that.onSubmit(1);
that.$message.closeAll();
that.$message({
message: "修改成功",
type: "success",
});
})
.catch((error) => {
console.log("error", error.message);
that.$message.error(error.message);
});
},
submitDetailsForm(formName) {
const that = this;
// this.newDialogFormVisible = false;
this.$refs[formName].validate((valid) => {
if (valid) {
// this.newDialogFormVisible = false;
that.updateDetails(that.detailsForm);
that.closeDetailForm(formName);
} else {
console.log("error submit!!");
return false;
}
});
},
async closeDetailForm(formName) {
this.detailsDialogFormVisible = false;
this.$nextTick(() => {
this.resetForm(formName);
});
},
openDeleteDialog(row) {
this.deleteDialogVisible = true;
this.deleteItem = _.cloneDeep(row);
},
deleleActivity(id) {
let that = this;
that
.$http({
method: apis.activity.delete.method,
url: apis.activity.delete.url,
headers: {
Authorization: that.$store.getters.getToken,
},
params: {
id: id,
},
})
.then((response) => {
that.onSubmit(1);
that.$message.closeAll();
that.$message({
message: "删除成功",
type: "success",
});
})
.catch((error) => {
console.log("error", error.message);
that.$message.error(error.message);
});
},
submitDeleteItem(id) {
this.deleleActivity(id);
this.deleteItem = {};
this.deleteDialogVisible = false;
},
formatCategoryName(row) {
const category = this.categories.find(
(c) => c.id === row.activityCategoryId
);
return category ? category.categoryName : "未知分类";
},
handlePayTypeChange(value) {
if (value === "1") {
this.isPriceDisabled = true;
this.ruleForm.activityPrice = 0; // 当选择免费时将价格设为0
} else if (value === "2") {
this.isPriceDisabled = false; // 当选择付费时,启用价格输入框
}
},
handleDetailsPayTypeChange(value) {
// console.log("触发了改变");
if (value === "1") {
// console.log("触发了改变");
this.isPriceDisabled = true;
this.detailsForm.activityPrice = 0; // 当选择免费时将价格设为0
} else if (value === "2") {
this.isPriceDisabled = false; // 当选择付费时,启用价格输入框
}
},
resetToFirstPage(pageNum) {
this.paginationCurrentPage = pageNum; // 将页码重置为1
// this.handleCurrentChange(1); // 手动触发第一页的分页逻辑
},
},
};
</script>
<style>
.buttons {
float: right;
}
</style>

131
src/views/hello/index.vue Normal file
View File

@@ -0,0 +1,131 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex"
target="_blank"
rel="noopener"
>vuex</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "hello",
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

201
src/views/home/index.vue Normal file
View File

@@ -0,0 +1,201 @@
<template>
<el-container class="container">
<el-header class="header">
<el-row class="head-row" justify="space-between" type="flex">
<el-col :span="8">
<div class="grid-content bg-purple-dark">
<div class="logo">logo</div>
</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple-dark">
<el-link type="primary" :underline="false" @click="logout"
>退出登录</el-link
>
<span class="username">{{ userInfo.username }}</span>
<div class="avatarImg"></div>
</div>
</el-col>
</el-row>
</el-header>
<el-container>
<el-aside class="aside">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
router="true"
>
<el-submenu index="1">
<template slot="title">
<span>用户模块</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="login">选项1</el-menu-item>
<el-menu-item index="hello">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<span>活动模块</span>
</template>
<el-menu-item-group>
<el-menu-item index="actlist">活动列表</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<span>分类模块</span>
</template>
<el-menu-item-group>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-main class="main" style="background-color: #fff">
<router-view></router-view>
</el-main>
</el-container>
<!-- <el-footer class="footer"></el-footer> -->
</el-container>
</template>
<script>
import { apis } from "../../api/index";
export default {
mounted() {
const that = this;
that
.$http({
// method: apis.user.userInfo.method,
// url: apis.user.userInfo.url,
// headers: {
// Authorization: that.$store.getters.getToken,
// },
//利用mock的
method: "GET", // 使用 POST 方法
url: "/userInfo", // 使用 mock 接口路径
headers: {
Authorization: that.$store.getters.getToken,
},
})
.then((response) => {
that.$store.commit("setUserInfo", response.data.data);
that.userInfo = that.$store.getters.getUserInfo;
console.log("res", response);
})
.catch((error) => {
console.log("error", error.message);
// that.$message.error(error.message);
that.$message("请先登录");
that.$router.push("/login");
});
// if (that.$store.getters.getToken == "") {
// that.$message("请先登录");
// that.$router.push("/login");
// }
},
data() {
return {
userInfo: this.$store.getters.getUserInfo,
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
logout() {
const that = this;
that.$store.commit("delToken");
this.$message.closeAll();
this.$message({
message: "已退出登录,请重新登录",
type: "success",
});
that.$router.push("/login");
console.log("已退出登录");
},
},
};
</script>
<style lang="less">
.container {
height: 100vh;
// background-color: blue;
}
.header {
background-color: white;
.grid-content {
border-radius: 4px;
height: 60px;
line-height: 60px;
display: flex;
align-items: center;
.logo {
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
border-radius: 10px;
background-color: #a5d8ff;
color: #fff;
}
}
.el-col:nth-child(2) .grid-content {
flex-direction: row-reverse;
}
.avatarImg {
width: 30px;
height: 30px;
box-sizing: border-box;
border-radius: 5px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background-color: #b2f2bb;
margin-right: 10px;
}
.username {
margin-right: 10px;
}
// line-height: 58px;
// text-align: center;
// border: 1px solid black;
}
.aside {
// scroll-behavior: auto;
// flex: 1;
// width: 250px;
border: 1px solid black;
background-color: #fff;
.el-menu-vertical-demo {
// width: 250px;
}
}
.main {
// background-color: green;
border: 1px solid black;
}
.footer {
background-color: black;
border: 1px solid black;
}
</style>

155
src/views/login/index.vue Normal file
View File

@@ -0,0 +1,155 @@
<template>
<div class="loginPage">
<el-row class="loginItem">
<el-form
:inline="false"
:model="ruleForm"
label-position="right"
class="formItem"
:rules="rules"
ref="ruleForm"
>
<el-col :span="8" :xs="24" :sm="24" :md="8" :lg="8">
<el-form-item
label="用户名:"
label-width="100px"
prop="username"
style="padding-right: 20px"
>
<el-input
v-model="ruleForm.username"
placeholder="请输入用户名"
class="usernameClass"
></el-input> </el-form-item
></el-col>
<el-col
:span="8"
:xs="24"
:sm="24"
:md="8"
:lg="8"
style="padding-right: 20px"
>
<el-form-item label="密码:" label-width="100px" prop="pwd">
<el-input
placeholder="请输入密码"
v-model="ruleForm.pwd"
show-password
class="usernameClass"
></el-input> </el-form-item
></el-col>
<el-col :span="8" :xs="24" :sm="24" :md="8" :lg="8">
<el-form-item>
<el-button type="primary" round @click="submitForm('ruleForm')"
>登录</el-button
>
</el-form-item></el-col
>
</el-form>
</el-row>
</div>
</template>
<script>
import { apis } from "../../api/index";
// console.log(apis);
export default {
data() {
return {
formInline: {},
ruleForm: {
username: "",
pwd: "",
},
rules: {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" },
{ min: 6, message: "用户名不得少于6字符", trigger: "blur" },
],
pwd: [
{ required: true, message: "请输入密码", trigger: "blur" },
{ min: 6, message: "密码不得少于6字符", trigger: "blur" },
],
},
};
},
methods: {
userLogin() {
let that = this;
that
.$http({
// 利用实际后端服务的
method: apis.user.login.method,
url: apis.user.login.url,
params: {
username: that.ruleForm.username,
password: that.ruleForm.pwd,
},
//利用mock的
// method: "POST", // 使用 POST 方法
// url: "/login", // 使用 mock 接口路径
// data: {
// username: that.ruleForm.username,
// password: that.ruleForm.pwd,
// },
})
.then((response) => {
that.$message.closeAll();
that.$message({
message: "登陆成功",
type: "success",
});
that.$store.commit("setToken", response.data.data);
console.log("res", response);
that.$router.push("/");
})
.catch((error) => {
console.log("error", error.message);
console.log("error", error);
that.$message.error(error.message);
});
},
submitForm(formName) {
let that = this;
console.log(that.$refs);
that.$refs[formName].validate((valid) => {
if (valid) {
that.userLogin();
} else {
return false;
}
});
},
},
// mounted() {
// console.log("*******", this.$http);
// this.userLogin();
// },
};
</script>
<style lang="less">
.loginPage {
text-align: center;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
// background-color: aquamarine;
.loginItem {
width: 100%;
// background-color: antiquewhite;
.formItem {
width: 100%;
// background-color: yellow;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
}
</style>

169
src/views/test/test.vue Normal file
View File

@@ -0,0 +1,169 @@
<template>
<div>
<el-row :gutter="20">
<el-form
:inline="true"
:model="formInline"
class="demo-form-inline"
ref="formInline"
>
<el-col :span="6">
<el-form-item prop="activityName">
<el-row :gutter="20"></el-row>
<el-input
v-model="formInline.activityName"
placeholder="请输入活动名"
></el-input>
</el-form-item>
</el-col>
<el-col :span="6" :offset="12">
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
<el-button @click="resetForm('formInline')">重置</el-button>
</el-form-item>
</el-col>
</el-form>
</el-row>
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="activityTitle" label="活动名"> </el-table-column>
<el-table-column :formatter="formatCategoryName" label="分类">
</el-table-column>
<el-table-column prop="activityStartTime" label="活动日期">
</el-table-column>
<el-table-column prop="activityPeopleLimit" label="活动限制人数">
</el-table-column>
<el-table-column prop="address" label="操作">
<el-button @click="handleClick(scope.row)" type="text" size="small"
>查看</el-button
>
<el-button type="text" size="small">编辑</el-button>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { apis } from "../../api/index";
export default {
name: "actlist",
data() {
return {
tableData: [
{
activityAddress: "待定111",
activityCategoryId: 1,
activityCreateUser: 1,
activityDetails: "活动详情",
activityEndTime: "2024-09-10 12:30:56",
activityInfo: "活动简介",
activityLineType: "1",
activityPayType: "1",
activityPeopleLimit: 10,
activityPrice: 0,
activityStartTime: "2024-09-07 12:30:53",
activityStatus: "2",
activitySubTitle: "深圳莲花山徒步",
activityTitle: "深圳莲花山徒步",
activityViewNum: 9,
avatarImgUrl:
"https://wimg.huodongxing.com/logo/201903/4484513874100/703364679296756_v2large.jpg@!wmlogo",
createTime: "2024-09-07 09:38:05",
id: 1,
updateTime: "2024-09-07 09:38:05",
},
],
formInline: {
activityName: "",
},
categories: [
{
categoryAlias: "徒步",
categoryName: "徒步",
createTime: "2024-Sep-07 09:43:52",
createUser: 1,
id: 1,
updateTime: "2024-Sep-07 04:32:57",
},
{
categoryAlias: "读书会",
categoryName: "读书会",
createTime: "2024-Sep-07 04:33:11",
createUser: 1,
id: 2,
updateTime: "2024-Sep-07 04:33:11",
},
],
};
},
computed: {},
mounted() {
this.fetchCategories();
},
methods: {
fetchCategories() {
this.$http({
method: apis.category.lists.method,
url: apis.category.lists.url,
headers: {
Authorization: this.$store.getters.getToken,
},
})
.then((response) => {
this.$store.commit("setCategories", response.data.data);
this.categories = this.$store.getters.getCategories;
})
.catch((error) => {
console.log("error", error.message);
this.$message.error(error.message);
});
},
onSubmit() {
const that = this;
that
.$http({
method: apis.activity.lists.method,
url: apis.activity.lists.url,
headers: {
Authorization: that.$store.getters.getToken,
},
params: {
pageNum: 1,
pageSize: 2,
activityTitle: this.formInline.activityName,
},
})
.then((response) => {
that.$message.closeAll();
that.$message({
message: "查询完毕",
type: "success",
});
that.$store.commit("setActivities", response.data.data);
that.tableData = this.$store.getters.getActivities;
console.log("res", response);
})
.catch((error) => {
console.log("error", error.message);
that.$message.error(error.message);
});
this.tableData = that.$store.getters.getActivities;
that.categories = this.$store.getters.getCategories;
console.log(
"this.categories",
that.categories,
this.$store.getters.getCategories
);
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.onSubmit();
},
handleClick(row) {
console.log(row);
},
},
};
</script>
<style>
</style>

70
vue.config.js Normal file
View File

@@ -0,0 +1,70 @@
const { defineConfig } = require('@vue/cli-service')
// const Mock = require('mockjs');
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
devServer: {
proxy: {
'/api': {
target: 'https://activityadminserver.dsx2020.com',
ws: true,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
},
}
}
// 可以继续添加其他 mock 接口
// devServer: {
// setupMiddlewares: (middlewares, devServer) => {
// // Mock 登录接口
// devServer.app.post('/api/login', (req, res) => {
// // 模拟的用户信息
// const userInfo = {
// username: 'dsx2016',
// password: '123456',
// };
// // 根据请求数据判断登录是否成功
// let body = '';
// req.on('data', chunk => {
// body += chunk.toString(); // 将请求体数据拼接
// });
// req.on('end', () => {
// const { username, password } = JSON.parse(body);
// if (username === userInfo.username && password === userInfo.password) {
// res.json({ code: 200, message: '登录成功', token: 'fake-token' });
// } else {
// res.json({ code: 401, message: '用户名或密码错误' });
// }
// });
// });
// // Mock 获取活动列表接口
// devServer.app.get('/api/activities', (req, res) => {
// const data = Mock.mock({
// code: 200,
// data: {
// 'list|10': [
// {
// 'id|+1': 1, // 自增的 id
// title: () => Mock.Random.ctitle(5, 10), // 随机中文标题
// description: () => Mock.Random.cparagraph(1, 3), // 随机中文段落
// date: () => Mock.Random.date(), // 随机日期
// },
// ],
// },
// });
// res.json(data);
// });
// // 其他 mock 接口可以继续添加
// return middlewares; // 返回中间件数组
// },
// },
})