代码合并,增肌挂账人支付

This commit is contained in:
YeMingfei666 2024-11-27 15:06:42 +08:00
commit 74bd8904ac
24 changed files with 2456 additions and 156 deletions

View File

@ -3,10 +3,10 @@ ENV = 'production'
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇Nginx 配置
# 接口地址,注意协议,如果你没有配置 ssl需要将 https 改为 http
# 测试
# VUE_APP_BASE_API = 'https://admintestpapi.sxczgkj.cn'
VUE_APP_BASE_API = 'https://admintestpapi.sxczgkj.cn'
# 生产
VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn'
# VUE_APP_BASE_API = 'https://cashieradmin.sxczgkj.cn'
# 预发布接口
# VUE_APP_BASE_API = 'https://pre-cashieradmin.sxczgkj.cn'

View File

@ -18,7 +18,7 @@ export function tbPrintMachine(data, method = "post") {
// 开票
export function getbinding(data) {
return request({
url: "/api/tbShopInfo/binding",
url: "/api/invoice/binding",
method: "post",
data: {
shopId: localStorage.getItem("shopId"),
@ -26,6 +26,53 @@ export function getbinding(data) {
}
});
}
// 提交开票
export function getsubInvoicing(data) {
return request({
url: "/api/invoice/subInvoicing",
method: "post",
data: {
shopId: localStorage.getItem("shopId"),
...data
}
});
}
// 获取数电发票类型
export function getdigitalInvoice(data) {
return request({
url: "/api/invoice/digitalInvoice",
method: "post",
data: {
shopId: localStorage.getItem("shopId"),
...data
}
});
}
// 获取项目分类
export function getindustry(data) {
return request({
url: "/api/invoice/industry",
method: "post",
data: {
shopId: localStorage.getItem("shopId"),
...data
}
});
}
// 计算税额
export function getstoreSe(data) {
return request({
url: "/api/invoice/storeSe",
method: "post",
data: {
shopId: localStorage.getItem("shopId"),
is_tax:1,
...data
}
});
}
/**
* 获取应用中心列表
* @returns

110
src/api/credit.js Normal file
View File

@ -0,0 +1,110 @@
import request from '@/utils/request'
/**
* 获取挂账人列表
* @returns
*/
export function getCreditBuyerList(params) {
return request({
url: '/api/credit/buyer/page',
method: 'get',
params: {
...params
}
})
}
/**
* 获取挂账人详情
* @returns
*/
export function getCreditBuyerInfo(id) {
return request({
url: '/api/credit/buyer/' + id,
method: 'get',
params: {}
})
}
/**
* 增加挂账人
* @returns
*/
export function addCreditBuyer(data) {
return request({
url: '/api/credit/buyer',
method: 'post',
data
})
}
/**
* 还款
* @returns
*/
export function creditRePayment(data) {
return request({
url: '/api/credit/buyer/repayment',
method: 'post',
data
})
}
/**
* 获取还款记录
* @returns
*/
export function creditRePaymentRecord(params) {
return request({
url: '/api/credit/payment-record/page',
method: 'get',
params
})
}
/**
* 删除挂账人
* @returns
*/
export function delCreditBuyer(id) {
return request({
url: `/api/credit/buyer/${id}`,
method: 'delete'
})
}
/**
* 挂账人-查看明细
* @returns
*/
export function creditBuyerOrderList(params) {
return request({
url: '/api/credit/buyer-order/page',
method: 'get',
params
})
}
/**
* 挂账人-查看明细-统计
* @returns
*/
export function creditBuyerOrderSummary(params) {
return request({
url: '/api/credit/buyer-order/summary',
method: 'get',
params
})
}
/**
* 挂账人-查看明细-付款
* @returns
*/
export function creditPayment(data) {
return request({
url: '/api/credit/buyer-order/pay',
method: 'post',
data
})
}

View File

@ -15,12 +15,27 @@ export function getInfo() {
});
}
export function changChildShop(data) {
return request({
url: "/api/tbShopInfo/changChildShop",
method: "post",
data
});
}
export function getCodeImg(header) {
return request({
url: "auth/code",
method: "get"
});
}
export function getqueryChildShop(params) {
return request({
url: "api/tbShopInfo/queryChildShop",
method: "get",
params
});
}
export function logout() {
return request({

View File

@ -6,7 +6,7 @@ import request from "@/utils/request";
*/
export function tbProduct(params) {
return request({
url: "/api/tbProduct",
url: "/api/tbProduct/list",
method: "get",
params
});

View File

@ -146,6 +146,8 @@ export default {
categoryId: this.searhForm.category,
shopId: localStorage.getItem('shopId'),
sort: 'id',
createdAt: [],
sort: 'createdAt,desc'
})
this.tableData.list = res.content
this.tableData.total = res.totalElements

View File

@ -7,9 +7,39 @@
<i class="el-icon-arrow-down icon"></i>
</div>
<div v-else key="expand" class="sidebar-logo-link">
<img v-if="logo" :src="logo || Avatar" class="sidebar-logo">
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<img :src="logo || Avatar" class="sidebar-logo">
<span class="shop_name">{{ shopName.length>8?shopName.substring(0,7)+'...' :shopName.substring(0,7) }}</span>
<i class="el-icon-arrow-down icon"></i>
</div>
<el-dropdown-menu slot="dropdown">
<!-- <span style="display:block;" @click="show = true">
<el-dropdown-item>
布局设置
</el-dropdown-item>
</span>
<router-link to="/shop/shop/shop_configuration">
<el-dropdown-item>
店铺配置
</el-dropdown-item>
</router-link>-->
<span v-for="(item, index) in list" :key="index">
<el-dropdown-item :disabled="item.tubeType==0">
<div style="display: flex;align-items: center;" @click="switchshopName(item.id)">
<i class="el-icon-check" style="color: #46a6ff;" v-if="item.id == shopId"></i>
<div v-if="mainId == item.id" style="line-height: 20px;text-align: center;">()</div>
{{ item.shopName }}
</div>
</el-dropdown-item>
</span>
</el-dropdown-menu>
</el-dropdown>
<!-- <img v-if="logo" :src="logo || Avatar" class="sidebar-logo">
<h1 class="sidebar-title">{{ shopName }} </h1>
<i class="el-icon-arrow-down icon"></i>
<i class="el-icon-arrow-down icon"></i> -->
</div>
</transition>
</div>
@ -17,6 +47,9 @@
<script>
import Avatar from '@/assets/images/avatar.png'
import { getqueryChildShop, changChildShop } from '@/api/login.js'
import { setToken } from "@/utils/auth";
export default {
name: 'SidebarLogo',
props: {
@ -30,6 +63,32 @@ export default {
shopName: localStorage.getItem('shopName'),
Avatar,
logo: localStorage.getItem('logo'),
list: [],
mainId: localStorage.getItem("mainId"),
shopId: localStorage.getItem("shopId"),
}
},
mounted() {
this.getlist()
},
methods: {
async getlist() {
const res = await getqueryChildShop({
id: this.mainId
})
this.list = res
},
async switchshopName(id) {
const res = await changChildShop({
id
})
localStorage.setItem("shopId", res.shopId);
localStorage.setItem("logo", res.logo);
localStorage.setItem("loginType", res.loginType);
localStorage.setItem("mainId", res.mainId);
localStorage.setItem("shopName", res.shopName);
setToken(res.token);
location.reload();
}
}
}
@ -96,4 +155,32 @@ h1 {
}
}
}
.avatar-container {
display: flex;
align-items: center;
.avatar-wrapper {
position: relative;
display: flex;
align-items: center;
.user-avatar {
cursor: pointer;
width: 40px;
height: 40px;
border-radius: 50%;
}
.el-icon-caret-bottom {
font-size: 12px;
margin-left: 6px;
}
.shop_name {
font-size: 16px;
// margin-left: 10px;
}
}
}
</style>

View File

@ -59,6 +59,19 @@ export const constantRouterMap = [
name: 'data_tables',
meta: { title: '桌台统计' }
},
{
path: 'data_credit',
component: (resolve) => require(['@/views/home/data_credit'], resolve),
name: 'data_credit',
meta: { title: '挂账管理' }
},
{
path: 'data_creditDetail',
component: (resolve) => require(['@/views/home/data_creditDetail'], resolve),
name: 'data_creditDetail',
hidden: true,
meta: { title: '挂账明细' }
},
{
path: 'data_record',
component: (resolve) => require(['@/views/home/data_record'], resolve),

View File

@ -43,6 +43,7 @@ const user = {
localStorage.setItem("logo", res.logo);
localStorage.setItem("loginType", res.loginType);
localStorage.setItem("userInfo", JSON.stringify(res.user.user));
localStorage.setItem("mainId", res.mainId);
setToken(res.token, rememberMe);
commit("SET_TOKEN", res.token);
setUserInfo(res.user, commit);

View File

@ -2,15 +2,6 @@
<div class="app-container">
<div class="title">应用中心</div>
<div class="list">
<!-- <div class="item" @click="upPop">
<img src="./kp.png" class="icon">
<div class="info">
<div class="name">开票</div>
<div class="intro">
</div>
</div>
</div> -->
<div class="item" v-for="item in list" :key="item.id" @click="to(item)">
<img :src="item.coverImg" class="icon">
<div class="info">
@ -22,28 +13,35 @@
</div>
</div>
<!-- 弹窗 -->
<el-dialog :title="title" :visible.sync="dialogVisible" width="30%" >
<el-dialog :title="title" :visible.sync="dialogVisible" width="30%">
<el-form :model="forms">
<el-form-item label="账号:" label-width="60px">
<el-form-item label="账号:" label-width="100px">
<el-input v-model="forms.account" :disabled="title != '绑定数点票账号'" autocomplete="off"></el-input>
</el-form-item>
<!-- <el-form-item label="密码/验证码" label-width="120px">
<el-input v-model="forms.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="开票项目:" label-width="120px">
<el-input v-model="forms.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="开票类型:" label-width="120px">
<el-input v-model="forms.name" autocomplete="off"></el-input>
</el-form-item> -->
<div style="text-align: right;" v-if="title == '绑定数点票账号'">联系区域经理开通</div>
<div style="text-align: center;" v-else @click="title = '绑定数点票账号'">更换绑定</div>
<!-- <el-form-item label="活动区域" label-width="120px">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
<el-form-item label="项目分类:" label-width="100px">
<el-select v-model="forms.article" :disabled="title != '绑定数点票账号'" :filter-method="getindustry"
filterable style="width: 100%;" placeholder="餐饮">
<el-option :label="item.name" :value="item.name" v-for="(item, index) in getindustryList"
:key="index"></el-option>
</el-select>
</el-form-item> -->
</el-form-item>
<el-form-item label="数电发票:" label-width="100px">
<el-select v-model="forms.sdType" :disabled="title != '绑定数点票账号'"
style="width: 100%;" placeholder="">
<el-option :label="item" :value="item" v-for="(item, index) in digitalInvoiceList[0]"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="税率:" label-width="100px">
<el-select :disabled="title != '绑定数点票账号'" v-model="forms.taxAmount" style="width: 100%;"
placeholder="">
<el-option :label="item" :value="item" v-for="(item, index) in digitalInvoiceList[1]"
:key="index"></el-option>
</el-select>
</el-form-item>
<div style="text-align: right;" v-if="title == '绑定数点票账号'">联系区域经理开通</div>
<div style="text-align: center;cursor: pointer;" v-else @click="title = '绑定数点票账号'">更换绑定</div>
</el-form>
<span slot="footer" class="dialog-footer" v-if="title == '绑定数点票账号'">
<el-button @click="dialogVisible = false"> </el-button>
@ -54,20 +52,26 @@
</template>
<script>
import { appCenterGet, getbinding } from "@/api/application";
import { appCenterGet, getbinding, getindustry, getdigitalInvoice } from "@/api/application";
export default {
data() {
return {
list: [],
dialogVisible: false,
forms: {},
forms: {
article: '餐饮',
sdType: ""
},
title: '绑定数点票账号',
digitalInvoiceList: [],
getindustryList: [],
}
},
mounted() {
this.appCenterGet()
// this.getbinding()
this.getbinding()
this.getdigitalInvoice()
this.getindustry()
},
methods: {
upPop() {
@ -75,16 +79,30 @@ export default {
},
sumbitEvent() {
if (this.forms.account) {
this.dialogVisible = false
this.getbinding(this.forms)
}
},
//
async getdigitalInvoice() {
const res = await getdigitalInvoice()
this.digitalInvoiceList = res
},
//
async getindustry(d = '餐饮') {
const res = await getindustry({ article: d })
this.getindustryList = res.list
},
//
to(item) {
localStorage.setItem('applocation', JSON.stringify(item))
this.$router.push({
name: item.absUrl
})
if (item.absUrl) {
this.$router.push({
name: item.absUrl
})
} else {
this.upPop()
}
},
//
async appCenterGet() {
@ -102,7 +120,11 @@ export default {
const res = await getbinding(d)
if (res) {
this.forms = res.store
this.$set(this.forms, 'article', res.article)
this.$set(this.forms, 'sdType', res.sdType)
this.$set(this.forms, 'taxAmount', res.taxAmount)
this.title = '数电票账号已绑定'
this.dialogVisible = false
} else {
this.title = '绑定数点票账号'
this.forms = {}

View File

@ -320,7 +320,6 @@ export default {
* @param item
*/
tabClick(item) {
console.log(this.form)
this.form = this.resetForm
this.form.number = ''
this.form.type = item.type

View File

@ -1,51 +1,51 @@
export default {
classType: [
{
value: 'product',
label: '商品券'
value: "product",
label: "商品券"
},
{
value: 'common',
label: '通用券'
value: "common",
label: "通用券"
}
],
type: [
{
value: '0',
label: '满减'
value: "0",
label: "满减"
},
{
value: '1',
label: '折扣'
value: "1",
label: "折扣"
}
],
cycle: [
{ label: '周一' },
{ label: '周二' },
{ label: '周三' },
{ label: '周四' },
{ label: '周五' },
{ label: '周六' },
{ label: '周七' }
{ label: "周一", value: "Monday" },
{ label: "周二", value: "Tuesday" },
{ label: "周三", value: "Wednesday" },
{ label: "周四", value: "Thursday" },
{ label: "周五", value: "Friday" },
{ label: "周六", value: "Saturday" },
{ label: "周七", value: "Sunday" }
],
validityType: [
{
value: 'fixed',
label: '领券后有效期内可用'
value: "fixed",
label: "领券后有效期内可用"
},
{
value: 'custom',
label: '固定有效期范围内可用'
value: "custom",
label: "固定有效期范围内可用"
}
],
useTimeType: [
{
value: 'all',
label: '全时段可用'
value: "all",
label: "全时段可用"
},
{
value: 'custom',
label: '指定时间段'
value: "custom",
label: "指定时间段"
}
]
}
};

View File

@ -0,0 +1,204 @@
<template>
<div>
<el-dialog title="账单还款记录" :visible.sync="dialogVisible" :close-on-click-modal="false" width="70%" @close="reset">
<div class="search">
<el-form :model="query" inline label-position="left">
<el-form-item>
<el-input v-model="query.paymentMethod" placeholder="支付方式" style="" />
</el-form-item>
<el-form-item>
<el-button @click="reset">重置</el-button>
<el-button type="primary" @click="getTableData">查询</el-button>
</el-form-item>
</el-form>
</div>
<div class="head-container">
<el-table v-loading="tableData.loading" :data="tableData.data">
<el-table-column label="支付方式" prpo="paymentMethod">
<template v-slot="scope"> <div>{{ scope.row.paymentMethod ? scope.row.paymentMethod : '-' }}</div> </template>
</el-table-column>
<el-table-column label="支付金额" prpo="repaymentAmount">
<template v-slot="scope"> <div>{{ scope.row.repaymentAmount ? scope.row.repaymentAmount : '-' }}</div> </template>
</el-table-column>
<el-table-column label="备注" prpo="remark">
<template v-slot="scope"> <div>{{ scope.row.remark ? scope.row.remark : '-' }}</div> </template>
</el-table-column>
<el-table-column label="操作时间" prop="createTime" />
</el-table>
</div>
<div class="head-container">
<el-pagination
:total="tableData.total"
:current-page="query.page"
:page-size="query.size"
layout="total, sizes, prev, pager, next, jumper"
@current-change="paginationChange"
@size-change="sizeChange"
/>
</div>
</el-dialog>
</div>
</template>
<script>
import { creditRePaymentRecord } from '@/api/credit'
export default {
data() {
return {
dialogVisible: false,
query: {
creditBuyerId: '',
paymentMethod: '',
orderId: '',
page: 1,
size: 10
},
resetQuery: null,
tableData: {
data: [],
loading: false,
total: 0
}
}
},
mounted() {
this.resetQuery = { ...this.query }
},
methods: {
/**
* 查询
*/
async getTableData() {
// eslint-disable-next-line no-unused-vars, prefer-const
let params = {
creditBuyerId: this.query.creditBuyerId,
value: this.query.value,
page: this.query.page,
size: this.query.size,
paymentMethod: this.query.paymentMethod
}
if (this.query.orderId) { params.orderId = this.query.orderId }
// eslint-disable-next-line prefer-const
let res = await creditRePaymentRecord(params)
this.tableData.loading = false
this.tableData.data = res.content
this.tableData.total = res.totalElements
},
/**
* 打开
* @param row
*/
show(row, orderId) {
this.query = { ...this.resetQuery }
this.dialogVisible = true
this.query.creditBuyerId = row.id
this.query.orderId = orderId
this.getTableData()
},
/**
* 分页大小改变
* @param e
*/
sizeChange(e) {
this.query.size = e
this.getTableData()
},
/**
* 分页回调
* @param e
*/
paginationChange(e) {
this.query.page = e
this.getTableData()
},
/**
* 关闭
*/
close() {
this.dialogVisible = false
},
/**
* 重置
*/
reset() {
this.query = { ...this.resetQuery }
this.getTableData()
}
}
}
</script>
<style scoped lang="scss">
.shop_list {
display: flex;
flex-wrap: wrap;
.item_wrap {
$size: 80px;
.item {
$radius: 4px;
width: $size;
height: $size;
border-radius: $radius;
overflow: hidden;
position: relative;
margin-right: 10px;
margin-top: 10px;
&:hover {
cursor: pointer;
}
&::after {
content: attr(data-index);
font-size: 12px;
height: 20px;
display: flex;
padding: 0 10px;
border-radius: 0 0 $radius 0;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
color: #fff;
position: absolute;
top: 0;
left: 0;
z-index: 10;
}
&::before {
content: '删除';
font-size: 12px;
width: 100%;
height: 20px;
display: flex;
padding: 0 10px;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
color: #fff;
position: absolute;
bottom: 0;
left: 0;
z-index: 10;
transition: all .1s ease-in-out;
}
}
.name {
width: $size;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
</style>

View File

@ -0,0 +1,181 @@
<template>
<div>
<el-dialog
:show-close="false"
:close-on-click-modal="false"
:visible.sync="dialogVisible"
width="30%"
center
>
<div slot="title" class="dialog-title">{{ form.id?'编辑':'创建' }}挂账人</div>
<div class="content">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="left">
<el-form-item label="状态" prop="status" style="width: 100%;">
<el-switch
v-model="form.status"
:active-value="1"
:inactive-value="0"
/>
</el-form-item>
<el-form-item label="挂账人" prop="debtor" style="width: 100%;">
<el-input v-model="form.debtor" placeholder="请输入挂账人名称" />
</el-form-item>
<el-form-item label="手机号" prop="mobile" style="width: 100%;">
<el-input v-model="form.mobile" placeholder="请输入手机号" oninput="value= value.replace(/[^1-9]/g, '')" maxlength="11" />
</el-form-item>
<el-form-item label="职位" prop="position" style="width: 100%;">
<el-input v-model="form.position" placeholder="请输入职位" />
</el-form-item>
<el-form-item label="挂账额度" prop="creditAmount" style="width: 100%;">
<el-input v-model="form.creditAmount" placeholder="" oninput="value= value.replace(/[^\d|\.]/g, '')">
<template slot="prepend"></template>
</el-input>
</el-form-item>
<el-form-item label="还款方式" style="width: 100%;">
<el-radio-group v-model="form.repaymentMethod" :disabled="isExist(form.id)">
<el-radio v-for="item in repaymentMethodList" :key="item.value" :label="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
<div style="font-size: 12px;color: #999;">一经创建无法更改还款方式</div>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :loading="loading" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { addCreditBuyer } from '@/api/credit'
export default {
// eslint-disable-next-line vue/require-prop-types
props: ['couponId'],
data() {
return {
dialogVisible: false,
loading: false,
repaymentMethodList: [
{ label: '按总金额还款', value: 'total' },
{ label: '按订单还款', value: 'order' }
],
form: {
id: '',
shopId: '',
status: 0,
debtor: '',
mobile: '',
position: '',
creditAmount: '',
repaymentMethod: 'total'
},
rules: {
debtor: [
{
required: true,
message: '请输入挂账人名称',
trigger: 'blur'
}
],
mobile: [
{
required: true,
message: '请输入手机号',
trigger: 'blur'
}
],
position: [
{
required: true,
message: '请输入职位',
trigger: 'blur'
}
],
creditAmount: [
{
required: true,
message: '请输入挂账额度',
trigger: 'blur'
}
]
},
resetForm: null
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
/**
* 校验是否存在
*/
isExist(val) {
if (val) {
return true
} else {
return false
}
},
/**
* 确定
*/
async onSubmitHandle() {
this.$refs.form.validate(async valid => {
if (valid) {
try {
this.loading = true
if (!this.form.shopId) { this.form.shopId = localStorage.getItem('shopId') }
// eslint-disable-next-line no-unused-vars, prefer-const
let res = await addCreditBuyer(this.form)
this.$notify({
title: '成功',
message: `${this.form.id ? '编辑' : '添加'}成功`,
type: 'success'
})
this.dialogVisible = false
this.loading = false
this.$emit('success', res)
} catch (error) {
this.loading = false
}
}
})
},
/**
* 打开详情
* @param row
*/
show(row) {
if (row && row.id) {
this.form = row
} else {
this.form = this.resetForm
}
this.form.status = Number(this.form.status)
this.dialogVisible = true
this.$refs.form.resetFields()
},
/**
* 关闭
*/
close() {
this.dialogVisible = false
}
}
}
</script>
<style scoped lang="scss">
.dialog-title{
text-align: left;
}
</style>

View File

@ -0,0 +1,179 @@
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<template>
<div>
<el-dialog
:show-close="false"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
width="30%"
center
>
<div slot="title" class="dialog-title">挂账还款</div>
<div class="content">
<div v-if="form.repaymentMethod == 'total' && !form.creditBuyerId" class="credit_info">
<div>挂账人{{ form.debtor }}</div>
<div>挂账金额{{ form.owedAmount || 0 }}</div>
<div>账户余额: {{ form.accountBalance || 0 }}</div>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="left">
<el-form-item v-if="form.repaymentMethod == 'total' && !form.creditBuyerId" label="还款方式" style="width: 100%;">
<el-radio-group v-model="form.repaymentMethod">
<el-radio v-for="item in repaymentMethodList" v-if="form.repaymentMethod == item.value" :key="item.value" :label="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="还款金额" prop="repaymentAmount" style="width: 100%;">
<el-input v-model="form.repaymentAmount" placeholder="" oninput="value= value.replace(/[^\d|\.]/g, '')">
<template slot="prepend"></template>
</el-input>
</el-form-item>
<el-form-item label="支付方式" prop="paymentMethod" style="width: 100%;">
<el-input v-model="form.paymentMethod" placeholder="请输入支付方式" />
</el-form-item>
<el-form-item label="备注" prop="remark" style="width: 100%;">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :loading="loading" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { creditRePayment, creditPayment } from '@/api/credit'
export default {
// eslint-disable-next-line vue/require-prop-types
props: ['couponId'],
data() {
return {
dialogVisible: false,
loading: false,
repaymentMethodList: [
{ label: '按总金额还款', value: 'total' },
{ label: '按订单还款', value: 'order' }
],
form: {
id: '',
creditBuyerId: '',
orderId: '',
repaymentMethod: '',
repaymentAmount: '',
paymentMethod: '',
remark: ''
},
rules: {
repaymentAmount: [
{
required: true,
message: '请输入还款金额',
trigger: 'blur'
}
],
paymentMethod: [
{
required: true,
message: '请输入支付方式',
trigger: 'blur'
}
]
},
resetForm: null
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
/**
* 确定
*/
// eslint-disable-next-line no-undef
onSubmitHandle: _.debounce(function async() {
this.$refs.form.validate(async valid => {
if (valid) {
try {
this.loading = true
// if (!this.form.shopId) { this.form.shopId = localStorage.getItem('shopId') }
let res
if (this.form.repaymentMethod === 'total') {
res = await creditRePayment(this.form)
} else {
res = await creditPayment(this.form)
}
this.$notify({
title: '成功',
message: res.repaymentMsg,
type: 'success'
})
this.dialogVisible = false
this.loading = false
this.$emit('success', res)
} catch (error) {
this.loading = false
console.log(error)
}
}
})
}, 1000),
/**
* 打开
* @param row
*/
show(row, order) {
this.form = { ...this.resetForm }
if (row.creditBuyerId) {
this.form.creditBuyerId = row.creditBuyerId
this.form.orderId = order.id
} else {
this.form.id = row.id
}
this.form.repaymentMethod = row.repaymentMethod
this.form.debtor = row.debtor
this.form.owedAmount = row.owedAmount
this.form.accountBalance = row.accountBalance
this.dialogVisible = true
},
/**
* 关闭
*/
close() {
this.dialogVisible = false
},
reset() {
this.query = { ...this.resetQuery }
}
}
}
</script>
<style scoped lang="scss">
.credit_info{
width: 100%;
background: #F7F7FA;
border-radius: 3px 3px 3px 3px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 15px 25px;
box-sizing: border-box;
margin-bottom: 30px;
view{
font-weight: 400;
font-size: 14px;
color: #000000;
}
}
.dialog-title{
text-align: left;
}
</style>

View File

@ -0,0 +1,202 @@
<template>
<div class="app-container">
<div class="head-container filtration">
<div class="l">
<el-button type="primary" icon="el-icon-plus" @click="openDialog(null,'add')">
创建挂账人
</el-button>
</div>
<div class="r">
<el-input v-model="tableData.keywords" placeholder="按挂账人或手机号" style="width: 138px;" />
<el-select v-model="tableData.status" placeholder="全部状态" clearable style="width: 123px;">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary" @click="getTableData()">
查询
</el-button>
</div>
</div>
<div class="head-container content">
<el-table v-loading="tableData.loading" :data="tableData.data">
<el-table-column label="挂账编码" prop="id" />
<el-table-column label="状态">
<template v-slot="scope">
{{ scope.row.status == '1' ? '启用' : '停用' }}
</template>
</el-table-column>
<el-table-column label="挂账人" prop="debtor" />
<el-table-column label="手机号" prop="mobile" />
<el-table-column label="挂账额度(元)" prop="creditAmount" />
<el-table-column label="已挂账金额(元)" prop="owedAmount" />
<el-table-column label="剩余挂账额度(元)" prop="remainingAmount" />
<el-table-column label="账户余额" prop="accountBalance" />
<el-table-column label="适用门店" prop="shopName" />
<el-table-column label="操作" width="250">
<template v-slot="scope">
<el-button type="text" @click="$router.push({name: 'data_creditDetail', query: {id: scope.row.id, repaymentMethod: scope.row.repaymentMethod}} )">查看明细</el-button>
<el-button type="text" @click="openDialog(scope.row,'edit')">编辑</el-button>
<el-button :style="{ color: scope.row.repaymentMethod == 'order' ? '#999' :''}" type="text" @click="openDialog(scope.row,'repayment')">还款</el-button>
<el-button type="text" @click="openDialog(scope.row,'rePaymentRecord')">还款记录</el-button>
<el-popconfirm title="确定删除吗?" @confirm="delTableHandle([scope.row.id])">
<el-button
slot="reference"
type="text"
>删除</el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
<div class="head-container">
<el-pagination
:total="tableData.total"
:current-page="tableData.page"
:page-size="tableData.size"
layout="total, sizes, prev, pager, next, jumper"
@current-change="paginationChange"
@size-change="sizeChange"
/>
</div>
<!-- 创建挂账人 -->
<creditAdd ref="creditAdd" @success="resetHandle" />
<!-- 还款 -->
<creditRepayment ref="creditRepayment" @success="resetHandle" />
<!-- 还款记录 -->
<creditRepaymentRecord ref="creditRepaymentRecord" @success="resetHandle" />
</div>
</template>
<script>
import creditAdd from './components/credit_add.vue'
import creditRepayment from './components/credit_repayment.vue'
import creditRepaymentRecord from './components/credit_RePaymentRecord.vue'
import { getCreditBuyerList, delCreditBuyer } from '@/api/credit'
export default {
// eslint-disable-next-line vue/no-unused-components
components: { creditAdd, creditRepayment, creditRepaymentRecord },
filters: {
typeFilter(value) {
// eslint-disable-next-line eqeqeq
},
effectTypeFilter(value) {
// eslint-disable-next-line eqeqeq
}
},
data() {
return {
options: [
{
value: '1',
label: '启用'
},
{
value: '0',
label: '停用'
}
],
tableData: {
keywords: '',
status: '',
data: [],
page: 1,
size: 10,
loading: false,
total: 0
}
}
},
mounted() {
this.getTableData()
},
methods: {
/**
* 获取挂账人列表
*/
async getTableData() {
this.tableData.loading = true
try {
const res = await getCreditBuyerList({
page: this.tableData.page,
size: this.tableData.size,
keywords: this.tableData.keywords,
status: this.tableData.status,
shopId: localStorage.getItem('shopId')
})
this.tableData.loading = false
this.tableData.data = res.content
this.tableData.total = res.totalElements
} catch (error) {
console.log(error)
}
},
/**
* 删除挂账人
* @param id
*/
async delTableHandle(id) {
// eslint-disable-next-line no-unused-vars
const res = await delCreditBuyer(id)
this.getTableData()
},
/**
* 操作
*/
openDialog(row, type) {
if (type === 'add') {
this.$refs.creditAdd.show()
} else if (type === 'edit') {
this.$refs.creditAdd.show(row)
} else if (type === 'repayment' && row.repaymentMethod === 'total') {
this.$refs.creditRepayment.show(row)
} else if (type === 'rePaymentRecord') {
this.$refs.creditRepaymentRecord.show(row)
}
},
//
resetHandle() {
this.page = 1
this.getTableData()
},
//
sizeChange(e) {
this.tableData.size = e
this.getTableData()
},
//
paginationChange(e) {
this.tableData.page = e
this.getTableData()
}
}
}
</script>
<style scoped lang="scss">
.title{
font-weight: bold;
font-size: 16px;
color: #333333;
}
.filtration{
overflow: hidden;
.l{
float: left;
}
.r{
float: right;
}
}
</style>

View File

@ -0,0 +1,464 @@
<!-- eslint-disable vue/valid-v-bind -->
<template>
<div class="app-container">
<div class="head-container">
<el-form :model="query" inline label-position="left">
<el-form-item>
<el-radio-group v-model="timeValue" @change="timeChange">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button label="0">今天</el-radio-button>
<el-radio-button label="-1">昨天</el-radio-button>
<el-radio-button label="-7">最近7天</el-radio-button>
<el-radio-button label="-30">最近30天</el-radio-button>
<el-radio-button label="week">本周</el-radio-button>
<el-radio-button label="month">本月</el-radio-button>
<el-radio-button label="custom">自定义</el-radio-button>
</el-radio-group>
<el-date-picker
v-if="timeValue == 'custom'"
v-model="query.createdAt"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']"
value-format="yyyy-MM-dd HH:mm:ss"
/>
</el-form-item>
<template>
<el-form-item>
<el-select v-model="query.status" placeholder="全部状态" style="width: 140px;">
<el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</template>
<el-form-item>
<el-button type="primary" @click="getTableData">查询</el-button>
<el-button @click="resetHandle">重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="head-container">
<div class="collect_wrap">
<div v-for="(item,index) in payCountList" :key="index" class="item">
<div class="icon_wrap" :style="{ backgroundColor: `rgba(${item.color},0.5)` }">
<div />
<i class="icon" :class="item.icon" :style="{ color: `rgba(${item.color},1)` }" />
</div>
<div class="info">
<div class="m">
{{ item.amount }}
</div>
<div class="t">{{ item.label }}{{ index == 0 ? item.count+'笔' : '' }}</div>
</div>
</div>
</div>
</div>
<div class="head-container">
<el-table v-loading="tableData.loading" :data="tableData.data">
<el-table-column label="创建日期" prop="createTime" />
<el-table-column label="订单号" prop="orderId" />
<el-table-column label="应付金额" prop="payAmount">
<template v-slot="scope"> {{ ''+scope.row.payAmount || '-' }} </template>
</el-table-column>
<el-table-column label="已付款金额" prop="paidAmount">
<template v-slot="scope"> {{ ''+scope.row.paidAmount || '-' }} </template>
</el-table-column>
<el-table-column label="待付款金额" prop="unpaidAmount">
<template v-slot="scope"> {{ ''+scope.row.unpaidAmount || '-' }} </template>
</el-table-column>
<el-table-column label="状态" prop="salesAmount">
<template v-slot="scope">
{{
scope.row.status == 'unpaid' ? '未付款' :
scope.row.status == 'partial' ? '部分支付' :
scope.row.status == 'paid' ? '已付款' : ''
}}
</template>
</el-table-column>
<el-table-column label="付款方式" prop="lastPaymentMethod">
<template v-slot="scope"> {{ scope.row.lastPaymentMethod }} </template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template v-slot="scope"> {{ scope.row.remark }} </template>
</el-table-column>
<el-table-column label="付款时间" prop="lastPaymentTime" />
<el-table-column label="操作" width="200">
<template v-slot="scope">
<el-button type="text" :style="{ color: repaymentMethod == 'total' ? '#999' :''}" @click="openDialog(scope.row,'payment')">付款</el-button>
<el-button type="text" @click="openDialog(scope.row,'paymentRecord')">账单付款记录</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="head-container">
<el-pagination
:total="tableData.total"
:current-page="query.page"
:page-size="query.size"
layout="total, sizes, prev, pager, next, jumper"
@current-change="paginationChange"
@size-change="sizeChange"
/>
</div>
<!-- 还款 -->
<creditRepayment ref="creditRepayment" @success="resetHandle" />
<!-- 还款记录 -->
<creditRepaymentRecord ref="creditRepaymentRecord" @success="resetHandle" />
</div>
</template>
<script>
import creditRepayment from './components/credit_repayment.vue'
import creditRepaymentRecord from './components/credit_RePaymentRecord.vue'
import { creditBuyerOrderList, creditBuyerOrderSummary } from '@/api/credit'
import dayjs from 'dayjs'
export default {
components: { creditRepayment, creditRepaymentRecord },
filters: {
},
data() {
return {
timeValue: '',
resetQuery: null,
repaymentMethod: '',
statusList: [
{ label: '未付款', value: 'unpaid' },
{ label: '部分支付', value: 'partial' },
{ label: '已付款', value: 'paid' }
],
query: {
page: 1,
size: 10,
creditBuyerId: '',
createdAt: [],
status: ''
},
tableData: {
data: [],
loading: false,
total: 0
},
downloadLoading: false,
payCountList: [
{ label: '总交易', icon: 'el-icon-info', color: '201, 120, 236', amount: 0, count: 0 },
{ label: '已支付金额', icon: 'el-icon-success', color: '70, 181, 24', amount: 0 },
{ label: '待支付金额', icon: 'el-icon-circle-plus', color: '248, 110, 16', amount: 0 },
{ label: '待支付笔数', icon: 'el-icon-warning', color: '254, 180, 38', amount: 0 }
],
payCountTotal: 0
}
},
mounted() {
this.query.creditBuyerId = this.$route.query.id
this.repaymentMethod = this.$route.query.repaymentMethod
this.resetQuery = { ...this.query }
// repaymentMethod
this.getTableData()
// this.tbShopCategoryGet()
},
methods: {
/**
* 获取明细数据
*/
async getTableData() {
this.tableData.loading = true
try {
this.creditDetailSummary()
// eslint-disable-next-line prefer-const
let params = {
page: this.query.page,
size: this.query.size,
creditBuyerId: this.query.creditBuyerId
}
if (this.query.createdAt.length > 0) {
params.beginDate = this.query.createdAt[0].substring(0, 10)
params.endDate = this.query.createdAt[1].substring(0, 10)
}
// eslint-disable-next-line prefer-const
let res = await creditBuyerOrderList(params)
this.tableData.loading = false
this.tableData.data = res.content
this.tableData.total = res.totalElements
} catch (error) {
console.log(error)
}
},
/**
* 获取明细统计
*/
async creditDetailSummary() {
try {
// eslint-disable-next-line prefer-const
let params = {
page: this.query.page,
size: this.query.size,
creditBuyerId: this.query.creditBuyerId
}
if (this.query.createdAt.length > 0) {
params.beginDate = this.query.createdAt[0].substring(0, 10)
params.endDate = this.query.createdAt[1].substring(0, 10)
}
// eslint-disable-next-line prefer-const
let res = await creditBuyerOrderSummary(params)
this.payCountList[0].amount = res.payAmountTotal
this.payCountList[0].count = res.count
this.payCountList[1].amount = res.paidAmountTotal
this.payCountList[2].amount = res.unpaidAmountTotal
this.payCountList[3].amount = res.unpaidCount
} catch (error) {
console.log(error)
}
},
/**
* 操作
*/
openDialog(row, type) {
if (type === 'payment' && this.repaymentMethod === 'order') {
this.$refs.creditRepayment.show({ creditBuyerId: this.query.creditBuyerId, repaymentMethod: this.repaymentMethod }, row)
} else if (type === 'paymentRecord') {
this.$refs.creditRepaymentRecord.show({ id: this.query.creditBuyerId, repaymentMethod: this.repaymentMethod }, row.orderId)
}
},
/**
* 切换时间
* @param e
*/
timeChange(e) {
const format = ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']
switch (e) {
case '':
//
this.query.createdAt = []
break
case '0':
//
this.query.createdAt = [
dayjs().format(format[0]),
dayjs().format(format[1])
]
break
case '-1':
//
this.query.createdAt = [
dayjs()
.add(-1, 'd')
.format(format[0]),
dayjs()
.add(-1, 'd')
.format(format[1])
]
break
case '-7':
// 7
this.query.createdAt = [
dayjs()
.add(-7, 'd')
.format(format[0]),
dayjs().format(format[1])
]
break
case '-30':
// 7
this.query.createdAt = [
dayjs()
.add(-30, 'd')
.format(format[0]),
dayjs().format(format[1])
]
break
case 'week':
//
this.query.createdAt = [
dayjs()
.startOf('week')
.format(format[0]),
dayjs()
.endOf('week')
.format(format[1])
]
break
case 'month':
//
this.query.createdAt = [
dayjs()
.startOf('month')
.format(format[0]),
dayjs()
.endOf('month')
.format(format[1])
]
break
case 'custom':
//
this.query.createdAt = []
break
default:
break
}
},
/**
* 重置查询
*/
resetHandle() {
this.timeValue = ''
this.query = { ...this.resetQuery }
this.getTableData()
},
/**
* 分页大小改变
* @param e
*/
sizeChange(e) {
this.tableData.size = e
this.getTableData()
},
/**
* 分页回调
* @param e
*/
paginationChange(e) {
this.query.page = e
this.getTableData()
}
}
}
</script>
<style scoped lang="scss">
.collect_wrap {
display: flex;
gap: 14px;
justify-content: space-between;
.item {
background-size: 100% 100%;
width: 255px;
display: flex;
align-items: center;
background-color: #F7F7FA;
padding: 20px;
border-radius: 7px 7px 7px 7px;
.icon_wrap {
$size: 34px;
$border: 6px;
width: $size;
height: $size;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--bg-color);
border-radius: 50%;
position: relative;
>div{
width: 24px;
height: 24px;
background-color: #fff;
border-radius: 50%;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
&::after {
content: "";
width: $size + $border;
height: $size + $border;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: var(--bg-color);
opacity: 0.3;
}
.icon {
font-size: 32px;
position: absolute;
left: 1px;
right: 0;
top: 1px;
bottom: 0;
margin: auto;
}
.img {
width: 20px;
height: 20px;
}
}
.info {
flex: 1;
display: flex;
flex-direction: column;
padding-left: 10px;
.m {
font-weight: bold;
}
.t {
font-size: 12px;
color: #999;
padding-top: 4px;
}
}
}
}
.refund {
color: #ff9731;
font-weight: bold;
}
.table_order_info {
.order_no {
color: #999;
}
.type {
color: #e6a23c;
}
}
.goods_info {
.row {
display: flex;
&:not(:first-child) {
margin-top: 10px;
}
.cover {
width: 40px;
height: 40px;
}
.info {
flex: 1;
display: flex;
flex-direction: column;
padding-left: 10px;
.sku {
color: #999;
}
}
}
}
</style>

View File

@ -179,7 +179,6 @@ export default {
this.$store.dispatch('Login', user).then(() => {
this.loading = false
//
localStorage.setItem('MerchantId', JSON.stringify({
merchantName: this.loginForm.merchantName,
username: this.loginForm.username,

View File

@ -0,0 +1,132 @@
<template>
<el-dialog title="开票" :visible.sync="dialogFormVisible">
<el-form :model="forms">
<el-form-item label="项目分类:" :label-width="labelWidth">
<el-select v-model="forms.article" :filter-method="getindustry" filterable style="width: 100%;"
placeholder="餐饮">
<el-option :label="item.name" :value="item.name" v-for="(item, index) in getindustryList"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数电发票:" :label-width="labelWidth">
<el-select v-model="forms.type" style="width: 100%;" placeholder="">
<el-option :label="item" :value="item" v-for="(item, index) in digitalInvoiceList[0]"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="税率:" :label-width="labelWidth">
<el-select v-model="forms.se_amount" @change="changeevent" style="width: 100%;" placeholder="">
<el-option :label="item" :value="item" v-for="(item, index) in digitalInvoiceList[1]"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="开票金额:" :label-width="labelWidth">
<el-input v-model="forms.price" @change="changeevent" type="number" placeholder="请输入金额"></el-input>
</el-form-item>
<el-form-item label="开票人账号:" :label-width="labelWidth">
<el-select v-model="forms.dlzh" style="width: 100%;" placeholder="">
<el-option :label="item.bsryxm" :value="item.dlzh" v-for="(item, index) in Binding"
:key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="单价:" :label-width="labelWidth">
<el-input v-model="forms.d_price" disabled placeholder=""></el-input>
</el-form-item>
<el-form-item label="税额:" :label-width="labelWidth">
<el-input v-model="forms.tax_amount" disabled placeholder=""></el-input>
</el-form-item>
<el-form-item label="数量:" :label-width="labelWidth">
<el-input v-model="forms.number" type="number" placeholder=""></el-input>
</el-form-item>
<el-form-item label="备注:" :label-width="labelWidth">
<el-input v-model="forms.notes" type="text" placeholder=""></el-input>
</el-form-item>
<el-form-item label="规格型号:" :label-width="labelWidth">
<el-input v-model="forms.notes" type="text" placeholder=""></el-input>
</el-form-item>
<el-form-item label="产品单位(桌)" :label-width="labelWidth">
<el-input v-model="forms.notes" type="number" placeholder=""></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" :loading="printloading" @click="SubmitEvent"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { getbinding, getindustry, getdigitalInvoice, getstoreSe, getsubInvoicing } from "@/api/application";
export default {
data() {
return {
dialogFormVisible: false,
forms: {},
digitalInvoiceList: [],
getindustryList: [],
labelWidth: '120px',
//
Binding: [],
item: "",
printloading: false,
}
},
mounted() {
this.getdigitalInvoice()
this.getindustry()
},
methods: {
show(d) {
this.dialogFormVisible = !this.dialogFormVisible
this.item = d
this.getbinding()
},
async changeevent() {
let obj = {
se_amount: this.forms.se_amount.slice(0, -1),
amount: this.forms.price
}
const res = await getstoreSe(obj)
this.forms.d_price = res.d_amount
this.forms.tax_amount = res.tx
},
async SubmitEvent() {
this.printloading = true
this.forms.se_amount = this.forms.se_amount.slice(0, -1)
const res = await getsubInvoicing(this.forms)
this.dialogFormVisible = !this.dialogFormVisible
this.printloading = false
this.$emit('qrcode', res.invoice_records)
},
//
async getindustry(d = '餐饮') {
const res = await getindustry({ article: d })
this.getindustryList = res.list
},
//
async getdigitalInvoice() {
const res = await getdigitalInvoice()
this.digitalInvoiceList = res
},
//
async getbinding(d = "") {
const res = await getbinding(d)
this.forms = {
account: res.bindAccount,
dlzh: res.taxation[0].dlzh,
article: res.article,
type: res.sdType,
se_amount: res.taxAmount,
number: 1,
d_price: '',
tax_amount: '',
price: this.item.payAmount,
cash_out: this.item.orderNo,
}
this.Binding = res.taxation
this.changeevent()
}
}
}
</script>

View File

@ -0,0 +1,188 @@
//==本JS是加载Lodop插件或Web打印服务CLodop/Lodop7的综合示例可直接使用建议理解后融入自己程序==
//用双端口加载主JS文件Lodop.js(或CLodopfuncs.js兼容老版本)以防其中某端口被占:
var MainJS ="CLodopfuncs.js",
URL_WS1 = "ws://localhost:8000/"+MainJS, //ws用8000/18000
URL_WS2 = "ws://localhost:18000/"+MainJS,
URL_HTTP1 = "http://localhost:8000/"+MainJS, //http用8000/18000
URL_HTTP2 = "http://localhost:18000/"+MainJS,
URL_HTTP3 = "https://localhost.lodop.net:8443/"+MainJS; //https用8000/8443
var CreatedOKLodopObject, CLodopIsLocal, LoadJsState;
//==判断是否需要CLodop(那些不支持插件的浏览器):==
function needCLodop() {
try {
var ua = navigator.userAgent;
if (ua.match(/Windows\sPhone/i) ||
ua.match(/iPhone|iPod|iPad/i) ||
ua.match(/Android/i) ||
ua.match(/Edge\D?\d+/i))
return true;
var verTrident = ua.match(/Trident\D?\d+/i);
var verIE = ua.match(/MSIE\D?\d+/i);
var verOPR = ua.match(/OPR\D?\d+/i);
var verFF = ua.match(/Firefox\D?\d+/i);
var x64 = ua.match(/x64/i);
if ((!verTrident) && (!verIE) && (x64)) return true;
else if (verFF) {
verFF = verFF[0].match(/\d+/);
if ((verFF[0] >= 41) || (x64)) return true;
} else if (verOPR) {
verOPR = verOPR[0].match(/\d+/);
if (verOPR[0] >= 32) return true;
} else if ((!verTrident) && (!verIE)) {
var verChrome = ua.match(/Chrome\D?\d+/i);
if (verChrome) {
verChrome = verChrome[0].match(/\d+/);
if (verChrome[0] >= 41) return true;
}
}
return false;
} catch (err) {
return true;
}
}
//==检查加载成功与否如没成功则用http(s)再试==
//==低版本CLODOP6.561/Lodop7.043及前)用本方法==
function checkOrTryHttp() {
if (window.getCLodop) {
LoadJsState = "complete";
return true;
}
if (LoadJsState == "loadingB" || LoadJsState == "complete") return;
LoadJsState = "loadingB";
var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
var JS1 = document.createElement("script")
,JS2 = document.createElement("script")
,JS3 = document.createElement("script");
JS1.src = URL_HTTP1;
JS2.src = URL_HTTP2;
JS3.src = URL_HTTP3;
JS1.onload = JS2.onload = JS3.onload = JS2.onerror = JS3.onerror=function(){LoadJsState = "complete";}
JS1.onerror = function(e) {
if (window.location.protocol !== 'https:')
head.insertBefore(JS2, head.firstChild); else
head.insertBefore(JS3, head.firstChild);
}
head.insertBefore(JS1,head.firstChild);
}
//==加载Lodop对象的主过程:==
(function loadCLodop(){
if (!needCLodop()) return;
CLodopIsLocal = !!((URL_WS1 + URL_WS2).match(/\/\/localho|\/\/127.0.0./i));
LoadJsState = "loadingA";
if (!window.WebSocket && window.MozWebSocket) window.WebSocket=window.MozWebSocket;
//ws方式速度快(小于200ms)且可避免CORS错误,但要求Lodop版本足够新:
try {
var WSK1=new WebSocket(URL_WS1);
WSK1.onopen = function(e) { setTimeout("checkOrTryHttp()",200); }
WSK1.onmessage = function(e) {if (!window.getCLodop) eval(e.data);}
WSK1.onerror = function(e) {
var WSK2=new WebSocket(URL_WS2);
WSK2.onopen = function(e) {setTimeout("checkOrTryHttp()",200);}
WSK2.onmessage = function(e) {if (!window.getCLodop) eval(e.data);}
WSK2.onerror= function(e) {checkOrTryHttp();}
}
} catch(e){
checkOrTryHttp();
}
})();
//==获取LODOP对象主过程,判断是否安装、需否升级:==
export function getLodop(oOBJECT, oEMBED) {
var strFontTag = "<br><font color='#FF00FF'>打印控件";
var strLodopInstall = strFontTag + "未安装!点击这里<a href='install_lodop32.exe' target='_self'>执行安装</a>";
var strLodopUpdate = strFontTag + "需要升级!点击这里<a href='install_lodop32.exe' target='_self'>执行升级</a>";
var strLodop64Install = strFontTag + "未安装!点击这里<a href='install_lodop64.exe' target='_self'>执行安装</a>";
var strLodop64Update = strFontTag + "需要升级!点击这里<a href='install_lodop64.exe' target='_self'>执行升级</a>";
var strCLodopInstallA = "<br><font color='#FF00FF'>Web打印服务CLodop未安装启动点击这里<a href='CLodop_Setup_for_Win32NT.exe' target='_self'>下载执行安装</a>";
var strCLodopInstallB = "<br>(若此前已安装过,可<a href='CLodop.protocol:setup' target='_self'>点这里直接再次启动</a>";
var strCLodopUpdate = "<br><font color='#FF00FF'>Web打印服务CLodop需升级!点击这里<a href='CLodop_Setup_for_Win32NT.exe' target='_self'>执行升级</a>";
var strLodop7FontTag = "<br><font color='#FF00FF'>Web打印服务Lodop7";
var strLodop7HrefX86 = "点击这里<a href='Lodop7_Linux_X86_64.tar.gz' target='_self'>下载安装</a>(下载后解压点击lodop文件开始执行)";
var strLodop7HrefARM = "点击这里<a href='Lodop7_Linux_ARM64.tar.gz' target='_self'>下载安装</a>(下载后解压点击lodop文件开始执行)";
var strLodop7Install_X86 = strLodop7FontTag + "未安装启动," + strLodop7HrefX86;
var strLodop7Install_ARM = strLodop7FontTag + "未安装启动," + strLodop7HrefARM;
var strLodop7Update_X86 = strLodop7FontTag + "需升级," + strLodop7HrefX86;
var strLodop7Update_ARM = strLodop7FontTag + "需升级," + strLodop7HrefARM;
var strInstallOK = ",成功后请刷新本页面或重启浏览器。</font>";
var LODOP;
try {
var isWinIE = (/MSIE/i.test(navigator.userAgent)) || (/Trident/i.test(navigator.userAgent));
var isWinIE64 = isWinIE && (/x64/i.test(navigator.userAgent));
var isLinuxX86 = (/Linux/i.test(navigator.platform)) && (/x86/i.test(navigator.platform));
var isLinuxARM = (/Linux/i.test(navigator.platform)) && (/aarch/i.test(navigator.platform));
if (needCLodop() || isLinuxX86 || isLinuxARM) {
try {
LODOP = window.getCLodop();
} catch (err) {}
if (!LODOP && LoadJsState !== "complete") {
if (!LoadJsState)
alert("未曾加载Lodop主JS文件请先调用loadCLodop过程."); else
alert("网页还没下载完毕,请稍等一下再操作.");
return;
}
var strAlertMessage;
if (!LODOP) {
if (isLinuxX86)
strAlertMessage = strLodop7Install_X86;
else if (isLinuxARM)
strAlertMessage = strLodop7Install_ARM;
else
strAlertMessage = strCLodopInstallA + (CLodopIsLocal ? strCLodopInstallB : "");
document.body.innerHTML = strAlertMessage + strInstallOK + document.body.innerHTML;
return;
} else {
if (isLinuxX86 && LODOP.CVERSION < "7.0.7.5")
strAlertMessage = strLodop7Update_X86;
else if (isLinuxARM && LODOP.CVERSION < "7.0.7.5")
strAlertMessage = strLodop7Update_ARM;
else if (CLODOP.CVERSION < "6.5.9.4")
strAlertMessage = strCLodopUpdate;
if (strAlertMessage)
document.body.innerHTML = strAlertMessage + strInstallOK + document.body.innerHTML;
}
} else {
//==如果页面有Lodop插件就直接使用,否则新建:==
if (oOBJECT || oEMBED) {
if (isWinIE)
LODOP = oOBJECT;
else
LODOP = oEMBED;
} else if (!CreatedOKLodopObject) {
LODOP = document.createElement("object");
LODOP.setAttribute("width", 0);
LODOP.setAttribute("height", 0);
LODOP.setAttribute("style", "position:absolute;left:0px;top:-100px;width:0px;height:0px;");
if (isWinIE)
LODOP.setAttribute("classid", "clsid:2105C259-1E0C-4534-8141-A753534CB4CA");
else
LODOP.setAttribute("type", "application/x-print-lodop");
document.documentElement.appendChild(LODOP);
CreatedOKLodopObject = LODOP;
} else
LODOP = CreatedOKLodopObject;
//==Lodop插件未安装时提示下载地址:==
if ((!LODOP) || (!LODOP.VERSION)) {
document.body.innerHTML = (isWinIE64 ? strLodop64Install : strLodopInstall) + strInstallOK + document.body.innerHTML;
return LODOP;
}
if (LODOP.VERSION < "6.2.2.6") {
document.body.innerHTML = (isWinIE64 ? strLodop64Update : strLodopUpdate) + strInstallOK + document.body.innerHTML;
}
}
//===如下空白位置适合调用统一功能(如注册语句、语言选择等):=======================
//===============================================================================
return LODOP;
} catch (err) {
alert("getLodop出错:" + err);
}
}

View File

@ -150,6 +150,8 @@
<template v-slot="scope">
<div class="u-flex gap-10">
<el-button type="text" @click="$refs.orderDetail.show(scope.row)">详情</el-button>
<el-button type="text" v-if="scope.row.status == 'closed'"
@click="$refs.Invoicing.show(scope.row)">开票</el-button>
<el-button v-if="scope.row.status == 'unpaid'" type="primary" size="mini"
@click="payOrder(scope.row)">结账</el-button>
</div>
@ -163,20 +165,38 @@
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
</div>
<orderDetail ref="orderDetail" @close="getTableData" />
<!-- 开票 -->
<Invoicing ref="Invoicing" @qrcode="qrcodeEvent"></Invoicing>
<!-- 二维码 -->
<div class="qrStyle" v-if="isuppop">
<div class="box">
<div> <span></span> {{ codeinfo.type }}<i class="el-icon-close" @click="isuppopEvent()"></i> </div>
<canvas ref="canvas" id="canvas"></canvas>
<div>
税率{{ codeinfo.se_amount + '%' }}&nbsp;&nbsp;
金额{{ codeinfo.price }}<br />
<div style="color: red;margin-top: 5px;"> {{ codeinfo.string1 }} </div> <br />
<el-button type="primary" style="margin-top: 10px;" @click="printEvent(codeinfo)">打印</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import orderEnum from "./orderEnum";
import { getLodop } from "./components/LodopFuncs.js";
import { tbShopPayTypeGet } from "@/api/setting";
import { tbOrderInfoData, tbOrderInfoDownload, payCount } from "@/api/order";
import dayjs from "dayjs";
import { downloadFile } from "@/utils/index";
import QRCode from "qrcode";
import orderDetail from "./components/orderDetail";
import Invoicing from "./components/Invoicing";
export default {
components: { orderDetail },
components: { orderDetail, Invoicing },
data() {
return {
orderEnum,
@ -201,7 +221,9 @@ export default {
},
downloadLoading: false,
payCountList: "",
payCountTotal: 0
payCountTotal: 0,
isuppop: false,
codeinfo: "",
};
},
@ -214,6 +236,7 @@ export default {
return t;
}
},
sendTypeFilter(t) {
if (t) {
const item = orderEnum.sendType.find(item => item.key == t);
@ -235,6 +258,8 @@ export default {
}
},
mounted() {
if (this.$route.query.tableName) {
this.query.tableName = this.$route.query.tableName
}
@ -258,6 +283,52 @@ export default {
},
methods: {
printEvent(data) {
console.log('打印方法执行', data)
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
LODOP.SET_PRINTER_INDEX('MHT-POS58');//()
// D
LODOP.SET_PRINT_PAGESIZE(3, 800, '', '')
//
LODOP.ADD_PRINT_BARCODE('', '30px', '150px', '150px', 'QRCode', data.url) //
LODOP.SET_PRINT_MODE('PRINT_PAGE_PERCENT', 'Full-Width ') //
LODOP.SET_PRINT_STYLE("Alignment", 2);
//
LODOP.ADD_PRINT_HTM(
'150px',
'5px',
'100%',
'100%',
`<div style="width: 100%;font-size: 12px; ">项目分类:${data.article}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">发票类型:${data.type}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">生成时间:${dayjs().format('YYYY-MM-DD HH:mm:ss')}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">*二维码有效期30天,超过自动失效</div>
<div style="width: 100%;font-size: 14px; margin-top: 15px;">您可以使用微信扫码开票</div>`
)
LODOP.SET_LICENSES('', 'DCFF409304DFCEB3E2C644BF96CD0720', '', '')
LODOP.PRINT()
},
qrcodeEvent(d) {
this.codeinfo = d
this.isuppopEvent()
setTimeout(() => {
QRCode.toCanvas(
this.$refs.canvas,
this.codeinfo.url, {
width: 160,
height: 160,
}, function (error) {
console.log(error);
}
);
}, 500);
},
isuppopEvent() {
this.isuppop = !this.isuppop
},
//
payOrder(order) {
console.log(order);
@ -544,4 +615,40 @@ export default {
.colorStyle {
color: #ffc315;
}
.qrStyle {
width: 100%;
height: 100%;
background-color: rgba($color: #000000, $alpha: 0.7);
position: fixed;
z-index: 999999;
top: 0;
left: 0;
.box {
width: 380px;
height: 320px;
position: absolute;
background: #fff;
top: 26%;
left: 36%;
padding: 18px;
>div:first-child {
display: flex;
align-items: center;
justify-content: space-between;
}
#canvas {
margin-left: 49%;
transform: translateX(-80px);
}
>div:last-child {
text-align: center;
}
}
}
</style>

View File

@ -1,9 +1,8 @@
<template>
<div class="app-container">
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px" label-position="left">
<el-form-item label="商品类型" prop="typeEnum">
<!-- <el-form-item label="商品类型" prop="typeEnum">
<div class="shop_type_box" :class="{}">
<!-- <div class="shop_type_box" :class="{ disabled: form.id }"> -->
<div class="item" v-for="(item, index) in shopTypes" :key="index"
:class="{ active: shopTypesActive == index }" @click="changeTypeEnum(index)">
<div class="s_title">{{ item.label }}</div>
@ -13,7 +12,7 @@
</div>
</div>
</div>
</el-form-item>
</el-form-item> -->
<el-form-item label="商品名称" prop="name">
<el-input v-model="form.name" placeholder="请输入商品名称" style="width: 500px"></el-input>
</el-form-item>
@ -58,46 +57,110 @@
<div class="tips">第一张图为商品封面图图片尺寸为750×750</div>
<!-- <el-button type="primary" plain icon="el-icon-plus" @click="$refs.addImg.show()">选择图片</el-button> -->
</el-form-item>
<el-form-item label="套餐商品" v-if="shopTypes[shopTypesActive].typeEnum == 'group'">
<el-table :data="form.groupSnap" border v-if="form.groupSnap.length">
<el-table-column label="标题" prop="title">
<template v-slot="scope">
<el-input v-model="scope.row.title" placeholder="请输入标题:自选小吃"></el-input>
</template>
</el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
<div class="shop_list">
<div class="item" v-for="(item, index) in scope.row.goods" :key="item.id">
<span class="dot"></span>
<div class="name">
<div class="t">{{ item.name }}</div>
<div class="t" v-if="!form.id">x{{ item.groupNum }}</div>
<el-input-number v-model="item.groupNum" :step="1" step-strictly :min="1" size="mini"
v-else></el-input-number>
</div>
<i class="del el-icon-delete" @click="delGoods(scope.row.goods, index, scope.$index)"></i>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="几选几">
<template v-slot="scope">
<span>{{ scope.row.goods.length }}</span>
<el-input-number v-model="scope.row.number" controls-position="right" :min="1"></el-input-number>
</template>
</el-table-column>
<el-table-column label="操作" width="160">
<template v-slot="scope">
<el-button type="text" @click="tableAddShop(scope.$index, scope.row.goods)">添加商品</el-button>
<el-button type="text" @click="form.groupSnap.splice(scope.$index, 1)">删除分组</el-button>
</template>
</el-table-column>
</el-table>
<el-button type="text" @click="$refs.shopListRef.show()">添加分组</el-button>
<shopList ref="shopListRef" @success="selectShopRes" />
<el-form-item label="显示/隐藏" prop="showType">
<el-checkbox-group v-model="form.showType">
<el-checkbox label="table">堂食</el-checkbox>
<el-checkbox label="dine">自取</el-checkbox>
<el-checkbox label="delivery">配送</el-checkbox>
<el-checkbox label="express">快递</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="规格属性" v-if="shopTypes[shopTypesActive].typeEnum != 'sku'">
<el-form-item label="商品类型">
<el-radio-group v-model="form.type" @change="typeChange">
<el-radio label="normal">普通商品</el-radio>
<el-radio label="package">套餐类型</el-radio>
<el-radio label="weigh">称重</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="规格类型" v-if="form.type == 'normal'">
<el-radio-group v-model="form.typeEnum" @change="changeTypeEnum">
<el-radio label="normal">单规格</el-radio>
<el-radio label="sku">多规格</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="套餐商品" v-if="form.type == 'package'">
<div class="head-container">
<el-radio-group v-model="form.groupType" @change="typeChange">
<el-radio-button label="0">固定套餐</el-radio-button>
<el-radio-button label="1">可选套餐</el-radio-button>
</el-radio-group>
</div>
<div v-if="form.groupType == 0">
<el-table border :data="item.goods" v-for="(item, index) in form.proGroupVo" :key="index">
<el-table-column label="名称" prop="proName"></el-table-column>
<el-table-column label="规格" prop="skuName">
<!-- <template slot-scope="scope">
<template v-if="scope.row.typeEnum == '多规格'">
<template v-if="scope.row.skuName">
{{ scope.row.skuName }}
</template>
<span class="tips" v-else>请设置规格</span>
</template>
<template v-else>
单规格
</template>
</template> -->
</el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
<el-table-column label="数量" prop="number">
<template v-slot="scope">
<el-input-number v-model="scope.row.number" :min="0" />
</template>
</el-table-column>
<el-table-column width="150">
<template slot="header" slot-scope="scope">
<el-button type="primary"
@click="$refs.shopListRef.show([...form.proGroupVo[index].goods])">添加商品</el-button>
</template>
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.typeEnum != '多规格'"
@click="showSelectSkuHandle(scope.row, scope.$index, index)">设置规格</el-button>
<el-button type="text" @click="form.proGroupVo[index].goods.splice(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-if="form.groupType == 1">
<div class="group_wrap" v-for="(item, index) in form.proGroupVo" :key="index">
<el-form inline :model="item">
<el-form-item label="规格组名">
<el-input v-model="item.title" />
</el-form-item>
<el-form-item :label="`本组菜品${item.goods.length}选`">
<el-input v-model="item.number" />
</el-form-item>
<el-form-item>
<el-button @click="form.proGroupVo.splice(index, 1)">删除</el-button>
</el-form-item>
</el-form>
<div>
<el-table border :data="item.goods">
<el-table-column label="名称" prop="proName"></el-table-column>
<el-table-column label="规格" prop="skuName"></el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
<el-table-column label="数量" prop="number">
<template v-slot="scope">
<el-input-number v-model="scope.row.number" :min="0" />
</template>
</el-table-column>
<el-table-column width="150">
<template slot="header" slot-scope="scope">
<el-button type="primary"
@click="$refs.shopListRef.show([...form.proGroupVo[index].goods]); addGroupIndex = index">添加商品</el-button>
</template>
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.typeEnum != '多规格'"
@click="showSelectSkuHandle(scope.row, scope.$index, index)">设置规格</el-button>
<el-button type="text" @click="form.proGroupVo[index].goods.splice(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-button type="primary" @click="$refs.shopListRef.show(); addGroupIndex = false">添加套餐组</el-button>
</div>
</el-form-item>
<el-form-item label="规格属性" v-if="form.typeEnum != 'sku'">
<el-table :data="form.skuList" border>
<el-table-column label="售价" prop="salePrice">
<template v-slot="scope">
@ -207,7 +270,7 @@
<Editor :minHeight="200" :value="form.notices.usageRules" v-model="form.notices.usageRules" />
</el-form-item>
</template>
<el-form-item label="选择规格" v-if="shopTypes[shopTypesActive].typeEnum == 'sku'">
<el-form-item label="选择规格" v-if="form.type == 'normal' && form.typeEnum == 'sku'">
<el-select v-model="form.specId" placeholder="请选择规格" style="width: 500px" @change="selectSpecHandle">
<el-option :label="item.name" :value="item.id" v-for="item in specList" :key="item.id"></el-option>
</el-select>
@ -217,7 +280,7 @@
<el-checkbox :label="item" v-for="(item, index) in item.value" :key="index"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item v-if="selectSpecResult && shopTypes[shopTypesActive].typeEnum == 'sku'">
<el-form-item v-if="selectSpecResult && form.typeEnum == 'sku'">
<el-table :data="form.skuList" border>
<el-table-column :label="item.label" :prop="item.value" v-for="(item, index) in specTableHeaders"
:key="index">
@ -331,6 +394,36 @@
小程序商城必须设置库存数量大于0
</div> -->
</el-form-item>
<el-form-item label="重量">
<el-input v-model="form.weight" style="width: 250px;">
<template slot="append">千克</template>
</el-input>
<div class="tips">用于快递或配送运费计重</div>
</el-form-item>
<el-form-item label="是否允许临时改价">
<el-radio-group v-model="form.isTempPrice">
<el-radio label="1">允许</el-radio>
<el-radio label="0">不允许</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="每日销量上限">
<el-input-number v-model="form.dayLimit" :min="0" />
</el-form-item>
<el-form-item label="每单限购">
<el-input-number v-model="form.singleOrderLimit" :min="0" />
</el-form-item>
<el-form-item label="每人限购">
<el-input-number v-model="form.singlePeopleLimit" :min="0" />
</el-form-item>
<el-form-item label="定时上下架" style="width: 100%;">
<el-checkbox-group v-model="form.days">
<el-checkbox v-for="(item, index) in couponEnum.cycle" :key="item.value" :label="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-time-picker v-model="useTime" is-range range-separator="" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']" value-format="HH:mm" format="HH:mm" @change="useTimeChange" />
</el-form-item>
<template v-if="form.typeEnum != 'group'">
<!-- <el-form-item label="上架区域">
<div class="shop_type_box">
@ -403,6 +496,29 @@
<!-- <groupTypeList ref="groupTypeList" @success="(res) => (form.groupCategoryId = res)" /> -->
<!-- 选择图片 -->
<addImg ref="addImg" @successEvent="successEvent"></addImg>
<!-- 选择商品 -->
<shopList ref="shopListRef" @success="selectShopRes" />
<el-dialog :title="selectSkuItem.proName" :visible.sync="showSelectSku">
<div class="pro_sku">
<div class="item">
<!-- <div class="row">
<div class="title">规格</div>
<div class="tag no">温度</div>
</div> -->
<div class="row">
<div class="title">选项值</div>
<div class="tag" :class="{ active: item.active }" v-for="(item, index) in selectSkuItem.skuList"
:key="item.id" @click="selectSkuHandle(item, index)">
{{ item.specSnap }}
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="showSelectSku = false"> </el-button>
<el-button type="primary" :disabled="selectSkuConfirmDisabled" @click="showSelectSkuConfirm"> </el-button>
</span>
</el-dialog>
</div>
</template>
@ -426,6 +542,7 @@ import settings from "@/settings";
import dayjs from "dayjs";
import { RandomNumBoth } from "@/utils";
import { formatPrice } from "@/utils/format";
import couponEnum from '@/views/coupon_manage/couponEnum.js'
export default {
components: {
@ -455,6 +572,7 @@ export default {
}
}
return {
couponEnum,
shopTypesActive: 0,
shopTypes: settings.typeEnum,
specTableHeaders: [],
@ -480,9 +598,19 @@ export default {
isEditor: false,
loading: false,
originSkuList: [],
showSelectSku: false,
selectSkuItem: {
skuList: []
},
selectSkuTableIndex: 0,
selectSkuConfirmIndex: 0,
selectSkuConfirmDisabled: true,
addGroupIndex: false,
form: {
id: "",
type: 'normal',
typeEnum: "normal",
groupType: '0',
name: "",
shortTitle: "", //
unitId: "",
@ -491,6 +619,7 @@ export default {
coverImg: "",
images: [],
shopId: localStorage.getItem("shopId"),
showType: ['table'],
lowPrice: "",
skuList: [],
isShowMall: 1,
@ -500,6 +629,14 @@ export default {
specId: "",
baseSalesNumber: 0,
sort: 0,
proGroupVo: [
{
title: '',
count: '',
number: '',
goods: []
}
],
groupSnap: [],
specInfo: [],
selectSpec: [],
@ -520,8 +657,17 @@ export default {
},
stockNumber: 0,
isHot: 1,
isGrounding: 1
isGrounding: 1,
isTempPrice: '1',
dayLimit: 0,
singleOrderLimit: 0,
singlePeopleLimit: 0,
weight: '',
days: [],
startTime: '',
endTime: ''
},
useTime: ['', ''],
imgList: [],
rules: {
typeEnum: [
@ -529,6 +675,13 @@ export default {
required: true,
},
],
showType: [
{
required: true,
trigger: "change",
message: "至少选择一项",
}
],
name: [
{
required: true,
@ -602,7 +755,7 @@ export default {
batchNumberForm: {
batchNumber: 0,
},
routequery:''
routequery: ''
};
},
mounted() {
@ -627,7 +780,75 @@ export default {
}
}
},
methods: {
methods: {
useTimeChange(e) {
this.form.startTime = e[0]
this.form.endTime = e[1]
},
//
typeChange() {
this.form.typeEnum = 'normal'
if (this.form.groupType == 0) {
this.$set(this.form.proGroupVo, 0, {
title: '',
count: '',
number: 1,
goods: []
})
} else {
this.form.proGroupVo = []
}
this.changeTypeEnum()
},
//
showSelectSkuConfirm() {
let item = this.selectSkuItem.skuList.filter(item => item.active)
this.$set(this.form.proGroupVo[this.selectSkuTableIndex].goods, this.selectSkuConfirmIndex, { ...this.form.proGroupVo[this.selectSkuTableIndex].goods[this.selectSkuConfirmIndex], skuId: item[0].id })
this.$set(this.form.proGroupVo[this.selectSkuTableIndex].goods, this.selectSkuConfirmIndex, { ...this.form.proGroupVo[this.selectSkuTableIndex].goods[this.selectSkuConfirmIndex], skuName: item[0].specSnap })
this.showSelectSku = false
// console.log(this.form.proGroupVo.goods[this.selectSkuConfirmIndex]
},
// sku
selectSkuHandle(item, index) {
// false
this.selectSkuItem.skuList.map((item, index) => {
let nitem = { ...item }
nitem.active = false
this.$set(this.selectSkuItem.skuList, index, nitem)
})
if (item.active) {
item.active = false
this.$set(this.selectSkuItem.skuList, index, { ...item })
} else {
item.active = true
this.$set(this.selectSkuItem.skuList, index, { ...item })
}
let arr = this.selectSkuItem.skuList.filter(item => item.active)
if (arr.length) {
this.selectSkuConfirmDisabled = false
} else {
this.selectSkuConfirmDisabled = true
}
},
//
showSelectSkuHandle(row, index, tabIndex) {
this.selectSkuTableIndex = tabIndex
this.selectSkuConfirmIndex = index
this.showSelectSku = true
let obj = { ...row }
obj.skuList.map(item => {
item.active = false
})
this.selectSkuItem = obj
},
uploadImgSucess(res, item) {
console.log(res);
console.log(item);
@ -735,7 +956,15 @@ export default {
url: item,
};
});
res.days = res.days.split(',')
res.showType = res.showType.split(',')
res.isTempPrice = JSON.stringify(res.isTempPrice)
this.form = res;
this.useTime = [res.startTime, res.endTime]
if (res.typeEnum == "sku") {
let skuList = [...res.skuList];
let specInfo = JSON.parse(res.specInfo);
@ -767,27 +996,31 @@ export default {
//
submitHandle() {
// undefinedtrue
const hasUndefined = this.form.skuList.some(obj => {
for (const key in obj) {
if (this.shopTypesActive == 0) {//
if (obj['salePrice'] == undefined || obj['memberPrice'] == undefined) {
return true;
}
} else {//
if (obj['salePrice'] == undefined || obj['memberPrice'] == undefined || obj['costPrice'] == undefined || obj['originPrice'] == undefined) {
return true;
console.log(this.form);
// return
if (this.form.type == 'normal') {
// undefinedtrue
const hasUndefined = this.form.skuList.some(obj => {
for (const key in obj) {
if (this.form.typeEnum == 'normal') {//
if (obj['salePrice'] == undefined || obj['memberPrice'] == undefined) {
return true;
}
} else {//
if (obj['salePrice'] == undefined || obj['memberPrice'] == undefined || obj['costPrice'] == undefined || obj['originPrice'] == undefined) {
return true;
}
}
}
}
return false;
});
if (hasUndefined) {
this.$message({
message: "请完善规格属性的参数!",
type: "warning",
return false;
});
return false;
if (hasUndefined) {
this.$message({
message: "请完善规格属性的参数!",
type: "warning",
});
return false;
}
}
let arr = [];
@ -807,6 +1040,10 @@ export default {
this.form.specInfo = JSON.stringify(this.form.skuList);
// this.form.skuList[0].costPrice = 0
this.form.skuList[0].originPrice = this.form.skuList[0].salePrice
this.form.showType = this.form.showType.join(',')
this.form.days = this.form.days.join(',')
if (this.form.id) {
await tbProductPut(this.form);
} else {
@ -833,30 +1070,45 @@ export default {
},
//
selectShopRes(res) {
let arr = res.map((item) => {
item.groupNum = 1;
return item;
});
if (this.tableAddShopIndex != null) {
this.form.groupSnap[this.tableAddShopIndex].goods = [...arr];
this.tableAddShopIndex = null;
let newres = res.map(item => {
item.proId = item.id
item.proName = item.name
item.price = item.lowPrice
item.skuId = ''
item.skuName = ''
item.number = 1
return item
})
if (this.form.groupType == 0) {
let obj = {
title: '',
count: newres.length,
number: '',
goods: newres
}
this.form.proGroupVo = [{ ...obj }]
} else {
this.form.groupSnap.push({
title: "",
goods: [...arr],
number: 1,
});
if (this.addGroupIndex !== false) {
this.form.proGroupVo[this.addGroupIndex].goods = newres
} else {
let arr = [...this.form.proGroupVo]
arr.push({
title: '',
count: newres.length,
number: '',
goods: newres
})
this.form.proGroupVo = [...arr]
}
}
console.log(this.form.groupSnap);
},
//
changeTypeEnum(index) {
// if (this.form.id) return;
this.shopTypesActive = index;
const typeEnum = this.shopTypes[index].typeEnum;
this.form.typeEnum = typeEnum;
if (typeEnum == "sku") {
// this.shopTypesActive = index;
// const typeEnum = this.shopTypes[index].typeEnum;
// this.form.typeEnum = typeEnum;
if (this.form.typeEnum == "sku") {
this.form.skuList = [];
this.tbProductSpecGet();
} else {
@ -1149,4 +1401,44 @@ export default {
.showStyle:hover>.buttonstyle {
display: block;
}
.pro_sku {
.item {
.row {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: 20px;
}
.title {
width: 80px;
}
.tag {
background-color: #F7F7FA;
padding: 6px 12px;
margin-right: 10px;
border-radius: 4px;
&.no {
background: none;
padding: 6px 0;
}
&.active {
background-color: #46A6FF;
color: #fff;
}
}
}
}
}
.group_wrap {
padding: 20px;
background-color: #F7F7FA;
margin-bottom: 20px;
}
</style>

View File

@ -5,6 +5,21 @@
<el-form-item label="店铺名称" prop="shopName">
<el-input v-model="form.shopName" placeholder="请输入门店名称"></el-input>
</el-form-item>
<el-form-item label="店铺类型">
<el-radio-group v-model="form.type">
<el-radio-button label="only">单店</el-radio-button>
<el-radio-button label="chain">连锁店</el-radio-button>
<el-radio-button label="join">加盟店</el-radio-button>
</el-radio-group>
<div class="tips">请谨慎修改</div>
</el-form-item>
<el-form-item label="主店账号" prop="mainId" v-if="form.type != 'only'">
<el-select v-model="form.mainId" placeholder="请选择主店铺" filterable remote reserve-keyword
:remote-method="getTableData" :loading="shopListLoading">
<el-option v-for="item in shopList" :label="`ID:${item.id} - 名称:${item.shopName}`" :value="item.id"
:key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="连锁店扩展店名">
<el-input v-model="form.chainName" placeholder="请输入连锁店扩展店名"></el-input>
</el-form-item>
@ -16,13 +31,20 @@
<el-image :src="form.coverImg || require('@/assets/images/upload.png')" fit="contain"
style="width: 80px;height: 80px;" @click="showUpload = true; uploadIndex = 2"></el-image>
</el-form-item>
<el-form-item label="店铺类型">
<el-form-item label="经营模式">
<el-radio-group v-model="form.registerType">
<el-radio-button label="munchies">快餐版</el-radio-button>
<el-radio-button label="restaurant">餐饮版</el-radio-button>
</el-radio-group>
<div class="tips">请谨慎修改</div>
</el-form-item>
<el-form-item label="管理方式" v-if="form.type != 'only'">
<el-radio-group v-model="form.tube_type">
<el-radio-button label="0">不可直接管理</el-radio-button>
<el-radio-button label="1">直接管理</el-radio-button>
</el-radio-group>
<div class="tips">请谨慎修改</div>
</el-form-item>
<el-form-item label="试用/正式">
<el-radio-group v-model="form.profiles">
<el-radio-button label="probation">试用</el-radio-button>
@ -36,7 +58,7 @@
<el-form-item label="登录账号" prop="account">
<el-input v-model="form.account" placeholder="请输入登录账号"></el-input>
</el-form-item>
<el-form-item label="登录密码" prop="password">
<el-form-item label="登录密码" prop="password" v-if="!form.id">
<el-input type="password" show-password v-model="form.password" placeholder="请输入登录密码"></el-input>
</el-form-item>
<el-form-item label="联系电话">
@ -135,7 +157,7 @@
import { getToken } from '@/utils/auth'
import { mapGetters } from 'vuex'
import crudQiNiu from '@/api/tools/qiniu'
import { tbShopInfoPost, geocode } from '@/api/shop'
import { tbShopInfoPost, geocode, tbShopInfo } from '@/api/shop'
export default {
computed: {
...mapGetters([
@ -161,6 +183,9 @@ export default {
form: {
id: '',
shopName: '',
mainId: '',
type: 'only',
tube_type: '0',
registerType: 'restaurant',
profiles: 'release',
registerCode: '',
@ -189,6 +214,13 @@ export default {
trigger: 'blur'
}
],
mainId: [
{
required: true,
message: ' ',
trigger: 'blur'
}
],
provinces: [
{
required: true,
@ -231,13 +263,32 @@ export default {
amapOptions: {
center: [108.946465, 34.347984],
position: []
}
},
shopListLoading: false,
shopList: []
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
//
async getTableData(query = '') {
this.shopListLoading = true
try {
const res = await tbShopInfo({
page: 0,
size: 100,
shopName: query,
type: 'only'
})
this.shopListLoading = false
this.shopList = res.content
} catch (error) {
this.shopListLoading = false
console.log(error)
}
},
onSearchResult(res) {
this.locationSearchList = res
this.amapOptions.center = [res[0].lng, res[0].lat]
@ -320,6 +371,8 @@ export default {
}
},
show(obj) {
this.getTableData()
this.dialogVisible = true
if (obj && obj.id) {
this.form = { ...obj }

View File

@ -157,6 +157,9 @@
<el-form-item label="店铺简介">
<el-input type="textarea" v-model.trim="form.detail" placeholder="请输入店铺简介" style="width: 500px;"></el-input>
</el-form-item>
<el-form-item label="台桌预订短信">
<el-input type="textarea" v-model.trim="form.bookingSms" placeholder="请输入台桌预订短信" style="width: 500px;"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio :label="1">营业中</el-radio>