优化添加商品问题 新增添加设备

This commit is contained in:
gyq
2024-03-13 09:05:08 +08:00
parent d0f69f9eb9
commit 87d084dfed
24 changed files with 1251 additions and 281 deletions

View File

@@ -1,8 +1,9 @@
ENV = 'development' ENV = 'development'
# 接口地址 # 接口地址
# VUE_APP_BASE_API = 'http://192.168.2.128:8000' # VUE_APP_BASE_API = 'http://192.168.2.128:8000' // 刘一帆
VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn' VUE_APP_BASE_API = 'http://192.168.2.98:8000'
# VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn'
# VUE_APP_BASE_API = 'http://192.168.2.16:8000' # VUE_APP_BASE_API = 'http://192.168.2.16:8000'
VUE_APP_WS_API = 'ws://192.168.2.128:8000' VUE_APP_WS_API = 'ws://192.168.2.128:8000'

View File

@@ -3,5 +3,6 @@ ENV = 'production'
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇Nginx 配置 # 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇Nginx 配置
# 接口地址,注意协议,如果你没有配置 ssl需要将 https 改为 http # 接口地址,注意协议,如果你没有配置 ssl需要将 https 改为 http
VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn' VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn'
# VUE_APP_BASE_API = 'http://192.168.2.98:8000'
# 如果接口是 http 形式, wss 需要改为 ws # 如果接口是 http 形式, wss 需要改为 ws
VUE_APP_WS_API = 'wss://123.56.110.252 VUE_APP_WS_API = 'wss://123.56.110.252

