admin-import

This commit is contained in:
xiaomlove
2021-04-12 20:31:02 +08:00
parent be9b8634c4
commit 3f13ec875f
131 changed files with 125950 additions and 10676 deletions
+113
View File
@@ -0,0 +1,113 @@
<template>
<el-card class="account-container">
<el-form :model="nameForm" :rules="rules" ref="nameRef" label-width="80px" label-position="right" class="demo-ruleForm">
<el-form-item required label="登录名:" prop="loginName">
<el-input style="width: 200px" v-model="nameForm.loginName"></el-input>
</el-form-item>
<el-form-item required label="昵称:" prop="nickName">
<el-input style="width: 200px" v-model="nameForm.nickName"></el-input>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="submitName">确认修改</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="account-container">
<el-form :model="passForm" :rules="rules" ref="passRef" label-width="80px" label-position="right" class="demo-ruleForm">
<el-form-item required label="原密码:" prop="oldpass">
<el-input style="width: 200px" v-model="passForm.oldpass"></el-input>
</el-form-item>
<el-form-item required label="新密码:" prop="newpass">
<el-input style="width: 200px" v-model="passForm.newpass"></el-input>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="submitPass">确认修改</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import axios from '@/utils/axios'
import { ElMessage } from 'element-plus'
import md5 from 'js-md5'
export default {
name: 'Account',
setup() {
const nameRef = ref(null)
const passRef = ref(null)
const state = reactive({
user: null,
nameForm: {
loginName: '',
nickName: ''
},
passForm: {
oldpass: '',
newpass: ''
},
rules: {
loginName: [
{ required: 'true', message: '登录名不能为空', trigger: ['change'] }
],
nickName: [
{ required: 'true', message: '昵称不能为空', trigger: ['change'] }
],
oldpass: [
{ required: 'true', message: '原密码不能为空', trigger: ['change'] }
],
newpass: [
{ required: 'true', message: '新密码不能为空', trigger: ['change'] }
]
},
})
onMounted(() => {
axios.get('/adminUser/profile').then(res => {
state.user = res
state.nameForm.loginName = res.loginUserName
state.nameForm.nickName = res.nickName
})
})
const submitName = () => {
nameRef.value.validate((vaild) => {
if (vaild) {
axios.put('/adminUser/name', {
loginUserName: state.nameForm.loginName,
nickName: state.nameForm.nickName
}).then(() => {
ElMessage.success('修改成功')
window.location.reload()
})
}
})
}
const submitPass = () => {
passRef.value.validate((vaild) => {
if (vaild) {
axios.put('/adminUser/password', {
originalPassword: md5(state.passForm.oldpass),
newPassword: md5(state.passForm.newpass)
}).then(() => {
ElMessage.success('修改成功')
window.location.reload()
})
}
})
}
return {
...toRefs(state),
nameRef,
passRef,
submitName,
submitPass
}
}
}
</script>
<style>
.account-container {
margin-bottom: 20px;
}
</style>
+267
View File
@@ -0,0 +1,267 @@
<template>
<div class="add">
<el-card class="add-container">
<el-form :model="goodForm" :rules="rules" ref="goodRef" label-width="100px" class="goodForm">
<el-form-item required label="商品分类">
<el-cascader :placeholder="defaultCate" style="width: 300px" :props="category" @change="handleChangeCate"></el-cascader>
</el-form-item>
<el-form-item label="商品名称" prop="goodsName">
<el-input style="width: 300px" v-model="goodForm.goodsName" placeholder="请输入商品名称"></el-input>
</el-form-item>
<el-form-item label="商品简介" prop="goodsIntro">
<el-input style="width: 300px" type="textarea" v-model="goodForm.goodsIntro" placeholder="请输入商品简介(100字)"></el-input>
</el-form-item>
<el-form-item label="商品价格" prop="originalPrice">
<el-input type="number" min="0" style="width: 300px" v-model="goodForm.originalPrice" placeholder="请输入商品价格"></el-input>
</el-form-item>
<el-form-item label="商品售卖价" prop="sellingPrice">
<el-input type="number" min="0" style="width: 300px" v-model="goodForm.sellingPrice" placeholder="请输入商品售价"></el-input>
</el-form-item>
<el-form-item label="商品库存" prop="stockNum">
<el-input type="number" min="0" style="width: 300px" v-model="goodForm.stockNum" placeholder="请输入商品库存"></el-input>
</el-form-item>
<el-form-item label="商品标签" prop="tag">
<el-input style="width: 300px" v-model="goodForm.tag" placeholder="请输入商品小标签"></el-input>
</el-form-item>
<el-form-item label="上架状态" prop="goodsSellStatus">
<el-radio-group v-model="goodForm.goodsSellStatus">
<el-radio label="0">上架</el-radio>
<el-radio label="1">下架</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item required label="商品主图" prop="goodsCoverImg">
<el-upload
class="avatar-uploader"
:action="uploadImgServer"
accept="jpg,jpeg,png"
:headers="{
token: token
}"
:show-file-list="false"
:before-upload="handleBeforeUpload"
:on-success="handleUrlSuccess"
>
<img style="width: 100px; height: 100px; border: 1px solid #e9e9e9;" v-if="goodForm.goodsCoverImg" :src="goodForm.goodsCoverImg" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
<el-form-item label="详情内容">
<div ref='editor'></div>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitAdd()">{{ id ? '立即修改' : '立即创建' }}</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
import WangEditor from 'wangeditor'
import axios from '@/utils/axios'
import { ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { localGet, uploadImgServer, uploadImgsServer, hasEmoji } from '@/utils'
export default {
name: 'AddGood',
setup() {
const { proxy } = getCurrentInstance()
console.log('proxy', proxy)
const editor = ref(null)
const goodRef = ref(null)
const route = useRoute()
const router = useRouter()
const { id } = route.query
const state = reactive({
uploadImgServer,
token: localGet('token') || '',
id: id,
defaultCate: '',
goodForm: {
goodsName: '',
goodsIntro: '',
originalPrice: '',
sellingPrice: '',
stockNum: '',
goodsSellStatus: '0',
goodsCoverImg: '',
tag: ''
},
rules: {
goodsName: [
{ required: 'true', message: '请填写商品名称', trigger: ['change'] }
],
originalPrice: [
{ required: 'true', message: '请填写商品价格', trigger: ['change'] }
],
sellingPrice: [
{ required: 'true', message: '请填写商品售价', trigger: ['change'] }
],
stockNum: [
{ required: 'true', message: '请填写商品库存', trigger: ['change'] }
],
},
categoryId: '',
category: {
lazy: true,
lazyLoad(node, resolve) {
const { level = 0, value } = node
axios.get('/categories', {
params: {
pageNumber: 1,
pageSize: 1000,
categoryLevel: level + 1,
parentId: value || 0
}
}).then(res => {
const list = res.list
const nodes = list.map(item => ({
value: item.categoryId,
label: item.categoryName,
leaf: level > 1
}))
resolve(nodes)
})
}
}
})
let instance
onMounted(() => {
instance = new WangEditor(editor.value)
instance.config.showLinkImg = false
instance.config.showLinkImgAlt = false
instance.config.showLinkImgHref = false
instance.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M
instance.config.uploadFileName = 'file'
instance.config.uploadImgHeaders = {
token: state.token
}
// 图片返回格式不同,需要自定义返回格式
instance.config.uploadImgHooks = {
// 图片上传并返回了结果,想要自己把图片插入到编辑器中
// 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert
customInsert: function(insertImgFn, result) {
console.log('result', result)
// result 即服务端返回的接口
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
if (result.data && result.data.length) {
result.data.forEach(item => insertImgFn(item))
}
}
}
instance.config.uploadImgServer = uploadImgsServer
Object.assign(instance.config, {
onchange() {
console.log('change')
},
})
instance.create()
if (id) {
axios.get(`/goods/${id}`).then(res => {
const { goods, firstCategory, secondCategory, thirdCategory } = res
state.goodForm = {
goodsName: goods.goodsName,
goodsIntro: goods.goodsIntro,
originalPrice: goods.originalPrice,
sellingPrice: goods.sellingPrice,
stockNum: goods.stockNum,
goodsSellStatus: String(goods.goodsSellStatus),
goodsCoverImg: proxy.$filters.prefix(goods.goodsCoverImg),
tag: goods.tag
}
state.categoryId = goods.goodsCategoryId
state.defaultCate = `${firstCategory.categoryName}/${secondCategory.categoryName}/${thirdCategory.categoryName}`
if (instance) {
// 初始化商品详情 html
instance.txt.html(goods.goodsDetailContent)
}
})
}
})
onBeforeUnmount(() => {
instance.destroy()
instance = null
})
const submitAdd = () => {
goodRef.value.validate((vaild) => {
if (vaild) {
// 默认新增用 post 方法
let httpOption = axios.post
let params = {
goodsCategoryId: state.categoryId,
goodsCoverImg: state.goodForm.goodsCoverImg,
goodsDetailContent: instance.txt.html(),
goodsIntro: state.goodForm.goodsIntro,
goodsName: state.goodForm.goodsName,
goodsSellStatus: state.goodForm.goodsSellStatus,
originalPrice: state.goodForm.originalPrice,
sellingPrice: state.goodForm.sellingPrice,
stockNum: state.goodForm.stockNum,
tag: state.goodForm.tag
}
if (hasEmoji(params.goodsIntro) || hasEmoji(params.goodsName) || hasEmoji(params.tag) || hasEmoji(params.goodsDetailContent)) {
ElMessage.error('不要输入表情包,再输入就打死你个龟孙儿~')
return
}
console.log('params', params)
if (id) {
params.goodsId = id
// 修改商品使用 put 方法
httpOption = axios.put
}
httpOption('/goods', params).then(() => {
ElMessage.success(id ? '修改成功' : '添加成功')
router.push({ path: '/good' })
})
}
})
}
const handleBeforeUpload = (file) => {
const sufix = file.name.split('.')[1] || ''
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
return false
}
}
const handleUrlSuccess = (val) => {
state.goodForm.goodsCoverImg = val.data || ''
}
const handleChangeCate = (val) => {
state.categoryId = val[2] || 0
}
return {
...toRefs(state),
goodRef,
submitAdd,
handleBeforeUpload,
handleUrlSuccess,
editor,
handleChangeCate
}
}
}
</script>
<style scoped>
.add {
display: flex;
}
.add-container {
flex: 1;
height: 100%;
}
.avatar-uploader {
width: 100px;
height: 100px;
color: #ddd;
font-size: 30px;
}
.avatar-uploader-icon {
display: block;
width: 100%;
height: 100%;
border: 1px solid #e9e9e9;
padding: 32px 17px;
}
</style>
+213
View File
@@ -0,0 +1,213 @@
<template>
<el-card class="category-container">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">增加</el-button>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDelete"
>
<template #reference>
<el-button type="danger" size="small" icon="el-icon-delete">批量删除</el-button>
</template>
</el-popconfirm>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55"
>
</el-table-column>
<el-table-column
prop="categoryName"
label="分类名称"
>
</el-table-column>
<el-table-column
prop="categoryRank"
label="排序值"
width="120"
>
</el-table-column>
<el-table-column
prop="createTime"
label="添加时间"
width="200"
>
</el-table-column>
<el-table-column
label="操作"
width="220"
>
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.categoryId)">修改</a>
<a style="cursor: pointer; margin-right: 10px" @click="handleNext(scope.row)">下级分类</a>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDeleteOne(scope.row.categoryId)"
>
<template #reference>
<a style="cursor: pointer">删除</a>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
<DialogAddCategory ref='addGood' :reload="getCategory" :type="type" :level="level" :parent_id="parent_id" />
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import DialogAddCategory from '@/components/DialogAddCategory.vue'
import axios from '@/utils/axios'
export default {
name: 'Category',
components: {
DialogAddCategory
},
setup() {
const multipleTable = ref(null)
const addGood = ref(null)
const router = useRouter()
const route = useRoute()
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10, // 分页大小
type: 'add', // 操作类型
level: 1,
parent_id: 0
})
onMounted(() => {
getCategory()
})
router.afterEach((to) => {
if (['category', 'level2', 'level3'].includes(to.name)) {
getCategory()
}
})
// 获取分类列表
const getCategory = () => {
const { level = 1, parent_id = 0 } = route.query
state.loading = true
axios.get('/categories', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize,
categoryLevel: level,
parentId: parent_id
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
state.level = level
state.parentId = parent_id
})
}
// 添加分类
const handleAdd = () => {
state.type = 'add'
addGood.value.open()
}
// 修改分类
const handleEdit = (id) => {
state.type = 'edit'
addGood.value.open(id)
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
// 批量删除
const handleDelete = () => {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
axios.delete('/categories', {
data: {
ids: state.multipleSelection.map(i => i.categoryId)
}
}).then(() => {
ElMessage.success('删除成功')
getCategory()
})
}
// 单个删除
const handleDeleteOne = (id) => {
axios.delete('/categories', {
data: {
ids: [id]
}
}).then(() => {
ElMessage.success('删除成功')
getCategory()
})
}
const changePage = (val) => {
state.currentPage = val
getCategory()
}
const handleNext = (item) => {
const levelNumber = item.categoryLevel + 1
if (levelNumber == 4) {
ElMessage.error('没有下一级')
return
}
router.push({
name: `level${levelNumber}`,
query: {
level: levelNumber,
parent_id: item.categoryId
}
})
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
addGood,
handleAdd,
handleEdit,
handleDelete,
handleDeleteOne,
getCategory,
changePage,
handleNext
}
}
}
</script>
<style scoped>
.category-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>
+163
View File
@@ -0,0 +1,163 @@
<template>
<el-card class="swiper-container">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">新增商品</el-button>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="goodsId"
label="商品编号"
>
</el-table-column>
<el-table-column
prop="goodsName"
label="商品名"
>
</el-table-column>
<el-table-column
prop="goodsIntro"
label="商品简介"
>
</el-table-column>
<el-table-column
label="商品图片"
width="150px"
>
<template #default="scope">
<img style="width: 100px; height: 100px;" :key="scope.row.goodsId" :src="$filters.prefix(scope.row.goodsCoverImg)" alt="商品主图">
</template>
</el-table-column>
<el-table-column
prop="stockNum"
label="商品库存"
>
</el-table-column>
<el-table-column
prop="sellingPrice"
label="商品售价"
>
</el-table-column>
<el-table-column
label="上架状态"
>
<template #default="scope">
<span style="color: green;" v-if="scope.row.goodsSellStatus == 0">销售中</span>
<span style="color: red;" v-else>已下架</span>
</template>
</el-table-column>
<el-table-column
label="操作"
width="100"
>
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.goodsId)">修改</a>
<a style="cursor: pointer; margin-right: 10px" v-if="scope.row.goodsSellStatus == 0" @click="handleStatus(scope.row.goodsId, 1)">下架</a>
<a style="cursor: pointer; margin-right: 10px" v-else @click="handleStatus(scope.row.goodsId, 0)">上架</a>
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import axios from '@/utils/axios'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
export default {
name: 'Good',
setup() {
const multipleTable = ref(null)
const router = useRouter()
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10 // 分页大小
})
onMounted(() => {
getGoodList()
})
// 获取轮播图列表
const getGoodList = () => {
state.loading = true
axios.get('/goods/list', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
})
}
const handleAdd = () => {
router.push({ path: '/add' })
}
const handleEdit = (id) => {
router.push({ path: '/add', query: { id } })
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
const changePage = (val) => {
state.currentPage = val
getGoodList()
}
const handleStatus = (id, status) => {
axios.put(`/goods/status/${status}`, {
ids: id ? [id] : []
}).then(() => {
ElMessage.success('修改成功')
getGoodList()
})
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
handleAdd,
handleEdit,
getGoodList,
changePage,
handleStatus
}
}
}
</script>
<style scoped>
.swiper-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>
+168
View File
@@ -0,0 +1,168 @@
<template>
<el-card class="guest-container">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleSolve">解除禁用</el-button>
<el-button type="danger" size="small" icon="el-icon-delete" @click="handleForbid">禁用账户</el-button>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="nickName"
label="昵称"
>
</el-table-column>
<el-table-column
prop="loginName"
label="登录名"
>
</el-table-column>
<el-table-column
label="身份状态"
>
<template #default="scope">
<span :style="scope.row.lockedFlag == 0 ? 'color: green;' : 'color: red;'">
{{ scope.row.lockedFlag == 0 ? '正常' : '禁用' }}
</span>
</template>
</el-table-column>
<el-table-column
label="是否注销"
>
<template #default="scope">
<span :style="scope.row.lockedFlag == 0 ? 'color: green;' : 'color: red;'">
{{ scope.row.isDeleted == 0 ? '正常' : '注销' }}
</span>
</template>
</el-table-column>
<el-table-column
prop="createTime"
label="注册时间"
>
</el-table-column>
<!-- <el-table-column
label="操作"
width="100"
>
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @confirm="handleSolve(scope.row)">解除禁用</a>
<el-popconfirm
title="确定禁用吗?"
@confirm="handleForbid(scope.row)"
>
<template #reference>
<a style="cursor: pointer">禁用账户</a>
</template>
</el-popconfirm>
</template>
</el-table-column> -->
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import axios from '@/utils/axios'
import { ElMessage } from 'element-plus'
export default {
name: 'Guest',
setup() {
const multipleTable = ref(null)
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10 // 分页大小
})
onMounted(() => {
getGuestList()
})
// 获取轮播图列表
const getGuestList = () => {
state.loading = true
axios.get('/users', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
})
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
const changePage = (val) => {
state.currentPage = val
getGuestList()
}
const handleSolve = () => {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
axios.put(`/users/0`, {
ids: state.multipleSelection.map(item => item.userId)
}).then(() => {
ElMessage.success('解除成功')
getGuestList()
})
}
const handleForbid = () => {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
axios.put(`/users/1`, {
ids: state.multipleSelection.map(item => item.userId)
}).then(() => {
ElMessage.success('禁用成功')
getGuestList()
})
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
getGuestList,
changePage,
handleSolve,
handleForbid
}
}
}
</script>
<style scoped>
.guest-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>
+169
View File
@@ -0,0 +1,169 @@
<template>
<el-card class="introduce">
<div class="order">
<el-card class="order-item">
<template #header>
<div class="card-header">
<span>今日订单数</span>
</div>
</template>
<div class="item">1888</div>
</el-card>
<el-card class="order-item">
<template #header>
<div class="card-header">
<span>今日日活</span>
</div>
</template>
<div class="item">36271</div>
</el-card>
<el-card class="order-item">
<template #header>
<div class="card-header">
<span>转化率</span>
</div>
</template>
<div class="item">20%</div>
</el-card>
</div>
<div id="zoom"></div>
</el-card>
</template>
<script>
import { onMounted, onUnmounted } from 'vue'
let myChart = null
export default {
name: 'Index',
setup() {
onMounted(() => {
if (window.echarts) {
// 基于准备好的dom,初始化echarts实例
myChart = window.echarts.init(document.getElementById('zoom'))
// 指定图表的配置项和数据
const option = {
title: {
text: '系统折线图'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: ['新增注册', '付费用户', '活跃用户', '订单数', '当日总收入']
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['2021-03-11', '2021-03-12', '2021-03-13', '2021-03-14', '2021-03-15', '2021-03-16', '2021-03-17']
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '新增注册',
type: 'line',
stack: '总量',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '付费用户',
type: 'line',
stack: '总量',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '活跃用户',
type: 'line',
stack: '总量',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '订单数',
type: 'line',
stack: '总量',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '当日总收入',
type: 'line',
stack: '总量',
label: {
show: true,
position: 'top'
},
areaStyle: {},
emphasis: {
focus: 'series'
},
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
}
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option)
}
})
onUnmounted(() => {
myChart.dispose()
})
}
}
</script>
<style scoped>
.introduce .order {
display: flex;
margin-bottom: 50px;
}
.introduce .order .order-item {
flex: 1;
margin-right: 20px;
}
.introduce .order .order-item:last-child{
margin-right: 0;
}
#zoom {
min-height: 300px;
}
</style>
+211
View File
@@ -0,0 +1,211 @@
<template>
<el-card class="index-container">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">增加</el-button>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDelete"
>
<template #reference>
<el-button type="danger" size="small" icon="el-icon-delete">批量删除</el-button>
</template>
</el-popconfirm>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="configName"
label="商品名称"
>
</el-table-column>
<el-table-column
label="跳转链接"
>
<template #default="scope">
<a target="_blank" :href="scope.row.redirectUrl">{{ scope.row.redirectUrl }}</a>
</template>
</el-table-column>
<el-table-column
prop="configRank"
label="排序值"
width="120"
>
</el-table-column>
<el-table-column
prop="goodsId"
label="商品编号"
width="200"
>
</el-table-column>
<el-table-column
prop="createTime"
label="添加时间"
width="200"
>
</el-table-column>
<el-table-column
label="操作"
width="100"
>
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.configId)">修改</a>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDeleteOne(scope.row.configId)"
>
<template #reference>
<a style="cursor: pointer">删除</a>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
<DialogAddGood ref='addGood' :reload="getIndexConfig" :type="type" :configType="configType" />
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import DialogAddGood from '@/components/DialogAddGood.vue'
import { useRoute, useRouter } from 'vue-router'
import axios from '@/utils/axios'
// 首页配置类型参数
const configTypeMap = {
hot: 3,
new: 4,
recommend: 5
}
export default {
name: 'Hot',
components: {
DialogAddGood
},
setup() {
const router = useRouter()
const route = useRoute()
const multipleTable = ref(null)
const addGood = ref(null)
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10, // 分页大小
type: 'add', // 操作类型
configType: 3 // 3-(首页)热销商品 4-(首页)新品上线 5-(首页)为你推荐
})
// 监听路由变化
router.beforeEach((to) => {
if (['hot', 'new', 'recommend'].includes(to.name)) {
state.configType = configTypeMap[to.name]
state.currentPage = 1
getIndexConfig()
}
})
// 初始化
onMounted(() => {
state.configType = configTypeMap[route.name]
getIndexConfig()
})
// 首页热销商品列表
const getIndexConfig = () => {
state.loading = true
axios.get('/indexConfigs', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize,
configType: state.configType
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
})
}
// 添加商品
const handleAdd = () => {
state.type = 'add'
addGood.value.open()
}
// 修改商品
const handleEdit = (id) => {
state.type = 'edit'
addGood.value.open(id)
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
// 删除
const handleDelete = () => {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
axios.post('/indexConfigs/delete', {
ids: state.multipleSelection.map(i => i.configId)
}).then(() => {
ElMessage.success('删除成功')
getIndexConfig()
})
}
// 单个删除
const handleDeleteOne = (id) => {
axios.post('/indexConfigs/delete', {
ids: [id]
}).then(() => {
ElMessage.success('删除成功')
getIndexConfig()
})
}
const changePage = (val) => {
state.currentPage = val
getIndexConfig()
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
addGood,
handleAdd,
handleEdit,
handleDelete,
handleDeleteOne,
getIndexConfig,
changePage
}
}
}
</script>
<style scoped>
.index-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>
+101
View File
@@ -0,0 +1,101 @@
<template>
<el-card class="account-container">
<h1>系统简介</h1>
<div style="line-height: 30px">
vue3-admin 是一套企业级后台管理系统基于 Spring Boot Vue 3.0 相关技术栈开发供各位开发者们体验和学习一定给你最好的学习体验
</div>
<img style="width: 70%;
display: block;
margin: 0 auto;" src="https://s.yezgea02.com/1616331765416/WechatIMG40038.png" alt="">
<h1>开发及部署文档</h1>
<img style="width: 70%;
display: block;
margin: 0 auto;" src="https://s.yezgea02.com/1616938239101/419241616938196_.pic.jpg" />
<ul class="course" @click="goJuejin">
<li>开篇词通关Vue3.0 企业级项目开发升职加薪快人一步</li>
<li>项目须知与课程约定</li>
<li>大势所趋前后端分离开发模式</li>
<li>Vue 3.0 简介及开发环境搭建</li>
<li>Vue 3.0 组合 API 入口 Setup 浅析</li>
<li>Vue 3.0 之响应式系统 API</li>
<li>Vue 3.0 之生命周期钩子函数提供注入</li>
<li>Vue 3.0 性能和业务层面上的提升</li>
<li>Vite 2.0 原理分析及简单插件编写</li>
<li>Vue-Router 4.x 使用方法及路由原理</li>
<li>Vue 3.0 实战项目启动篇</li>
<li>技术选型之 Spring Boot</li>
<li>后端开发环境搭建</li>
<li>快速搭建一个 Spring Boot 项目</li>
<li>Spring Boot 实践之 Web 功能开发</li>
<li>Spring Boot 实践之文件上传处理</li>
<li>Spring Boot 实践之整合 MyBatis 操作数据库</li>
<li>Spring Boot 实践之整合 Lombok</li>
<li>Spring Boot 实践之整合 Swagger 生成接口文档</li>
<li>后端 API 项目启动和运行注意事项</li>
</ul>
<ul class="course" @click="goJuejin">
<li>接口参数处理和统一响应结果处理</li>
<li>API 接口开发实战之用户登录接口开发</li>
<li>API 接口开发实战之用户身份认证详解</li>
<li>API 接口开发实战之轮播图管理模块接口开发</li>
<li>API 接口开发实战之商品分类管理模块接口开发</li>
<li>API 接口开发实战之商品管理模块接口开发</li>
<li>API 接口开发实战之商品配置管理模块接口开发</li>
<li>API 接口开发实战之订单管理模块接口开发</li>
<li>成为一名有独立开发能力的前端工程师</li>
<li>Vite 2.0 + Vue 3.0 + Element-plus 搭建管理后台项目</li>
<li>Vue 3.0 实战之管理后台左右栏目布局Menu 菜单组件</li>
<li>Vue 3.0 实战之登录鉴权Form 表单组件</li>
<li>Vue 3.0 实战之首页大盘数据Echart 5.x</li>
<li>Vue 3.0 实战之首页配置 Table</li>
<li>Vue 3.0 实战之分类管理多级共用 Table</li>
<li>Vue 3.0 实战之商品管理</li>
<li>Vue 3.0 实战之订单管理操作多级判断</li>
<li>Vue 3.0 实战之会员管理账户修改</li>
<li>pm2 实现一键部署云端服务器</li>
<li>常见问题汇总讲解</li>
</ul>
<h1>技术选型</h1>
<ul style="font-weight: bold;">
<li>Vue 3.x</li>
<li>Vite 2.x</li>
<li>Vue-Router 4.x</li>
<li>Element-Plus适配全新 Vue 3.x PC 端组件库</li>
<li>Echarts 5.0</li>
<li>axios</li>
<li>wangEditor</li>
</ul>
<h1>联系作者</h1>
<ul>
<li>我的邮箱2449207463@qq.com</li>
<li>QQ技术交流群932227898707779034</li>
</ul>
</el-card>
</template>
<script>
export default {
name: 'Introduce',
setup() {
const goJuejin = () => {
console.log('goJuejin')
window.open('https://juejin.cn/book/6933939264455442444', 'target')
}
return {
goJuejin
}
}
}
</script>
<style scoped>
.course {
font-weight: bold;
display: inline-block;
}
.course li {
line-height: 36px;
color: #409eff;
cursor: pointer;
}
</style>
+129
View File
@@ -0,0 +1,129 @@
<template>
<div class="login-body">
<div class="login-container">
<div class="head">
<img class="logo" src="https://s.weituibao.com/1582958061265/mlogo.png" />
<div class="name">
<div class="title">新蜂商城</div>
<div class="tips">Vue3.0 后台管理系统</div>
</div>
</div>
<el-form label-position="top" :rules="rules" :model="ruleForm" ref="loginForm" class="login-form">
<el-form-item label="账号" prop="username">
<el-input type="text" v-model.trim="ruleForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model.trim="ruleForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<div style="color: #333">登录表示您已同意<a>服务条款</a></div>
<el-button style="width: 100%" type="primary" @click="submitForm">立即登录</el-button>
<el-checkbox v-model="checked" @change="!checked">下次自动登录</el-checkbox>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import axios from '@/utils/axios'
import md5 from 'js-md5'
import { reactive, ref, toRefs } from 'vue'
import { localSet } from '@/utils'
export default {
name: 'Login',
setup() {
const loginForm = ref(null)
const state = reactive({
ruleForm: {
username: '',
password: ''
},
checked: true,
rules: {
username: [
{ required: 'true', message: '账户不能为空', trigger: 'blur' }
],
password: [
{ required: 'true', message: '密码不能为空', trigger: 'blur' }
]
}
})
const submitForm = async () => {
loginForm.value.validate((valid) => {
if (valid) {
axios.post('/adminUser/login', {
userName: state.ruleForm.username || '',
passwordMd5: md5(state.ruleForm.password)
}).then(res => {
localSet('token', res)
window.location.href = '/'
})
} else {
console.log('error submit!!')
return false;
}
})
}
const resetForm = () => {
loginForm.value.resetFields();
}
return {
...toRefs(state),
loginForm,
submitForm,
resetForm
}
}
}
</script>
<style scoped>
.login-body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
background-color: #fff;
/* background-image: linear-gradient(25deg, #077f7c, #3aa693, #5ecfaa, #7ffac2); */
}
.login-container {
width: 420px;
height: 500px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0px 21px 41px 0px rgba(0, 0, 0, 0.2);
}
.head {
display: flex;
justify-content: center;
align-items: center;
padding: 40px 0 20px 0;
}
.head img {
width: 100px;
height: 100px;
margin-right: 20px;
}
.head .title {
font-size: 28px;
color: #1BAEAE;
font-weight: bold;
}
.head .tips {
font-size: 12px;
color: #999;
}
.login-form {
width: 70%;
margin: 0 auto;
}
</style>
<style>
.el-form--label-top .el-form-item__label {
padding: 0;
}
.login-form .el-form-item {
margin-bottom: 12px;
}
</style>
+276
View File
@@ -0,0 +1,276 @@
<template>
<el-card class="order-container">
<template #header>
<div class="header">
<el-input
style="width: 200px; margin-right: 10px"
placeholder="请输入订单号"
v-model="orderNo"
@change="handleOption"
size="small"
clearable
/>
<el-select @change="handleOption" v-model="orderStatus" size="small" style="width: 200px; margin-right: 10px">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- <el-button type="primary" size="small" icon="el-icon-edit">修改订单</el-button> -->
<el-button type="primary" size="small" icon="el-icon-s-home" @click="handleConfig()">配货完成</el-button>
<el-button type="primary" size="small" icon="el-icon-s-home" @click="handleSend()">出库</el-button>
<el-button type="danger" size="small" icon="el-icon-delete" @click="handleClose()">关闭订单</el-button>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="orderNo"
label="订单号"
>
</el-table-column>
<el-table-column
prop="totalPrice"
label="订单总价"
>
</el-table-column>
<el-table-column
prop="orderStatus"
label="订单状态"
>
<template #default="scope">
<span>{{ $filters.orderMap(scope.row.orderStatus) }}</span>
</template>
</el-table-column>
<el-table-column
prop="payType"
label="支付方式"
>
<template #default='scope'>
<span v-if="scope.row.payType == 1">微信支付</span>
<span v-else-if="scope.row.payType == 2">支付宝支付</span>
<span v-else>未知</span>
</template>
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
>
</el-table-column>
<el-table-column
label="操作"
>
<template #default="scope">
<el-popconfirm
v-if="scope.row.orderStatus == 1"
title="确定配货完成吗?"
@confirm="handleConfig(scope.row.orderId)"
>
<template #reference>
<a style="cursor: pointer; margin-right: 10px">配货完成</a>
</template>
</el-popconfirm>
<el-popconfirm
v-if="scope.row.orderStatus == 2"
title="确定出库吗?"
@confirm="handleSend(scope.row.orderId)"
>
<template #reference>
<a style="cursor: pointer; margin-right: 10px">出库</a>
</template>
</el-popconfirm>
<el-popconfirm
v-if="!(scope.row.orderStatus == 4 || scope.row.orderStatus < 0)"
title="确定关闭订单吗?"
@confirm="handleClose(scope.row.orderId)"
>
<template #reference>
<a style="cursor: pointer; margin-right: 10px">关闭订单</a>
</template>
</el-popconfirm>
<router-link :to="{ path: '/order_detail', query: { id: scope.row.orderId }}">订单详情</router-link>
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import axios from '@/utils/axios'
export default {
name: 'Order',
setup() {
const multipleTable = ref(null)
const addGood = ref(null)
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10, // 分页大小
orderNo: '', // 订单号
orderStatus: '', // 订单状态
options: [{
value: '',
label: '全部'
}, {
value: 0,
label: '待支付'
}, {
value: 1,
label: '已支付'
}, {
value: 2,
label: '配货完成'
}, {
value: 3,
label: '出库成功'
}, {
value: 4,
label: '交易成功'
}, {
value: -1,
label: '手动关闭'
}, {
value: -2,
label: '超时关闭'
}, {
value: -3,
label: '商家关闭'
}]
})
onMounted(() => {
getOrderList()
})
// 获取轮播图列表
const getOrderList = () => {
state.loading = true
axios.get('/orders', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize,
orderNo: state.orderNo,
orderStatus: state.orderStatus
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
})
}
const handleOption = () => {
state.currentPage = 1
getOrderList()
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
const changePage = (val) => {
state.currentPage = val
getOrderList()
}
const handleConfig = (id) => {
console.log('id', id)
let params
if (id) {
params = [id]
} else {
if (!state.multipleSelection.length) {
console.log('state.multipleSelection', state.multipleSelection.length)
ElMessage.error('请选择项')
return
}
params = state.multipleSelection.map(i => i.orderId)
}
axios.put('/orders/checkDone', {
ids: params
}).then(() => {
ElMessage.success('配货成功')
getOrderList()
})
}
const handleSend = (id) => {
let params
if (id) {
params = [id]
} else {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
params = state.multipleSelection.map(i => i.orderId)
}
axios.put('/orders/checkOut', {
ids: params
}).then(() => {
ElMessage.success('出库成功')
getOrderList()
})
}
const handleClose = (id) => {
let params
if (id) {
params = [id]
} else {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
params = state.multipleSelection.map(i => i.orderId)
}
axios.put('/orders/close', {
ids: params
}).then(() => {
ElMessage.success('关闭成功')
getOrderList()
})
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
addGood,
getOrderList,
changePage,
handleOption,
handleConfig,
handleSend,
handleClose
}
}
}
</script>
<style scoped>
.order-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>
+124
View File
@@ -0,0 +1,124 @@
<template>
<el-card class="order-container">
<div class="data">
<el-card class="data-item" shadow="hover">
<template #header>
<div class="card-header">
<span>订单状态</span>
</div>
</template>
<div>
{{ data.orderStatusString }}
</div>
</el-card>
<el-card class="data-item" shadow="hover">
<template #header>
<div class="card-header">
<span>创建时间</span>
</div>
</template>
<div>
{{ data.createTime }}
</div>
</el-card>
<el-card class="data-item" shadow="hover">
<template #header>
<div class="card-header">
<span>订单号</span>
</div>
</template>
<div>
{{ data.orderNo }}
</div>
</el-card>
</div>
<el-table
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
>
<el-table-column
label="商品图片"
>
<template #default="scope">
<img style="width: 100px" :key="scope.row.goodsId" :src="$filters.prefix(scope.row.goodsCoverImg)" alt="商品主图">
</template>
</el-table-column>
<el-table-column
prop="goodsId"
label="商品编号"
>
</el-table-column>
<el-table-column
prop="goodsName"
label="商品名"
></el-table-column>
<el-table-column
prop="goodsCount"
label="商品数量"
>
</el-table-column>
<el-table-column
prop="sellingPrice"
label="价格"
>
</el-table-column>
</el-table>
</el-card>
</template>
<script>
import { onMounted, reactive, toRefs } from 'vue'
import { useRoute } from 'vue-router'
import axios from '@/utils/axios'
export default {
name: 'OrderDetail',
setup() {
const route = useRoute()
const { id } = route.query
const state = reactive({
data: {},
tableData: []
})
onMounted(() => {
axios.get(`/orders/${id}`).then(res => {
console.log(res)
state.data = res
state.tableData = res.newBeeMallOrderItemVOS
})
})
return {
...toRefs(state)
}
}
}
</script>
<style scoped>
.data {
display: flex;
margin-bottom: 50px;
}
.data .data-item {
flex: 1;
margin: 0 10px;
}
.el-table {
border: 1px solid #EBEEF5;
border-bottom: none;
}
.has-gutter th {
border-right: 1px solid #EBEEF5;
}
.has-gutter th:last-child {
border-right: none;
}
.el-table__row td {
border-right: 1px solid #EBEEF5;
}
.el-table__row td:last-child {
border-right: none;
}
</style>
+190
View File
@@ -0,0 +1,190 @@
<template>
<el-card class="swiper-container">
<template #header>
<div class="header">
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">增加</el-button>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDelete"
>
<template #reference>
<el-button type="danger" size="small" icon="el-icon-delete">批量删除</el-button>
</template>
</el-popconfirm>
</div>
</template>
<el-table
v-loading="loading"
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="轮播图"
width="200">
<template #default="scope">
<img style="width: 150px;height: 150px" :src="scope.row.carouselUrl" alt="轮播图">
</template>
</el-table-column>
<el-table-column
label="跳转链接"
>
<template #default="scope">
<a target="_blank" :href="scope.row.redirectUrl">{{ scope.row.redirectUrl }}</a>
</template>
</el-table-column>
<el-table-column
prop="carouselRank"
label="排序值"
width="120"
>
</el-table-column>
<el-table-column
prop="createTime"
label="添加时间"
width="200"
>
</el-table-column>
<el-table-column
label="操作"
width="100"
>
<template #default="scope">
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.carouselId)">修改</a>
<el-popconfirm
title="确定删除吗?"
@confirm="handleDeleteOne(scope.row.carouselId)"
>
<template #reference>
<a style="cursor: pointer">删除</a>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--总数超过一页再展示分页器-->
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage"
/>
</el-card>
<DialogAddSwiper ref='addGood' :reload="getCarousels" :type="type" />
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import DialogAddSwiper from '@/components/DialogAddSwiper.vue'
import axios from '@/utils/axios'
export default {
name: 'Swiper',
components: {
DialogAddSwiper
},
setup() {
const multipleTable = ref(null)
const addGood = ref(null)
const state = reactive({
loading: false,
tableData: [], // 数据列表
multipleSelection: [], // 选中项
total: 0, // 总条数
currentPage: 1, // 当前页
pageSize: 10, // 分页大小
type: 'add', // 操作类型
})
onMounted(() => {
getCarousels()
})
// 获取轮播图列表
const getCarousels = () => {
state.loading = true
axios.get('/carousels', {
params: {
pageNumber: state.currentPage,
pageSize: state.pageSize
}
}).then(res => {
state.tableData = res.list
state.total = res.totalCount
state.currentPage = res.currPage
state.loading = false
})
}
// 添加轮播项
const handleAdd = () => {
state.type = 'add'
addGood.value.open()
}
// 修改轮播图
const handleEdit = (id) => {
state.type = 'edit'
addGood.value.open(id)
}
// 选择项
const handleSelectionChange = (val) => {
state.multipleSelection = val
}
// 批量删除
const handleDelete = () => {
if (!state.multipleSelection.length) {
ElMessage.error('请选择项')
return
}
axios.delete('/carousels', {
data: {
ids: state.multipleSelection.map(i => i.carouselId)
}
}).then(() => {
ElMessage.success('删除成功')
getCarousels()
})
}
// 单个删除
const handleDeleteOne = (id) => {
axios.delete('/carousels', {
data: {
ids: [id]
}
}).then(() => {
ElMessage.success('删除成功')
getCarousels()
})
}
const changePage = (val) => {
state.currentPage = val
getCarousels()
}
return {
...toRefs(state),
multipleTable,
handleSelectionChange,
addGood,
handleAdd,
handleEdit,
handleDelete,
handleDeleteOne,
getCarousels,
changePage
}
}
}
</script>
<style scoped>
.swiper-container {
min-height: 100%;
}
.el-card.is-always-shadow {
min-height: 100%!important;
}
</style>