Initial commit: first version of project
This commit is contained in:
11
src/views/NotFound.vue
Normal file
11
src/views/NotFound.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="not-found">
|
||||
<div class="not-found-title">404</div>
|
||||
<div class="not-found-text">您访问的页面不存在</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
19
src/views/admin/dashboard.vue
Normal file
19
src/views/admin/dashboard.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- 面板主页 -->
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-text">欢迎来到面板首页</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.dashboard {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
116
src/views/admin/index.vue
Normal file
116
src/views/admin/index.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
<!-- 主页 -->
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 左侧 导航栏 -->
|
||||
<div class="container-left">
|
||||
<h4>东方低碳</h4>
|
||||
<div class="left-nav">
|
||||
<AdminMenu />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧 主体 -->
|
||||
<div class="container-right">
|
||||
<div class="top">
|
||||
<MenuFoldOutlined />
|
||||
<div class="account">
|
||||
<img src="../../assets/images/avatar.png" alt="头像" />
|
||||
<span>admin</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="breadcrumb">
|
||||
<!-- 面包屑 -->
|
||||
<router-link to="/admin">首页</router-link>/{{ currentRouteName }}
|
||||
</div>
|
||||
<div class="main">
|
||||
<!-- 主内容区 -->
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import AdminMenu from '@/components/admin/Menu.vue'
|
||||
const route = useRoute()
|
||||
// 根据当前路由获取面包屑名称
|
||||
const currentRouteName = computed(() => {
|
||||
return route.meta?.breadcrumb || ''
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
gap: 0px;
|
||||
|
||||
.container-left {
|
||||
width: 260px;
|
||||
background-color: #013249;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
h4 {
|
||||
color: #ffffff;
|
||||
padding: 20px 16px 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.left-nav {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.container-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.top {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #ffffff;
|
||||
|
||||
.anticon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.account {
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
margin-right: 8px;
|
||||
width: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//面包屑
|
||||
.breadcrumb {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
a {
|
||||
color: #666666;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
112
src/views/admin/login.vue
Normal file
112
src/views/admin/login.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<!-- src/views/Login.vue -->
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div class="login-form">
|
||||
<h2>用户登录</h2>
|
||||
<a-form :model="formState" :rules="rules" @finish="handleLogin">
|
||||
<a-form-item name="username">
|
||||
<a-input v-model:value="formState.username" placeholder="请输入用户名" size="large">
|
||||
<template #prefix>
|
||||
<UserOutlined />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="password">
|
||||
<a-input-password v-model:value="formState.password" placeholder="请输入密码" size="large">
|
||||
<template #prefix>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button type="primary" html-type="submit" size="large" block :loading="loading">
|
||||
登录
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { http } from '@/utils/axios';
|
||||
|
||||
interface FormState {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const formState = ref<FormState>({
|
||||
username: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const rules = {
|
||||
username: [{ required: true, message: '请输入用户名' }],
|
||||
password: [{ required: true, message: '请输入密码' }]
|
||||
}
|
||||
|
||||
const handleLogin = async (values: FormState) => {
|
||||
loading.value = true
|
||||
const params = { data: values.username, pwd: values.password };
|
||||
http.post('/perm/login', params).then(res => {
|
||||
console.log(res.data);
|
||||
if (res.data.code === '0') {
|
||||
message.success('登录成功')
|
||||
window.sessionStorage.setItem('token', res.data.data.token);
|
||||
console.log(res.data.data.token, 'hahah', window.sessionStorage.getItem('token'));
|
||||
router.push('/admin')//跳转到管理端首页
|
||||
} else {
|
||||
message.error(res.data.message)
|
||||
}
|
||||
})
|
||||
// try {
|
||||
// await userStore.login({
|
||||
// username: values.username,
|
||||
// password: values.password
|
||||
// })
|
||||
// message.success('登录成功')
|
||||
// router.push('/admin')//跳转到管理端首页
|
||||
// } catch (error) {
|
||||
// message.error('登录失败,请检查用户名和密码')
|
||||
// } finally {
|
||||
// loading.value = false
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
width: 360px;
|
||||
padding: 36px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.login-form h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
color: #1890ff;
|
||||
}
|
||||
</style>
|
397
src/views/admin/newsCenter/add.vue
Normal file
397
src/views/admin/newsCenter/add.vue
Normal file
@@ -0,0 +1,397 @@
|
||||
<template>
|
||||
<div class="addOredit">
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<span class="" @click="save">保存</span>
|
||||
<span class="" @click="publish" v-if="typeValue == '2'">发布</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="" @click="cancel">取消</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<div class="top">
|
||||
<a-form-item name="newTitle" label="新闻标题">
|
||||
<a-textarea v-model:value="titleName" />
|
||||
<div class="num">{{ titleName.length }}/150</div>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<!-- 富文本编辑器 -->
|
||||
<Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" style="border-bottom: 1px solid #f2f2f2" />
|
||||
<Editor v-model="valueHtml" :defaultConfig="editorConfig"
|
||||
style="height: 800px; overflow-y: hidden; border: 1px solid #f2f2f2;" @onCreated="handleCreated"
|
||||
@onChange="handleChange" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h4>基本属性</h4>
|
||||
<a-form ref="formRef" name="custom-validation" :model="formState" class="basicattribute">
|
||||
<a-form-item has-feedback label="作者" name="author">
|
||||
<a-input v-model:value="formState.author" type="text" autocomplete="off" />
|
||||
</a-form-item>
|
||||
<a-form-item has-feedback label="编辑" name="editor">
|
||||
<a-input v-model:value="formState.editor" type="text" autocomplete="off" />
|
||||
</a-form-item>
|
||||
<a-form-item ref="name" label="封面图">
|
||||
<!-- <a-image :width="80" :height="80" class="imgItem" :src="imageUrl" /> -->
|
||||
<a-upload v-model:file-list="fileList" name="coverImage" list-type="picture-card" class="cover-uploader"
|
||||
:show-upload-list="true" :action="uploadUrl" :max-count="1" :customRequest="setRequest">
|
||||
<div v-if="fileList.length < 1">
|
||||
<plus-outlined />
|
||||
<div style="margin-top: 8px">上传</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<!-- 图片预览 -->
|
||||
<a-modal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancelPreview">
|
||||
<img alt="预览图片" :src="previewImage" style="width: 100%" />
|
||||
</a-modal>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUnmount, shallowRef, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { PlusOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { UploadProps } from 'ant-design-vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { IDomEditor } from '@wangeditor/editor'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import { http } from '@/utils/axios';
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
// 编辑器实例
|
||||
const editorRef = shallowRef()
|
||||
const valueHtml = ref('')
|
||||
|
||||
//当前编辑传来的data数据
|
||||
const currentData = ref();
|
||||
const typeValue = ref();
|
||||
|
||||
// 上传相关
|
||||
const fileList = ref<UploadProps['fileList']>([]);
|
||||
const uploadUrl = ref('/api/system/minio/upload') // 替换为实际上传接口
|
||||
const previewVisible = ref(false)
|
||||
const previewImage = ref('')
|
||||
const previewTitle = ref('')
|
||||
const imageUrl = ref('');
|
||||
|
||||
const titleName = ref('');//新闻标题
|
||||
const formState = ref({
|
||||
author: '',
|
||||
editor: '',
|
||||
coverImageUrl: '',
|
||||
attachId: '',//图片id
|
||||
});
|
||||
//接收跳转路由过来的参数
|
||||
onMounted(() => {
|
||||
const { data, type } = route.query;
|
||||
if (data && typeof data === 'string' && type == '2') {//编辑
|
||||
console.log(JSON.parse(data), '我是新增页面新增新增', type);
|
||||
const parsedData = JSON.parse(data);
|
||||
console.log(parsedData, type);
|
||||
typeValue.value = type;
|
||||
currentData.value = parsedData;
|
||||
getByEditData()
|
||||
}
|
||||
});
|
||||
//获取编辑数据
|
||||
const getByEditData = async () => {
|
||||
await http.post("/api/journalism/getDetailById", currentData.value.id).then(res => {
|
||||
console.log(res, '获取编辑数据');
|
||||
if (res.data.code == '0') {
|
||||
const dataData = res.data.data;
|
||||
if (dataData) {
|
||||
//回填表单数据
|
||||
titleName.value = dataData.title;
|
||||
formState.value.author = dataData.author;
|
||||
formState.value.editor = dataData.editor;
|
||||
formState.value.attachId = dataData.attachId;
|
||||
//富文本编辑器回填
|
||||
if (editorRef.value) {
|
||||
valueHtml.value = dataData.content;
|
||||
} else {
|
||||
// 延迟一点时间再设置
|
||||
setTimeout(() => {
|
||||
valueHtml.value = dataData.content;
|
||||
}, 100);
|
||||
}
|
||||
//获取图片
|
||||
// 请求图片文件
|
||||
const attachId = dataData.attachId;
|
||||
const config: any = {
|
||||
responseType: 'blob',
|
||||
};
|
||||
if (attachId) {
|
||||
// 下载图片用以显示
|
||||
http.post("/api/minio/download" + "?attachId=" + attachId, config).then((res: any) => {
|
||||
const blob = new Blob([res]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
console.log(url, '图片地址222222');
|
||||
imageUrl.value = url;
|
||||
fileList.value = [{
|
||||
uid: '-1',
|
||||
name: dataData.title ? `${dataData.title}.jpg` : 'image.jpg',
|
||||
status: 'done',
|
||||
url: url,
|
||||
thumbUrl: url,
|
||||
response: { url: url }
|
||||
}];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
});
|
||||
}
|
||||
//获取上传图片的id
|
||||
|
||||
/************************富文本编辑器*********************/
|
||||
// 工具栏配置
|
||||
const toolbarConfig = {}
|
||||
// 编辑器配置
|
||||
const editorConfig = {
|
||||
placeholder: '请输入内容...',
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
// 图片上传配置
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑器创建回调
|
||||
const handleCreated = (editor: IDomEditor) => {
|
||||
editorRef.value = editor
|
||||
}
|
||||
|
||||
// 内容变化回调
|
||||
const handleChange = (editor: IDomEditor) => {
|
||||
valueHtml.value = editor.getHtml()
|
||||
}
|
||||
|
||||
// 组件销毁时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value
|
||||
if (editor == null) return
|
||||
editor.destroy()
|
||||
})
|
||||
/*********************上传图片***************************/
|
||||
// 预览图片
|
||||
const handlePreview = async (file: any) => {
|
||||
if (!file.url && !file.preview) {
|
||||
file.preview = await getBase64(file.originFileObj)
|
||||
}
|
||||
previewImage.value = file.url || file.preview
|
||||
previewVisible.value = true
|
||||
previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
|
||||
}
|
||||
|
||||
// 取消预览
|
||||
const handleCancelPreview = () => {
|
||||
previewVisible.value = false
|
||||
previewTitle.value = ''
|
||||
}
|
||||
|
||||
// 转换为base64
|
||||
const getBase64 = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
const limit = 10;
|
||||
// 上传图片文件
|
||||
const setRequest = (f: any) => {
|
||||
const file1 = f.file;
|
||||
const isJpgOrPng = file1.type === 'image/jpeg' || file1.type === 'image/png';
|
||||
if (!isJpgOrPng) {
|
||||
return message.warn('只能上传图片!');
|
||||
}
|
||||
const isLt2M = file1.size / 1024 / 1024 < limit;
|
||||
if (!isLt2M) {
|
||||
return message.warn(`文件最大不能超过${limit}M!`);
|
||||
}
|
||||
const formData = new FormData();
|
||||
formData.append('file', file1);
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
};
|
||||
http.post('/api/minio/upload', formData, config).then((res: any) => {
|
||||
const data = res.data;
|
||||
fileList.value = [
|
||||
{
|
||||
uid: file1.uid,
|
||||
name: file1.name,
|
||||
status: 'done',
|
||||
url: data.data.link,
|
||||
thumbUrl: data.data.link//缩略图显示
|
||||
},
|
||||
];
|
||||
formState.value.attachId = data.data.id;
|
||||
formState.value.coverImageUrl = data.data.link;
|
||||
console.log(res);
|
||||
})
|
||||
};
|
||||
|
||||
// 保存
|
||||
const save = async () => {
|
||||
console.log('save')
|
||||
const params = {
|
||||
title: titleName.value,
|
||||
content: valueHtml.value,
|
||||
author: formState.value.author,
|
||||
editor: formState.value.editor,
|
||||
publishStatus: "3",
|
||||
attachId: formState.value?.attachId,//图片的id
|
||||
}
|
||||
if (currentData.value) {//编辑时
|
||||
params.id = currentData.value.id;
|
||||
}
|
||||
await http.post('/api/journalism/save', params).then(res => {
|
||||
if (res.data.code === '0') {
|
||||
message.success('保存成功')
|
||||
router.push('/admin/news')
|
||||
} else {
|
||||
message.error(res.data.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 发布(编辑时发布)
|
||||
const publish = () => {
|
||||
console.log('publish')
|
||||
const params: any[] = [];
|
||||
params.push(currentData?.value.code);
|
||||
http.post('/api/journalism/publishByCodeList', params).then(res => {
|
||||
if (res.data.code == '0') {
|
||||
message.success('重新发布成功');
|
||||
router.push('/admin/news')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
//取消
|
||||
const cancel = () => {
|
||||
console.log('cancel')
|
||||
router.push('/admin/news')
|
||||
}
|
||||
//页面关闭时销毁当前页数据
|
||||
onUnmounted(() => {
|
||||
// 重置所有响应式数据
|
||||
titleName.value = '';
|
||||
valueHtml.value = '';
|
||||
formState.value = {
|
||||
author: '',
|
||||
editor: '',
|
||||
coverImageUrl: '',
|
||||
attachId: '',
|
||||
};
|
||||
|
||||
// 清空文件列表
|
||||
fileList.value = [];
|
||||
|
||||
// 重置当前数据
|
||||
currentData.value = null;
|
||||
typeValue.value = null;
|
||||
|
||||
// 重置预览相关数据
|
||||
previewVisible.value = false;
|
||||
previewImage.value = '';
|
||||
previewTitle.value = '';
|
||||
|
||||
// 销毁编辑器实例
|
||||
if (editorRef.value) {
|
||||
editorRef.value.destroy();
|
||||
editorRef.value = null;
|
||||
}
|
||||
|
||||
console.log('页面数据已清理');
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.addOredit {
|
||||
width: 1200px;
|
||||
margin: auto;
|
||||
|
||||
.header {
|
||||
height: 52px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
|
||||
.left {
|
||||
span {
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
height: calc(100vh - 212px);
|
||||
gap: 10px;
|
||||
|
||||
.left {
|
||||
flex: 2;
|
||||
|
||||
|
||||
|
||||
.top {
|
||||
background: #fff;
|
||||
padding: 20px 20px 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.num {
|
||||
text-align: right;
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
height: calc(100% - 120px);
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
|
||||
h4 {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.basicattribute {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
405
src/views/admin/newsCenter/news.vue
Normal file
405
src/views/admin/newsCenter/news.vue
Normal file
@@ -0,0 +1,405 @@
|
||||
<!-- src/views/admin/users.vue -->
|
||||
<template>
|
||||
<div class="newsCenter">
|
||||
<div class="form">
|
||||
<a-form :model="formState" :layout="'inline'" @finish="onFinish" class="ant-form-inline-custom">
|
||||
<a-form-item name="inputValue" label="标题">
|
||||
<a-input v-model:value="formState.inputValue" placeholder="请输入标题" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item name="selectValue" label="状态">
|
||||
<a-select v-model:value="formState.selectValue" style="width: 150px" placeholder="请选择状态" :option="newStatus">
|
||||
<a-select-option v-for="item in newStatus" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="发布时间">
|
||||
<a-range-picker v-model:value="dateRange" format="YYYY-MM-DD" :placeholder="['开始日期', '结束日期']" />
|
||||
</a-form-item>
|
||||
<a-form-item label="创建时间">
|
||||
<a-range-picker v-model:value="createDate" format="YYYY-MM-DD" :placeholder="['开始日期', '结束日期']" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button type="primary" html-type="submit" @click="getTableData()">查询</a-button>
|
||||
<a-button style="margin-left: 8px" @click="resetForm">
|
||||
重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a-button type="primary" @click="addEditNews('', '1')">新增</a-button>
|
||||
<a-button type="primary" @click="batchPublish">批量发布</a-button>
|
||||
<a-button type="primary" danger @click=deleteNews>批量删除</a-button>
|
||||
</div>
|
||||
<a-table :dataSource="dataSource" :columns="columns" bordered :pagination="pagination" @change="handleTableChange"
|
||||
:row-selection="rowSelection" row-key="id">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'status'">
|
||||
{{ record.publishStatus.label }}
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<div class="operEdit">
|
||||
<!-- 草稿时为发布 -->
|
||||
<a-button type="text" @click="publish(record)" v-if="record.publishStatus.value === 0" class="blue">
|
||||
发布
|
||||
</a-button>
|
||||
<!-- 已撤回的话,是重新发布 -->
|
||||
<a-button type="text" @click="rePublish(record)"
|
||||
v-if="record.publishStatus.value === 2 || record.publishStatus.value === 3" class="blue">
|
||||
重新发布
|
||||
</a-button>
|
||||
<a-button type="text" v-if="record.publishStatus.value === 0 || record.publishStatus.value === 1"
|
||||
class="blue" @click="addEditNews(record, '3')">
|
||||
撤销
|
||||
</a-button>
|
||||
<a-button type="text" class="blue" @click="addEditNews(record, '2')">
|
||||
编辑
|
||||
</a-button>
|
||||
<a-button type="text" danger @click="deleteNews(record, '2')">删除</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { http } from '@/utils/axios';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
const router = useRouter()
|
||||
|
||||
const newStatus = ref([]);//状态枚举
|
||||
|
||||
// 表单部分
|
||||
interface FormState {
|
||||
inputValue: string;
|
||||
selectValue?: string;
|
||||
}
|
||||
|
||||
const formState = reactive<FormState>({
|
||||
inputValue: '',
|
||||
selectValue: undefined,
|
||||
});
|
||||
|
||||
// 修改日期范围的类型定义
|
||||
const dateRange = ref<[Dayjs | null, Dayjs | null]>([null, null]);
|
||||
const createDate = ref<[Dayjs | null, Dayjs | null]>([null, null]);
|
||||
|
||||
|
||||
// 表单-获取枚举数据
|
||||
const getEnum = async () => {
|
||||
// 请求枚举数据
|
||||
await http.postText('/system/common/getEnum', 'PublishStatus')
|
||||
try {
|
||||
const res = await http.postText('/system/common/getEnum', 'PublishStatus');
|
||||
if (res?.data?.code === "0" && res.data.data?.length > 0) {
|
||||
// 确保数据格式正确
|
||||
newStatus.value = res.data.data.map((item: any) => ({
|
||||
label: item.label,
|
||||
value: item.value
|
||||
}));
|
||||
} else {
|
||||
newStatus.value = [];
|
||||
}
|
||||
console.log(newStatus.value, '枚举数据');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
const onFinish = (values: FormState) => {
|
||||
console.log('Received values:', values);
|
||||
console.log('Date range:', dateRange.value);
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
formState.inputValue = '';
|
||||
formState.selectValue = undefined;
|
||||
dateRange.value = [null, null];
|
||||
createDate.value = [null, null];
|
||||
};
|
||||
/***********************新增新闻******************************/
|
||||
const addEditNews = (data: any, type: string) => {
|
||||
console.log('新增新闻');
|
||||
if (type === '1') {//新增
|
||||
router.push('/admin/news/add')
|
||||
} else if (type === '2') {//编辑
|
||||
console.log(data, '编辑');
|
||||
const dataParams = { id: data.id, code: data.code }
|
||||
router.push({
|
||||
name: 'AdminNewsAdd',
|
||||
query: {
|
||||
data: JSON.stringify(dataParams),
|
||||
type: '2'
|
||||
}
|
||||
})
|
||||
} else if (type === '3') {//撤销,掉接口提交即可
|
||||
console.log(data, '撤销');
|
||||
const params = {
|
||||
// title: data.title,
|
||||
// content: "标题内容",
|
||||
// author: "sjs",
|
||||
// editor: "sjs",
|
||||
publishStatus: "2",
|
||||
id: data.id
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '警告',
|
||||
content: '确定要撤销吗?此操作不可恢复。',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
http.post('/api/journalism/save', params).then(res => {
|
||||
if (res.data.code === '0') {
|
||||
message.success('撤销成功')
|
||||
getTableData();
|
||||
} else {
|
||||
message.error(res.data.message)
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
console.log('取消删除');
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
//删除
|
||||
const deleteNews = (data: any, type: string) => {
|
||||
console.log(data, '删除');
|
||||
if (!type && selectedRows.value.length == 0) {//批量删除
|
||||
message.warning('请选择要删除的新闻');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '警告',
|
||||
content: '确定要删除选中的新闻吗?此操作不可恢复。',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
const getCodeArr: any[] = [];
|
||||
if (!type) {//批量删除
|
||||
for (let i = 0; i < selectedRows.value.length; i++) {
|
||||
getCodeArr.push(selectedRows.value[i].code)
|
||||
}
|
||||
}
|
||||
if (type == '2') {//单个删除
|
||||
getCodeArr.push(data.code)
|
||||
}
|
||||
|
||||
return http.post('/api/journalism/deleteByCodeList', getCodeArr).then(res => {
|
||||
if (res.data.code === '0') {
|
||||
message.success('删除成功')
|
||||
getTableData();
|
||||
} else {
|
||||
message.error(res.data.message)
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
console.log('取消删除');
|
||||
},
|
||||
});
|
||||
}
|
||||
//批量发布
|
||||
const batchPublish = () => {
|
||||
if (selectedRows.value.length == 0) {
|
||||
message.warning('请选择要发布的新闻');
|
||||
return
|
||||
} else {
|
||||
const getCode: any[] = [];
|
||||
for (let i = 0; i < selectedRows.value.length; i++) {
|
||||
getCode.push(selectedRows.value[i].code)
|
||||
}
|
||||
console.log(getCode, '批量发布');
|
||||
releaseFunc(getCode, '1')
|
||||
}
|
||||
}
|
||||
//发布
|
||||
const publish = (data: any) => {
|
||||
const getCode: any[] = [];
|
||||
getCode.push(data.code)
|
||||
releaseFunc(getCode, '2')
|
||||
}
|
||||
//重新发布
|
||||
const rePublish = (data: any) => {
|
||||
const getCode: any[] = [];
|
||||
getCode.push(data.code)
|
||||
releaseFunc(getCode, '3')
|
||||
}
|
||||
/***********************表格部分******************************/
|
||||
// 表格选中项
|
||||
const selectedRowKeys = ref<string[]>([]);
|
||||
const selectedRows = ref<any[]>([]);
|
||||
|
||||
// 表格行选择配置
|
||||
const rowSelection = computed(() => ({
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onChange: (selectedKeys: any[], selectedRowsData: any[]) => {
|
||||
selectedRowKeys.value = selectedKeys;
|
||||
selectedRows.value = selectedRowsData;
|
||||
},
|
||||
columnWidth: '60px',
|
||||
}));
|
||||
// 分页配置
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: (total: number) => `共 ${total} 条数据`,
|
||||
});
|
||||
const dataSource = ref()//表格数据源
|
||||
const columns = ref([
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'address',
|
||||
customRender: (text: any) => {
|
||||
return text.index + 1;
|
||||
},
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '标题',
|
||||
dataIndex: 'title',
|
||||
key: 'title'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status'
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'publishTimeStr',
|
||||
key: 'publishTimeStr'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTimeStr',
|
||||
key: 'createTimeStr'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
key: 'operation'
|
||||
}
|
||||
])
|
||||
// 表格分页变化处理
|
||||
const handleTableChange = (pag: any) => {
|
||||
pagination.current = pag.current;
|
||||
pagination.pageSize = pag.pageSize;
|
||||
// 重新获取数据
|
||||
getTableData();
|
||||
};
|
||||
// 获取表格数据
|
||||
const getTableData = async () => {
|
||||
console.log('获取表格数据');
|
||||
const params = {
|
||||
"page": {
|
||||
"pageNum": pagination.current,
|
||||
"pageSize": pagination.pageSize
|
||||
},
|
||||
"selectParam": {
|
||||
"title": formState.inputValue ? formState.inputValue : undefined,
|
||||
"publishStatus": formState?.selectValue ?? undefined,
|
||||
}
|
||||
}
|
||||
// 发布时间范围
|
||||
if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
|
||||
params.selectParam.publishStartTime = dayjs(dateRange.value[0]).format('YYYY-MM-DD');
|
||||
params.selectParam.publishEndTime = dayjs(dateRange.value[1]).format('YYYY-MM-DD');
|
||||
}
|
||||
// 创建时间范围
|
||||
if (createDate.value && createDate.value[0] && createDate.value[1]) {
|
||||
params.selectParam.createStartTime = dayjs(createDate.value[0]).format('YYYY-MM-DD');
|
||||
params.selectParam.createEndTime = dayjs(createDate.value[1]).format('YYYY-MM-DD');
|
||||
}
|
||||
await http.post('/api/journalism/getPageList', params).then(res => {
|
||||
console.log("hahahres", res)
|
||||
if (res.data?.data?.records.length > 0) {
|
||||
dataSource.value = res.data.data.records;
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
//表格批量发布:1、发布:2、重新发布:3
|
||||
const releaseFunc = async (params: any, type: string) => {
|
||||
console.log('表格批量发布、发布、重新发布');
|
||||
await http.post('/api/journalism/publishByCodeList', params).then(res => {
|
||||
if (res.data.code == '0') {
|
||||
if (type == '1') {//批量发布
|
||||
message.success('批量发布成功');
|
||||
getTableData();
|
||||
} else if (type == '2') {//重新发布
|
||||
message.success('重新发布成功');
|
||||
getTableData();
|
||||
} else {//发布
|
||||
message.success('发布成功');
|
||||
getTableData();
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getEnum();
|
||||
getTableData();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.newsCenter {
|
||||
background-color: #ffffff;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 25px;
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 15px 0;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.operEdit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.blue {
|
||||
color: #2778FF;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
padding: 4px 2px;
|
||||
}
|
||||
|
||||
.ant-btn:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
51
src/views/admin/users.vue
Normal file
51
src/views/admin/users.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<!-- src/views/admin/users.vue -->
|
||||
<template>
|
||||
<div class="users">
|
||||
<h2>用户管理</h2>
|
||||
<p>这里是用户管理页面</p>
|
||||
<a-table :dataSource="dataSource" :columns="columns" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const dataSource = ref([
|
||||
{
|
||||
key: '1',
|
||||
name: '张三',
|
||||
age: 32,
|
||||
address: '上海市浦东新区'
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '李四',
|
||||
age: 42,
|
||||
address: '北京市朝阳区'
|
||||
}
|
||||
])
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age'
|
||||
},
|
||||
{
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.users {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
24
src/views/pc/about.vue
Normal file
24
src/views/pc/about.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<a-layout>
|
||||
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible width="256">
|
||||
<Navigation />
|
||||
</a-layout-sider>
|
||||
|
||||
<a-layout>
|
||||
<a-layout-content class="content">
|
||||
<div class="content-inner">
|
||||
<h1>欢迎来到about页2222222222222</h1>
|
||||
<p>这里是网站的主要内容区域</p>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Navigation from '@/components/navigation.vue'
|
||||
const collapsed = ref(false)
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
33
src/views/pc/index.vue
Normal file
33
src/views/pc/index.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<!-- src/views/News.vue -->
|
||||
<template>
|
||||
<div class="index-home">
|
||||
啊哈哈哈哈我来了
|
||||
<div class="content">
|
||||
我是首页内容
|
||||
<!-- 将轮播图放在内容区域或页脚区域 -->
|
||||
<div class="carousel-wrapper">
|
||||
<a-carousel autoplay :autoplay-speed="5000">
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_1.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_2.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_3.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
</a-carousel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
104
src/views/pc/news.vue
Normal file
104
src/views/pc/news.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<!-- src/views/News.vue -->
|
||||
<template>
|
||||
<div class="news">
|
||||
<a-layout>
|
||||
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible width="256">
|
||||
<Navigation />
|
||||
</a-layout-sider>
|
||||
|
||||
<a-layout>
|
||||
<a-layout-content class="content">
|
||||
<div class="content-inner">
|
||||
<h1>新闻消息22222</h1>
|
||||
<a-list class="news-list" item-layout="vertical" size="large" :pagination="pagination"
|
||||
:data-source="newsList">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item key="item.title">
|
||||
<a-list-item-meta :description="item.date">
|
||||
<template #title>
|
||||
<a :href="item.href">{{ item.title }}</a>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
{{ item.content }}
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
<!-- 将轮播图放在内容区域或页脚区域 -->
|
||||
<div class="carousel-wrapper">
|
||||
<a-carousel autoplay :autoplay-speed="5000">
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_1.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_2.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
<div>
|
||||
<video src="https://ec-resource20.oss-cn-shanghai.aliyuncs.com/ec_official_website/3_3.mp4" autoplay loop
|
||||
muted playsinline style="width: 100%; height: auto;"></video>
|
||||
</div>
|
||||
</a-carousel>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Navigation from '@/components/navigation.vue'
|
||||
|
||||
const collapsed = ref(false)
|
||||
|
||||
const newsList = ref([
|
||||
{
|
||||
title: '网站正式上线',
|
||||
href: '#',
|
||||
date: '2025-01-01',
|
||||
content: '我们的网站今天正式上线了,欢迎大家访问!'
|
||||
},
|
||||
{
|
||||
title: '新功能发布',
|
||||
href: '#',
|
||||
date: '2025-01-05',
|
||||
content: '我们发布了全新的个人中心功能,提供更多个性化服务。'
|
||||
},
|
||||
{
|
||||
title: '系统维护通知',
|
||||
href: '#',
|
||||
date: '2025-01-10',
|
||||
content: '为了提供更好的服务,系统将于本周末进行维护升级。'
|
||||
}
|
||||
])
|
||||
|
||||
const pagination = {
|
||||
onChange: (page: number) => {
|
||||
console.log(page)
|
||||
},
|
||||
pageSize: 5,
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.news {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 24px 16px;
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
.content-inner {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.news-list {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
111
src/views/pc/profile.vue
Normal file
111
src/views/pc/profile.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<!-- src/views/Profile.vue -->
|
||||
<template>
|
||||
<div class="profile">
|
||||
<a-layout>
|
||||
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible width="256">
|
||||
<Navigation />
|
||||
</a-layout-sider>
|
||||
|
||||
<a-layout>
|
||||
<a-layout-content class="content">
|
||||
<div class="content-inner">
|
||||
<h1>个人中心</h1>
|
||||
<a-card title="基本信息" style="margin-bottom: 24px;">
|
||||
<a-descriptions :column="1">
|
||||
<a-descriptions-item label="用户名">
|
||||
{{ userInfo.username }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="邮箱">
|
||||
{{ userInfo.email }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="注册时间">
|
||||
{{ userInfo.registerDate }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
|
||||
<a-card title="修改密码">
|
||||
<a-form :model="passwordForm" :rules="passwordRules" @finish="handleChangePassword">
|
||||
<a-form-item label="原密码" name="oldPassword">
|
||||
<a-input-password v-model:value="passwordForm.oldPassword" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="新密码" name="newPassword">
|
||||
<a-input-password v-model:value="passwordForm.newPassword" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="确认新密码" name="confirmPassword">
|
||||
<a-input-password v-model:value="passwordForm.confirmPassword" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button type="primary" html-type="submit">
|
||||
修改密码
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Navigation from '@/components/navigation.vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const collapsed = ref(false)
|
||||
const userStore = useUserStore()
|
||||
|
||||
const userInfo = ref({
|
||||
username: '张三',
|
||||
email: 'zhangsan@example.com',
|
||||
registerDate: '2025-01-01'
|
||||
})
|
||||
|
||||
interface PasswordForm {
|
||||
oldPassword: string
|
||||
newPassword: string
|
||||
confirmPassword: string
|
||||
}
|
||||
|
||||
const passwordForm = ref<PasswordForm>({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
|
||||
const passwordRules = {
|
||||
oldPassword: [{ required: true, message: '请输入原密码' }],
|
||||
newPassword: [{ required: true, message: '请输入新密码' }],
|
||||
confirmPassword: [{ required: true, message: '请确认新密码' }]
|
||||
}
|
||||
|
||||
const handleChangePassword = (values: PasswordForm) => {
|
||||
if (values.newPassword !== values.confirmPassword) {
|
||||
console.log('两次输入的密码不一致')
|
||||
return
|
||||
}
|
||||
console.log('修改密码:', values)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.profile {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 24px 16px;
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
.content-inner {
|
||||
padding: 24px;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user