BIN
dist.zip Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -71,7 +71,6 @@ export default {
&:hover { &:hover {
cursor: pointer; cursor: pointer;
border-color: $borderColor;
} }
&.active { &.active {

32
src/api/devices.js Normal file
View File

@@ -0,0 +1,32 @@
import request from '@/utils/request'
/**
* 增加打印机
* @returns
*/
export function tbPrintMachine(data, method = 'post') {
return request({
url: '/api/tbPrintMachine',
method: method,
data: {
shopId: localStorage.getItem('shopId'),
...data
}
})
}
/**
* 打印机列表
* @returns
*/
export function tbPrintMachineGet(params) {
return request({
url: '/api/tbPrintMachine',
method: 'get',
params: {
shopId: localStorage.getItem('shopId'),
sort: '',
...params
}
})
}

91
src/api/home.js Normal file
View File

@@ -0,0 +1,91 @@
import request from '@/utils/request'
/**
* 汇总数据
* @returns
*/
export function summaryGet() {
return request({
url: '/api/summary',
method: 'get',
params: {
shopId: localStorage.getItem('shopId')
}
})
}
/**
* 今日数据
* @returns
*/
export function summaryTodayGet() {
return request({
url: '/api/summary/today',
method: 'get',
params: {
shopId: localStorage.getItem('shopId')
}
})
}
/**
* 今日数据
* @returns
*/
export function summaryDateGet(day) {
return request({
url: '/api/summary/date',
method: 'get',
params: {
shopId: localStorage.getItem('shopId'),
day: day
}
})
}
/**
* 销售额柱状图
* @returns
*/
export function dateAmount(day) {
return request({
url: '/api/summary/dateAmount',
method: 'get',
params: {
shopId: localStorage.getItem('shopId'),
day: day
}
})
}
/**
* 商品销售排行
* @returns
*/
export function dateProduct(day, page) {
return request({
url: '/api/summary/dateProduct',
method: 'get',
params: {
shopId: localStorage.getItem('shopId'),
day: day,
page: page
}
})
}
/**
* 支付类型占比
* @returns
*/
export function datePayType(day) {
return request({
url: '/api/summary/datePayType',
method: 'get',
params: {
shopId: localStorage.getItem('shopId'),
day: day
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -1,23 +1,23 @@
// base color // base color
$blue:#324157; $blue: #324157;
$light-blue:#3A71A8; $light-blue: #3a71a8;
$red:#C03639; $red: #c03639;
$pink: #E65D6E; $pink: #e65d6e;
$green: #30B08F; $green: #30b08f;
$tiffany: #4AB7BD; $tiffany: #4ab7bd;
$yellow:#FEC171; $yellow: #fec171;
$panGreen: #30B08F; $panGreen: #30b08f;
// sidebar // sidebar
$menuText:#bfcbd9; $menuText: #bfcbd9;
$menuActiveText:#409EFF; $menuActiveText: #409eff;
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951 $subMenuActiveText: #f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156; $menuBg: #333;
$menuHover:#263445; $menuHover: #444;
$subMenuBg:#1f2d3d; $subMenuBg: #444;
$subMenuHover:#001528; $subMenuHover: #555;
$sideBarWidth: 205px; $sideBarWidth: 205px;

View File

@@ -0,0 +1,119 @@
<template>
<el-dialog title="选择分类" :visible.sync="dialogVisible">
<div class="list" v-loading="loading">
<div class="row" v-for="(item, index) in categorys" :key="item.id">
<div class="list_title">{{ item.name }}</div>
<div class="item_wrap">
<el-button :type="item.active ? 'primary' : ''" @click="selectHandle(item)">全部</el-button>
<el-button :type="item.active ? 'primary' : ''" v-for="val in item.childrenList" :key="val.id"
@click="selectHandle(val, index)">{{
val.name }}</el-button>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
</template>
<script>
import { tbShopCategoryGet } from '@/api/shop'
export default {
data() {
return {
dialogVisible: false,
loading: false,
categorys: []
}
},
mounted() {
this.tbShopCategoryGet()
},
methods: {
// 确认选择分类
onSubmitHandle() {
let categorys = []
for (let item of this.categorys) {
if (item.active) {
categorys.push({
name: `${item.name}`,
id: item.id
})
}
if (item.childrenList.length) {
for (let val of item.childrenList) {
if (val.active) {
categorys.push({
name: `${val.name}`,
id: val.id
})
}
}
}
}
this.$emit('success', categorys)
this.dialogVisible = false
},
// 选择分类
selectHandle(item, index = -1) {
if (index != -1) {
this.categorys[index].childrenList.map(val => {
val.active = false
})
}
item.active = !item.active
},
// 获取分类
async tbShopCategoryGet() {
try {
this.loading = true
const res = await tbShopCategoryGet({
shopId: localStorage.getItem('shopId'),
sort: 'sort,desc',
page: 0,
size: 500
})
res.content.map(item => {
item.active = false
item.childrenList.map(item => {
item.active = false
})
})
this.categorys = res.content
setTimeout(() => {
this.loading = false
}, 300);
} catch (error) {
console.log(error)
this.loading = false
}
},
show() {
this.dialogVisible = true
this.tbShopCategoryGet()
}
}
}
</script>
<style scoped lang="scss">
.list {
min-height: 200px;
.row {
padding-bottom: 20px;
.list_title {
color: #999;
padding-bottom: 10px;
}
.item_wrap {
display: flex;
}
}
}
</style>

View File

@@ -2,39 +2,32 @@
<div class="navbar"> <div class="navbar">
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container"
@toggleClick="toggleSideBar" /> @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" /> <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
<div class="right-menu"> <div class="right-menu">
<template v-if="device !== 'mobile'"> <!-- <template v-if="device !== 'mobile'">
<search id="header-search" class="right-menu-item" /> <search id="header-search" class="right-menu-item" />
<el-tooltip content="项目文档" effect="dark" placement="bottom">
<!-- <el-tooltip content="项目文档" effect="dark" placement="bottom">
<Doc class="right-menu-item hover-effect" /> <Doc class="right-menu-item hover-effect" />
</el-tooltip> --> </el-tooltip>
<el-tooltip content="全屏缩放" effect="dark" placement="bottom"> <el-tooltip content="全屏缩放" effect="dark" placement="bottom">
<screenfull id="screenfull" class="right-menu-item hover-effect" /> <screenfull id="screenfull" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
<el-tooltip content="布局设置" effect="dark" placement="bottom"> <el-tooltip content="布局设置" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" /> <size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
</template> -->
</template> <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="hover">
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img :src="user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar" class="user-avatar"> <img :src="user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar" class="user-avatar">
<i class="el-icon-caret-bottom" /> <!-- <i class="el-icon-caret-bottom" /> -->
</div> </div>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<span style="display:block;" @click="show = true"> <!-- <span style="display:block;" @click="show = true">
<el-dropdown-item> <el-dropdown-item>
布局设置 布局设置
</el-dropdown-item> </el-dropdown-item>
</span> </span> -->
<router-link to="/user/center"> <router-link to="/shop/shop/shop_configuration">
<el-dropdown-item> <el-dropdown-item>
个人中心 个人中心
</el-dropdown-item> </el-dropdown-item>
@@ -175,7 +168,7 @@ export default {
} }
.avatar-container { .avatar-container {
margin-right: 30px; margin-right: 10px;
.avatar-wrapper { .avatar-wrapper {
margin-top: 5px; margin-top: 5px;
@@ -185,7 +178,7 @@ export default {
cursor: pointer; cursor: pointer;
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 10px; border-radius: 50%;
} }
.el-icon-caret-bottom { .el-icon-caret-bottom {

View File

@@ -5,7 +5,8 @@ import Layout from '../layout/index'
Vue.use(Router) Vue.use(Router)
export const constantRouterMap = [ export const constantRouterMap = [
{ path: '/login', {
path: '/login',
meta: { title: '登录', noCache: true }, meta: { title: '登录', noCache: true },
component: (resolve) => require(['@/views/login'], resolve), component: (resolve) => require(['@/views/login'], resolve),
hidden: true hidden: true
@@ -34,13 +35,23 @@ export const constantRouterMap = [
{ {
path: '/', path: '/',
component: Layout, component: Layout,
redirect: '/dashboard', redirect: '/data_statistics',
meta: {
title: '数据统计',
icon: 'index'
},
children: [ children: [
{ {
path: 'dashboard', path: 'data_statistics',
component: (resolve) => require(['@/views/home'], resolve), component: (resolve) => require(['@/views/home/home'], resolve),
name: 'Dashboard', name: 'data_statistics',
meta: { title: '首页', icon: 'index', affix: true, noCache: true } meta: { title: '数据统计' }
},
{
path: 'data_forms',
component: (resolve) => require(['@/views/home/data_forms'], resolve),
name: 'data_forms',
meta: { title: '数据报表' }
} }
] ]
}, },

View File

@@ -39,7 +39,7 @@ export function parseTime(time, cFormat) {
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key] let value = formatObj[key]
// Note: getDay() returns 0 on Sunday // Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] } if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) { if (result.length > 0 && value < 10) {
value = '0' + value value = '0' + value
} }
@@ -165,12 +165,12 @@ export function param2Obj(url) {
} }
return JSON.parse( return JSON.parse(
'{"' + '{"' +
decodeURIComponent(search) decodeURIComponent(search)
.replace(/"/g, '\\"') .replace(/"/g, '\\"')
.replace(/&/g, '","') .replace(/&/g, '","')
.replace(/=/g, '":"') .replace(/=/g, '":"')
.replace(/\+/g, ' ') + .replace(/\+/g, ' ') +
'"}' '"}'
) )
} }
@@ -249,7 +249,7 @@ export function getTime(type) {
export function debounce(func, wait, immediate) { export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result let timeout, args, context, timestamp, result
const later = function() { const later = function () {
// 据上一次触发时间间隔 // 据上一次触发时间间隔
const last = +new Date() - timestamp const last = +new Date() - timestamp
@@ -266,7 +266,7 @@ export function debounce(func, wait, immediate) {
} }
} }
return function(...args) { return function (...args) {
context = this context = this
timestamp = +new Date() timestamp = +new Date()
const callNow = immediate && !timeout const callNow = immediate && !timeout
@@ -386,3 +386,15 @@ export function downloadFile(obj, name, suffix) {
link.click() link.click()
document.body.removeChild(link) document.body.removeChild(link)
} }
/**
* 生成范围随机数
* @param {Object} Min
* @param {Object} Max
*/
export function RandomNumBoth(Max, Min = 0) {
var Range = Max - Min;
var Rand = Math.random();
var num = Min + Math.round(Rand * Range); //四舍五入
return num;
}

View File

@@ -0,0 +1,192 @@
<template>
<div>
<el-dialog title="添加云打印机" :visible.sync="dialogVisible" @close="reset">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="left">
<el-form-item label="层级">
<el-select v-model="form.contentType">
<el-option :label="item.name" :value="item.value" v-for="item in devices"
:key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备尺寸">
<el-radio-group v-model="form.config.width">
<el-radio-button label="58mm"></el-radio-button>
<el-radio-button label="80mm"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="设备名称" prop="name">
<el-input v-model="form.name" placeholder="请输入设备名称"></el-input>
</el-form-item>
<el-form-item label="设备号" prop="address">
<el-input v-model="form.address" placeholder="请输入设备号"></el-input>
</el-form-item>
<el-form-item label="打印份数">
<el-select v-model="form.config.printerNum">
<el-option :label="item" :value="item" v-for="item in 4" :key="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="出品模式">
<el-select v-model="form.config.model">
<el-option :label="item.name" :value="item.value" v-for="item in models"
:key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="打印类型">
<el-select v-model="form.subType">
<el-option :label="item.name" :value="item.value" v-for="item in subTypes"
:key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="尾部留空">
<el-radio-group v-model="form.config.feet">
<el-radio-button :label="`${item}`" v-for="item in feets" :key="item">{{ item
}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="自动切刀">
<el-switch v-model="form.config.autoCut" :active-value="0" :inactive-value="1"></el-switch>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="form.status" :active-value="0" :inactive-value="1"></el-switch>
</el-form-item>
<el-form-item label="排序">
<el-input-number v-model="form.sort" controls-position="right" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="商品分类">
<div style="cursor: pointer;" @click="$refs.classify.show()">
<span style="color: #409eff;" v-for="item in form.config.categoryList">{{ item.name }},</span>
<span style="color: #e65d6e;" v-if="!form.config.categoryList.length">请选择分类</span>
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
<classify ref="classify" @success="classifySuccess" />
</div>
</template>
<script>
import devices from '../devices'
import { tbPrintMachine } from '@/api/devices'
import classify from '@/components/classify'
export default {
components: { classify },
data() {
return {
dialogVisible: false,
devices,
models: [
{
value: 'normal',
name: '普通出单'
},
{
value: 'one',
name: '一菜一品'
},
{
value: 'category',
name: '分类出单'
}
],
subTypes: [
{
value: 'kitchen',
name: '出品'
},
{
value: 'cash',
name: '小票'
},
{
value: 'label',
name: '标签'
}
],
feets: [0, 1, 2, 3, 4, 5, 8],
loading: false,
form: {
id: '',
contentType: '',
config: {
width: '80mm', // 设备尺寸
printerNum: 1, //打印份数
categoryList: '', // 商品分类
model: 'normal', // 出品模式,
feet: '0',
autoCut: 0
},
name: '',
subType: 'kitchen', // 打印类型
status: 0,
sort: ''
},
resetForm: '',
rules: {
name: [
{
required: true,
message: ' ',
trigger: 'blur'
}
],
address: [
{
required: true,
message: ' ',
trigger: 'blur'
}
]
}
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
// 确认选择商品分类
classifySuccess(e) {
this.form.config.categoryList = e
},
onSubmitHandle() {
console.log(this.form)
this.$refs.form.validate(async valid => {
if (valid) {
try {
this.loading = true
this.form.shopId = localStorage.getItem('shopId')
let res = await tbPrintMachine(this.form, this.form.id ? 'put' : 'post')
this.$emit('success', res)
this.close()
this.$notify({
title: '成功',
message: `${this.form.id ? '编辑' : '添加'}成功`,
type: 'success'
});
this.loading = false
} catch (error) {
this.loading = false
console.log(error)
}
}
})
},
show(obj) {
this.dialogVisible = true
if (obj && obj.id) {
this.form = obj
}
},
close() {
this.dialogVisible = false
},
reset() {
this.form = { ...this.resetForm }
}
}
}
</script>

View File

@@ -0,0 +1,10 @@
export default [
{
value: 'yxyPrinter',
name: '云想印'
},
{
value: 'fePrinter',
name: '飞鹅'
}
]

View File

@@ -0,0 +1,94 @@
<template>
<div class="app-container">
<div class="head-container">
<el-form :model="query" inline>
<el-form-item>
<el-input v-model="query.name" placeholder="请输入设备名称"></el-input>
</el-form-item>
<el-form-item>
<el-select v-model="query.type" placeholder="请选择设备类型">
<el-option :label="item.name" :value="item.value" v-for="item in devices" :key="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary">查询</el-button>
<el-button>重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="head-container">
<el-button type="primary" icon="el-icon-plus" @click="$refs.addDevice.show()">添加云打印机</el-button>
</div>
<div class="head-container">
<el-table :data="tableData.data" v-loading="tableData.loading">
<el-table-column label="设备名称" prop="name"></el-table-column>
</el-table>
</div>
<div class="head-container">
<el-pagination :total="tableData.total" :current-page="tableData.page + 1" :page-size="tableData.size"
@current-change="paginationChange" layout="total"></el-pagination>
</div>
<addDevice ref="addDevice" />
</div>
</template>
<script>
import devices from './devices'
import addDevice from './components/addDevice'
import { tbPrintMachineGet } from '@/api/devices'
export default {
components: {
addDevice
},
data() {
return {
query: {
name: '',
type: ''
},
devices,
tableData: {
data: [],
page: 0,
size: 10,
loading: false,
total: 0
}
}
},
mounted() {
this.getTableData()
},
methods: {
// 重置查询
resetHandle() {
this.query.name = ''
this.query.categoryId = ''
this.query.typeEnum = ''
this.getTableData()
},
// 分页回调
paginationChange(e) {
this.tableData.page = e - 1
this.getTableData()
},
// 获取商品列表
async getTableData() {
this.tableData.loading = true
try {
const res = await tbPrintMachineGet({
page: this.tableData.page,
size: this.tableData.size,
name: this.query.name,
contentType: this.query.type
})
this.tableData.loading = false
this.tableData.data = res
this.tableData.total = res.length
} catch (error) {
console.log(error)
}
},
}
}
</script>

View File

@@ -1,115 +0,0 @@
<template>
<el-image :src="this.shouye"></el-image>
<!-- <div class="dashboard-container">
<div class="dashboard-editor-container">
<github-corner class="github-corner" />
<panel-group @handleSetLineChartData="handleSetLineChartData" />
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData" />
</el-row>
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<radar-chart />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<pie-chart />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<bar-chart />
</div>
</el-col>
</el-row>
</div>
</div> -->
</template>
<script>
import GithubCorner from '@/components/GithubCorner'
import PanelGroup from './dashboard/PanelGroup'
import LineChart from './dashboard/LineChart'
import RadarChart from '@/components/Echarts/RadarChart'
import PieChart from '@/components/Echarts/PieChart'
import BarChart from '@/components/Echarts/BarChart'
import shouye from '@/assets/images/background.webp'
const lineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
export default {
name: 'Dashboard',
components: {
GithubCorner,
PanelGroup,
LineChart,
RadarChart,
PieChart,
BarChart
},
data() {
return {
shouye:shouye,
lineChartData: lineChartData.newVisitis
}
},
created(){
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type]
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.dashboard-editor-container {
padding: 32px;
background-color: rgb(240, 242, 245);
position: relative;
.github-corner {
position: absolute;
top: 0;
border: 0;
right: 0;
}
.chart-wrapper {
background: #fff;
padding: 16px 16px 0;
margin-bottom: 32px;
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
</style>

View File

@@ -0,0 +1,3 @@
<template>
<div>数据报表</div>
</template>

448
src/views/home/home.vue Normal file
View File

@@ -0,0 +1,448 @@
<template>
<div class="app-container" style="padding-bottom: 100px;">
<div class="card_wrap">
<div class="card">
<div class="header">
<div class="card_title">总销售额</div>
<el-tooltip effect="dark" content="订单支付金额" placement="top">
<i class="icon el-icon-warning-outline"></i>
</el-tooltip>
</div>
<div class="number">{{ topData.totalSales || 0 }}</div>
<div class="row">平均每单{{ topData.averageSales || 0 }}</div>
<div class="row">今日销售额{{ topData.totalSalesToday || 0 }}</div>
</div>
<div class="card">
<div class="header">
<div class="card_title">支付笔数</div>
</div>
<div class="number">{{ topData.paymentsNumber }}</div>
<div class="row"></div>
<div class="row">今日支付笔数{{ topData.paymentsNumberToday || 0 }}</div>
</div>
<div class="card">
<div class="header">
<div class="card_title">用户数</div>
</div>
<div class="number">{{ topData.totalUser }}</div>
<div class="row"></div>
<div class="row">今日新增 {{ topData.userToday || 0 }} <i class="icon el-icon-caret-top"></i> </div>
</div>
</div>
<!-- 销售额 -->
<div class="chart_wrap">
<div class="item">
<div class="header">
<div class="tab_wrap">
<div class="item active">销售额</div>
</div>
<el-radio-group v-model="saleActive" @change="dateAmount">
<el-radio-button label="7">近7天</el-radio-button>
<el-radio-button label="30">30</el-radio-button>
</el-radio-group>
</div>
<div class="chart" ref="saleChart" v-loading="saleLoading" style="height: 400px;">
</div>
</div>
</div>
<div class="chart_wrap" style="display: flex;">
<!-- 商品销售排行 -->
<div class="item">
<div class="header">
<div class="tab_wrap">
<div class="item active">商品销售排行</div>
</div>
<el-radio-group v-model="saleTableActive" @change="dateProduct">
<el-radio-button label="7">近7天</el-radio-button>
<el-radio-button label="30">30</el-radio-button>
</el-radio-group>
</div>
<div class="sale_data">
<div class="card">
<div class="sale_data_header">
<div class="card_title">销售数量</div>
</div>
<div class="number">{{ productCount }}</div>
</div>
<div class="card">
<div class="sale_data_header">
<div class="card_title">销售金额</div>
</div>
<div class="number">{{ productSum }}</div>
</div>
</div>
<div class="table">
<el-table :data="saleTable" v-loading="saleTableLoading">
<el-table-column label="排名" prop="productId"></el-table-column>
<el-table-column label="商品名称" prop="productName"></el-table-column>
<el-table-column label="数量" prop="productNum"></el-table-column>
<el-table-column label="金额" prop="amount"></el-table-column>
</el-table>
<div class="head-container" style="padding-top: 20px;display: flex;justify-content: flex-end;">
<el-pagination :total="saleTableTotal" :current-page="saleTablePage" @current-change="paginationChange"
layout="total, prev, pager, next, jumper"></el-pagination>
</div>
</div>
</div>
<!-- 支付类型占比 -->
<div class="item" style="margin-left: 20px;">
<div class="header">
<div class="tab_wrap">
<div class="item active">支付占比类型</div>
</div>
<el-radio-group v-model="payChartDay" @change="datePayType">
<el-radio-button label="7">近7天</el-radio-button>
<el-radio-button label="30">30</el-radio-button>
</el-radio-group>
</div>
<div style="height: 400px;margin-top: 30px;" ref="payChart" v-loading="payChartLoading"></div>
</div>
</div>
</div>
</template>
<script>
import { summaryGet, summaryTodayGet, dateProduct, dateAmount, datePayType } from '@/api/home'
import echarts from 'echarts'
import { debounce } from '@/utils'
export default {
name: 'home',
data() {
return {
topData: '',
saleTab: 'sale',
saleActive: '7',
saleLoading: false,
saleChart: null,
payChartDay: '7',
payChartLoading: false,
payChart: null,
chartType: 1,
productCount: 0,
productSum: 0,
saleTableActive: '7',
saleTable: [],
saleTableLoading: false,
saleTablePage: 1,
saleTableTotal: 0,
__resizeHandler: null
}
},
mounted() {
this.summaryGet()
this.dateAmount()
this.dateProduct()
this.datePayType()
this.__resizeHandler = debounce(() => {
if (this.saleChart) {
this.saleChart.resize()
}
if (this.payChart) {
this.payChart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
},
methods: {
// 初始化销售额图标
initSaleChart(time, data) {
this.saleChart = null
this.saleChart = echarts.init(this.$refs.saleChart)
this.saleChart.setOption({
title: {
text: '销售趋势',
x: 'center'
},
tooltip: {
trigger: 'axis'
},
xAxis: [{
type: 'category',
data: time,
axisTick: {
alignWithLabel: true
},
axisLine: {
lineStyle: {
color: '#999'
}
},
axisLabel: {
rotate: time.length <= 7 ? 0 : 45,
interval: 0,
textStyle: {
fontSize: '9'
}
}
}],
color: '#409eff',
yAxis: [
{
type: 'value',
axisLine: {
lineStyle: {
color: '#999'
}
},
splitLine: {
lineStyle: {
type: 'dashed',
color: '#ececec'
}
}
}
],
series: [
{
data: data,
type: 'bar',
barWidth: time.length <= 7 ? '50%' : '30%'
}
]
})
},
// 初始化销售额图表
initPayChart(data) {
this.payChart = echarts.init(this.$refs.payChart)
this.payChart.setOption({
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center'
},
color: ['#409eff', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
series: [
{
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: 20
}
},
labelLine: {
show: false
},
data: data
}
]
})
},
// 获取销售额柱状图数据
async dateAmount() {
try {
this.saleLoading = true
const res = await dateAmount(this.saleActive)
const data = res.total.map(item => item.amount)
const time = res.total.map(item => item.tradeDay)
this.initSaleChart(time, data)
setTimeout(() => {
this.saleLoading = false
}, 300);
} catch (error) {
console.log(error)
}
},
paginationChange(e) {
this.saleTablePage = e
this.dateProduct()
},
// 获取销售额排行表格数据
async dateProduct() {
try {
this.saleTableLoading = true
const res = await dateProduct(this.saleTableActive, this.saleTablePage)
this.saleTable = res.totalProduct
this.saleTableTotal = res.productCount
this.productCount = res.productCount
this.productSum = res.productSum
setTimeout(() => {
this.saleTableLoading = false
}, 300);
} catch (error) {
console.log(error)
}
},
// 支付类型占比 饼图
async datePayType() {
try {
this.payChartLoading = true
const res = await datePayType(this.payChartDay)
const data = res.countPayType.map(item => {
return {
value: item.count,
name: item.payType
}
})
setTimeout(() => {
this.payChartLoading = false
}, 300);
this.initPayChart(data)
} catch (error) {
console.log(error)
}
},
// 汇总数据
async summaryGet() {
try {
const res1 = await summaryGet()
const res2 = await summaryTodayGet()
this.topData = {
...res1,
...res2
}
} catch (error) {
console.log(error)
}
},
}
}
</script>
<style scoped lang="scss">
.app-container {
padding: 20px;
background-color: #F5F5F5;
}
.card_wrap {
display: flex;
flex-wrap: wrap;
gap: 20px;
.card {
flex: 1;
background-color: #fff;
border-radius: 2px;
padding: 0 20px;
.header {
display: flex;
justify-content: space-between;
color: #999;
padding-top: 20px;
.card_title {
font-size: 14px;
flex: 1;
}
}
.number {
padding: 20px 0 10px 0;
font-size: 24px;
height: 60px;
}
.row {
height: 40px;
color: #555;
font-size: 14px;
display: flex;
align-items: center;
&:not(:last-child) {
border-bottom: 1px solid #ececec;
}
.icon {
color: rgb(255, 85, 85);
margin-left: 4px;
}
}
}
}
.chart_wrap {
margin-top: 20px;
.sale_data {
display: flex;
.card {
flex: 1;
background-color: #fff;
border-radius: 2px;
padding: 0 20px;
.sale_data_header {
display: flex;
justify-content: space-between;
color: #999;
padding-top: 20px;
.card_title {
font-size: 14px;
flex: 1;
}
}
.number {
padding-top: 10px;
font-size: 24px;
height: 60px;
}
}
}
.item {
flex: 1;
background-color: #fff;
border-radius: 2px;
.header {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #ececec;
padding: 0 20px;
.tab_wrap {
display: flex;
$color: #1890FF;
.item {
padding: 0 10px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: $color;
&.active {
position: relative;
&::after {
content: "";
width: 100%;
border-bottom: 2px solid $color;
position: absolute;
bottom: 0;
left: 0;
}
}
}
}
}
.chart {
padding: 20px 0;
height: 300px;
}
.table {
padding: 20px;
}
}
}
</style>

View File

@@ -125,9 +125,9 @@
<shopList ref="shopList" @success="selectShop" /> <shopList ref="shopList" @success="selectShop" />
<el-dialog :visible.sync="showResult" :show-close="false" :close-on-press-escape="false" <el-dialog :visible.sync="showResult" :show-close="false" :close-on-press-escape="false"
:close-on-click-modal="false"> :close-on-click-modal="false">
<el-result icon="success" title="库提交成功" :subTitle="`共操作${tableData.list.length}件商品`"> <el-result icon="success" title="库提交成功" :subTitle="`共操作${tableData.list.length}件商品`">
<template slot="extra"> <template slot="extra">
<el-button type="primary" size="medium" @click="resetHandle">创建新的库单</el-button> <el-button type="primary" size="medium" @click="resetHandle">创建新的库单</el-button>
<router-link to="/invoicing/operating_record"> <router-link to="/invoicing/operating_record">
<el-button size="medium">历史提交</el-button> <el-button size="medium">历史提交</el-button>
</router-link> </router-link>

View File

@@ -1,8 +1,9 @@
<template> <template>
<div class="login" :style="'background-image:url('+ Background +');'"> <div class="login" :style="'background-image:url(' + Background + ');'">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px"
class="login-form">
<h3 class="title"> <h3 class="title">
收银机后台 银收客后台管理
</h3> </h3>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号"> <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
@@ -10,23 +11,28 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin"> <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码"
@keyup.enter.native="handleLogin">
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code"> <el-form-item prop="code">
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin"> <div class="code_wrap">
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%"
</el-input> @keyup.enter.native="handleLogin">
<div class="login-code"> <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
<img :src="codeUrl" @click="getCode"> </el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode">
</div>
</div> </div>
</el-form-item> </el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;"> <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;">
记住我 记住我
</el-checkbox> </el-checkbox>
<el-form-item style="width:100%;"> <el-form-item style="width:100%;">
<el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin"> <el-button :loading="loading" size="medium" type="primary" style="width:100%;"
@click.native.prevent="handleLogin">
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> 中...</span> <span v-else> 中...</span>
</el-button> </el-button>
@@ -47,7 +53,7 @@ import Config from '@/settings'
import { getCodeImg } from '@/api/login' import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import qs from 'qs' import qs from 'qs'
import Background from '@/assets/images/background.webp' import Background from '@/assets/images/background_img.jpg'
export default { export default {
name: 'Login', name: 'Login',
data() { data() {
@@ -56,8 +62,8 @@ export default {
codeUrl: '', codeUrl: '',
cookiePass: '', cookiePass: '',
loginForm: { loginForm: {
username: 'admin', username: '',
password: '123456', password: '',
rememberMe: false, rememberMe: false,
code: '', code: '',
uuid: '' uuid: ''
@@ -73,7 +79,7 @@ export default {
}, },
watch: { watch: {
$route: { $route: {
handler: function(route) { handler: function (route) {
const data = route.query const data = route.query
if (data && data.redirect) { if (data && data.redirect) {
this.redirect = data.redirect this.redirect = data.redirect
@@ -169,47 +175,60 @@ export default {
</script> </script>
<style rel="stylesheet/scss" lang="scss"> <style rel="stylesheet/scss" lang="scss">
.login { .login {
display: flex; display: flex;
justify-content: center; justify-content: flex-end;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-size: cover; background-size: cover;
} padding-right: 15%;
.title { }
margin: 0 auto 30px auto;
text-align: center; .title {
color: #707070; margin: 0 auto 50px auto;
text-align: center;
color: #707070;
font-size: 36px;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 500px;
padding: 50px 50px 50px 50px;
.el-input {
height: 38px;
input {
height: 38px;
}
} }
.login-form { .input-icon {
border-radius: 6px; height: 39px;
background: #ffffff; width: 14px;
width: 385px; margin-left: 2px;
padding: 25px 25px 5px 25px;
.el-input {
height: 38px;
input {
height: 38px;
}
}
.input-icon{
height: 39px;width: 14px;margin-left: 2px;
}
} }
.login-tip { }
font-size: 13px;
text-align: center; .login-tip {
color: #bfbfbf; font-size: 13px;
} text-align: center;
.login-code { color: #bfbfbf;
width: 33%; }
display: inline-block; .code_wrap {
height: 38px; display: flex;
float: right; justify-content: space-between;
img{ }
cursor: pointer; .login-code {
vertical-align:middle width: 33%;
} display: inline-block;
height: 38px;
img {
cursor: pointer;
vertical-align: middle
} }
}
</style> </style>

View File

@@ -78,42 +78,42 @@
<el-form-item label="规格属性" v-if="shopTypes[shopTypesActive].typeEnum != 'sku'"> <el-form-item label="规格属性" v-if="shopTypes[shopTypesActive].typeEnum != 'sku'">
<el-table :data="form.skuList" border> <el-table :data="form.skuList" border>
<el-table-column label="售价" prop="salePrice"> <el-table-column label="售价" prop="salePrice">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.salePrice"></el-input-number> <el-input-number v-model="scope.row.salePrice"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="会员价" prop="memberPrice"> <el-table-column label="会员价" prop="memberPrice">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.memberPrice"></el-input-number> <el-input-number v-model="scope.row.memberPrice"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="成本价" prop="costPrice"> <el-table-column label="成本价" prop="costPrice">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.costPrice"></el-input-number> <el-input-number v-model="scope.row.costPrice"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="原价" prop="originPrice"> <el-table-column label="原价" prop="originPrice">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.originPrice"></el-input-number> <el-input-number v-model="scope.row.originPrice"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="库存数量" prop="stockNumber"> <el-table-column label="库存数量" prop="stockNumber">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.stockNumber"></el-input-number> <el-input-number v-model="scope.row.stockNumber" :disabled="!!form.id"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="分销金额" prop="firstShared"> <el-table-column label="分销金额" prop="firstShared">
<template v-slot="scope"> <template v-slot="scope">
<el-input-number v-model="scope.row.firstShared"></el-input-number> <el-input-number v-model="scope.row.firstShared"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="商品条码">
<template v-slot="scope">
<el-input v-model="scope.row.barCode" disabled></el-input>
</template>
</el-table-column>
</el-table> </el-table>
<div class="tips" v-if="form.isShowMall">小程序商城必须设置库存数量大于0</div>
</el-form-item> </el-form-item>
<el-form-item label="选择规格" v-if="shopTypes[shopTypesActive].typeEnum == 'sku'"> <el-form-item label="选择规格" v-if="shopTypes[shopTypesActive].typeEnum == 'sku'">
<el-select v-model="form.specId" placeholder="请选择规格" style="width: 500px;" @change="selectSpecHandle"> <el-select v-model="form.specId" placeholder="请选择规格" style="width: 500px;" @change="selectSpecHandle">
@@ -141,66 +141,103 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="售价" prop="salePrice"> <el-table-column label="售价" prop="salePrice">
<template slot="header" slot-scope="scope"> <template slot="header" slot-scope="scope">
<span>售价</span> <span>售价</span>
<i class="icon el-icon-edit" @click="showNumberChange(scope.$index)"></i> <i class="icon el-icon-edit" @click="batchNumber('salePrice')"></i>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input-number v-model="scope.row.salePrice" controls-position="right"></el-input-number> <el-input-number v-model="scope.row.salePrice" controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="会员价" prop="memberPrice"> <el-table-column label="会员价" prop="memberPrice">
<template slot="header" slot-scope="scope">
<template v-slot="scope"> <span>会员价</span>
<i class="icon el-icon-edit" @click="batchNumber('memberPrice')"></i>
</template>
<template slot-scope="scope">
<el-input-number v-model="scope.row.memberPrice" <el-input-number v-model="scope.row.memberPrice"
controls-position="right"></el-input-number> controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="成本价" prop="costPrice"> <el-table-column label="成本价" prop="costPrice">
<template slot="header" slot-scope="scope">
<template v-slot="scope"> <span>成本价</span>
<i class="icon el-icon-edit" @click="batchNumber('costPrice')"></i>
</template>
<template slot-scope="scope">
<el-input-number v-model="scope.row.costPrice" controls-position="right"></el-input-number> <el-input-number v-model="scope.row.costPrice" controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="原价" prop="originPrice"> <el-table-column label="原价" prop="originPrice">
<template slot="header" slot-scope="scope">
<template v-slot="scope"> <span>原价</span>
<i class="icon el-icon-edit" @click="batchNumber('originPrice')"></i>
</template>
<template slot-scope="scope">
<el-input-number v-model="scope.row.originPrice" <el-input-number v-model="scope.row.originPrice"
controls-position="right"></el-input-number> controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="库存数量" prop="stockNumber"> <el-table-column label="库存数量" prop="stockNumber">
<template slot="header" slot-scope="scope">
<template v-slot="scope"> <span>库存数量</span>
<i class="icon el-icon-edit" @click="batchNumber('stockNumber')"></i>
</template>
<template slot-scope="scope">
<el-input-number v-model="scope.row.stockNumber" <el-input-number v-model="scope.row.stockNumber"
controls-position="right"></el-input-number> controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="分销金额" prop="firstShared"> <el-table-column label="分销金额" prop="firstShared">
<template slot="header" slot-scope="scope">
<template v-slot="scope"> <span>分销金额</span>
<i class="icon el-icon-edit" @click="batchNumber('firstShared')"></i>
</template>
<template slot-scope="scope">
<el-input-number v-model="scope.row.firstShared" <el-input-number v-model="scope.row.firstShared"
controls-position="right"></el-input-number> controls-position="right"></el-input-number>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="商品条码">
<template v-slot="scope">
<el-input v-model="scope.row.barCode" disabled></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="80"> <el-table-column label="操作" width="80">
<template v-slot="scope"> <template v-slot="scope">
<el-button type="text" @click="form.skuList.splice(scope.$index, 1)">删除</el-button> <el-button type="text" @click="form.skuList.splice(scope.$index, 1)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="tips" v-if="form.isShowMall">注小程序商城必须设置库存数量大于0</div>
</el-form-item>
<el-form-item label="上架区域">
<div class="shop_type_box">
<div class="item" :class="{ active: form.isShowCash }" @click="areaChange('isShowCash')">
<div class="s_title">收银台</div>
<div class="active_dot">
<i class="el-icon-check"></i>
</div>
</div>
<div class="item" :class="{ active: form.isShowMall }" @click="areaChange('isShowMall')">
<div class="s_title">小程序商城</div>
<div class="active_dot">
<i class="el-icon-check"></i>
</div>
</div>
</div>
</el-form-item> </el-form-item>
<el-form-item label="库存开关"> <el-form-item label="库存开关">
<el-switch v-model="form.isStock" :active-value="1" :inactive-value="0"></el-switch> <el-switch v-model="form.isStock" :active-value="1" :inactive-value="0"></el-switch>
<div class="tips">注:关闭则不计算出入库数据</div>
</el-form-item> </el-form-item>
<el-form-item label="标签打印"> <el-form-item label="标签打印">
<el-switch v-model="form.enableLabel" :active-value="1" :inactive-value="0"></el-switch> <el-switch v-model="form.enableLabel" :active-value="1" :inactive-value="0"></el-switch>
<div class="tips">开启后: 收银完成后会自动打印对应数量的标签数</div>
</el-form-item> </el-form-item>
<el-form-item label="打包费"> <el-form-item label="打包费">
<el-input-number v-model="form.packFee" controls-position="right" :min="0"></el-input-number> <el-input-number v-model="form.packFee" controls-position="right" :min="0"></el-input-number>
<div class="tips">单份商品打包费。注:店铺开启外卖模式下该数据才生效</div>
</el-form-item> </el-form-item>
<el-form-item label="虚拟销量"> <el-form-item label="虚拟销量">
<el-input-number v-model="form.baseSalesNumber" controls-position="right" :min="0"></el-input-number> <el-input-number v-model="form.baseSalesNumber" controls-position="right" :min="0"></el-input-number>
@@ -210,9 +247,21 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" v-loading="loading" @click="submitHandle">确定</el-button> <el-button type="primary" v-loading="loading" @click="submitHandle">确定</el-button>
<el-button>取消</el-button> <el-button @click="$router.back()">取消</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-dialog title="批量修改" width="400px" :visible.sync="showBatchModal">
<el-form :model="batchNumberForm">
<el-form-item>
<el-input-number v-model="batchNumberForm.batchNumber" :min="0" controls-position="right"
style="width: 100%;"></el-input-number>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="showBatchModal = false">取 消</el-button>
<el-button type="primary" @click="batchNumberFormConfirm">确 定</el-button>
</span>
</el-dialog>
</div> </div>
</template> </template>
@@ -223,6 +272,9 @@ import addClassify from './components/addClassify'
import shopList from '@/components/shopList' import shopList from '@/components/shopList'
import uploadImg from '@/components/uploadImg' import uploadImg from '@/components/uploadImg'
import settings from '@/settings' import settings from '@/settings'
import dayjs from 'dayjs'
import { RandomNumBoth } from "@/utils";
export default { export default {
components: { components: {
addUnit, addUnit,
@@ -234,32 +286,6 @@ export default {
return { return {
shopTypesActive: 0, shopTypesActive: 0,
shopTypes: settings.typeEnum, shopTypes: settings.typeEnum,
skuList: [
{
label: '售价',
value: 'salePrice'
},
{
label: '会员价',
value: 'memberPrice'
},
{
label: '成本价',
value: 'costPrice'
},
{
label: '原价',
value: 'originPrice'
},
{
label: '库存数量',
value: 'stockNumber'
},
{
label: '一级分销金额',
value: 'firstShared'
}
],
specTableHeaders: [], specTableHeaders: [],
specTableBodys: [], specTableBodys: [],
specId: '', specId: '',
@@ -272,7 +298,8 @@ export default {
costPrice: 0, costPrice: 0,
originPrice: 0, originPrice: 0,
stockNumber: 0, stockNumber: 0,
firstShared: 0 firstShared: 0,
barCode: `${localStorage.getItem('shopId')}${dayjs().valueOf()}`
}, },
tableAddShopIndex: null, tableAddShopIndex: null,
isEditor: false, isEditor: false,
@@ -289,7 +316,8 @@ export default {
shopId: localStorage.getItem('shopId'), shopId: localStorage.getItem('shopId'),
lowPrice: '', lowPrice: '',
skuList: [], skuList: [],
isStock: 0, isShowMall: 1,
isShowCash: 1,
isStock: 0, isStock: 0,
packFee: 0, packFee: 0,
specId: '', specId: '',
@@ -323,7 +351,13 @@ export default {
] ]
}, },
units: [], units: [],
categorys: [] categorys: [],
// 批量修改规格
showBatchModal: false,
batchNumberKey: '',
batchNumberForm: {
batchNumber: 0
}
} }
}, },
mounted() { mounted() {
@@ -336,11 +370,29 @@ export default {
} }
}, },
methods: { methods: {
// 修改商家区域
areaChange(key) {
if (this.form[key] == 1) {
this.form[key] = 0
} else {
this.form[key] = 1
}
},
selectUnitt(e) { selectUnitt(e) {
this.form.unitName = this.units.find(item => item.id == e).name this.form.unitName = this.units.find(item => item.id == e).name
}, },
showNumberChange(index) { // 批量修改规格
console.log(index) batchNumber(key) {
this.batchNumberKey = key
this.showBatchModal = true
},
// 确认批量修改规格
batchNumberFormConfirm() {
this.form.skuList.map(item => {
item[this.batchNumberKey] = this.batchNumberForm.batchNumber
})
this.showBatchModal = false
this.batchNumberForm.batchNumber = 0
}, },
// 商品详情 // 商品详情
async tbProductGetDetail() { async tbProductGetDetail() {
@@ -494,7 +546,8 @@ export default {
newarr.push({ newarr.push({
specSnap: specSnap.join(','), specSnap: specSnap.join(','),
...m, ...m,
...obj ...obj,
barCode: `${dayjs().valueOf()}${RandomNumBoth(1, 9999)}`
}) })
} else { } else {
let specSnap = [] let specSnap = []
@@ -504,7 +557,8 @@ export default {
newarr.push({ newarr.push({
specSnap: specSnap.join(','), specSnap: specSnap.join(','),
...m, ...m,
...item ...item,
barCode: `${dayjs().valueOf()}${RandomNumBoth(1, 9999)}`
}) })
} }
} }

View File

@@ -7,9 +7,9 @@
class="filter-item" @keyup.enter.native="getTableData" /> class="filter-item" @keyup.enter.native="getTableData" />
</el-col> </el-col>
<el-col :span="3"> <el-col :span="3">
<el-cascader :options="categorys" v-model="query.categoryId" :show-all-levels="false" <el-select v-model="query.categoryId" placeholder="请选择商品分类" style="width: 100%;">
:props="{ value: 'id', label: 'name', children: 'childrenList', expandTrigger: 'hover', emitPath: false }" <el-option :label="item.name" :value="item.id" v-for="item in categorys" :key="item.id" />
clearable placeholder="请选择商品分类"></el-cascader> </el-select>
</el-col> </el-col>
<el-col :span="3"> <el-col :span="3">
<el-select v-model="query.typeEnum" placeholder="请选择商品规格" style="width: 100%;"> <el-select v-model="query.typeEnum" placeholder="请选择商品规格" style="width: 100%;">
@@ -55,10 +55,16 @@
</el-table-column> </el-table-column>
<el-table-column label="销量/库存"> <el-table-column label="销量/库存">
<template v-slot="scope"> <template v-slot="scope">
<span>{{ scope.row.xl }}/{{ scope.row.kc }}</span> <span>{{ scope.row.realSalesNumber }}/{{ scope.row.stockNumber }}</span>
</template>
</el-table-column>
<el-table-column label="上架区域">
<template v-slot="scope">
<div v-if="scope.row.isShowCash">收银端</div>
<div v-if="scope.row.isShowMall">小程序</div>
<div v-if="!scope.row.isShowCash && !scope.row.isShowMall">未上架</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="上架区域" prop="area" />
<el-table-column label="排序" prop="sort" sortable /> <el-table-column label="排序" prop="sort" sortable />
<el-table-column label="更新时间" prop="createdAt"> <el-table-column label="更新时间" prop="createdAt">
<template v-slot="scope"> <template v-slot="scope">