This commit is contained in:
魏啾 2024-11-26 11:02:34 +08:00
commit 4218084ebf
18 changed files with 2030 additions and 58 deletions

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

@ -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

@ -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,176 @@
<!-- 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: {
/**
* 确定
*/
async onSubmitHandle() {
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)
}
}
})
},
/**
* 打开
* @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.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({ creditBuyerId: this.query.creditBuyerId, repaymentMethod: this.repaymentMethod }, row.id)
}
},
/**
* 切换时间
* @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

@ -67,8 +67,8 @@
<div class="m">{{ payCountTotal }}</div>
<div class="t">总金额</div>
</div>
</div>
<div class="item" v-for="item in payCountList" :key="item.payType">
</div> -->
<!-- <div class="item" v-for="item in payCountList" :key="item.payType">
<div class="icon_wrap" style="--bg-color:#fff">
<el-image class="img" :src="item.icon"></el-image>
</div>
@ -76,7 +76,7 @@
<div class="m">{{ item.payAmount || 0 }}</div>
<div class="t">{{ item.payType }}</div>
</div>
</div>
</div>
</div>
</div>-->
<div class="head-container">
@ -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

@ -5,8 +5,20 @@
<el-form-item label="店铺名称" prop="shopName">
<el-input v-model="form.shopName" placeholder="请输入门店名称"></el-input>
</el-form-item>
<el-form-item label="主店账号" prop="mainId">
<el-input v-model="form.mainId" placeholder="请输入主店账号"></el-input>
<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>
@ -26,14 +38,6 @@
</el-radio-group>
<div class="tips">请谨慎修改</div>
</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="管理方式" v-if="form.type != 'only'">
<el-radio-group v-model="form.tube_type">
<el-radio-button label="0">不可直接管理</el-radio-button>
@ -54,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="联系电话">
@ -153,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([
@ -259,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]
@ -348,6 +371,8 @@ export default {
}
},
show(obj) {
this.getTableData()
this.dialogVisible = true
if (obj && obj.id) {
this.form = { ...obj }