增加店铺相关操作
This commit is contained in:
parent
755204171e
commit
fa9ffa66e3
37
src/api/shop.ts
Normal file
37
src/api/shop.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import request from '@/utils/request'
|
||||
import { IShopData } from './types'
|
||||
|
||||
export const defaultShopData: IShopData = {
|
||||
name: '',
|
||||
id: ''
|
||||
|
||||
}
|
||||
|
||||
export const getShops = (params: any) =>
|
||||
request({
|
||||
url: '/shops',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
|
||||
export const getShop = (id: string, params: any) =>
|
||||
request({
|
||||
url: `/shop/${id}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
|
||||
|
||||
export const saveShop = (data: any) =>
|
||||
request({
|
||||
url: `/shop/save`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
|
||||
export const deleteShop = (id: string) =>
|
||||
request({
|
||||
url: `/shop/${id}/delete`,
|
||||
method: 'post'
|
||||
})
|
||||
|
6
src/api/types.d.ts
vendored
6
src/api/types.d.ts
vendored
@ -40,3 +40,9 @@ export interface IQuestionData {
|
||||
stars: number,
|
||||
status: number,
|
||||
}
|
||||
|
||||
export interface IShopData {
|
||||
id: string,
|
||||
name: string,
|
||||
createdAt?: Date
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import './question_list'
|
||||
import './role'
|
||||
import './search'
|
||||
import './sell'
|
||||
import './shop_list'
|
||||
import './shop'
|
||||
import './shopping'
|
||||
import './size'
|
||||
|
12
src/icons/components/shop_list.ts
Normal file
12
src/icons/components/shop_list.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
// @ts-ignore
|
||||
import icon from 'vue-svgicon'
|
||||
icon.register({
|
||||
'shop_list': {
|
||||
width: 64,
|
||||
height: 64,
|
||||
viewBox: '0 0 1024 1024',
|
||||
data: '<defs/><path pid="0" d="M85.705 0h329.143a73.143 73.143 0 0173.143 73.143v329.143a73.143 73.143 0 01-73.143 73.143H85.705a73.143 73.143 0 01-73.143-73.143V73.143A73.143 73.143 0 0185.705 0zm0 548.571h329.143a73.143 73.143 0 0173.143 73.143v329.143A73.143 73.143 0 01414.848 1024H85.705a73.143 73.143 0 01-73.143-73.143V621.714a73.143 73.143 0 0173.143-73.143zm563.42-414.866h322.304a40.01 40.01 0 0140.009 40.01 40.01 40.01 0 01-40.01 40.008H649.126a39.973 39.973 0 01-39.973-40.009 39.973 39.973 0 0139.973-40.009zm0 158.866h322.304a40.01 40.01 0 0140.009 39.973 40.01 40.01 0 01-40.01 40.01H649.126a39.973 39.973 0 01-39.973-40.01 39.973 39.973 0 0139.973-39.973zm0 378.295h322.304a39.973 39.973 0 0140.009 39.973 39.973 39.973 0 01-40.01 39.972H649.126a39.973 39.973 0 01-39.973-39.972 39.973 39.973 0 0139.973-39.973zm0 194.268h322.304a40.01 40.01 0 0140.009 40.009 40.01 40.01 0 01-40.01 40.009H649.126a39.973 39.973 0 01-39.973-40.01 39.973 39.973 0 0139.973-40.008z" _fill="#333"/><path pid="1" d="M85.705 73.143h329.143v329.143H85.705zM85.705 621.714h329.143v329.143H85.705z" _fill="#FFF"/>'
|
||||
}
|
||||
})
|
1
src/icons/svg/shop_list.svg
Normal file
1
src/icons/svg/shop_list.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1618811796115" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17726" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M85.705143 0h329.142857a73.142857 73.142857 0 0 1 73.142857 73.142857v329.142857a73.142857 73.142857 0 0 1-73.142857 73.142857H85.705143a73.142857 73.142857 0 0 1-73.142857-73.142857V73.142857a73.142857 73.142857 0 0 1 73.142857-73.142857z m0 548.571429h329.142857a73.142857 73.142857 0 0 1 73.142857 73.142857v329.142857a73.142857 73.142857 0 0 1-73.142857 73.142857H85.705143a73.142857 73.142857 0 0 1-73.142857-73.142857v-329.142857a73.142857 73.142857 0 0 1 73.142857-73.142857zM649.124571 133.705143h322.304a40.009143 40.009143 0 0 1 40.009143 40.009143 40.009143 40.009143 0 0 1-40.009143 40.009143h-322.304a39.972571 39.972571 0 0 1-39.972571-40.009143 39.972571 39.972571 0 0 1 39.972571-40.009143z m0 158.866286h322.304a40.009143 40.009143 0 0 1 40.009143 39.972571 40.009143 40.009143 0 0 1-40.009143 40.009143h-322.304a39.972571 39.972571 0 0 1-39.972571-40.009143A39.972571 39.972571 0 0 1 649.124571 292.571429z m0 378.294857h322.304a39.972571 39.972571 0 0 1 40.009143 39.972571 39.972571 39.972571 0 0 1-40.009143 39.972572h-322.304a39.972571 39.972571 0 0 1-39.972571-39.972572 39.972571 39.972571 0 0 1 39.972571-39.972571z m0 194.267428h322.304a40.009143 40.009143 0 0 1 40.009143 40.009143 40.009143 40.009143 0 0 1-40.009143 40.009143h-322.304a39.972571 39.972571 0 0 1-39.972571-40.009143 39.972571 39.972571 0 0 1 39.972571-40.009143z" fill="#333333" p-id="17727"></path><path d="M85.705143 73.142857h329.142857v329.142857H85.705143z" fill="#FFFFFF" p-id="17728"></path><path d="M85.705143 621.714286h329.142857v329.142857H85.705143z" fill="#FFFFFF" p-id="17729"></path></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -75,6 +75,9 @@ export default {
|
||||
question_prepare: 'Question Edit',
|
||||
createQuestion: 'Create Question',
|
||||
shop: 'Shop Setting',
|
||||
shop_list: 'Shop List',
|
||||
create_shop: 'Create Shop',
|
||||
shop_edit: 'Shop Editor',
|
||||
game_setting: 'Game Setting'
|
||||
},
|
||||
navbar: {
|
||||
|
@ -75,6 +75,9 @@ export default {
|
||||
question_prepare: '题目编辑',
|
||||
createQuestion: '创建题目',
|
||||
shop: '店铺设置',
|
||||
shop_list: '店铺列表',
|
||||
create_shop: '创建店铺',
|
||||
shop_edit: '编辑店铺',
|
||||
game_setting: '游戏设置'
|
||||
},
|
||||
navbar: {
|
||||
|
@ -10,6 +10,37 @@ const shopRoutes: RouteConfig = {
|
||||
alwaysShow: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
component: () => import('@/views/shop/list.vue'),
|
||||
name: 'ShopList',
|
||||
meta: {
|
||||
title: 'shop_list',
|
||||
permissions: ['shop:read'],
|
||||
icon: 'shop_list'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
component: () => import('@/views/shop/edit.vue'),
|
||||
name: 'CreateShop',
|
||||
meta: {
|
||||
title: 'create_shop',
|
||||
icon: 'edit',
|
||||
hidden: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'edit/:id',
|
||||
component: () => import('@/views/shop/edit.vue'),
|
||||
name: 'ShopEditor',
|
||||
meta: {
|
||||
title: 'shop_edit',
|
||||
permissions: ['shop:read'],
|
||||
elicon: 'el-icon-arrow-right',
|
||||
hidden: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
component: () => import('@/views/shop/game_setting.vue'),
|
||||
|
@ -18,7 +18,7 @@ export const parseTime = (
|
||||
} else {
|
||||
// support safari
|
||||
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
|
||||
time = time.replace(new RegExp(/-/gm), '/')
|
||||
// time = time.replace(new RegExp(/-/gm), '/')
|
||||
}
|
||||
}
|
||||
if (typeof time === 'number' && time.toString().length === 10) {
|
||||
|
210
src/views/shop/edit.vue
Normal file
210
src/views/shop/edit.vue
Normal file
@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<div class="createPost-container">
|
||||
<el-form
|
||||
ref="postForm"
|
||||
:model="postForm"
|
||||
:rules="rules"
|
||||
class="form-container"
|
||||
>
|
||||
<sticky
|
||||
:z-index="10"
|
||||
:class-name="'sub-navbar '+postForm.status"
|
||||
>
|
||||
<el-button
|
||||
v-loading="loading"
|
||||
style="margin-left: 10px;"
|
||||
type="success"
|
||||
@click="submitForm"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
<el-button
|
||||
v-loading="loading"
|
||||
type="warning"
|
||||
@click="draftForm"
|
||||
>
|
||||
Draft
|
||||
</el-button>
|
||||
</sticky>
|
||||
|
||||
<div class="createPost-main-container">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item
|
||||
style="margin-bottom: 40px;"
|
||||
prop="name"
|
||||
>
|
||||
<material-input
|
||||
v-model="postForm.name"
|
||||
:maxlength="100"
|
||||
name="name"
|
||||
required
|
||||
>
|
||||
店铺名
|
||||
</material-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||
import { AppModule } from '@/store/modules/app'
|
||||
import { TagsViewModule, ITagView } from '@/store/modules/tags-view'
|
||||
import MaterialInput from '@/components/MaterialInput/index.vue'
|
||||
import Sticky from '@/components/Sticky/index.vue'
|
||||
import UploadImage from '@/components/UploadImage/index.vue'
|
||||
import { Form } from 'element-ui'
|
||||
import { defaultShopData, getShop, saveShop } from '@/api/shop'
|
||||
|
||||
@Component({
|
||||
name: 'ShopEditor',
|
||||
components: {
|
||||
MaterialInput,
|
||||
Sticky,
|
||||
UploadImage
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
|
||||
private validateRequire = (rule: any, value: string, callback: Function) => {
|
||||
if (value === '') {
|
||||
if (rule.field === 'imageURL') {
|
||||
this.$message({
|
||||
message: 'Upload cover image is required',
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: rule.field + ' 是必填的',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
callback(new Error(rule.field + ' 是必填的'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private postForm = Object.assign({}, defaultShopData)
|
||||
private loading = false
|
||||
private rules = {
|
||||
title: [{ validator: this.validateRequire }],
|
||||
}
|
||||
|
||||
private tempTagView?: ITagView
|
||||
|
||||
|
||||
get lang() {
|
||||
return AppModule.language
|
||||
}
|
||||
|
||||
|
||||
created() {
|
||||
const id = this.$route.params?.id
|
||||
if (id) {
|
||||
this.fetchData(id)
|
||||
}
|
||||
|
||||
this.tempTagView = Object.assign({}, this.$route)
|
||||
}
|
||||
|
||||
deactivated() {
|
||||
}
|
||||
|
||||
activated() {
|
||||
}
|
||||
|
||||
private async fetchData(id: string) {
|
||||
try {
|
||||
const { data } = await getShop(id, { /* Your params here */ })
|
||||
console.log(data)
|
||||
this.postForm = data
|
||||
// Just for test
|
||||
this.postForm.title += ` 店铺 Id:${this.postForm._id}`
|
||||
const title = this.lang === 'zh' ? '编辑店铺' : 'Edit Shop'
|
||||
// Set tagsview title
|
||||
this.setTagsViewTitle(title)
|
||||
// Set page title
|
||||
this.setPageTitle(title)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
private setTagsViewTitle(title: string) {
|
||||
const tagView = this.tempTagView
|
||||
if (tagView) {
|
||||
tagView.title = `${title}-${this.postForm._id}`
|
||||
TagsViewModule.updateVisitedView(tagView)
|
||||
}
|
||||
}
|
||||
|
||||
private setPageTitle(title: string) {
|
||||
document.title = `${title} - ${this.postForm._id}`
|
||||
}
|
||||
|
||||
private submitForm() {
|
||||
(this.$refs.postForm as Form).validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
saveShop(this.postForm)
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'The post published successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
} else {
|
||||
console.error('Submit Error!')
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private draftForm() {
|
||||
this.$message({
|
||||
message: 'The draft saved successfully',
|
||||
type: 'success',
|
||||
showClose: true,
|
||||
duration: 1000
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.createPost-container {
|
||||
position: relative;
|
||||
|
||||
.createPost-main-container {
|
||||
padding: 40px 45px 20px 50px;
|
||||
|
||||
.postInfo-container {
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.postInfo-container-item {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.word-counter {
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
155
src/views/shop/list.vue
Normal file
155
src/views/shop/list.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<router-link to="/shop/create">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
>
|
||||
添加
|
||||
</el-button>
|
||||
</router-link>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
style="width: 100%;margin-top:30px;"
|
||||
>
|
||||
|
||||
<el-table-column
|
||||
width="180px"
|
||||
align="center"
|
||||
label="添加时间"
|
||||
>
|
||||
<template slot-scope="{row}">
|
||||
<span>{{ row.createdAt | parseTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
min-width="300px"
|
||||
label="店铺名"
|
||||
>
|
||||
<template slot-scope="{row}">
|
||||
<router-link
|
||||
:to="'/shop/edit/'+row._id"
|
||||
class="link-type"
|
||||
>
|
||||
<span>{{ row.name }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<router-link :to="'/shop/edit/'+scope.row._id">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="el-icon-edit"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</router-link>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
style="margin-left: 10px"
|
||||
@click="handleDelete(scope)"
|
||||
>
|
||||
{{ $t('permission.delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.page"
|
||||
:limit.sync="listQuery.limit"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
import { IShopData } from '@/api/types'
|
||||
import Pagination from '@/components/Pagination/index.vue'
|
||||
import { deleteShop, getShops } from '@/api/shop'
|
||||
import { parseTime } from '@/utils'
|
||||
import { deleteRole } from '@/api/roles'
|
||||
|
||||
@Component({
|
||||
name: 'ShopList',
|
||||
components: {
|
||||
Pagination
|
||||
},
|
||||
filters: {
|
||||
parseTime: (timestamp: string) => {
|
||||
return parseTime(timestamp)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default class extends Vue {
|
||||
private total = 0
|
||||
private list: IShopData[] = []
|
||||
private listLoading = true
|
||||
private listQuery = {
|
||||
page: 1,
|
||||
limit: 20
|
||||
}
|
||||
|
||||
created() {
|
||||
this.getList()
|
||||
}
|
||||
|
||||
private async getList() {
|
||||
this.listLoading = true
|
||||
const { data } = await getShops(this.listQuery)
|
||||
this.list = data.records
|
||||
this.total = data.total
|
||||
// Just to simulate the time of the request
|
||||
setTimeout(() => {
|
||||
this.listLoading = false
|
||||
}, 0.5 * 1000)
|
||||
}
|
||||
private handleDelete(scope: any) {
|
||||
const { $index, row } = scope
|
||||
console.log($index, scope)
|
||||
this.$confirm('确认删除该店铺?', 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async() => {
|
||||
await deleteShop(row._id)
|
||||
this.list.splice($index, 1)
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
})
|
||||
.catch(err => { console.error(err) })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-input {
|
||||
padding-right: 100px;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user