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
+135
View File
@@ -0,0 +1,135 @@
<template>
<el-dialog
:title="type == 'add' ? '添加分类' : '修改分类'"
v-model="visible"
width="400px"
>
<el-form :model="ruleForm" :rules="rules" ref="formRef" label-width="100px" class="good-form">
<el-form-item label="商品名称" prop="name">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="排序值" prop="rank">
<el-input type="number" v-model="ruleForm.rank"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="submitForm"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, ref, toRefs } from 'vue'
import { useRoute } from 'vue-router'
import axios from '@/utils/axios'
import { hasEmoji } from '@/utils/index'
import { ElMessage } from 'element-plus'
export default {
name: 'DialogAddCategory',
props: {
type: String,
reload: Function
},
setup(props) {
const formRef = ref(null)
const route = useRoute()
const state = reactive({
visible: false,
categoryLevel: 1,
parentId: 0,
ruleForm: {
name: '',
rank: ''
},
rules: {
name: [
{ required: 'true', message: '名称不能为空', trigger: ['change'] }
],
rank: [
{ required: 'true', message: '编号不能为空', trigger: ['change'] }
]
},
id: ''
})
// 获取详情
const getDetail = (id) => {
axios.get(`/categories/${id}`).then(res => {
state.ruleForm = {
name: res.categoryName,
rank: res.categoryRank
}
state.parentId = res.parentId
state.categoryLevel = res.categoryLevel
})
}
// 开启弹窗
const open = (id) => {
state.visible = true
if (id) {
state.id = id
getDetail(id)
} else {
// 新增类目,从路由获取父分类id 和 分类级别
const { level, parent_id } = route.query
state.ruleForm = {
name: '',
rank: ''
}
state.parentId = parent_id
state.categoryLevel = level
}
}
// 关闭弹窗
const close = () => {
state.visible = false
}
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
if (hasEmoji(state.ruleForm.name)) {
ElMessage.error('不要输入表情包,再输入就打死你个龟孙儿~')
return
}
if (props.type == 'add') {
axios.post('/categories', {
categoryLevel: state.categoryLevel,
parentId: state.parentId,
categoryName: state.ruleForm.name,
categoryRank: state.ruleForm.rank
}).then(() => {
ElMessage.success('添加成功')
state.visible = false
if (props.reload) props.reload()
})
} else {
axios.put('/categories', {
categoryId: state.id,
categoryLevel: state.categoryLevel,
parentId: state.categoryLevel,
categoryName: state.ruleForm.name,
categoryRank: state.ruleForm.rank
}).then(() => {
ElMessage.success('修改成功')
state.visible = false
if (props.reload) props.reload()
})
}
}
})
}
return {
...toRefs(state),
open,
close,
formRef,
submitForm
}
}
}
</script>
<style scoped>
</style>
+147
View File
@@ -0,0 +1,147 @@
<template>
<el-dialog
:title="type == 'add' ? '添加商品' : '修改商品'"
v-model="visible"
width="400px"
>
<el-form :model="ruleForm" :rules="rules" ref="formRef" label-width="100px" class="good-form">
<el-form-item label="商品名称" prop="name">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="跳转链接" prop="link">
<el-input type="text" v-model="ruleForm.link"></el-input>
</el-form-item>
<el-form-item label="商品编号" prop="id">
<el-input type="number" min="0" v-model="ruleForm.id"></el-input>
</el-form-item>
<el-form-item label="排序值" prop="sort">
<el-input type="number" v-model="ruleForm.sort"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="submitForm"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, ref, toRefs } from 'vue'
import axios from '@/utils/axios'
import { hasEmoji } from '@/utils/index'
import { ElMessage } from 'element-plus'
export default {
name: 'DialogAddHotGood',
props: {
type: String,
configType: Number,
reload: Function
},
setup(props) {
const formRef = ref(null)
const state = reactive({
visible: false,
ruleForm: {
name: '',
link: '',
id: '',
sort: ''
},
rules: {
name: [
{ required: 'true', message: '名称不能为空', trigger: ['change'] }
],
id: [
{ required: 'true', message: '编号不能为空', trigger: ['change'] }
],
sort: [
{ required: 'true', message: '排序不能为空', trigger: ['change'] }
]
},
id: ''
})
// 获取详情
const getDetail = (id) => {
axios.get(`/indexConfigs/${id}`).then(res => {
state.ruleForm = {
name: res.configName,
id: res.goodsId,
link: res.redirectUrl,
sort: res.configRank
}
})
}
// 开启弹窗
const open = (id) => {
state.visible = true
if (id) {
state.id = id
getDetail(id)
} else {
state.ruleForm = {
name: '',
id: '',
link: '',
sort: ''
}
}
}
// 关闭弹窗
const close = () => {
state.visible = false
}
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
if (hasEmoji(state.ruleForm.name) || hasEmoji(state.ruleForm.link)) {
ElMessage.error('不要输入表情包,再输入就打死你个龟孙儿~')
return
}
if (state.ruleForm.id < 0 || state.ruleForm.id > 200) {
ElMessage.error('商品编号不能小于 0 或大于 200')
return
}
if (props.type == 'add') {
axios.post('/indexConfigs', {
configType: props.configType || 3,
configName: state.ruleForm.name,
redirectUrl: state.ruleForm.link,
goodsId: state.ruleForm.id,
configRank: state.ruleForm.sort
}).then(() => {
ElMessage.success('添加成功')
state.visible = false
if (props.reload) props.reload()
})
} else {
axios.put('/indexConfigs', {
configId: state.id,
configType: props.configType || 3,
configName: state.ruleForm.name,
redirectUrl: state.ruleForm.link,
goodsId: state.ruleForm.id,
configRank: state.ruleForm.sort
}).then(() => {
ElMessage.success('修改成功')
state.visible = false
if (props.reload) props.reload()
})
}
}
})
}
return {
...toRefs(state),
open,
close,
formRef,
submitForm
}
}
}
</script>
<style scoped>
</style>
+172
View File
@@ -0,0 +1,172 @@
<template>
<el-dialog
:title="type == 'add' ? '添加轮播图' : '修改轮播图'"
v-model="visible"
width="400px"
>
<el-form :model="ruleForm" :rules="rules" ref="formRef" label-width="100px" class="good-form">
<el-form-item label="图片" prop="url">
<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: 200px; height: 100px; border: 1px solid #e9e9e9;" v-if="ruleForm.url" :src="ruleForm.url" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
<el-form-item label="跳转链接" prop="link">
<el-input type="text" v-model="ruleForm.link"></el-input>
</el-form-item>
<el-form-item label="排序值" prop="sort">
<el-input type="number" v-model="ruleForm.sort"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="submitForm"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { reactive, ref, toRefs } from 'vue'
import axios from '@/utils/axios'
import { localGet, uploadImgServer, hasEmoji } from '@/utils'
import { ElMessage } from 'element-plus'
export default {
name: 'DialogAddSwiper',
props: {
type: String,
reload: Function
},
setup(props) {
const formRef = ref(null)
const state = reactive({
uploadImgServer,
token: localGet('token') || '',
visible: false,
ruleForm: {
url: '',
link: '',
sort: ''
},
rules: {
url: [
{ required: 'true', message: '图片不能为空', trigger: ['change'] }
],
sort: [
{ required: 'true', message: '排序不能为空', trigger: ['change'] }
]
},
id: ''
})
// 获取详情
const getDetail = (id) => {
axios.get(`/carousels/${id}`).then(res => {
state.ruleForm = {
url: res.carouselUrl,
link: res.redirectUrl,
sort: res.carouselRank
}
})
}
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.ruleForm.url = val.data || ''
}
// 开启弹窗
const open = (id) => {
state.visible = true
if (id) {
state.id = id
getDetail(id)
} else {
state.ruleForm = {
url: '',
link: '',
sort: ''
}
}
}
// 关闭弹窗
const close = () => {
state.visible = false
}
const submitForm = () => {
console.log(formRef.value.validate)
formRef.value.validate((valid) => {
if (valid) {
if (hasEmoji(state.ruleForm.link)) {
ElMessage.error('不要输入表情包,再输入就打死你个龟孙儿~')
return
}
if (props.type == 'add') {
axios.post('/carousels', {
carouselUrl: state.ruleForm.url,
redirectUrl: state.ruleForm.link,
carouselRank: state.ruleForm.sort
}).then(() => {
ElMessage.success('添加成功')
state.visible = false
if (props.reload) props.reload()
})
} else {
axios.put('/carousels', {
carouselId: state.id,
carouselUrl: state.ruleForm.url,
redirectUrl: state.ruleForm.link,
carouselRank: state.ruleForm.sort
}).then(() => {
ElMessage.success('修改成功')
state.visible = false
if (props.reload) props.reload()
})
}
}
})
}
return {
...toRefs(state),
open,
close,
formRef,
handleBeforeUpload,
handleUrlSuccess,
submitForm
}
}
}
</script>
<style scoped>
.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>
+25
View File
@@ -0,0 +1,25 @@
<template>
<div class="footer">
<div class="left">Copyright © 2019-2021 十三. All rights reserved.</div>
<div class="right">
<a target="_blank" href="https://github.com/newbee-ltd/vue3-admin">vue3-admin Version 3.0.0</a>
</div>
</div>
</template>
<script>
export default {
name: 'Footer'
}
</script>
<style scoped>
.footer {
height: 50px;
border-top: 1px solid #e9e9e9;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
</style>
+122
View File
@@ -0,0 +1,122 @@
<template>
<div class="header">
<div class="left">
<i v-if="hasBack" class="el-icon-back" @click="back"></i>
<span style="font-size: 20px">{{ name }}</span>
</div>
<div class="right">
<el-popover
placement="bottom"
:width="320"
trigger="click"
popper-class="popper-user-box"
>
<template #reference>
<div class="author">
<i class="icon el-icon-s-custom" />
{{ userInfo && userInfo.nickName || '' }}
<i class="el-icon-caret-bottom" />
</div>
</template>
<div class="nickname">
<p>登录名{{ userInfo && userInfo.loginUserName || '' }}</p>
<p>昵称{{ userInfo && userInfo.nickName || '' }}</p>
<el-tag size="small" effect="dark" class="logout" @click="logout">退出</el-tag>
</div>
</el-popover>
</div>
</div>
</template>
<script>
import { onMounted, reactive, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import axios from '@/utils/axios'
import { localRemove, pathMap } from '@/utils'
export default {
name: 'Header',
setup() {
const router = useRouter()
const state = reactive({
name: 'dashboard',
userInfo: null,
hasBack: false
})
onMounted(() => {
const pathname = window.location.hash.split('/')[1] || ''
if (!['login'].includes(pathname)) {
getUserInfo()
}
})
const getUserInfo = async () => {
const userInfo = await axios.get('/adminUser/profile')
state.userInfo = userInfo
}
const logout = () => {
axios.delete('/logout').then(() => {
localRemove('token')
router.push({ path: '/login' })
})
}
const back = () => {
router.back()
}
router.afterEach((to) => {
console.log('to', to)
const { id } = to.query
state.name = pathMap[to.name]
if (id && to.name == 'add') {
state.name = '编辑商品'
}
state.hasBack = ['level2', 'level3', 'order_detail'].includes(to.name)
})
return {
...toRefs(state),
logout,
back
}
}
}
</script>
<style scoped>
.header {
height: 50px;
border-bottom: 1px solid #e9e9e9;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
.el-icon-back {
border: 1px solid #e9e9e9;
padding: 4px;
border-radius: 50px;
margin-right: 10px;
}
.right > div > .icon{
font-size: 18px;
margin-right: 6px;
}
.author {
margin-left: 10px;
cursor: pointer;
}
</style>
<style>
.popper-user-box {
background: url('https://s.yezgea02.com/lingling-h5/static/account-banner-bg.png') 50% 50% no-repeat!important;
background-size: cover!important;
border-radius: 0!important;
}
.popper-user-box .nickname {
position: relative;
color: #ffffff;
}
.popper-user-box .nickname .logout {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
</style>
-58
View File
@@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>