mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-23 11:27:24 +08:00
admin-import
This commit is contained in:
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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技术交流群:932227898、707779034</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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user