This commit is contained in:
2025-01-08 09:59:37 +08:00
parent bb0ca75b42
commit 026e45e9c1
76 changed files with 10046 additions and 3620 deletions
+22
View File
@@ -0,0 +1,22 @@
import request from '@/utils/request';
import type {ApiResult} from '@/api';
import {Area} from "@/api/system/area/model";
import { THINK_API_URL } from "@/config/setting";
export async function listArea(param: any) {
const res = await request.post<ApiResult<Area[]>>(`${THINK_API_URL}/common/area/list-by-level`, param);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function listCity() {
const res = await request.post<ApiResult<Area[]>>(`${THINK_API_URL}/common/area/city-list`);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+8
View File
@@ -0,0 +1,8 @@
export interface Area {
id?: any,
name?: any,
fid?: any,
levelId?: any,
children?: any,
}
+11
View File
@@ -49,6 +49,17 @@ export async function addThinkCard(data: ThinkCard) {
return Promise.reject(new Error(res.data.message));
}
export async function makeThinkCard(data: ThinkCard) {
const res = await request.post<ApiResult<unknown>>(
THINK_API_URL + '/think/think-card/make-card',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改
*/
+1
View File
@@ -66,6 +66,7 @@ export interface ThinkCard {
isInvoice?: number;
// vip卡到期时间
expireTime?: number;
makeNum?: number;
// 紧急联系人
urgentName?: string;
// 紧急联系人号码
+118
View File
@@ -0,0 +1,118 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ThinkCardsBills, ThinkCardsBillsParam } from './model';
import { THINK_API_URL } from "@/config/setting";
import type { ThinkVipCardsBillsParam } from "@/api/think/thinkVipCardsBills/model";
/**
* 分页查询Vip卡每日账单
*/
export async function pageThinkCardsBills(params: ThinkCardsBillsParam) {
const res = await request.get<ApiResult<PageResult<ThinkCardsBills>>>(
THINK_API_URL + '/think/think-cards-bills/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询Vip卡每日账单列表
*/
export async function listThinkCardsBills(params?: ThinkCardsBillsParam) {
const res = await request.get<ApiResult<ThinkCardsBills[]>>(
THINK_API_URL + '/think/think-cards-bills',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function thinkCardsBillsTotalAmount(params?: ThinkVipCardsBillsParam) {
const res = await request.get<ApiResult<any>>(
THINK_API_URL + '/think/think-cards-bills/total-amount',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加Vip卡每日账单
*/
export async function addThinkCardsBills(data: ThinkCardsBills) {
const res = await request.post<ApiResult<unknown>>(
THINK_API_URL + '/think/think-cards-bills',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改Vip卡每日账单
*/
export async function updateThinkCardsBills(data: ThinkCardsBills) {
const res = await request.put<ApiResult<unknown>>(
THINK_API_URL + '/think/think-cards-bills',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除Vip卡每日账单
*/
export async function removeThinkCardsBills(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-cards-bills/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除Vip卡每日账单
*/
export async function removeBatchThinkCardsBills(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-cards-bills/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询Vip卡每日账单
*/
export async function getThinkCardsBills(id: number) {
const res = await request.get<ApiResult<ThinkCardsBills>>(
THINK_API_URL + '/think/think-cards-bills/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,37 @@
import type { PageParam } from '@/api';
/**
* Vip卡每日账单
*/
export interface ThinkCardsBills {
//
id?: number;
//
uid?: number;
//
cid?: number;
//
date?: string;
//
amount?: string;
// 租户id
tenantId?: number;
// 状态, 0已发布, 1待审核 2已驳回 3违规内容
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* Vip卡每日账单搜索条件
*/
export interface ThinkCardsBillsParam extends PageParam {
id?: number;
keywords?: string;
dateStart?: string;
dateEnd?: string;
}
+9 -9
View File
@@ -1,15 +1,15 @@
import type { PageParam } from '@/api';
/**
*
*
*/
export interface ThinkDeposit {
//
//
id?: number;
// 1收押金、2退押金
type?: string;
type?: number;
// 1微信支付,2支付宝支付,3现金支付,4POS机支付
moneyType?: string;
moneyType?: number;
// 场馆名称
siteName?: string;
// 姓名
@@ -17,16 +17,16 @@ export interface ThinkDeposit {
// 手机号码
phone?: string;
// 押金
money?: string;
money?: number;
// 1已付,2已退
status?: string;
//
status?: number;
//
info?: string;
// 管理员id
aid?: number;
//
//
createTime?: number;
//
//
updateTime?: number;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ThinkDepositItem, ThinkDepositItemParam } from './model';
import { THINK_API_URL } from "@/config/setting";
/**
* 分页查询押金物品
*/
export async function pageThinkDepositItem(params: ThinkDepositItemParam) {
const res = await request.get<ApiResult<PageResult<ThinkDepositItem>>>(
THINK_API_URL + '/think/think-deposit-item/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询押金物品列表
*/
export async function listThinkDepositItem(params?: ThinkDepositItemParam) {
const res = await request.get<ApiResult<ThinkDepositItem[]>>(
THINK_API_URL + '/think/think-deposit-item',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加押金物品
*/
export async function addThinkDepositItem(data: ThinkDepositItem) {
const res = await request.post<ApiResult<unknown>>(
THINK_API_URL + '/think/think-deposit-item',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改押金物品
*/
export async function updateThinkDepositItem(data: ThinkDepositItem) {
const res = await request.put<ApiResult<unknown>>(
THINK_API_URL + '/think/think-deposit-item',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除押金物品
*/
export async function removeThinkDepositItem(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-deposit-item/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除押金物品
*/
export async function removeBatchThinkDepositItem(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-deposit-item/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询押金物品
*/
export async function getThinkDepositItem(id: number) {
const res = await request.get<ApiResult<ThinkDepositItem>>(
THINK_API_URL + '/think/think-deposit-item/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,28 @@
import type { PageParam } from '@/api';
/**
* 押金物品
*/
export interface ThinkDepositItem {
//
id?: number;
//
title?: string;
//
amount?: string;
//
siteId?: number;
siteName?: string;
// 创建时间
createTime?: number;
// 租户id
tenantId?: number;
}
/**
* 押金物品搜索条件
*/
export interface ThinkDepositItemParam extends PageParam {
id?: number;
keywords?: string;
}
+17 -15
View File
@@ -1,25 +1,25 @@
import type { PageParam } from '@/api';
import type { PageParam } from "@/api";
/**
*
*
*/
export interface ThinkGoods {
//
//
goodsId?: number;
// 关联商品分类id
cid?: number;
// 商品标题
title?: string;
// 划线价
linePrice?: string;
linePrice?: number;
// 最低价格
minPrice?: string;
minPrice?: number;
// 最高价格
maxPrice?: string;
maxPrice?: number;
// 最低积分
minIntegral?: string;
minIntegral?: number;
// 最高积分
maxIntegral?: string;
maxIntegral?: number;
// 总库存
stockNum?: number;
// 总销量
@@ -27,9 +27,9 @@ export interface ThinkGoods {
// 封面图
image?: string;
// 商品规格(1单规格 2多规格)
specType?: string;
specType?: number;
// 状态:1上架,2下架
status?: string;
status?: number;
// 商品简介
desc?: string;
// 商品详细介绍
@@ -37,14 +37,14 @@ export interface ThinkGoods {
// 排序
sort?: number;
// 是否需要发货:1是;0否
isFh?: string;
isFh?: number;
// 积分/金额:1仅积分;2仅金额;3积分/金额
isIntegral?: string;
isIntegral?: number;
// 收货方式:1自提;2快递;3自提/快递
shType?: string;
//
shType?: number;
//
createTime?: number;
//
//
updateTime?: number;
}
@@ -53,5 +53,7 @@ export interface ThinkGoods {
*/
export interface ThinkGoodsParam extends PageParam {
goodsId?: number;
cid?: number;
status?: number;
keywords?: string;
}
@@ -50,6 +50,7 @@ export interface ThinkInvoice {
invoicetype?: number;
//
vid?: number;
status?: number;
}
/**
@@ -59,5 +60,7 @@ export interface ThinkInvoiceParam extends PageParam {
id?: number;
uid?: number;
oid?: number;
itype?: number;
isOpen?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ThinkMachineOpenLog, ThinkMachineOpenLogParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询闸机开门记录
*/
export async function pageThinkMachineOpenLog(params: ThinkMachineOpenLogParam) {
const res = await request.get<ApiResult<PageResult<ThinkMachineOpenLog>>>(
MODULES_API_URL + '/think/think-machine-open-log/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询闸机开门记录列表
*/
export async function listThinkMachineOpenLog(params?: ThinkMachineOpenLogParam) {
const res = await request.get<ApiResult<ThinkMachineOpenLog[]>>(
MODULES_API_URL + '/think/think-machine-open-log',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加闸机开门记录
*/
export async function addThinkMachineOpenLog(data: ThinkMachineOpenLog) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/think/think-machine-open-log',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改闸机开门记录
*/
export async function updateThinkMachineOpenLog(data: ThinkMachineOpenLog) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/think/think-machine-open-log',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除闸机开门记录
*/
export async function removeThinkMachineOpenLog(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/think/think-machine-open-log/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除闸机开门记录
*/
export async function removeBatchThinkMachineOpenLog(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/think/think-machine-open-log/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询闸机开门记录
*/
export async function getThinkMachineOpenLog(id: number) {
const res = await request.get<ApiResult<ThinkMachineOpenLog>>(
MODULES_API_URL + '/think/think-machine-open-log/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,31 @@
import type { PageParam } from '@/api';
/**
* 闸机开门记录
*/
export interface ThinkMachineOpenLog {
//
id?: number;
//
orderId?: number;
// 租户id
tenantId?: number;
// 备注
comments?: string;
// 状态, 0在线, 1离线
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 注册时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* 闸机开门记录搜索条件
*/
export interface ThinkMachineOpenLogParam extends PageParam {
id?: number;
keywords?: string;
}
+47 -13
View File
@@ -1,14 +1,14 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ThinkOrder, ThinkOrderParam } from './model';
import { THINK_API_URL } from '@/config/setting';
import request from "@/utils/request";
import type { ApiResult, PageResult } from "@/api";
import type { ThinkOrder, ThinkOrderParam } from "./model";
import { THINK_API_URL } from "@/config/setting";
/**
* 分页查询
*/
export async function pageThinkOrder(params: ThinkOrderParam) {
const res = await request.get<ApiResult<PageResult<ThinkOrder>>>(
THINK_API_URL + '/think/think-order/page',
THINK_API_URL + "/think/think-order/page",
{
params
}
@@ -24,7 +24,7 @@ export async function pageThinkOrder(params: ThinkOrderParam) {
*/
export async function listThinkOrder(params?: ThinkOrderParam) {
const res = await request.get<ApiResult<ThinkOrder[]>>(
THINK_API_URL + '/think/think-order',
THINK_API_URL + "/think/think-order",
{
params
}
@@ -35,12 +35,25 @@ export async function listThinkOrder(params?: ThinkOrderParam) {
return Promise.reject(new Error(res.data.message));
}
export async function thinkOrderTotalAmount(params?: ThinkOrderParam) {
const res = await request.get<ApiResult<any>>(
THINK_API_URL + "/think/think-order/total-amount",
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加
*/
export async function addThinkOrder(data: ThinkOrder) {
const res = await request.post<ApiResult<unknown>>(
THINK_API_URL + '/think/think-order',
THINK_API_URL + "/think/think-order",
data
);
if (res.data.code === 0) {
@@ -54,7 +67,18 @@ export async function addThinkOrder(data: ThinkOrder) {
*/
export async function updateThinkOrder(data: ThinkOrder) {
const res = await request.put<ApiResult<unknown>>(
THINK_API_URL + '/think/think-order',
THINK_API_URL + "/think/think-order",
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
export async function updateBatchThinkOrder(data: ThinkOrder[]) {
const res = await request.put<ApiResult<unknown>>(
THINK_API_URL + "/think/think-order/batch",
data
);
if (res.data.code === 0) {
@@ -68,7 +92,7 @@ export async function updateThinkOrder(data: ThinkOrder) {
*/
export async function removeThinkOrder(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-order/' + id
THINK_API_URL + "/think/think-order/" + id
);
if (res.data.code === 0) {
return res.data.message;
@@ -81,7 +105,7 @@ export async function removeThinkOrder(id?: number) {
*/
export async function removeBatchThinkOrder(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-order/batch',
THINK_API_URL + "/think/think-order/batch",
{
data
}
@@ -95,9 +119,19 @@ export async function removeBatchThinkOrder(data: (number | undefined)[]) {
/**
* 根据id查询
*/
export async function getThinkOrder(id: number) {
const res = await request.get<ApiResult<ThinkOrder>>(
THINK_API_URL + '/think/think-order/' + id
export async function thinkOrderExport(params?: ThinkOrderParam) {
const res = await request.post<ApiResult<ThinkOrder>>(
THINK_API_URL + "/think/think-order/export", params
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function getThinkOrder(id: number) {
const res = await request.get<ApiResult<ThinkOrder>>(
THINK_API_URL + "/think/think-order/" + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
+4
View File
@@ -88,6 +88,10 @@ export interface ThinkOrder {
export interface ThinkOrderParam extends PageParam {
id?: number;
sid?: number;
payStatus?: number;
orderStatus?: number;
payType?: number;
isInvoice?: number;
siteName?: string;
keywords?: string;
}
@@ -1,13 +1,14 @@
import type { PageParam } from '@/api';
import type { PageParam } from "@/api";
/**
* 微信退款记录
*/
export interface ThinkOrderRefundLog {
//
//
int?: number;
// 用户ID
uid?: number;
refundAmount?: number;
// 场馆ID
sid?: number;
// 订单ID
@@ -17,7 +18,7 @@ export interface ThinkOrderRefundLog {
// 来源
source?: string;
// 状态:1新增,2退款成功,3已全额退款,4退款失败
status?: string;
status?: number;
// 创建时间
createTime?: string;
}
+10 -2
View File
@@ -16,8 +16,15 @@ export interface ThinkSite {
businessTime?: string;
// 场馆地址
address?: string;
lat?: string;
lng?: string;
province?: string;
city?: string;
region?: string;
rentStartDate?: string;
rentEndDate?: string;
realPropertyCertificate?: string;
size?: string;
lat?: string | number;
lng?: string | number;
// 场馆介绍
info?: string;
// 场馆电话
@@ -38,6 +45,7 @@ export interface ThinkSite {
updateTime?: number;
// 周末活动订场开关:1开,0关
weekendOpen?: number;
dailyMaxNum?: number;
key?: number;
value?: number;
title?: string;
+10
View File
@@ -104,3 +104,13 @@ export async function getThinkUsersVip(id: number) {
}
return Promise.reject(new Error(res.data.message));
}
export async function thinkUsersVipLog(id: number) {
const res = await request.get<ApiResult<ThinkUsersVip>>(
THINK_API_URL + '/think/think-users-vip/log/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+8 -8
View File
@@ -35,21 +35,21 @@ export interface ThinkUsersVip {
// 剩余次数
num?: number;
// 付款状态
status?: string;
status?: number;
// 是否已充值,1已充值,2未充值
isRecharge?: string;
isRecharge?: number;
// 充值金额
rechargePrice?: string;
rechargePrice?: number;
// 会员卡年限
term?: string;
term?: number;
// 月限
month?: string;
month?: number;
// 会员卡类型:1年卡,2次卡,3月卡,4会员VIP
type?: string;
type?: number;
// 卡类型:1成人卡,2儿童卡
cardType?: string;
cardType?: number;
// vip卡等级类型:1特殊vip卡,2普通vip卡
vipType?: string;
vipType?: number;
// 特殊卡开发凭证图
pic?: string;
// VIP充值卡价格组
+10
View File
@@ -104,3 +104,13 @@ export async function getThinkVip(id: number) {
}
return Promise.reject(new Error(res.data.message));
}
export async function thinkVipTotal(params?: ThinkVipParam) {
const res = await request.get<ApiResult<ThinkVip[]>>(
THINK_API_URL + '/think/think-vip/total', {params}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+3 -2
View File
@@ -1,4 +1,3 @@
import type { PageParam } from '@/api';
/**
*
@@ -53,7 +52,9 @@ export interface ThinkVip {
/**
* 搜索条件
*/
export interface ThinkVipParam extends PageParam {
export interface ThinkVipParam{
id?: number;
createTimeStart?: number;
createTimeEnd?: number;
keywords?: string;
}
+119
View File
@@ -0,0 +1,119 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ThinkVipCardsBills, ThinkVipCardsBillsParam } from './model';
import { THINK_API_URL } from '@/config/setting';
/**
* 分页查询Vip卡每日账单
*/
export async function pageThinkVipCardsBills(params: ThinkVipCardsBillsParam) {
const res = await request.get<ApiResult<PageResult<ThinkVipCardsBills>>>(
THINK_API_URL + '/think/think-vip-cards-bills/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询Vip卡每日账单列表
*/
export async function listThinkVipCardsBills(params?: ThinkVipCardsBillsParam) {
const res = await request.get<ApiResult<ThinkVipCardsBills[]>>(
THINK_API_URL + '/think/think-vip-cards-bills',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
export async function thinkVipCardsBillsTotalAmount(params?: ThinkVipCardsBillsParam) {
const res = await request.get<ApiResult<ThinkVipCardsBills[]>>(
THINK_API_URL + '/think/think-vip-cards-bills/total-amount',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加Vip卡每日账单
*/
export async function addThinkVipCardsBills(data: ThinkVipCardsBills) {
const res = await request.post<ApiResult<unknown>>(
THINK_API_URL + '/think/think-vip-cards-bills',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改Vip卡每日账单
*/
export async function updateThinkVipCardsBills(data: ThinkVipCardsBills) {
const res = await request.put<ApiResult<unknown>>(
THINK_API_URL + '/think/think-vip-cards-bills',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除Vip卡每日账单
*/
export async function removeThinkVipCardsBills(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-vip-cards-bills/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除Vip卡每日账单
*/
export async function removeBatchThinkVipCardsBills(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/think/think-vip-cards-bills/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询Vip卡每日账单
*/
export async function getThinkVipCardsBills(id: number) {
const res = await request.get<ApiResult<ThinkVipCardsBills>>(
THINK_API_URL + '/think/think-vip-cards-bills/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,37 @@
import type { PageParam } from '@/api';
/**
* Vip卡每日账单
*/
export interface ThinkVipCardsBills {
//
id?: number;
//
uid?: number;
//
vid?: number;
//
date?: string;
//
amount?: string;
// 租户id
tenantId?: number;
// 状态, 0已发布, 1待审核 2已驳回 3违规内容
status?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 创建时间
createTime?: string;
// 修改时间
updateTime?: string;
}
/**
* Vip卡每日账单搜索条件
*/
export interface ThinkVipCardsBillsParam extends PageParam {
id?: number;
keywords?: string;
dateStart?: string;
dateEnd?: string;
}
+7 -1
View File
@@ -60,7 +60,13 @@
label: '现金支付',
key: 'cashPayment',
icon: 'PayCircleOutlined'
}
},
{
value: 5,
label: 'IC卡支付',
key: 'ICCardPay',
icon: 'IdcardOutlined'
},
]);
/* 更新选中数据 */
@@ -69,7 +69,7 @@
};
// 搜索内容
const searchText = ref(null);
const searchText = ref();
// 表单数据
const { where } = useSearch<ThinkUsersParam>({
id: undefined,
@@ -0,0 +1,306 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '开具发票2' : '开具发票'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<!-- <a-form-item label="订单编号" name="incoiveNum">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入发票的订单"-->
<!-- v-model:value="form.incoiveNum"-->
<!-- />-->
<!-- </a-form-item>-->
<!-- <a-form-item label="纳税人识别号" name="incoiveCode">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入纳税人识别号"-->
<!-- v-model:value="form.incoiveCode"-->
<!-- />-->
<!-- </a-form-item>-->
<!-- <a-form-item label="订单号" name="orderNum">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入订单号"-->
<!-- v-model:value="form.orderNum"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="发票金额" name="price">
<a-input
allow-clear
placeholder="请输入发票金额"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="单位名称" name="name">
<a-input
allow-clear
placeholder="请输入单位名称"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="税号" name="code">
<a-input
allow-clear
placeholder="请输入税号"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="开户行" name="bank">
<a-input
allow-clear
placeholder="请输入开户行"
v-model:value="form.bank"
/>
</a-form-item>
<a-form-item label="开户账号" name="account">
<a-input
allow-clear
placeholder="请输入开户账号"
v-model:value="form.account"
/>
</a-form-item>
<a-form-item label="单位地址" name="address">
<a-input
allow-clear
placeholder="请输入单位地址"
v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="公司电话" name="tel">
<a-input
allow-clear
placeholder="请输入公司电话"
v-model:value="form.tel"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="电子邮箱" name="email">
<a-input
allow-clear
placeholder="请输入电子邮箱"
v-model:value="form.email"
/>
</a-form-item>
<a-form-item label="备注信息" name="info">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入备注信息"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="发票类型" name="type">
<a-radio-group v-model:value="form.type">
<a-radio :value="1">纸质发票</a-radio>
<a-radio :value="2">电子发票</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="发票类型" name="itype">
<a-radio-group v-model:value="form.itype" :disabled="true">
<a-radio :value="1">场地发票</a-radio>
<a-radio :value="2">vip卡发票</a-radio>
<a-radio :value="2">ic卡发票</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="发票类型" name="invoicetype">
<a-radio-group v-model:value="form.invoicetype">
<a-radio :value="1">普票</a-radio>
<a-radio :value="2">专票</a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import {
addThinkInvoice,
doInvoice,
pageThinkInvoice,
updateThinkInvoice
} from '@/api/think/thinkInvoice';
import { ThinkInvoice } from '@/api/think/thinkInvoice/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { FormInstance } from 'ant-design-vue/es/form';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 用户信息
const form = reactive<ThinkInvoice>({
id: undefined,
incoiveNum: undefined,
incoiveCode: undefined,
orderNum: undefined,
oid: undefined,
uid: undefined,
price: undefined,
name: undefined,
tel: undefined,
address: undefined,
bank: undefined,
account: undefined,
code: undefined,
phone: undefined,
email: undefined,
info: undefined,
isOpen: undefined,
type: 2,
itype: 1,
invoicetype: 1,
createTime: undefined,
updateTime: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
price: [
{
required: true,
type: 'number',
message: '请填写发票金额',
trigger: 'blur'
}
],
name: [
{
required: true,
type: 'string',
message: '请填写单位名称',
trigger: 'blur'
}
],
code: [
{
required: true,
type: 'string',
message: '请填写税号',
trigger: 'blur'
}
]
});
const onChangeInvoice = (data: ThinkInvoice) => {
console.log(data);
console.log(form);
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
// const saveOrUpdate = isUpdate.value
// ? updateThinkInvoice
// : addThinkInvoice;
doInvoice(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
// 第一次开票
isUpdate.value = false;
form.oid = props.data?.id;
form.price = props.data?.totalPrice;
form.incoiveNum = props.data?.orderNum;
form.orderNum = props.data?.orderNum;
form.vid = props.data?.vid;
form.phone = props.data?.phone;
// 开过票
pageThinkInvoice({ uid: props.data?.uid, limit: 1 }).then((res) => {
if (res && res.list.length > 0) {
assignObject(form, res?.list[0]);
isUpdate.value = true;
form.oid = props.data?.id;
form.price = props.data?.payPrice;
form.incoiveNum = props.data?.orderNum;
form.vid = props.data?.vid;
form.phone = props.data?.phone;
}
});
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,429 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="`80%`"
:visible="visible"
:confirm-loading="loading"
:maxable="maxAble"
:title="isUpdate ? '编辑订单' : '订单详情'"
:body-style="{ paddingBottom: '8px', background: '#f3f3f3' }"
@update:visible="updateVisible"
:maskClosable="false"
:footer="null"
@ok="save"
>
<a-card class="order-card" :bordered="false">
<a-descriptions title="基本信息" :column="3">
<a-descriptions-item
label="订单号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.id }}
</a-descriptions-item>
<a-descriptions-item
label="订单编号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.orderNum }}
</a-descriptions-item>
<a-descriptions-item
label="订单状态"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<a-tag v-if="form.orderStatus == 1">已完成</a-tag>
<a-tag v-if="form.orderStatus == 2">未使用</a-tag>
<a-tag v-if="form.orderStatus == 3">已取消</a-tag>
<a-tag v-if="form.orderStatus == 4">退款申请中</a-tag>
<a-tag v-if="form.orderStatus == 5">退款被拒绝</a-tag>
<a-tag v-if="form.orderStatus == 6">退款成功</a-tag>
<a-tag v-if="form.orderStatus == 7">客户端申请退款</a-tag>
</a-descriptions-item>
<a-descriptions-item
label="买家信息"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.name }}
</a-descriptions-item>
<a-descriptions-item
label="手机号码"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.phone }}
</a-descriptions-item>
<a-descriptions-item
label="交易流水号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.wechatOrder }}
</a-descriptions-item>
<a-descriptions-item
label="订单总金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.totalPrice }}
</a-descriptions-item>
<a-descriptions-item
label="实付金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.payPrice }}
</a-descriptions-item>
<a-descriptions-item
label="减少的金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.reducePrice }}
</a-descriptions-item>
<a-descriptions-item
label="支付方式"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<template v-if="form.payStatus == 1">
<a-tag v-if="form.payType == 0">余额支付</a-tag>
<a-tag v-if="form.payType == 1">微信支付</a-tag>
<a-tag v-if="form.payType == 2">积分</a-tag>
<a-tag v-if="form.payType == 3">支付宝</a-tag>
<a-tag v-if="form.payType == 4">现金</a-tag>
<a-tag v-if="form.payType == 5">POS机</a-tag>
<a-tag v-if="form.payType == 6">VIP月卡</a-tag>
<a-tag v-if="form.payType == 7">formVIP年卡</a-tag>
<a-tag v-if="form.payType == 8">formVIP次卡</a-tag>
<a-tag v-if="form.payType == 9">formIC月卡</a-tag>
<a-tag v-if="form.payType == 10">formIC年卡</a-tag>
<a-tag v-if="form.payType == 11">formIC次卡</a-tag>
<a-tag v-if="form.payType == 12">form免费</a-tag>
<a-tag v-if="form.payType == 13">formVIP充值卡</a-tag>
<a-tag v-if="form.payType == 14">formIC充值卡</a-tag>
<a-tag v-if="form.payType == 15">form积分支付</a-tag>
<a-tag v-if="form.payType == 16">formVIP季卡</a-tag>
<a-tag v-if="form.payType == 17">formIC季卡</a-tag>
</template>
<template v-else>
<span></span>
</template>
</a-descriptions-item>
<a-descriptions-item
label="支付状态"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<a-tag v-if="form.payStatus == 1" color="green"
><CheckOutlined class="tag-icon" />已付款</a-tag
>
<a-tag v-if="form.payStatus == 0" color="error"
><CloseOutlined class="tag-icon" />未付款</a-tag
>
<a-tag v-if="form.payStatus == 3" color="cyan"
><CoffeeOutlined class="tag-icon" />未付款,占场中</a-tag
>
</a-descriptions-item>
<a-descriptions-item
label="付款时间"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ toDateString(form.payTime, 'yyyy-MM-dd HH:mm') }}
</a-descriptions-item>
<a-descriptions-item
label="下单时间"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ toDateString(form.createTime, 'yyyy-MM-dd HH:mm') }}
</a-descriptions-item>
<a-descriptions-item
label="信息备注"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<div
>{{ form.siteName }} {{ form.dateTime }} ¥{{
form.totalPrice
}}元</div
>
</a-descriptions-item>
</a-descriptions>
</a-card>
<a-card class="order-card" :bordered="false">
<a-spin :spinning="loading">
<a-table
:data-source="orderInfo"
:columns="columns"
:pagination="false"
/>
</a-spin>
</a-card>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { ColumnItem } from 'ele-admin-pro/es/ele-pro-table/types';
import {
CheckOutlined,
CloseOutlined,
CoffeeOutlined
} from '@ant-design/icons-vue';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
import { ThinkOrderInfo } from '@/api/think/thinkOrderInfo/model';
import { pageThinkOrderInfo } from '@/api/think/thinkOrderInfo';
import { toDateString } from 'ele-admin-pro';
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
export interface step {
title?: String | undefined;
subTitle?: String | undefined;
description?: String | undefined;
}
// 是否是修改
const isUpdate = ref(false);
// 是否显示最大化切换按钮
const maxAble = ref(true);
// 订单信息
const orderInfo = ref<ThinkOrderInfo[]>([]);
// 步骤条
const steps = ref<step[]>([
{
title: '报餐',
description: undefined
},
{
title: '付款',
description: undefined
},
{
title: '发餐',
description: undefined
},
{
title: '取餐',
description: undefined
},
{
title: '完成',
description: undefined
}
]);
const active = ref(2);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 订单信息
const form = reactive<ThinkOrder>({
id: undefined,
orderNum: undefined,
wechatOrder: undefined,
refundOrder: undefined,
sid: undefined,
uid: undefined,
cid: undefined,
vid: undefined,
aid: undefined,
adminId: undefined,
code: undefined,
name: undefined,
phone: undefined,
totalPrice: undefined,
reducePrice: undefined,
payPrice: undefined,
price: undefined,
money: undefined,
dateTime: undefined,
refundMoney: undefined,
coachPrice: undefined,
coachId: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
type: undefined,
qrcode: undefined,
desc2: undefined,
returnNum: undefined,
returnMoney: undefined,
startTime: undefined,
isInvoice: undefined,
createTime: undefined,
updateTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined,
siteName: undefined
});
// 请求状态
const loading = ref(true);
const { resetFields } = useForm(form);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const columns = ref<ColumnItem[]>([
{
title: '场馆名称',
dataIndex: 'siteName',
key: 'siteName',
align: 'center'
},
{
title: '场地',
dataIndex: 'fieldName',
align: 'center'
},
{
title: '价格',
dataIndex: 'price',
align: 'center'
},
{
title: '儿童价',
dataIndex: 'childrenPrice',
align: 'center'
},
{
title: '成人数',
dataIndex: 'adultNum',
align: 'center'
},
{
title: '儿童数',
dataIndex: 'childrenNum',
align: 'center'
},
{
title: '预定信息',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center'
},
{
title: '是否免费',
dataIndex: 'isFree',
align: 'center',
customRender: ({ text }) => ['', '免费', '付费'][text]
}
]);
/* 制作步骤条 */
const loadSteps = (order) => {
steps.value = [];
steps.value.push({
title: '下单'
});
steps.value.push({
title: '付款'
});
steps.value.push({
title: '发货'
});
steps.value.push({
title: '收货'
});
steps.value.push({
title: '完成'
});
// 下单
if (order.payStatus == 10) {
active.value = 0;
steps.value[0].description = order.createTime;
}
// 付款
if (order.payStatus == 20) {
active.value = 1;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
}
// 发货
if (order.payStatus == 20 && order.deliveryStatus == 20) {
active.value = 2;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
}
// 收货
if (order.payStatus == 20 && order.receiptStatus == 20) {
active.value = 3;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
steps.value[3].description = order.receiptTime;
}
// 完成
if (order.payStatus == 20 && order.orderStatus == 30) {
active.value = 4;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
steps.value[3].description = order.receiptTime;
}
// 已取消
if (order.orderStatus == 20) {
active.value = 4;
}
};
// const getOrderInfo = () => {
// const orderId = props.data?.orderId;
// listOrderInfo({ orderId }).then((data) => {
// orderInfo.value = data.filter((d) => d.totalNum > 0);
// });
// };
/* 保存编辑 */
const save = () => {};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
loading.value = true;
assignObject(form, props.data);
pageThinkOrderInfo({ oid: form.id }).then((res) => {
if (res?.list) {
orderInfo.value = res?.list;
}
loading.value = false;
});
loadSteps(props.data);
}
} else {
resetFields();
}
}
);
</script>
<style lang="less" scoped>
.order-card {
margin-bottom: 20px;
}
.ant-form-item {
margin-bottom: 5px;
}
.order-info {
display: flex;
.info {
padding-left: 5px;
display: flex;
flex-direction: column;
}
}
.tag-icon {
padding-right: 6px;
}
</style>
@@ -0,0 +1,112 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="`60%`"
:visible="visible"
:confirm-loading="loading"
title="退款"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
:maskClosable="false"
@ok="save"
>
<a-form>
<a-form-item label="订单金额">
<span>{{ data.totalPrice }}元</span>
</a-form-item>
<a-form-item label="支付金额">
<span>{{ data.payPrice }}元</span>
</a-form-item>
<a-form-item label="退款金额">
<a-input-number placeholder="请输入退款金额" style="width: 300px" v-model:value="form.refundAmount"
:max="data.payPrice" />
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from "vue";
import { ThinkOrder } from "@/api/think/thinkOrder/model";
import { ThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog/model";
import { message } from "ant-design-vue";
import { addThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog";
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data: ThinkOrder;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
const form = reactive<ThinkOrderRefundLog>({
int: undefined,
uid: undefined,
refundAmount: undefined,
sid: undefined,
oid: undefined,
status: 1,
type: 0
});
// 请求状态
const loading = ref(false);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
const save = async () => {
if (!form.refundAmount) return message.error("请输入退款金额");
loading.value = true;
await addThinkOrderRefundLog(form);
loading.value = false;
message.success("已提交");
updateVisible(false);
emit("done");
};
watch(
() => props.visible,
(visible) => {
if (visible) {
loading.value = false;
if (props.data) {
form.uid = props.data.uid;
form.oid = props.data.id;
form.sid = props.data.sid;
form.refundAmount = 0;
}
}
}
);
</script>
<style lang="less" scoped>
.order-card {
margin-bottom: 20px;
}
.ant-form-item {
margin-bottom: 5px;
}
.order-info {
display: flex;
.info {
padding-left: 5px;
display: flex;
flex-direction: column;
}
}
.tag-icon {
padding-right: 6px;
}
</style>
@@ -0,0 +1,166 @@
<!-- 搜索表单 -->
<template>
<div class="search">
<a-space class="flex items-center" :size="10" style="flex-wrap: wrap">
<span class="text-gray-400">付款状态</span>
<a-select v-model:value="where.payStatus" style="width: 150px" placeholder="付款状态筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">已付款</a-select-option>
<a-select-option :value="2">未付款</a-select-option>
</a-select>
<span class="text-gray-400">订单状态</span>
<a-select v-model:value="where.orderStatus" style="width: 150px" placeholder="订单状态筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">已完成</a-select-option>
<a-select-option :value="2">未使用</a-select-option>
<a-select-option :value="3">已取消</a-select-option>
<a-select-option :value="4">退款中</a-select-option>
<a-select-option :value="5">退款被拒</a-select-option>
<a-select-option :value="6">退款成功</a-select-option>
</a-select>
<span class="text-gray-400">付款方式</span>
<a-select v-model:value="where.payType" style="width: 150px" placeholder="付款方式筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">微信支付</a-select-option>
<a-select-option :value="2">余额支付</a-select-option>
<a-select-option :value="3">支付宝</a-select-option>
<a-select-option :value="4">现金</a-select-option>
<a-select-option :value="5">POS机</a-select-option>
<a-select-option :value="6">VIP月卡</a-select-option>
<a-select-option :value="7">VIP年卡</a-select-option>
<a-select-option :value="8">VIP次卡</a-select-option>
<a-select-option :value="9">IC月卡</a-select-option>
<a-select-option :value="10">IC年卡</a-select-option>
<a-select-option :value="11">IC次卡</a-select-option>
<a-select-option :value="12">免费</a-select-option>
<a-select-option :value="13">VIP充值卡</a-select-option>
<a-select-option :value="14">IC充值卡</a-select-option>
<a-select-option :value="15">积分支付</a-select-option>
<a-select-option :value="16">VIP季卡</a-select-option>
<a-select-option :value="17">IC季卡</a-select-option>
</a-select>
<span class="text-gray-400">开票状态</span>
<a-select v-model:value="where.isInvoice" style="width: 150px" placeholder="开票状态筛选" @change="search">
<a-select-option value="1">已开票</a-select-option>
<a-select-option :value="2">未开票</a-select-option>
<a-select-option :value="3">不能开票</a-select-option>
</a-select>
<ThinkSelectSite
:placeholder="`选择场馆`"
class="input-item"
v-model:value="where.siteName"
@done="chooseSiteId"
/>
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入订单号|编号|手机号"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
<a-button class="ele-btn-icon" :disabled="loading" @click="handleExport">
<template #icon>
<download-outlined />
</template>
<span>导出报表</span>
</a-button>
</a-space>
</div>
</template>
<script lang="ts" setup>
import useSearch from "@/utils/use-search";
import { ref, watch } from "vue";
import { ThinkOrderInfoParam } from "@/api/think/thinkOrderInfo/model";
import { utils, writeFile } from "xlsx";
import { message } from "ant-design-vue";
import { messageLoading, toDateString } from "ele-admin-pro";
import dayjs from "dayjs";
import { listThinkOrder, thinkOrderExport } from "@/api/think/thinkOrder";
import { ThinkOrder, ThinkOrderParam } from "@/api/think/thinkOrder/model";
import { ThinkSite } from "@/api/think/thinkSite/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: "search", where?: ThinkOrderInfoParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "advanced"): void;
}>();
// 表单数据
const { where, resetFields } = useSearch<ThinkOrderParam>({
sid: undefined,
siteName: undefined,
createTimeStart: undefined,
createTimeEnd: undefined,
timeStart: undefined,
timeEnd: undefined,
categoryId: undefined,
payStatus: undefined,
orderStatus: undefined,
payType: undefined,
isInvoice: undefined,
keywords: undefined
});
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(["", ""]);
const orders = ref<ThinkOrder[] | any[]>();
const xlsFileName = ref<string>();
/* 搜索 */
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
// where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
// where.createTimeEnd = d2 ? d2 + ' 00:00:00' : undefined;
emit("search", {
...where
});
};
const chooseSiteId = (data: ThinkSite) => {
where.sid = data.id;
where.siteName = data.name;
search();
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
const hide = messageLoading("导出中...", 0);
const res = await thinkOrderExport(where);
hide();
window.open(res.url);
};
watch(
() => props.selection,
() => {
}
);
</script>
@@ -0,0 +1,465 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑' : '添加'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="订单号" name="orderNum">
<a-input
allow-clear
placeholder="请输入订单号"
v-model:value="form.orderNum"
/>
</a-form-item>
<a-form-item label="微信支付订单号" name="wechatOrder">
<a-input
allow-clear
placeholder="请输入微信支付订单号"
v-model:value="form.wechatOrder"
/>
</a-form-item>
<a-form-item label="微信退款订单号" name="refundOrder">
<a-input
allow-clear
placeholder="请输入微信退款订单号"
v-model:value="form.refundOrder"
/>
</a-form-item>
<a-form-item label="场馆id用于权限判断" name="sid">
<a-input
allow-clear
placeholder="请输入场馆id用于权限判断"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="用户id" name="uid">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="使用的优惠券id" name="cid">
<a-input
allow-clear
placeholder="请输入使用的优惠券id"
v-model:value="form.cid"
/>
</a-form-item>
<a-form-item label="使用的会员卡id" name="vid">
<a-input
allow-clear
placeholder="请输入使用的会员卡id"
v-model:value="form.vid"
/>
</a-form-item>
<a-form-item label="关联管理员id" name="aid">
<a-input
allow-clear
placeholder="请输入关联管理员id"
v-model:value="form.aid"
/>
</a-form-item>
<a-form-item label="核销管理员id" name="adminId">
<a-input
allow-clear
placeholder="请输入核销管理员id"
v-model:value="form.adminId"
/>
</a-form-item>
<a-form-item label="IC卡号" name="code">
<a-input
allow-clear
placeholder="请输入IC卡号"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="真实姓名" name="name">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="订单总额" name="totalPrice">
<a-input
allow-clear
placeholder="请输入订单总额"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item
label="减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
name="reducePrice"
>
<a-input
allow-clear
placeholder="请输入减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
v-model:value="form.reducePrice"
/>
</a-form-item>
<a-form-item label="实际付款" name="payPrice">
<a-input
allow-clear
placeholder="请输入实际付款"
v-model:value="form.payPrice"
/>
</a-form-item>
<a-form-item label="用于统计" name="price">
<a-input
allow-clear
placeholder="请输入用于统计"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="价钱,用于积分赠送" name="money">
<a-input
allow-clear
placeholder="请输入价钱,用于积分赠送"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="退款金额" name="refundMoney">
<a-input
allow-clear
placeholder="请输入退款金额"
v-model:value="form.refundMoney"
/>
</a-form-item>
<a-form-item label="教练价格" name="coachPrice">
<a-input
allow-clear
placeholder="请输入教练价格"
v-model:value="form.coachPrice"
/>
</a-form-item>
<a-form-item label="教练id" name="coachId">
<a-input
allow-clear
placeholder="请输入教练id"
v-model:value="form.coachId"
/>
</a-form-item>
<a-form-item
label="1微信支付,2积分,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡"
name="payType"
>
<a-input
allow-clear
placeholder="请输入1微信支付,2积分,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="1已付款,2未付款" name="payStatus">
<a-input
allow-clear
placeholder="请输入1已付款,2未付款"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item
label="1已完成,2未使用,3已取消,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
name="orderStatus"
>
<a-input
allow-clear
placeholder="请输入1已完成,2未使用,3已取消,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item
label="优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
name="type"
>
<a-input
allow-clear
placeholder="请输入优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item
label="二维码地址,保存订单号,支付成功后才生成"
name="qrcode"
>
<a-input
allow-clear
placeholder="请输入二维码地址,保存订单号,支付成功后才生成"
v-model:value="form.qrcode"
/>
</a-form-item>
<a-form-item label="优惠说明" name="desc2">
<a-input
allow-clear
placeholder="请输入优惠说明"
v-model:value="form.desc2"
/>
</a-form-item>
<a-form-item label="vip月卡年卡、ic月卡年卡回退次数" name="returnNum">
<a-input
allow-clear
placeholder="请输入vip月卡年卡、ic月卡年卡回退次数"
v-model:value="form.returnNum"
/>
</a-form-item>
<a-form-item label="vip充值回退金额" name="returnMoney">
<a-input
allow-clear
placeholder="请输入vip充值回退金额"
v-model:value="form.returnMoney"
/>
</a-form-item>
<a-form-item label="预约详情开始时间数组" name="startTime">
<a-input
allow-clear
placeholder="请输入预约详情开始时间数组"
v-model:value="form.startTime"
/>
</a-form-item>
<a-form-item
label="是否已开具发票:1已开发票,2未开发票,3不能开具发票"
name="isInvoice"
>
<a-input
allow-clear
placeholder="请输入是否已开具发票:1已开发票,2未开发票,3不能开具发票"
v-model:value="form.isInvoice"
/>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="付款时间" name="payTime">
<a-input
allow-clear
placeholder="请输入付款时间"
v-model:value="form.payTime"
/>
</a-form-item>
<a-form-item label="退款时间" name="refundTime">
<a-input
allow-clear
placeholder="请输入退款时间"
v-model:value="form.refundTime"
/>
</a-form-item>
<a-form-item label="申请退款时间" name="refundApplyTime">
<a-input
allow-clear
placeholder="请输入申请退款时间"
v-model:value="form.refundApplyTime"
/>
</a-form-item>
<a-form-item
label="对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单"
name="checkBill"
>
<a-input
allow-clear
placeholder="请输入对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单"
v-model:value="form.checkBill"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkOrder, updateThinkOrder } from '@/api/think/thinkOrder';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkOrder>({
id: undefined,
orderNum: undefined,
wechatOrder: undefined,
refundOrder: undefined,
sid: undefined,
uid: undefined,
cid: undefined,
vid: undefined,
aid: undefined,
adminId: undefined,
code: undefined,
name: undefined,
phone: undefined,
totalPrice: undefined,
reducePrice: undefined,
payPrice: undefined,
price: undefined,
money: undefined,
refundMoney: undefined,
coachPrice: undefined,
coachId: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
type: undefined,
qrcode: undefined,
desc2: undefined,
returnNum: undefined,
returnMoney: undefined,
startTime: undefined,
isInvoice: undefined,
createTime: undefined,
updateTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkOrder : addThinkOrder;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if (props.data.image) {
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
});
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+412
View File
@@ -0,0 +1,412 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 800 }"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'dateTime'">
<div>{{ record.siteName }}</div>
<div>{{ record.dateTime }} ¥{{ record.totalPrice }}元</div>
</template>
<template v-if="column.key === 'payType'">
<template v-if="record.payStatus == 1">
<a-tag v-if="record.payType == 0">余额支付</a-tag>
<a-tag v-if="record.payType == 1">
<WechatOutlined class="tag-icon" />
微信支付
</a-tag>
<a-tag v-if="record.payType == 2">积分</a-tag>
<a-tag v-if="record.payType == 3">
<AlipayCircleOutlined class="tag-icon" />
支付宝
</a-tag>
<a-tag v-if="record.payType == 4">
<IdcardOutlined class="tag-icon" />
现金
</a-tag>
<a-tag v-if="record.payType == 5">
<IdcardOutlined class="tag-icon" />
POS机
</a-tag>
<a-tag v-if="record.payType == 6">
<IdcardOutlined class="tag-icon" />
VIP月卡
</a-tag>
<a-tag v-if="record.payType == 7">
<IdcardOutlined class="tag-icon" />
VIP年卡
</a-tag>
<a-tag v-if="record.payType == 8">
<IdcardOutlined class="tag-icon" />
VIP次卡
</a-tag>
<a-tag v-if="record.payType == 9">
<IdcardOutlined class="tag-icon" />
IC月卡
</a-tag>
<a-tag v-if="record.payType == 10">
<IdcardOutlined class="tag-icon" />
IC年卡
</a-tag>
<a-tag v-if="record.payType == 11">
<IdcardOutlined class="tag-icon" />
IC次卡
</a-tag>
<a-tag v-if="record.payType == 12">
<IdcardOutlined class="tag-icon" />
免费
</a-tag>
<a-tag v-if="record.payType == 13">
<IdcardOutlined class="tag-icon" />
VIP充值卡
</a-tag>
<a-tag v-if="record.payType == 14">
<IdcardOutlined class="tag-icon" />
IC充值卡
</a-tag>
<a-tag v-if="record.payType == 15">
<IdcardOutlined class="tag-icon" />
积分支付
</a-tag>
<a-tag v-if="record.payType == 16">
<IdcardOutlined class="tag-icon" />
VIP季卡
</a-tag>
<a-tag v-if="record.payType == 17">
<IdcardOutlined class="tag-icon" />
IC季卡
</a-tag>
</template>
<template v-else>
<span></span>
</template>
</template>
<template v-if="column.key === 'payStatus'">
<a-tag v-if="record.payStatus == 2" color="error">
<CloseOutlined class="tag-icon" />
未付款
</a-tag>
<a-tag v-if="record.payStatus == 1" color="green">
<CheckOutlined class="tag-icon" />
已付款
</a-tag>
<a-tag
v-if="record.payStatus == 3 || record.payStatus == 0"
color="cyan">
<CoffeeOutlined class="tag-icon" />
未付款,占场中
</a-tag>
</template>
<template v-if="column.key === 'orderInfo'">
{{ record.orderInfoList }}
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'code'">
<span v-if="record.card">{{ record.card.code }}</span>
<span v-if="record.thinkVip">{{ record.thinkVip.code }}</span>
</template>
<template v-if="column.key === 'expiredTime'">
<span v-if="record.card">{{ dayjs(record.card.expireTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}</span>
<span v-if="record.thinkVip">{{ dayjs(record.thinkVip.expireTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">详情</a>
<a-divider type="vertical" />
<a @click="openRefund(record)"
v-if="record.payStatus === 1 && [1, 3].includes(record.payType) && [1, 2].includes(record.orderStatus)">退款</a>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 开具发票 -->
<Invoice v-model:visible="showInvoice" :data="current" @done="reload" />
<Refund v-model:visible="showRefund" :data="refundOrder" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import {
ExclamationCircleOutlined,
CheckOutlined,
CloseOutlined,
AlipayCircleOutlined
} from "@ant-design/icons-vue";
import { EleProTable, toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import OrderInfo from "./components/orderInfo.vue";
import Invoice from "./components/invoice.vue";
import {
pageThinkOrder,
removeThinkOrder,
removeBatchThinkOrder
} from "@/api/think/thinkOrder";
import * as InvoiceApi from "@/api/think/thinkInvoice";
import type {
ThinkOrder,
ThinkOrderParam
} from "@/api/think/thinkOrder/model";
import { formatNumber } from "ele-admin-pro/es";
import type { ThinkInvoice } from "@/api/think/thinkInvoice/model";
import Refund from "@/views/think/thinkOrder/components/refund.vue";
import dayjs from "dayjs";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkOrder | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 开具发票弹窗
const showInvoice = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
return pageThinkOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "场馆名称",
dataIndex: "siteName",
key: "iod",
width: 90
},
{
title: "下单时间",
dataIndex: "createTime",
align: "center",
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
},
{
title: "单位",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "手机号",
dataIndex: "phone",
key: "phone",
width: 120,
align: "center"
},
{
title: "实际转账单位/个人",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "价格",
dataIndex: "totalPrice",
key: "totalPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "积分",
dataIndex: "totalPrice",
key: "totalPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "支付方式",
dataIndex: "payType",
key: "payType",
align: "center"
},
{
title: "预付卡号",
key: "code",
align: "center"
},
{
title: "预付卡到期时间",
key: "expiredTime",
align: "center",
sorter: true
}
]);
/* 搜索 */
const reload = (where?: ThinkOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
const showRefund = ref(false);
const refundOrder = ref<ThinkOrder>();
const openRefund = (row: ThinkOrder) => {
refundOrder.value = row;
showRefund.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkOrder) => {
const hide = message.loading("请求中..", 0);
removeThinkOrder(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkOrder(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 开具发票 */
const onInvoice = (row?: ThinkOrder) => {
console.log(row?.payStatus);
if (row?.payStatus != 1) {
return false;
}
current.value = row ?? null;
showInvoice.value = true;
};
const openInvoicePdf = (row?: ThinkInvoice) => {
if (row?.id) {
InvoiceApi.showInvoice(row?.id).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
window.open(pdfUrl);
});
}
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
import * as MenuIcons from "@/layout/menu-icons";
export default {
name: "ThinkOrder",
components: MenuIcons
};
</script>
<style lang="less" scoped>
.tag-icon {
padding-right: 6px;
}
</style>
+13 -126
View File
@@ -91,18 +91,14 @@
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import GoodsEdit from './components/goodsEdit.vue';
import {
pageGoods,
removeGoods,
removeBatchGoods,
updateGoods
} from '@/api/shop/goods';
import type { Goods, GoodsParam } from '@/api/shop/goods/model';
import { formatNumber } from 'ele-admin-pro/es';
import router from '@/router';
import { openSpmUrl, openUrl } from '@/utils/common';
import { getSiteDomain } from '@/utils/domain';
import { getMerchantId } from '@/utils/merchant';
import { pageThinkGoods, removeBatchThinkGoods, removeThinkGoods, updateThinkGoods } from "@/api/think/thinkGoods";
import dayjs from "dayjs";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
@@ -115,8 +111,6 @@
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 网站域名
const domain = getSiteDomain();
// 表格数据源
const datasource: DatasourceFunction = ({
@@ -130,7 +124,7 @@
where.status = filters.status;
}
where.merchantId = getMerchantId();
return pageGoods({
return pageThinkGoods({
...where,
...orders,
page,
@@ -141,7 +135,7 @@
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '22商品ID',
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
@@ -149,37 +143,9 @@
},
{
title: '商品名称',
dataIndex: 'goodsName',
key: 'goodsName',
dataIndex: 'title',
align: 'center'
},
{
title: '商品图片',
dataIndex: 'image',
key: 'image',
align: 'center'
},
{
title: '所属门店',
dataIndex: 'merchantName',
key: 'merchantName',
ellipsis: true,
align: 'center'
},
{
title: '商品编码',
dataIndex: 'code',
key: 'code',
align: 'center',
hideInTable: true
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
align: 'center',
hideInTable: true
},
{
title: '分类ID',
dataIndex: 'categoryId',
@@ -187,38 +153,9 @@
align: 'center',
hideInTable: true
},
{
title: '一级分类',
dataIndex: 'categoryParent',
key: 'categoryParent',
align: 'center',
hideInTable: true
},
{
title: '二级分类',
dataIndex: 'categoryChildren',
key: 'categoryChildren',
align: 'center',
hideInTable: true
},
{
title: '多规格',
dataIndex: 'specs',
key: 'specs',
align: 'center',
hideInTable: true
},
{
title: '货架',
dataIndex: 'position',
key: 'position',
align: 'center',
hideInTable: true
},
{
title: '商品价格',
dataIndex: 'salePrice',
key: 'salePrice',
dataIndex: 'linePrice',
sorter: true,
align: 'center'
},
@@ -229,60 +166,9 @@
align: 'center',
hideInTable: true
},
{
title: '库存计算方式',
dataIndex: 'deductStockType',
key: 'deductStockType',
align: 'center',
hideInTable: true
},
{
title: '销量',
dataIndex: 'sales',
key: 'sales',
sorter: true,
align: 'center'
},
{
title: '库存',
dataIndex: 'stock',
key: 'stock',
sorter: true,
align: 'center'
},
{
title: '商品重量',
dataIndex: 'goodsWeight',
key: 'goodsWeight',
align: 'center',
hideInTable: true
},
{
title: '推荐',
dataIndex: 'recommend',
key: 'recommend',
sorter: true,
align: 'center',
hideInTable: true
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
hideInTable: true
},
{
title: '状态',
dataIndex: 'isShow',
key: 'isShow',
sorter: true,
align: 'center'
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
dataIndex: 'sort',
sorter: true,
align: 'center',
hideInTable: true
@@ -293,7 +179,8 @@
key: 'createTime',
align: 'center',
width: 120,
sorter: true
sorter: true,
customRender: ({text}) => dayjs(text * 1000).format('YYYY-MM-DD HH:mm')
},
{
title: '操作',
@@ -324,7 +211,7 @@
const onUpdate = (row?: Goods) => {
const isShow = row?.isShow == 0 ? 1 : 0;
updateGoods({ ...row, isShow }).then((msg) => {
updateThinkGoods({ ...row, isShow }).then((msg) => {
message.success(msg);
reload();
});
@@ -333,7 +220,7 @@
/* 删除单个 */
const remove = (row: Goods) => {
const hide = message.loading('请求中..', 0);
removeGoods(row.goodsId)
removeThinkGoods(row.goodsId)
.then((msg) => {
hide();
message.success(msg);
@@ -358,7 +245,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchGoods(selection.value.map((d) => d.goodsId))
removeBatchThinkGoods(selection.value.map((d) => d.goodsId))
.then((msg) => {
hide();
message.success(msg);
@@ -1,173 +0,0 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="600"
:visible="visible"
:maskClosable="false"
:title="isUpdate ? '发货' : '发货'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="物流公司" name="expressName">
<SelectExpress
:placeholder="`选择物流公司`"
v-model:value="form.expressName"
@done="chooseExpressId"
/>
</a-form-item>
<a-form-item label="快递单号" name="expressNo">
<a-input
allow-clear
placeholder="快递单号"
v-model:value="form.expressNo"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { Order } from '@/api/shop/order/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { OrderDelivery } from '@/api/shop/orderDelivery/model';
import { Express } from '@/api/shop/express/model';
import {
addOrderDelivery,
updateOrderDelivery
} from '@/api/shop/orderDelivery';
import { FormInstance } from 'ant-design-vue/es/form';
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: Order | null;
}>();
export interface step {
title?: String | undefined;
subTitle?: String | undefined;
description?: String | undefined;
}
// 是否是修改
const isUpdate = ref(false);
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 表单验证规则
const rules = reactive({
expressName: [
{
required: true,
type: 'string',
message: '请选择物流公司',
trigger: 'blur'
}
],
expressNo: [
{
required: true,
type: 'string',
message: '请填写快递单号',
trigger: 'blur'
}
]
});
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 订单信息
const form = reactive<OrderDelivery>({
deliveryId: undefined,
orderId: undefined,
deliveryMethod: undefined,
packMethod: undefined,
expressId: undefined,
expressName: undefined,
expressNo: undefined,
eorderHtml: undefined,
sortNumber: undefined,
tenantId: undefined
});
// 请求状态
const loading = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const { resetFields } = useForm(form, rules);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const chooseExpressId = (data: Express) => {
form.expressName = data.expressName;
form.expressId = data.expressId;
};
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value
? updateOrderDelivery
: addOrderDelivery;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
loading.value = true;
assignObject(form, props.data);
}
} else {
resetFields();
}
}
);
</script>
+1 -3
View File
@@ -219,7 +219,7 @@
<!-- 编辑弹窗 -->
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 发货弹窗 -->
<Delivery v-model:visible="showDelivery" :data="current" @done="reload" />
<!-- <Delivery v-model:visible="showDelivery" :data="current" @done="reload" />-->
</div>
</div>
</template>
@@ -232,7 +232,6 @@
CheckOutlined,
CloseOutlined,
AlipayCircleOutlined,
EllipsisOutlined,
DownOutlined
} from '@ant-design/icons-vue';
@@ -243,7 +242,6 @@
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import OrderInfo from './components/orderInfo.vue';
import Delivery from './components/delivery.vue';
import { pageOrder, removeOrder, removeBatchOrder } from '@/api/shop/order';
import type { Order, OrderParam } from '@/api/shop/order/model';
import { formatNumber } from 'ele-admin-pro/es';
@@ -0,0 +1,254 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
title="生成IC卡"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="生成数量" name="makeNum">
<a-input-number
:min="1"
style="width: 300px;"
allow-clear
placeholder="请输入生成数量"
v-model:value="form.makeNum"
/>
</a-form-item>
<a-form-item label="绑定用户">
<a-space v-if="form.phone">
<p>{{ form.username }}/{{ form.phone }}</p>
<a-button type="link" @click="clearBindCard">取消绑定</a-button>
</a-space>
<ThinkSelectUsers @done="changeBindCard" />
</a-form-item>
<a-form-item label="选择VIP卡" name="vid">
<a-select v-model:value="form.vid" show-search optionFilterProp="label">
<a-select-option v-for="(item, index) in vipList" :key="index" :value="item.id" :label="item.name">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="到期时间" name="expireTime">
<a-date-picker
placeholder="请选择到期时间"
value-format="YYYY-MM-DD"
v-model:value="expireTime"
/>
</a-form-item>
<a-form-item label="凭证" name="expireTime">
<SelectFile
:placeholder="`请选择凭证`"
:limit="1"
:data="photo"
@done="chooseFile"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="备注" name="remark">
<a-input
allow-clear
placeholder="请输入备注"
v-model:value="form.remark"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from "vue";
import { Form, message } from "ant-design-vue";
import { assignObject } from "ele-admin-pro";
import { makeThinkCard } from "@/api/think/thinkCard";
import { ThinkCard } from "@/api/think/thinkCard/model";
import { useThemeStore } from "@/store/modules/theme";
import { storeToRefs } from "pinia";
import { FormInstance } from "ant-design-vue/es/form";
import { ThinkVip } from "@/api/think/thinkVip/model";
import { listThinkVip } from "@/api/think/thinkVip";
import { FileRecord } from "@/api/system/file/model";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import dayjs from "dayjs";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkCard | null;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 用户信息
const form = reactive<ThinkCard>({
id: undefined,
sid: undefined,
makeNum: undefined,
uid: 0,
vid: undefined,
aid: undefined,
wechatOrder: undefined,
code: undefined,
name: undefined,
username: "",
phone: "",
price: undefined,
desc: undefined,
info: undefined,
discount: undefined,
count: undefined,
eachMoney: undefined,
remainingMoney: undefined,
number: undefined,
num: undefined,
status: undefined,
term: undefined,
month: undefined,
type: undefined,
cardType: undefined,
vipType: undefined,
pic: undefined,
prices: undefined,
payType: undefined,
isIntegral: undefined,
isInvoice: undefined,
expireTime: undefined,
urgentName: undefined,
urgentPhone: undefined,
cardNum: undefined,
password: undefined,
useTime: undefined,
createTime: undefined,
updateTime: undefined,
remark: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
const expireTime = ref<String>("");
// 表单验证规则
const rules = reactive({
vid: [
{ required: true, message: "请选择VIP卡", trigger: "blur" }
],
makeNum: [
{ required: true, message: "请输入生成数量", trigger: "blur" }
]
});
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
if (!expireTime.value) {
return message.error("请选择到期时间");
}
formData.expireTime = dayjs(expireTime.value).unix()
makeThinkCard(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit("done");
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
};
const photo = ref<ItemType[]>([]);
const chooseFile = (data: FileRecord) => {
photo.value.push({
uid: data.id,
url: data.downloadUrl,
status: 'done'
});
form.pic = data.downloadUrl;
};
const onDeleteItem = (index: number) => {
photo.value.splice(index, 1);
form.pic = '';
};
const changeBindCard = (data: any) => {
form.uid = data.id;
form.username = data.username;
form.phone = data.phone;
};
const clearBindCard = () => {
form.uid = 0;
form.username = "";
form.phone = "";
};
const vipList = ref<ThinkVip[]>([]);
const getVipList = async () => {
vipList.value = await listThinkVip();
};
watch(
() => props.visible,
async (visible) => {
if (visible) {
await getVipList();
if (props.data) {
assignObject(form, props.data);
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -22,11 +22,11 @@
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
<a-button @click="makeCard" type="primary">生成IC卡</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import { watch, ref } from 'vue';
import useSearch from '@/utils/use-search';
import dayjs from 'dayjs';
@@ -52,6 +52,7 @@
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
(e: 'makeCard'): void;
}>();
// 请求状态
@@ -77,8 +78,8 @@
});
// 新增
const add = () => {
emit('add');
const makeCard = () => {
emit('makeCard');
};
const search = () => {
+458 -442
View File
@@ -8,6 +8,7 @@
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:selection="selection"
:scroll="{ x: 3800 }"
tool-class="ele-toolbar-form"
class="sys-org-table"
@@ -19,6 +20,7 @@
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
@makeCard="openMakeCard"
/>
</template>
<template #bodyCell="{ column, record }">
@@ -43,8 +45,8 @@
</a-popconfirm>
</a-space>
</template>
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
<template v-if="column.key === 'sid'">
<span>{{ record.siteList.map(item => item.name).join() }}</span>
</template>
<template v-if="column.key === 'type'">
<a-tag>{{ types[record.type] }}</a-tag>
@@ -88,463 +90,477 @@
:data="current"
@done="reload"
/>
<MakeICCard v-model:visible="showMakeCard" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkCardEdit from './components/thinkCardEdit.vue';
import {
pageThinkCard,
removeThinkCard,
removeBatchThinkCard,
updateThinkCard
} from '@/api/think/thinkCard';
import type { ThinkCard, ThinkCardParam } from '@/api/think/thinkCard/model';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import { toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkCardEdit from "./components/thinkCardEdit.vue";
import {
pageThinkCard,
removeThinkCard,
removeBatchThinkCard,
updateThinkCard
} from "@/api/think/thinkCard";
import type { ThinkCard, ThinkCardParam } from "@/api/think/thinkCard/model";
import MakeICCard from "@/views/think/thinkCard/components/makeICCard.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCard[]>([]);
// 当前编辑数据
const current = ref<ThinkCard | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
const types = ref<string[]>([
'',
'年卡',
'次卡',
'月卡',
'会员IC卡',
'充值卡'
]);
const payTypes = ref<string[]>([
'',
'微信支付',
'支付宝支付',
'现金',
'POS机刷卡',
'平安健康卡'
]);
const isIntegral = ref<string[]>(['', '赠送', '不赠送']);
// 表格选中数据
const selection = ref<ThinkCard[]>([]);
// 当前编辑数据
const current = ref<ThinkCard | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
const types = ref<string[]>([
"",
"年卡",
"次卡",
"月卡",
"会员IC卡",
"充值卡"
]);
const payTypes = ref<string[]>([
"",
"微信支付",
"支付宝支付",
"现金",
"POS机刷卡",
"平安健康卡"
]);
const isIntegral = ref<string[]>(["", "赠送", "不赠送"]);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkCard({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "姓名",
dataIndex: "username",
key: "username",
align: "center",
fixed: "left",
width: 280
},
{
title: "卡号",
dataIndex: "code",
key: "code",
align: "center",
fixed: "left",
width: 140
},
{
title: "手机号",
dataIndex: "phone",
key: "phone",
align: "center",
fixed: "left",
width: 140
},
{
title: "会员卡名称",
dataIndex: "name",
key: "name",
align: "center",
width: 140,
fixed: "left"
},
{
title: "IC卡数字",
dataIndex: "cardNum",
key: "cardNum",
width: 140,
align: "center"
},
{
title: "紧急联系人",
dataIndex: "urgentName",
key: "urgentName",
width: 140,
align: "center"
},
{
title: "紧急联系人号码",
dataIndex: "urgentPhone",
key: "urgentPhone",
width: 140,
align: "center"
},
{
title: "可用场馆",
dataIndex: "sid",
key: "sid",
width: 140,
align: "center"
},
{
title: "vip购卡价格",
dataIndex: "price",
key: "price",
width: 140,
sorter: true,
align: "center"
},
{
title: "vip卡折扣率",
dataIndex: "discount",
key: "discount",
width: 140,
sorter: true,
align: "center"
},
{
title: "使用次数",
dataIndex: "count",
key: "count",
width: 140,
sorter: true,
align: "center"
},
{
title: "剩余次数",
dataIndex: "num",
key: "num",
width: 140,
sorter: true,
align: "center"
},
{
title: "每使用一次减少的金额",
dataIndex: "eachMoney",
key: "eachMoney",
width: 140,
sorter: true,
align: "center"
},
{
title: "剩余金额",
dataIndex: "remainingMoney",
key: "remainingMoney",
width: 140,
sorter: true,
align: "center"
},
{
title: "月限",
dataIndex: "month",
key: "month",
width: 140,
align: "center"
},
{
title: "年限",
dataIndex: "term",
key: "term",
width: 140,
align: "center"
},
{
title: "IC卡类型",
dataIndex: "type",
key: "type",
width: 140,
align: "center"
},
{
title: "到期时间",
dataIndex: "expireTime",
key: "expireTime",
width: 140,
sorter: true,
align: "center"
},
{
title: "支付状态",
dataIndex: "status",
key: "status",
width: 140,
sorter: true,
align: "center"
},
{
title: "付款方式",
dataIndex: "payType",
key: "payType",
width: 140,
align: "center"
},
{
title: "是否赠送积分",
dataIndex: "isIntegral",
key: "isIntegral",
width: 140,
sorter: true,
align: "center"
},
{
title: "是否已开具发票",
dataIndex: "isInvoice",
key: "isInvoice",
width: 140,
sorter: true,
align: "center"
},
{
title: "购卡时间",
dataIndex: "createTime",
key: "createTime",
align: "center",
sorter: true,
ellipsis: true,
width: 180,
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
}
// {
// title: '微信订单号',
// dataIndex: 'wechatOrder',
// key: 'wechatOrder',
// align: 'center'
// },
// {
// title: '手机号码',
// dataIndex: 'phone',
// key: 'phone',
// align: 'center',
// },
// {
// title: '会员卡介绍',
// dataIndex: 'desc',
// key: 'desc',
// align: 'center',
// },
// {
// title: '会员卡说明',
// dataIndex: 'info',
// key: 'info',
// align: 'center',
// },
// {
// title: '续费累加次数',
// dataIndex: 'number',
// key: 'number',
// align: 'center',
// },
// {
// title: '付款状态,1已付款,2未付款',
// dataIndex: 'status',
// key: 'status',
// align: 'center',
// },
// {
// title: '卡类型:1成人卡,2儿童卡',
// dataIndex: 'cardType',
// key: 'cardType',
// align: 'center',
// },
// {
// title: 'vip卡等级类型:1特殊vip卡,2普通vip卡',
// dataIndex: 'vipType',
// key: 'vipType',
// align: 'center',
// },
// {
// title: '特殊卡开发凭证图',
// dataIndex: 'pic',
// key: 'pic',
// align: 'center',
// },
// {
// title: '价格组',
// dataIndex: 'prices',
// key: 'prices',
// align: 'center',
// },
// {
// title: '卡号',
// dataIndex: 'cardNum',
// key: 'cardNum',
// align: 'center'
// }
// {
// title: '密码',
// dataIndex: 'password',
// key: 'password',
// align: 'center',
// },
// {
// title: '使用时间',
// dataIndex: 'useTime',
// key: 'useTime',
// align: 'center',
// },
// {
// title: '',
// dataIndex: 'updateTime',
// key: 'updateTime',
// align: 'center',
// },
// {
// title: '身份证号码',
// dataIndex: 'idcard',
// key: 'idcard',
// align: 'center',
// },
// {
// title: '备注',
// dataIndex: 'remark',
// key: 'remark',
// align: 'center',
// },
// {
// title: '操作',
// key: 'action',
// width: 180,
// fixed: 'right',
// align: 'center',
// hideInSetting: true
// }
]);
/* 搜索 */
const reload = (where?: ThinkCardParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCard) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
const showMakeCard = ref(false);
const openMakeCard = () => {
showMakeCard.value = true;
};
const unBindCard = (row: ThinkCard) => {
updateThinkCard({ id: row.id, uid: 0, username: "", phone: "" }).then(() => {
message.success("操作成功");
reload();
});
};
const changeBindCard = (row: any, id: number) => {
// console.log(row, id);
updateThinkCard({
id, uid: row.id,
username: row.truename ?? row.phone,
phone: row.phone
}).then(() => {
message.success("操作成功");
reload();
});
};
/* 删除单个 */
const remove = (row: ThinkCard) => {
const hide = message.loading("请求中..", 0);
removeThinkCard(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkCard(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
return pageThinkCard({
...where,
...orders,
page,
limit
});
};
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '姓名',
dataIndex: 'username',
key: 'username',
align: 'center',
fixed: 'left',
width: 280
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCard) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
{
title: '卡号',
dataIndex: 'code',
key: 'code',
align: 'center',
fixed: 'left',
width: 140
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
fixed: 'left',
width: 140
},
{
title: '会员卡名称',
dataIndex: 'name',
key: 'name',
align: 'center',
width: 140,
fixed: 'left'
},
{
title: 'IC卡数字',
dataIndex: 'cardNum',
key: 'cardNum',
width: 140,
align: 'center'
},
{
title: '紧急联系人',
dataIndex: 'urgentName',
key: 'urgentName',
width: 140,
align: 'center'
},
{
title: '紧急联系人号码',
dataIndex: 'urgentPhone',
key: 'urgentPhone',
width: 140,
align: 'center'
},
{
title: '可用场馆',
dataIndex: 'sid',
key: 'sid',
width: 140,
align: 'center'
},
{
title: 'vip购卡价格',
dataIndex: 'price',
key: 'price',
width: 140,
sorter: true,
align: 'center'
},
{
title: 'vip卡折扣率',
dataIndex: 'discount',
key: 'discount',
width: 140,
sorter: true,
align: 'center'
},
{
title: '使用次数',
dataIndex: 'count',
key: 'count',
width: 140,
sorter: true,
align: 'center'
},
{
title: '剩余次数',
dataIndex: 'num',
key: 'num',
width: 140,
sorter: true,
align: 'center'
},
{
title: '每使用一次减少的金额',
dataIndex: 'eachMoney',
key: 'eachMoney',
width: 140,
sorter: true,
align: 'center'
},
{
title: '剩余金额',
dataIndex: 'remainingMoney',
key: 'remainingMoney',
width: 140,
sorter: true,
align: 'center'
},
{
title: '月限',
dataIndex: 'month',
key: 'month',
width: 140,
align: 'center'
},
{
title: '年限',
dataIndex: 'term',
key: 'term',
width: 140,
align: 'center'
},
{
title: 'IC卡类型',
dataIndex: 'type',
key: 'type',
width: 140,
align: 'center'
},
{
title: '到期时间',
dataIndex: 'expireTime',
key: 'expireTime',
width: 140,
sorter: true,
align: 'center'
},
{
title: '支付状态',
dataIndex: 'status',
key: 'status',
width: 140,
sorter: true,
align: 'center'
},
{
title: '付款方式',
dataIndex: 'payType',
key: 'payType',
width: 140,
align: 'center'
},
{
title: '是否赠送积分',
dataIndex: 'isIntegral',
key: 'isIntegral',
width: 140,
sorter: true,
align: 'center'
},
{
title: '是否已开具发票',
dataIndex: 'isInvoice',
key: 'isInvoice',
width: 140,
sorter: true,
align: 'center'
},
{
title: '购卡时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
width: 180,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
// 行双击事件
onDblclick: () => {
openEdit(record);
}
// {
// title: '微信订单号',
// dataIndex: 'wechatOrder',
// key: 'wechatOrder',
// align: 'center'
// },
// {
// title: '手机号码',
// dataIndex: 'phone',
// key: 'phone',
// align: 'center',
// },
// {
// title: '会员卡介绍',
// dataIndex: 'desc',
// key: 'desc',
// align: 'center',
// },
// {
// title: '会员卡说明',
// dataIndex: 'info',
// key: 'info',
// align: 'center',
// },
// {
// title: '续费累加次数',
// dataIndex: 'number',
// key: 'number',
// align: 'center',
// },
// {
// title: '付款状态,1已付款,2未付款',
// dataIndex: 'status',
// key: 'status',
// align: 'center',
// },
// {
// title: '卡类型:1成人卡,2儿童卡',
// dataIndex: 'cardType',
// key: 'cardType',
// align: 'center',
// },
// {
// title: 'vip卡等级类型:1特殊vip卡,2普通vip卡',
// dataIndex: 'vipType',
// key: 'vipType',
// align: 'center',
// },
// {
// title: '特殊卡开发凭证图',
// dataIndex: 'pic',
// key: 'pic',
// align: 'center',
// },
// {
// title: '价格组',
// dataIndex: 'prices',
// key: 'prices',
// align: 'center',
// },
// {
// title: '卡号',
// dataIndex: 'cardNum',
// key: 'cardNum',
// align: 'center'
// }
// {
// title: '密码',
// dataIndex: 'password',
// key: 'password',
// align: 'center',
// },
// {
// title: '使用时间',
// dataIndex: 'useTime',
// key: 'useTime',
// align: 'center',
// },
// {
// title: '',
// dataIndex: 'updateTime',
// key: 'updateTime',
// align: 'center',
// },
// {
// title: '身份证号码',
// dataIndex: 'idcard',
// key: 'idcard',
// align: 'center',
// },
// {
// title: '备注',
// dataIndex: 'remark',
// key: 'remark',
// align: 'center',
// },
// {
// title: '操作',
// key: 'action',
// width: 180,
// fixed: 'right',
// align: 'center',
// hideInSetting: true
// }
]);
/* 搜索 */
const reload = (where?: ThinkCardParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCard) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
const unBindCard = (row: ThinkCard) => {
updateThinkCard({ id: row.id, uid: 0 }).then((res) => {
message.success('操作成功');
});
};
const changeBindCard = (row: any, id: number) => {
console.log(row, id);
updateThinkCard({ id, uid: row.id }).then((res) => {
message.success('操作成功');
});
};
/* 删除单个 */
const remove = (row: ThinkCard) => {
const hide = message.loading('请求中..', 0);
removeThinkCard(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkCard(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCard) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCard'
};
export default {
name: "ThinkCard"
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,54 @@
<!-- 搜索表单 -->
<template>
<div>
<a-space :size="10" style="flex-wrap: wrap">
<a-range-picker
allow-clear
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
</a-space>
<p class="ele-text-danger font-bold mt-2">总金额:{{ totalAmount }}元</p>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import { ThinkCardsBillsParam } from "@/api/think/thinkCardsBills/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
totalAmount?: number;
}>(),
{}
);
const dateRange = ref<[string, string] | null>();
const emit = defineEmits<{
(e: "search", where?: ThinkCardsBillsParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "batchMove"): void;
}>();
const search = () => {
let dateStart: string = "", dateEnd: string = "";
if (dateRange.value && dateRange.value?.length > 0 && dateRange.value[0]) {
[dateStart, dateEnd] = dateRange.value;
}
emit("search", {
dateStart,
dateEnd
});
};
watch(
() => props.selection,
() => {
}
);
</script>
@@ -0,0 +1,217 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑Vip卡每日账单' : '添加Vip卡每日账单'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="" name="uid">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="" name="cid">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.cid"
/>
</a-form-item>
<a-form-item label="" name="date">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.date"
/>
</a-form-item>
<a-form-item label="" name="amount">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.amount"
/>
</a-form-item>
<a-form-item label="状态, 0已发布, 1待审核 2已驳回 3违规内容" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkCardsBills, updateThinkCardsBills } from '@/api/think/thinkCardsBills';
import { ThinkCardsBills } from '@/api/think/thinkCardsBills/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkCardsBills | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkCardsBills>({
id: undefined,
uid: undefined,
cid: undefined,
date: undefined,
amount: undefined,
tenantId: undefined,
status: undefined,
deleted: undefined,
createTime: undefined,
updateTime: undefined,
thinkCardsBillsId: undefined,
thinkCardsBillsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardsBillsName: [
{
required: true,
type: 'string',
message: '请填写Vip卡每日账单名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkCardsBills : addThinkCardsBills;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+222
View File
@@ -0,0 +1,222 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCardsBillsId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
:totalAmount="totalAmount"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'user'">
<template v-if="record.user">
<p>{{ record.user.username }}</p>
<p>{{ record.user.phone }}</p>
</template>
<p v-else>散客</p>
</template>
<template v-if="column.key === 'used'">
<a-tag v-if="record.used === 1" color="green">已使用</a-tag>
<a-tag v-if="record.used === 0" color="red">未使用</a-tag>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ThinkCardsBillsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkCardsBillsEdit from "./components/thinkCardsBillsEdit.vue";
import {
pageThinkCardsBills,
removeThinkCardsBills,
removeBatchThinkCardsBills,
thinkCardsBillsTotalAmount
} from "@/api/think/thinkCardsBills";
import type { ThinkCardsBills, ThinkCardsBillsParam } from "@/api/think/thinkCardsBills/model";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardsBills[]>([]);
// 当前编辑数据
const current = ref<ThinkCardsBills | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
getTotalAmount(where);
return pageThinkCardsBills({
...where,
...orders,
page,
limit
});
};
const totalAmount = ref();
const getTotalAmount = async (where) => {
totalAmount.value = await thinkCardsBillsTotalAmount(where);
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "用户",
key: "user",
align: "center"
},
{
title: "VIP卡",
dataIndex: ["vip", "name"],
key: "vid",
align: "center"
},
{
title: "日期",
dataIndex: "date",
key: "date",
align: "center"
},
{
title: "金额",
dataIndex: "amount",
key: "amount",
align: "center"
},
{
title: "是否使用",
key: "used",
align: "center"
}
]);
/* 搜索 */
const reload = (where?: ThinkCardsBillsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardsBills) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardsBills) => {
const hide = message.loading("请求中..", 0);
removeThinkCardsBills(row.thinkCardsBillsId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkCardsBills(selection.value.map((d) => d.thinkCardsBillsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardsBills) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: "ThinkCardsBills"
};
</script>
<style lang="less" scoped></style>
@@ -1,12 +1,12 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
<!-- <template #icon>-->
<!-- <PlusOutlined />-->
<!-- </template>-->
<!-- <span>添加</span>-->
<!-- </a-button>-->
</a-space>
</template>
+203 -214
View File
@@ -24,19 +24,15 @@
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
<!-- <a @click="openEdit(record)">修改</a>-->
<!-- <a-divider type="vertical" />-->
<a-popconfirm v-if="record.status === 1"
title="确定退款吗?"
@confirm="refund(record)"
>
<a class="ele-text-danger">删除</a>
<a class="ele-text-danger">退款</a>
</a-popconfirm>
</a-space>
</template>
@@ -51,225 +47,218 @@
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkDepositEdit from './components/thinkDepositEdit.vue';
import { pageThinkDeposit, removeThinkDeposit, removeBatchThinkDeposit } from '@/api/think/thinkDeposit';
import type { ThinkDeposit, ThinkDepositParam } from '@/api/think/thinkDeposit/model';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import { toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkDepositEdit from "./components/thinkDepositEdit.vue";
import {
pageThinkDeposit,
removeThinkDeposit,
removeBatchThinkDeposit,
updateThinkDeposit
} from "@/api/think/thinkDeposit";
import type { ThinkDeposit, ThinkDepositParam } from "@/api/think/thinkDeposit/model";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkDeposit[]>([]);
// 当前编辑数据
const current = ref<ThinkDeposit | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格选中数据
const selection = ref<ThinkDeposit[]>([]);
// 当前编辑数据
const current = ref<ThinkDeposit | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
return pageThinkDeposit({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkDeposit({
...where,
...orders,
page,
limit
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "ID",
dataIndex: "id",
key: "id",
align: "center",
width: 90
},
{
title: "支付方式",
dataIndex: "moneyType",
key: "moneyType",
align: "center",
customRender: ({ text }) => ["", "微信支付", "支付宝支付", "现金支付", "POS机支付"][text]
},
{
title: "场馆名称",
dataIndex: "siteName",
key: "siteName",
align: "center"
},
{
title: "姓名",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "手机号码",
dataIndex: "phone",
key: "phone",
align: "center"
},
{
title: "押金",
dataIndex: "money",
key: "money",
align: "center"
},
{
title: "状态",
dataIndex: "status",
key: "status",
align: "center",
customRender: ({ text }) => ["未支付", "已支付", "已退款"][text]
},
{
title: "下单时间",
dataIndex: "createTime",
key: "createTime",
align: "center",
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd")
},
{
title: "操作",
key: "action",
width: 180,
fixed: "right",
align: "center",
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkDepositParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkDeposit) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkDeposit) => {
const hide = message.loading("请求中..", 0);
removeThinkDeposit(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '1收押金、2退押金',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '1微信支付,2支付宝支付,3现金支付,4POS机支付',
dataIndex: 'moneyType',
key: 'moneyType',
align: 'center',
},
{
title: '场馆名称',
dataIndex: 'siteName',
key: 'siteName',
align: 'center',
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '押金',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '1已付,2已退',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '',
dataIndex: 'info',
key: 'info',
align: 'center',
},
{
title: '管理员id',
dataIndex: 'aid',
key: 'aid',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkDeposit(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
]);
});
};
/* 搜索 */
const reload = (where?: ThinkDepositParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
const refund = async (row: ThinkDeposit) => {
await updateThinkDeposit({
id: row.id,
status: 2
});
message.success("退款成功");
reload()
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkDeposit) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkDeposit) => {
const hide = message.loading('请求中..', 0);
removeThinkDeposit(row.thinkDepositId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
/* 自定义行属性 */
const customRow = (record: ThinkDeposit) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkDeposit(selection.value.map((d) => d.thinkDepositId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkDeposit) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkDeposit'
};
export default {
name: "ThinkDeposit"
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,167 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑押金物品' : '添加押金物品'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="名称" name="title">
<a-input
allow-clear
placeholder="请输入名称"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="金额" name="amount">
<a-input-number style="width: 300px"
allow-clear
placeholder="请输入金额"
v-model:value="form.amount"
/>
</a-form-item>
<a-form-item label="所属场馆" name="siteName">
<ThinkSelectSite
:placeholder="`选择场馆`"
class="input-item"
v-model:value="form.siteName"
@done="chooseSite"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from "vue";
import { Form, message } from "ant-design-vue";
import { assignObject, uuid } from "ele-admin-pro";
import { addThinkDepositItem, updateThinkDepositItem } from "@/api/think/thinkDepositItem";
import { ThinkDepositItem } from "@/api/think/thinkDepositItem/model";
import { useThemeStore } from "@/store/modules/theme";
import { storeToRefs } from "pinia";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { FormInstance } from "ant-design-vue/es/form";
import { ThinkSite } from "@/api/think/thinkSite/model";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkDepositItem | null;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkDepositItem>({
id: undefined,
title: undefined,
amount: undefined,
siteName: undefined,
siteId: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
// 表单验证规则
const rules = reactive({
title: [
{ required: true, message: "请输入名称", trigger: "blur" }
],
amount: [
{ required: true, message: "请输入金额", trigger: "blur" }
],
siteName: [
{ required: true, message: "请选择场馆", trigger: "blur" }
]
});
const chooseSite = (data: ThinkSite) => {
form.siteId = data.id;
form.siteName = data.name;
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkDepositItem : addThinkDepositItem;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit("done");
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+217
View File
@@ -0,0 +1,217 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkDepositItemId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ThinkDepositItemEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkDepositItemEdit from './components/thinkDepositItemEdit.vue';
import { pageThinkDepositItem, removeThinkDepositItem, removeBatchThinkDepositItem } from '@/api/think/thinkDepositItem';
import type { ThinkDepositItem, ThinkDepositItemParam } from '@/api/think/thinkDepositItem/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkDepositItem[]>([]);
// 当前编辑数据
const current = ref<ThinkDepositItem | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkDepositItem({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '名称',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '金额',
dataIndex: 'amount',
key: 'amount',
align: 'center',
},
{
title: '场馆',
dataIndex: 'siteName',
key: 'siteName',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkDepositItemParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkDepositItem) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkDepositItem) => {
const hide = message.loading('请求中..', 0);
removeThinkDepositItem(row.thinkDepositItemId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkDepositItem(selection.value.map((d) => d.thinkDepositItemId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkDepositItem) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkDepositItem'
};
</script>
<style lang="less" scoped></style>
@@ -7,36 +7,67 @@
</template>
<span>添加</span>
</a-button>
<a-input v-model:value="keywords" placeholder="关键字搜索" @change="search" allow-clear></a-input>
<a-select v-model:value="cid" @change="search" allow-clear style="width: 200px;" placeholder="分类筛选">
<a-select-option v-for="item in categoryList" :key="item.id">{{
item.catname
}}
</a-select-option>
</a-select>
<a-select v-model:value="status" @change="search" allow-clear style="width: 200px;" placeholder="状态筛选">
<a-select-option :value="1">上架</a-select-option>
<a-select-option :value="2">下架</a-select-option>
</a-select>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
import { PlusOutlined } from "@ant-design/icons-vue";
import { ref, watch } from "vue";
import { ThinkGoodsParam } from "@/api/think/thinkGoods/model";
import { ThinkGoodsCategory } from "@/api/think/thinkGoodsCategory/model";
import { listThinkGoodsCategory } from "@/api/think/thinkGoodsCategory";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
const emit = defineEmits<{
(e: "search", where?: ThinkGoodsParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "batchMove"): void;
}>();
// 新增
const add = () => {
emit('add');
};
// 新增
const add = () => {
emit("add");
};
watch(
() => props.selection,
() => {}
);
const keywords = ref("");
const cid = ref<number>();
const status = ref<number>();
const search = () => {
emit("search", {
keywords: keywords.value,
cid: cid.value,
status: status.value
});
};
const categoryList = ref<ThinkGoodsCategory[]>([]);
const getCategoryList = async () => {
categoryList.value = await listThinkGoodsCategory();
};
getCategoryList();
watch(
() => props.selection,
() => {
}
);
</script>
@@ -1,7 +1,7 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:width="'80%'"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
@@ -19,12 +19,13 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="关联商品分类id" name="cid">
<a-input
allow-clear
placeholder="请输入关联商品分类id"
v-model:value="form.cid"
/>
<a-form-item label="商品分类" name="cid">
<a-select v-model:value="form.cid">
<a-select-option v-for="item in categoryList" :key="item.id">{{
item.catname
}}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="商品标题" name="title">
<a-input
@@ -34,28 +35,37 @@
/>
</a-form-item>
<a-form-item label="划线价" name="linePrice">
<a-input
<a-input-number
allow-clear
placeholder="请输入划线价"
v-model:value="form.linePrice"
/>
</a-form-item>
<a-form-item label="最低价格" name="minPrice">
<a-input
<template v-if="form.specType === 2">
<a-form-item label="最低价格" name="minPrice">
<a-input-number
allow-clear
placeholder="请输入最低价格"
v-model:value="form.minPrice"
/>
</a-form-item>
<a-form-item label="最高价格" name="maxPrice">
<a-input-number
allow-clear
placeholder="请输入最高价格"
v-model:value="form.maxPrice"
/>
</a-form-item>
</template>
<a-form-item label="售价" name="minPrice" v-else>
<a-input-number
allow-clear
placeholder="请输入最低价格"
placeholder="请输入售价"
v-model:value="form.minPrice"
/>
</a-form-item>
<a-form-item label="最高价格" name="maxPrice">
<a-input
allow-clear
placeholder="请输入最高价格"
v-model:value="form.maxPrice"
/>
</a-form-item>
<a-form-item label="最低积分" name="minIntegral">
<a-input
<a-input-number
allow-clear
placeholder="请输入最低积分"
v-model:value="form.minIntegral"
@@ -69,42 +79,34 @@
/>
</a-form-item>
<a-form-item label="总库存" name="stockNum">
<a-input
<a-input-number
allow-clear
placeholder="请输入总库存"
v-model:value="form.stockNum"
/>
</a-form-item>
<a-form-item label="总销量" name="goodsSales">
<a-input
allow-clear
placeholder="请输入总销量"
v-model:value="form.goodsSales"
<a-form-item
label="封面图"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item
label="封面图"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商品规格(1单规格 2多规格)" name="specType">
<a-input
allow-clear
placeholder="请输入商品规格(1单规格 2多规格)"
v-model:value="form.specType"
/>
<a-form-item label="商品规格" name="specType">
<a-select v-model:value="form.specType">
<a-select-option :value="1">单规格</a-select-option>
<a-select-option :value="2">多规格</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="状态:1上架,2下架" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
<a-form-item label="状态" name="status">
<a-select v-model:value="form.status">
<a-select-option :value="1">上架</a-select-option>
<a-select-option :value="2">下架</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="商品简介" name="desc">
<a-input
@@ -114,10 +116,11 @@
/>
</a-form-item>
<a-form-item label="商品详细介绍" name="content">
<a-input
allow-clear
placeholder="请输入商品详细介绍"
v-model:value="form.content"
<tinymce-editor
v-model:value="content"
:init="config"
placeholder="图片直接粘贴自动上传"
@paste="onPaste"
/>
</a-form-item>
<a-form-item label="排序" name="sort">
@@ -127,190 +130,268 @@
v-model:value="form.sort"
/>
</a-form-item>
<a-form-item label="是否需要发货:1是;0否" name="isFh">
<a-input
allow-clear
placeholder="请输入是否需要发货:1是;0否"
v-model:value="form.isFh"
/>
<a-form-item label="是否需要发货" name="isFh">
<a-select v-model:value="form.isFh">
<a-select-option :value="1">需要</a-select-option>
<a-select-option :value="0">不需要</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="积分/金额:1仅积分;2仅金额;3积分/金额" name="isIntegral">
<a-input
allow-clear
placeholder="请输入积分/金额:1仅积分;2仅金额;3积分/金额"
v-model:value="form.isIntegral"
/>
<a-form-item label="积分/金额" name="isIntegral">
<a-select v-model:value="form.isIntegral">
<a-select-option :value="1">仅积分</a-select-option>
<a-select-option :value="2">仅金额</a-select-option>
<a-select-option :value="2">积分/金额</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="收货方式:1自提;2快递;3自提/快递" name="shType">
<a-input
allow-clear
placeholder="请输入收货方式:1自提;2快递;3自提/快递"
v-model:value="form.shType"
/>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
<a-form-item label="收货方式" name="shType">
<a-select v-model:value="form.shType">
<a-select-option :value="1">自提</a-select-option>
<a-select-option :value="2">快递</a-select-option>
<a-select-option :value="2">自提/快递</a-select-option>
</a-select>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkGoods, updateThinkGoods } from '@/api/think/thinkGoods';
import { ThinkGoods } from '@/api/think/thinkGoods/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
import { ref, reactive, watch } from "vue";
import { Form, message } from "ant-design-vue";
import { assignObject, uuid } from "ele-admin-pro";
import { addThinkGoods, updateThinkGoods } from "@/api/think/thinkGoods";
import { ThinkGoods } from "@/api/think/thinkGoods/model";
import { useThemeStore } from "@/store/modules/theme";
import { storeToRefs } from "pinia";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { FormInstance } from "ant-design-vue/es/form";
import { FileRecord } from "@/api/system/file/model";
import { ThinkGoodsCategory } from "@/api/think/thinkGoodsCategory/model";
import { listThinkGoodsCategory } from "@/api/think/thinkGoodsCategory";
import TinymceEditor from "@/components/TinymceEditor/index.vue";
import { uploadFile, uploadOss } from "@/api/system/file";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkGoods | null;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkGoods | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkGoods>({
goodsId: undefined,
cid: undefined,
title: undefined,
linePrice: undefined,
minPrice: undefined,
maxPrice: undefined,
minIntegral: undefined,
maxIntegral: undefined,
stockNum: undefined,
goodsSales: undefined,
image: undefined,
specType: undefined,
status: undefined,
desc: undefined,
content: undefined,
sort: undefined,
isFh: undefined,
isIntegral: undefined,
shType: undefined,
createTime: undefined,
updateTime: undefined,
thinkGoodsId: undefined,
thinkGoodsName: '',
status: 0,
comments: '',
sortNumber: 100
});
// 用户信息
const form = reactive<ThinkGoods>({
goodsId: undefined,
cid: undefined,
title: undefined,
linePrice: undefined,
minPrice: undefined,
maxPrice: undefined,
minIntegral: undefined,
maxIntegral: undefined,
stockNum: undefined,
goodsSales: undefined,
image: undefined,
specType: 1,
status: 1,
desc: undefined,
content: undefined,
sort: undefined,
isFh: undefined,
isIntegral: undefined,
shType: undefined,
createTime: undefined,
updateTime: undefined,
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsName: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
// 表单验证规则
const rules = reactive({
thinkGoodsName: [
{
required: true,
type: "string",
message: "请填写名称",
trigger: "blur"
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkGoods : addThinkGoods;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
]
});
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: "done"
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = "";
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkGoods : addThinkGoods;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit("done");
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
};
const categoryList = ref<ThinkGoodsCategory[]>([]);
const getCategoryList = async () => {
categoryList.value = await listThinkGoodsCategory();
};
const content = ref("");
const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
const config = ref({
height: 500,
images_upload_handler: (blobInfo, success, error) => {
const file = blobInfo.blob();
const formData = new FormData();
formData.append('file', file, file.name);
uploadOss(file).then(res => {
success(res.url)
}).catch((msg) => {
error(msg);
})
return false;
},
// 自定义文件上传(这里使用把选择的文件转成 blob 演示)
file_picker_callback: (callback: any, _value: any, meta: any) => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
// 设定文件可选类型
if (meta.filetype === 'image') {
input.setAttribute('accept', 'image/*');
} else if (meta.filetype === 'media') {
input.setAttribute('accept', 'video/*,.pdf');
}
input.onchange = () => {
const file = input.files?.[0];
if (!file) {
return;
}
},
{ immediate: true }
);
if (meta.filetype === 'media') {
if (file.size / 1024 / 1024 > 200) {
editorRef.value?.alert({ content: '大小不能超过 200MB' });
return;
}
if (!file.type.startsWith('video/')) {
editorRef.value?.alert({ content: '只能选择视频文件' });
return;
}
uploadOss(file).then(res => {
callback(res.downloadUrl);
})
}
};
input.click();
}
});
/* 粘贴图片上传服务器并插入编辑器 */
const onPaste = (e) => {
const items = (e.clipboardData || e.originalEvent.clipboardData).items;
let hasFile = false;
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
let file = items[i].getAsFile();
const item: ItemType = {
file,
uid: (file as any).lastModified,
name: file.name
};
uploadFile(<File>item.file)
.then((result) => {
const addPath = `<p><img class="content-img" src="${result.url}"></p>`;
content.value = content.value + addPath
})
.catch((e) => {
message.error(e.message);
});
hasFile = true;
}
}
if (hasFile) {
e.preventDefault();
}
}
watch(
() => props.visible,
async (visible) => {
if (visible) {
await getCategoryList();
images.value = [];
content.value = '';
if (props.data) {
assignObject(form, props.data);
if (props.data.content) {
content.value = props.data.content;
}
if (props.data.image) {
images.value.push({
uid: uuid(),
url: props.data.image,
status: "done"
});
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+240 -260
View File
@@ -25,8 +25,8 @@
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
<a-tag v-if="record.status == 2" color="red">下架</a-tag>
<a-tag v-else color="green">上架</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
@@ -51,279 +51,259 @@
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkGoodsEdit from './components/thinkGoodsEdit.vue';
import { pageThinkGoods, removeThinkGoods, removeBatchThinkGoods } from '@/api/think/thinkGoods';
import type { ThinkGoods, ThinkGoodsParam } from '@/api/think/thinkGoods/model';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import { toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkGoodsEdit from "./components/thinkGoodsEdit.vue";
import { pageThinkGoods, removeThinkGoods, removeBatchThinkGoods } from "@/api/think/thinkGoods";
import type { ThinkGoods, ThinkGoodsParam } from "@/api/think/thinkGoods/model";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGoods[]>([]);
// 当前编辑数据
const current = ref<ThinkGoods | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格选中数据
const selection = ref<ThinkGoods[]>([]);
// 当前编辑数据
const current = ref<ThinkGoods | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
console.log(where)
return pageThinkGoods({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "ID",
dataIndex: "goodsId",
key: "goodsId",
align: "center",
width: 90
},
{
title: "分类",
dataIndex: ["category", "catname"],
key: "cid",
align: "center"
},
{
title: "商品标题",
dataIndex: "title",
key: "title",
align: "center"
},
{
title: "划线价",
dataIndex: "linePrice",
key: "linePrice",
align: "center"
},
{
title: "最低价格",
dataIndex: "minPrice",
key: "minPrice",
align: "center"
},
{
title: "最高价格",
dataIndex: "maxPrice",
key: "maxPrice",
align: "center"
},
{
title: "最低积分",
dataIndex: "minIntegral",
key: "minIntegral",
align: "center"
},
{
title: "最高积分",
dataIndex: "maxIntegral",
key: "maxIntegral",
align: "center"
},
{
title: "总库存",
dataIndex: "stockNum",
key: "stockNum",
align: "center"
},
{
title: "总销量",
dataIndex: "goodsSales",
key: "goodsSales",
align: "center"
},
{
title: "状态",
dataIndex: "status",
key: "status",
align: "center"
},
{
title: "排序",
dataIndex: "sort",
key: "sort",
align: "center"
},
{
title: "是否需要发货",
dataIndex: "isFh",
key: "isFh",
align: "center",
customRender: ({ text }) => text === 1 ? "是" : "否"
},
{
title: "积分/金额",
dataIndex: "isIntegral",
key: "isIntegral",
align: "center",
customRender: ({ text }) => {
if (text === 1) return "仅积分";
if (text === 2) return "仅金额";
return "积分/金额";
}
return pageThinkGoods({
...where,
...orders,
page,
limit
},
{
title: "收货方式",
dataIndex: "shType",
key: "shType",
align: "center",
customRender: ({ text }) => {
if (text === 1) return "自提";
if (text === 2) return "快递";
return "自提/快递";
}
},
{
title: "创建时间",
dataIndex: "createTime",
key: "createTime",
align: "center",
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
},
{
title: "操作",
key: "action",
width: 180,
fixed: "right",
align: "center",
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGoodsParam) => {
console.log(where)
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoods) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoods) => {
const hide = message.loading("请求中..", 0);
removeThinkGoods(row.goodsId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
width: 90,
},
{
title: '关联商品分类id',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '商品标题',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '划线价',
dataIndex: 'linePrice',
key: 'linePrice',
align: 'center',
},
{
title: '最低价格',
dataIndex: 'minPrice',
key: 'minPrice',
align: 'center',
},
{
title: '最高价格',
dataIndex: 'maxPrice',
key: 'maxPrice',
align: 'center',
},
{
title: '最低积分',
dataIndex: 'minIntegral',
key: 'minIntegral',
align: 'center',
},
{
title: '最高积分',
dataIndex: 'maxIntegral',
key: 'maxIntegral',
align: 'center',
},
{
title: '总库存',
dataIndex: 'stockNum',
key: 'stockNum',
align: 'center',
},
{
title: '总销量',
dataIndex: 'goodsSales',
key: 'goodsSales',
align: 'center',
},
{
title: '封面图',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商品规格(1单规格 2多规格)',
dataIndex: 'specType',
key: 'specType',
align: 'center',
},
{
title: '状态:1上架,2下架',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '商品简介',
dataIndex: 'desc',
key: 'desc',
align: 'center',
},
{
title: '商品详细介绍',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '是否需要发货:1是;0否',
dataIndex: 'isFh',
key: 'isFh',
align: 'center',
},
{
title: '积分/金额:1仅积分;2仅金额;3积分/金额',
dataIndex: 'isIntegral',
key: 'isIntegral',
align: 'center',
},
{
title: '收货方式:1自提;2快递;3自提/快递',
dataIndex: 'shType',
key: 'shType',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkGoods(selection.value.map((d) => d.goodsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
]);
});
};
/* 搜索 */
const reload = (where?: ThinkGoodsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoods) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoods) => {
const hide = message.loading('请求中..', 0);
removeThinkGoods(row.thinkGoodsId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
/* 自定义行属性 */
const customRow = (record: ThinkGoods) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkGoods(selection.value.map((d) => d.thinkGoodsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGoods) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGoods'
};
export default {
name: "ThinkGoods"
};
</script>
<style lang="less" scoped></style>
+1 -22
View File
@@ -101,18 +101,12 @@
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '上级id',
dataIndex: 'pid',
key: 'pid',
align: 'center',
},
{
title: '分类名称',
dataIndex: 'catname',
@@ -131,21 +125,6 @@
key: 'sort',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
@@ -1,12 +1,6 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
+2 -23
View File
@@ -100,13 +100,6 @@
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户id',
dataIndex: 'uid',
@@ -132,17 +125,11 @@
align: 'center',
},
{
title: '日期',
title: '签到日期',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center',
},
{
title: '天',
dataIndex: 'day',
key: 'day',
align: 'center',
},
{
title: '签到时间',
dataIndex: 'createTime',
@@ -150,15 +137,7 @@
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
}
]);
@@ -7,6 +7,10 @@
<a-radio-button :value="2">VIP卡发票</a-radio-button>
<a-radio-button :value="3">IC卡发票</a-radio-button>
</a-radio-group>
<a-select placeholder="开票状态" v-model:value="where.isOpen" @change="search" allow-clear>
<a-select-option :value="1">已开</a-select-option>
<a-select-option :value="2">未开</a-select-option>
</a-select>
<a-input-search
allow-clear
placeholder="订单号"
@@ -19,38 +23,41 @@
</template>
<script lang="ts" setup>
import { watch } from 'vue';
import useSearch from '@/utils/use-search';
import { ThinkInvoiceParam } from '@/api/think/thinkInvoice/model';
import { watch } from "vue";
import useSearch from "@/utils/use-search";
import { ThinkInvoiceParam } from "@/api/think/thinkInvoice/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkInvoiceParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
const emit = defineEmits<{
(e: "search", where?: ThinkInvoiceParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "batchMove"): void;
}>();
// 表单数据
const { where } = useSearch<ThinkInvoiceParam>({
oid: undefined,
keywords: undefined
});
// 表单数据
const { where } = useSearch<ThinkInvoiceParam>({
oid: undefined,
itype: undefined,
isOpen: undefined,
keywords: undefined
});
// 新增
const search = () => {
emit('search', where);
};
// 新增
const search = () => {
emit("search", where);
};
watch(
() => props.selection,
() => {}
);
watch(
() => props.selection,
() => {
}
);
</script>
+252 -225
View File
@@ -25,12 +25,17 @@
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
<template v-if="column.key === 'isOpen'">
<a-tag v-if="record.isOpen === 1" color="green">已开</a-tag>
<a-tag v-else color="red">未开</a-tag>
</template>
<template v-if="column.key === 'info'">
<span v-if="record.itype !== 4">{{ record.info }}</span>
<span v-else>开票金额:{{ record.price }}元,租赁面积:{{ record.size }}㎡,租赁时间:{{ record.rentStartDate
}}~{{ record.rentEndDate }}</span>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-space v-if="record.isOpen === 1">
<a @click="openInvoicePdf(record)">查看</a>
<a-divider type="vertical" />
<a @click="openEdit(record)">作废</a>
@@ -42,6 +47,12 @@
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
<a-space v-if="record.isOpen === 2 && record.status === 0">
<a @click="openInvoice(record)">开票</a>
<a-divider type="vertical" />
<a class="ele-text-danger" @click="refuse(record)">拒绝</a>
</a-space>
<span v-if="record.status === 2" class="ele-text-danger">已拒绝</span>
</template>
</template>
</ele-pro-table>
@@ -58,238 +69,254 @@
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkInvoiceEdit from './components/thinkInvoiceEdit.vue';
import {
pageThinkInvoice,
removeThinkInvoice,
removeBatchThinkInvoice
} from '@/api/think/thinkInvoice';
import type {
ThinkInvoice,
ThinkInvoiceParam
} from '@/api/think/thinkInvoice/model';
import * as InvoiceApi from '@/api/think/thinkInvoice';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import { toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkInvoiceEdit from "./components/thinkInvoiceEdit.vue";
import {
pageThinkInvoice,
removeThinkInvoice,
removeBatchThinkInvoice, updateThinkInvoice, doInvoice
} from "@/api/think/thinkInvoice";
import type {
ThinkInvoice,
ThinkInvoiceParam
} from "@/api/think/thinkInvoice/model";
import * as InvoiceApi from "@/api/think/thinkInvoice";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkInvoice[]>([]);
// 当前编辑数据
const current = ref<ThinkInvoice | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格选中数据
const selection = ref<ThinkInvoice[]>([]);
// 当前编辑数据
const current = ref<ThinkInvoice | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
return pageThinkInvoice({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkInvoice({
...where,
...orders,
page,
limit
});
};
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '操作',
key: 'action',
width: 180,
fixed: 'left',
align: 'center',
hideInSetting: true
},
{
title: '订单号',
dataIndex: 'oid',
key: 'oid',
align: 'center'
},
{
title: '公司名称',
dataIndex: 'name',
key: 'name',
align: 'center'
},
{
title: '发票金额',
dataIndex: 'price',
key: 'price',
align: 'center'
},
{
title: '税号',
dataIndex: 'code',
key: 'code',
align: 'center'
},
{
title: '备注信息',
dataIndex: 'info',
key: 'info',
align: 'center',
width: 360,
ellipsis: true
},
{
title: '是否已开',
dataIndex: 'isOpen',
key: 'isOpen',
align: 'center'
},
{
title: '发票类型',
dataIndex: 'type',
key: 'type',
align: 'center'
},
{
title: '发票类型',
dataIndex: 'itype',
key: 'itype',
align: 'center'
},
{
title: '发票类型',
dataIndex: 'invoicetype',
key: 'invoicetype',
align: 'center'
},
{
title: 'VID',
dataIndex: 'vid',
key: 'vid',
align: 'center'
},
{
title: '开票时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
}
]);
/* 搜索 */
const reload = (where?: ThinkInvoiceParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkInvoice) => {
current.value = row ?? null;
showEdit.value = true;
};
const openInvoicePdf = (row?: ThinkInvoice) => {
if (row?.oid) {
InvoiceApi.showInvoice(row?.oid).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
window.open(pdfUrl);
});
}
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkInvoice) => {
const hide = message.loading('请求中..', 0);
removeThinkInvoice(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkInvoice(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "操作",
key: "action",
width: 180,
fixed: "left",
align: "center",
hideInSetting: true
},
{
title: "订单号",
dataIndex: "orderNum",
key: "oid",
align: "center"
},
{
title: "公司名称",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "发票金额",
dataIndex: "price",
key: "price",
align: "center"
},
{
title: "税号",
dataIndex: "code",
key: "code",
align: "center"
},
{
title: "备注信息",
dataIndex: "info",
key: "info",
align: "center"
},
{
title: "是否已开",
dataIndex: "isOpen",
key: "isOpen",
align: "center",
},
{
title: "发票类型",
dataIndex: "type",
key: "type",
align: "center",
customRender: ({ text }) => {
if (text === 1) {
return "电子";
} else {
return "纸质";
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkInvoice) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
},
{
title: "开票类型",
dataIndex: "invoicetype",
key: "invoicetype",
align: "center",
customRender: ({ text }) => {
if (text === 1) {
return "普票";
} else {
return "专票";
}
};
}
},
{
title: "开票时间",
dataIndex: "createTime",
key: "createTime",
align: "center",
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
}
]);
/* 搜索 */
const reload = (where?: ThinkInvoiceParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkInvoice) => {
current.value = row ?? null;
showEdit.value = true;
};
const openInvoicePdf = (row: ThinkInvoice) => {
const hide = message.loading("请求中..", 0);
InvoiceApi.showInvoice(row?.id).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
hide();
window.open(pdfUrl);
});
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkInvoice) => {
const hide = message.loading("请求中..", 0);
removeThinkInvoice(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkInvoice(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
const openInvoice = async (row: ThinkInvoice) => {
await doInvoice(row);
message.success("操作成功");
reload();
};
const refuse = async (row: ThinkInvoice) => {
await updateThinkInvoice({
id: row.id,
status: 2
});
message.success("操作成功");
reload();
};
/* 自定义行属性 */
const customRow = (record: ThinkInvoice) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
query();
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkInvoice'
};
export default {
name: "ThinkInvoice"
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,202 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑闸机开门记录' : '添加闸机开门记录'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="" name="orderId">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态, 0在线, 1离线" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkMachineOpenLog, updateThinkMachineOpenLog } from '@/api/think/thinkMachineOpenLog';
import { ThinkMachineOpenLog } from '@/api/think/thinkMachineOpenLog/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkMachineOpenLog | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkMachineOpenLog>({
id: undefined,
orderId: undefined,
tenantId: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
createTime: undefined,
updateTime: undefined,
thinkMachineOpenLogId: undefined,
thinkMachineOpenLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkMachineOpenLogName: [
{
required: true,
type: 'string',
message: '请填写闸机开门记录名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkMachineOpenLog : addThinkMachineOpenLog;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkMachineOpenLogId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ThinkMachineOpenLogEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkMachineOpenLogEdit from './components/thinkMachineOpenLogEdit.vue';
import { pageThinkMachineOpenLog, removeThinkMachineOpenLog, removeBatchThinkMachineOpenLog } from '@/api/think/thinkMachineOpenLog';
import type { ThinkMachineOpenLog, ThinkMachineOpenLogParam } from '@/api/think/thinkMachineOpenLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkMachineOpenLog[]>([]);
// 当前编辑数据
const current = ref<ThinkMachineOpenLog | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkMachineOpenLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0在线, 1离线',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkMachineOpenLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkMachineOpenLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkMachineOpenLog) => {
const hide = message.loading('请求中..', 0);
removeThinkMachineOpenLog(row.thinkMachineOpenLogId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkMachineOpenLog(selection.value.map((d) => d.thinkMachineOpenLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkMachineOpenLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkMachineOpenLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,112 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="`60%`"
:visible="visible"
:confirm-loading="loading"
title="退款"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
:maskClosable="false"
@ok="save"
>
<a-form>
<a-form-item label="订单金额">
<span>{{ data.totalPrice }}元</span>
</a-form-item>
<a-form-item label="支付金额">
<span>{{ data.payPrice }}元</span>
</a-form-item>
<a-form-item label="退款金额">
<a-input-number placeholder="请输入退款金额" style="width: 300px" v-model:value="form.refundAmount"
:max="data.payPrice" />
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from "vue";
import { ThinkOrder } from "@/api/think/thinkOrder/model";
import { ThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog/model";
import { message } from "ant-design-vue";
import { addThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog";
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data: ThinkOrder;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
const form = reactive<ThinkOrderRefundLog>({
int: undefined,
uid: undefined,
refundAmount: undefined,
sid: undefined,
oid: undefined,
status: 1,
type: 0
});
// 请求状态
const loading = ref(false);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
const save = async () => {
if (!form.refundAmount) return message.error("请输入退款金额");
loading.value = true;
await addThinkOrderRefundLog(form);
loading.value = false;
message.success("已提交");
updateVisible(false);
emit("done");
};
watch(
() => props.visible,
(visible) => {
if (visible) {
loading.value = false;
if (props.data) {
form.uid = props.data.uid;
form.oid = props.data.id;
form.sid = props.data.sid;
form.refundAmount = 0;
}
}
}
);
</script>
<style lang="less" scoped>
.order-card {
margin-bottom: 20px;
}
.ant-form-item {
margin-bottom: 5px;
}
.order-info {
display: flex;
.info {
padding-left: 5px;
display: flex;
flex-direction: column;
}
}
.tag-icon {
padding-right: 6px;
}
</style>
+225 -206
View File
@@ -1,221 +1,240 @@
<!-- 搜索表单 -->
<template>
<div class="search">
<a-space class="flex items-center" :size="10" style="flex-wrap: wrap">
<span class="text-gray-400">付款状态</span>
<a-radio-group v-model:value="where.payStatus" @change="search">
<a-radio-button :value="1">已付款</a-radio-button>
<a-radio-button :value="2">未付款</a-radio-button>
</a-radio-group>
<span class="text-gray-400">订单状态</span>
<a-radio-group v-model:value="where.orderStatus" @change="search">
<a-radio-button :value="1">已完成</a-radio-button>
<a-radio-button :value="2">未使用</a-radio-button>
<a-radio-button :value="3">已取消</a-radio-button>
<a-radio-button :value="4">退款中</a-radio-button>
<a-radio-button :value="5">退款被拒</a-radio-button>
<a-radio-button :value="6">退款成功</a-radio-button>
</a-radio-group>
<span class="text-gray-400">开票状态</span>
<a-radio-group v-model:value="where.isInvoice" @change="search">
<a-radio-button :value="1">已开票</a-radio-button>
<a-radio-button :value="2">未开票</a-radio-button>
<a-radio-button :value="3">不能开票</a-radio-button>
</a-radio-group>
<span class="text-gray-400">付款方式</span>
<a-radio-group v-model:value="where.payType" @change="search">
<a-radio-button :value="1">微信支付</a-radio-button>
<a-radio-button :value="2">余额支付</a-radio-button>
<a-radio-button :value="3">支付宝</a-radio-button>
<a-radio-button :value="4">现金</a-radio-button>
<a-radio-button :value="5">POS机</a-radio-button>
<a-radio-button :value="6">VIP月卡</a-radio-button>
<a-radio-button :value="7">VIP年卡</a-radio-button>
<a-radio-button :value="8">VIP次卡</a-radio-button>
<a-radio-button :value="9">IC月卡</a-radio-button>
<a-radio-button :value="10">IC年卡</a-radio-button>
<a-radio-button :value="11">IC次卡</a-radio-button>
<a-radio-button :value="12">免费</a-radio-button>
<a-radio-button :value="13">VIP充值卡</a-radio-button>
<a-radio-button :value="14">IC充值卡</a-radio-button>
<a-radio-button :value="15">积分支付</a-radio-button>
<a-radio-button :value="16">VIP季卡</a-radio-button>
<a-radio-button :value="17">IC季卡</a-radio-button>
</a-radio-group>
</a-space>
<a-space :size="10" class="mt-5" style="flex-wrap: wrap">
<ThinkSelectSite
:placeholder="`选择场馆`"
class="input-item"
v-model:value="where.siteName"
@done="chooseSiteId"
/>
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入订单号|编号|手机号"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
<a-button class="ele-btn-icon" :disabled="loading" @click="handleExport">
<template #icon>
<download-outlined />
</template>
<span>导出订单</span>
</a-button>
</a-space>
</div>
<a-space class="flex items-center" :size="10" style="flex-wrap: wrap">
<span class="text-gray-400">付款状态</span>
<a-select v-model:value="where.payStatus" style="width: 150px" placeholder="付款状态筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">已付款</a-select-option>
<a-select-option :value="2">未付款</a-select-option>
</a-select>
<span class="text-gray-400">订单状态</span>
<a-select v-model:value="where.orderStatus" style="width: 150px" placeholder="订单状态筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">已完成</a-select-option>
<a-select-option :value="2">未使用</a-select-option>
<a-select-option :value="3">已取消</a-select-option>
<a-select-option :value="4">退款中</a-select-option>
<a-select-option :value="5">退款被拒</a-select-option>
<a-select-option :value="6">退款成功</a-select-option>
</a-select>
<span class="text-gray-400">付款方式</span>
<a-select v-model:value="where.payType" style="width: 150px" placeholder="付款方式筛选" @change="search">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="1">微信支付</a-select-option>
<a-select-option :value="2">余额支付</a-select-option>
<a-select-option :value="3">支付宝</a-select-option>
<a-select-option :value="4">现金</a-select-option>
<a-select-option :value="5">POS机</a-select-option>
<a-select-option :value="6">VIP月卡</a-select-option>
<a-select-option :value="7">VIP年卡</a-select-option>
<a-select-option :value="8">VIP次卡</a-select-option>
<a-select-option :value="9">IC月卡</a-select-option>
<a-select-option :value="10">IC年卡</a-select-option>
<a-select-option :value="11">IC次卡</a-select-option>
<a-select-option :value="12">免费</a-select-option>
<a-select-option :value="13">VIP充值卡</a-select-option>
<a-select-option :value="14">IC充值卡</a-select-option>
<a-select-option :value="15">积分支付</a-select-option>
<a-select-option :value="16">VIP季卡</a-select-option>
<a-select-option :value="17">IC季卡</a-select-option>
</a-select>
<span class="text-gray-400">开票状态</span>
<a-select v-model:value="where.isInvoice" style="width: 150px" placeholder="开票状态筛选" @change="search">
<a-select-option value="1">已开票</a-select-option>
<a-select-option :value="2">未开票</a-select-option>
<a-select-option :value="3">不能开票</a-select-option>
</a-select>
<ThinkSelectSite
:placeholder="`选择场馆`"
class="input-item"
v-model:value="where.siteName"
@done="chooseSiteId"
/>
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入订单号|编号|手机号"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
<a-button @click="setHasInvoice" :disabled="!selection?.length">设置已开票</a-button>
<!-- <a-button class="ele-btn-icon" :disabled="loading" @click="handleExport">-->
<!-- <template #icon>-->
<!-- <download-outlined />-->
<!-- </template>-->
<!-- <span>导出订单</span>-->
<!-- </a-button>-->
</a-space>
</template>
<script lang="ts" setup>
import useSearch from '@/utils/use-search';
import { ref, watch } from 'vue';
import { ThinkOrderInfoParam } from '@/api/think/thinkOrderInfo/model';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
import { toDateString } from 'ele-admin-pro';
import dayjs from 'dayjs';
import { listThinkOrder } from '@/api/think/thinkOrder';
import { ThinkOrder, ThinkOrderParam } from '@/api/think/thinkOrder/model';
import { ThinkSite } from '@/api/think/thinkSite/model';
import useSearch from "@/utils/use-search";
import { ref, watch } from "vue";
import { ThinkOrderInfoParam } from "@/api/think/thinkOrderInfo/model";
import { utils, writeFile } from "xlsx";
import { message } from "ant-design-vue";
import { toDateString } from "ele-admin-pro";
import dayjs from "dayjs";
import { listThinkOrder, updateBatchThinkOrder, updateThinkOrder } from "@/api/think/thinkOrder";
import { ThinkOrder, ThinkOrderParam } from "@/api/think/thinkOrder/model";
import { ThinkSite } from "@/api/think/thinkSite/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: ThinkOrder[];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkOrderInfoParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'advanced'): void;
}>();
const emit = defineEmits<{
(e: "search", where?: ThinkOrderInfoParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "advanced"): void;
}>();
// 表单数据
const { where, resetFields } = useSearch<ThinkOrderParam>({
sid: undefined,
siteName: undefined,
createTimeStart: undefined,
createTimeEnd: undefined,
timeStart: undefined,
timeEnd: undefined,
categoryId: undefined,
keywords: undefined
// 表单数据
const { where, resetFields } = useSearch<ThinkOrderParam>({
sid: undefined,
siteName: undefined,
createTimeStart: undefined,
createTimeEnd: undefined,
timeStart: undefined,
timeEnd: undefined,
categoryId: undefined,
keywords: undefined,
payStatus: undefined,
orderStatus: undefined,
payType: undefined,
isInvoice: undefined
});
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(["", ""]);
const orders = ref<ThinkOrder[] | any[]>();
const xlsFileName = ref<string>();
/* 搜索 */
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
// where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
// where.createTimeEnd = d2 ? d2 + ' 00:00:00' : undefined;
emit("search", {
...where
});
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<ThinkOrder[] | any[]>();
const xlsFileName = ref<string>();
};
/* 搜索 */
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
// where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
// where.createTimeEnd = d2 ? d2 + ' 00:00:00' : undefined;
emit('search', {
...where
});
};
const chooseSiteId = (data: ThinkSite) => {
where.sid = data.id;
where.siteName = data.name;
search();
};
const chooseSiteId = (data: ThinkSite) => {
where.sid = data.id;
where.siteName = data.name;
search();
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'订单号',
'订单编号',
'姓名',
'电话号码',
'预定信息',
'消费金额',
'实付金额',
'下单日期'
]
];
if (!where.timeStart) {
message.error('请选择导出的开始日期、结束日期,每次最多导出5000条记录');
return false;
}
await listThinkOrder(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkOrder) => {
array.push([
`${d.id}`,
`${d.orderNum}`,
`${d.name}`,
`${d.phone}`,
`${d.siteName} ${d.dateTime} ${d.totalPrice}`,
`${d.totalPrice}`,
`${d.payPrice}`,
`${toDateString(d.payTime)}`
]);
});
const sheetName = `订单数据导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
})
.catch((msg) => {
message.error(msg);
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
"订单号",
"订单编号",
"姓名",
"电话号码",
"预定信息",
"消费金额",
"实付金额",
"下单日期"
]
];
if (!where.timeStart) {
message.error("请选择导出的开始日期、结束日期,每次最多导出5000条记录");
return false;
}
await listThinkOrder(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkOrder) => {
array.push([
`${d.id}`,
`${d.orderNum}`,
`${d.name}`,
`${d.phone}`,
`${d.siteName} ${d.dateTime} ${d.totalPrice}`,
`${d.totalPrice}`,
`${d.payPrice}`,
`${toDateString(d.payTime)}`
]);
});
const sheetName = `订单数据导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet["!cols"] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading("正在导出...");
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + "_" : ""
}${sheetName}.xlsx`
);
loading.value = false;
})
.finally(() => {});
};
}, 2000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {
});
};
watch(
() => props.selection,
() => {}
);
const setHasInvoice = async () => {
const hide = message.loading("请求中..", 0);
if (props.selection) {
props.selection.filter(item => item.isInvoice === 2).map(async item => {
item.isInvoice = 1;
await updateThinkOrder(item);
});
}
hide();
message.success("设置成功");
};
watch(
() => props.selection,
() => {
}
);
</script>
+450 -412
View File
@@ -11,6 +11,7 @@
:scroll="{ x: 800 }"
tool-class="ele-toolbar-form"
class="sys-org-table"
v-model:selection="selection"
>
<template #toolbar>
<search
@@ -32,55 +33,71 @@
<template v-if="column.key === 'payType'">
<template v-if="record.payStatus == 1">
<a-tag v-if="record.payType == 0">余额支付</a-tag>
<a-tag v-if="record.payType == 1"
><WechatOutlined class="tag-icon" />微信支付</a-tag
>
<a-tag v-if="record.payType == 1">
<WechatOutlined class="tag-icon" />
微信支付
</a-tag>
<a-tag v-if="record.payType == 2">积分</a-tag>
<a-tag v-if="record.payType == 3"
><AlipayCircleOutlined class="tag-icon" />支付宝</a-tag
>
<a-tag v-if="record.payType == 4"
><IdcardOutlined class="tag-icon" />现金</a-tag
>
<a-tag v-if="record.payType == 5"
><IdcardOutlined class="tag-icon" />POS机</a-tag
>
<a-tag v-if="record.payType == 6"
><IdcardOutlined class="tag-icon" />VIP月卡</a-tag
>
<a-tag v-if="record.payType == 7"
><IdcardOutlined class="tag-icon" />VIP年卡</a-tag
>
<a-tag v-if="record.payType == 8"
><IdcardOutlined class="tag-icon" />VIP次卡</a-tag
>
<a-tag v-if="record.payType == 9"
><IdcardOutlined class="tag-icon" />IC月卡</a-tag
>
<a-tag v-if="record.payType == 10"
><IdcardOutlined class="tag-icon" />IC年卡</a-tag
>
<a-tag v-if="record.payType == 11"
><IdcardOutlined class="tag-icon" />IC次卡</a-tag
>
<a-tag v-if="record.payType == 12"
><IdcardOutlined class="tag-icon" />免费</a-tag
>
<a-tag v-if="record.payType == 13"
><IdcardOutlined class="tag-icon" />VIP充值卡</a-tag
>
<a-tag v-if="record.payType == 14"
><IdcardOutlined class="tag-icon" />IC充值卡</a-tag
>
<a-tag v-if="record.payType == 15"
><IdcardOutlined class="tag-icon" />积分支付</a-tag
>
<a-tag v-if="record.payType == 16"
><IdcardOutlined class="tag-icon" />VIP季卡</a-tag
>
<a-tag v-if="record.payType == 17"
><IdcardOutlined class="tag-icon" />IC季卡</a-tag
>
<a-tag v-if="record.payType == 3">
<AlipayCircleOutlined class="tag-icon" />
支付宝
</a-tag>
<a-tag v-if="record.payType == 4">
<IdcardOutlined class="tag-icon" />
现金
</a-tag>
<a-tag v-if="record.payType == 5">
<IdcardOutlined class="tag-icon" />
POS机
</a-tag>
<a-tag v-if="record.payType == 6">
<IdcardOutlined class="tag-icon" />
VIP月卡
</a-tag>
<a-tag v-if="record.payType == 7">
<IdcardOutlined class="tag-icon" />
VIP年卡
</a-tag>
<a-tag v-if="record.payType == 8">
<IdcardOutlined class="tag-icon" />
VIP次卡
</a-tag>
<a-tag v-if="record.payType == 9">
<IdcardOutlined class="tag-icon" />
IC月卡
</a-tag>
<a-tag v-if="record.payType == 10">
<IdcardOutlined class="tag-icon" />
IC年卡
</a-tag>
<a-tag v-if="record.payType == 11">
<IdcardOutlined class="tag-icon" />
IC次卡
</a-tag>
<a-tag v-if="record.payType == 12">
<IdcardOutlined class="tag-icon" />
免费
</a-tag>
<a-tag v-if="record.payType == 13">
<IdcardOutlined class="tag-icon" />
VIP充值卡
</a-tag>
<a-tag v-if="record.payType == 14">
<IdcardOutlined class="tag-icon" />
IC充值卡
</a-tag>
<a-tag v-if="record.payType == 15">
<IdcardOutlined class="tag-icon" />
积分支付
</a-tag>
<a-tag v-if="record.payType == 16">
<IdcardOutlined class="tag-icon" />
VIP季卡
</a-tag>
<a-tag v-if="record.payType == 17">
<IdcardOutlined class="tag-icon" />
IC季卡
</a-tag>
</template>
<template v-else>
<span></span>
@@ -88,93 +105,103 @@
</template>
<template v-if="column.key === 'couponType'">
<a-tag v-if="record.couponType == 0">无</a-tag>
<a-tag v-if="record.couponType == 1" color="blue"
><IdcardOutlined class="tag-icon" />抵扣优惠券</a-tag
>
<a-tag v-if="record.couponType == 2" color="blue"
><IdcardOutlined class="tag-icon" />折扣优惠券</a-tag
>
<a-tag v-if="record.couponType == 3" color="blue"
><IdcardOutlined class="tag-icon" />VIP月卡</a-tag
>
<a-tag v-if="record.couponType == 4" color="blue"
><IdcardOutlined class="tag-icon" />VIP年卡</a-tag
>
<a-tag v-if="record.couponType == 5" color="blue"
><IdcardOutlined class="tag-icon" />VIP次卡</a-tag
>
<a-tag v-if="record.couponType == 6" color="blue"
><IdcardOutlined class="tag-icon" />VIP会员卡</a-tag
>
<a-tag v-if="record.couponType == 7" color="blue"
><IdcardOutlined class="tag-icon" />IC月卡</a-tag
>
<a-tag v-if="record.couponType == 8" color="blue"
><IdcardOutlined class="tag-icon" />IC年卡</a-tag
>
<a-tag v-if="record.couponType == 9" color="blue"
><IdcardOutlined class="tag-icon" />IC次卡</a-tag
>
<a-tag v-if="record.couponType == 10" color="blue"
><IdcardOutlined class="tag-icon" />IC会员卡</a-tag
>
<a-tag v-if="record.couponType == 1" color="blue">
<IdcardOutlined class="tag-icon" />
抵扣优惠券
</a-tag>
<a-tag v-if="record.couponType == 2" color="blue">
<IdcardOutlined class="tag-icon" />
折扣优惠券
</a-tag>
<a-tag v-if="record.couponType == 3" color="blue">
<IdcardOutlined class="tag-icon" />
VIP月卡
</a-tag>
<a-tag v-if="record.couponType == 4" color="blue">
<IdcardOutlined class="tag-icon" />
VIP年卡
</a-tag>
<a-tag v-if="record.couponType == 5" color="blue">
<IdcardOutlined class="tag-icon" />
VIP次卡
</a-tag>
<a-tag v-if="record.couponType == 6" color="blue">
<IdcardOutlined class="tag-icon" />
VIP会员卡
</a-tag>
<a-tag v-if="record.couponType == 7" color="blue">
<IdcardOutlined class="tag-icon" />
IC月卡
</a-tag>
<a-tag v-if="record.couponType == 8" color="blue">
<IdcardOutlined class="tag-icon" />
IC年卡
</a-tag>
<a-tag v-if="record.couponType == 9" color="blue">
<IdcardOutlined class="tag-icon" />
IC次卡
</a-tag>
<a-tag v-if="record.couponType == 10" color="blue">
<IdcardOutlined class="tag-icon" />
IC会员卡
</a-tag>
<a-tag v-if="record.couponType == 11" color="blue"
><IdcardOutlined class="tag-icon" />免费订单</a-tag
>
<a-tag v-if="record.couponType == 12" color="blue"
><IdcardOutlined class="tag-icon" />VIP充值卡</a-tag
>
<a-tag v-if="record.couponType == 13" color="blue"
><IdcardOutlined class="tag-icon" />IC充值卡</a-tag
>
<a-tag v-if="record.couponType == 14" color="blue"
><IdcardOutlined class="tag-icon" />VIP季卡</a-tag
>
<a-tag v-if="record.couponType == 15" color="blue"
><IdcardOutlined class="tag-icon" />IC季卡</a-tag
>
<IdcardOutlined class="tag-icon" />
免费订单
</a-tag>
<a-tag v-if="record.couponType == 12" color="blue">
<IdcardOutlined class="tag-icon" />
VIP充值卡
</a-tag>
<a-tag v-if="record.couponType == 13" color="blue">
<IdcardOutlined class="tag-icon" />
IC充值卡
</a-tag>
<a-tag v-if="record.couponType == 14" color="blue">
<IdcardOutlined class="tag-icon" />
VIP季卡
</a-tag>
<a-tag v-if="record.couponType == 15" color="blue">
<IdcardOutlined class="tag-icon" />
IC季卡
</a-tag>
</template>
<template v-if="column.key === 'payStatus'">
<a-tag v-if="record.payStatus == 2" color="error"
><CloseOutlined class="tag-icon" />未付款</a-tag
>
<a-tag v-if="record.payStatus == 1" color="green"
><CheckOutlined class="tag-icon" />已付款</a-tag
>
<a-tag v-if="record.payStatus == 2" color="error">
<CloseOutlined class="tag-icon" />
未付款
</a-tag>
<a-tag v-if="record.payStatus == 1" color="green">
<CheckOutlined class="tag-icon" />
已付款
</a-tag>
<a-tag
v-if="record.payStatus == 3 || record.payStatus == 0"
color="cyan"
><CoffeeOutlined class="tag-icon" />未付款,占场中</a-tag
>
color="cyan">
<CoffeeOutlined class="tag-icon" />
未付款,占场中
</a-tag>
</template>
<template v-if="column.key === 'orderInfo'">
{{ record.orderInfoList }}
</template>
<template v-if="column.key === 'orderStatus'">
<span v-if="record.orderStatus == 1" class="ele-text-success"
>已完成</span
>
>已完成</span>
<span v-if="record.orderStatus == 2" class="ele-text-placeholder"
>未使用</span
>
>未使用</span>
<span v-if="record.orderStatus == 3" class="ele-text-placeholder"
>已取消</span
>
>已取消</span>
<span v-if="record.orderStatus == 4" class="ele-text-warning"
>退款申请中</span
>
>退款申请中</span>
<span v-if="record.orderStatus == 5" class="ele-text-danger"
>退款被拒绝</span
>
<span v-if="record.orderStatus == 6" class="ele-text-heading"
>退款成功</span
>
>退款被拒绝</span>
<span v-if="record.orderStatus == 6" class="ele-text-heading">退款成功</span>
<span v-if="record.orderStatus == 7" class="ele-text-warning"
>客户端申请退款</span
>
>客户端申请退款</span>
<span v-if="record.orderStatus == 9" class="ele-text-warning"
>未完成</span
>
>未完成</span>
</template>
<template v-if="column.key === 'isInvoice'">
<a-tag
@@ -182,15 +209,15 @@
color="green"
class="cursor-pointer"
@click="openInvoicePdf(record)"
>已开票</a-tag
>
>已开票
</a-tag>
<a-tag
v-if="record.isInvoice == 2"
color="red"
class="cursor-pointer"
@click="onInvoice(record)"
>未开票</a-tag
>
>未开票
</a-tag>
<a-tag v-if="record.isInvoice == 3" color="purple">不能开</a-tag>
</template>
<template v-if="column.key === 'status'">
@@ -200,8 +227,9 @@
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">详情</a>
<!-- <a-divider type="vertical" />-->
<!-- <a @click="openEdit(record)">编辑</a>-->
<a-divider type="vertical" />
<a @click="openRefund(record)"
v-if="record.payStatus === 1 && [1, 3].includes(record.payType) && [1, 2].includes(record.orderStatus)">退款</a>
</a-space>
</template>
</template>
@@ -211,317 +239,327 @@
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 开具发票 -->
<Invoice v-model:visible="showInvoice" :data="current" @done="reload" />
<Refund v-model:visible="showRefund" :data="refundOrder" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import {
ExclamationCircleOutlined,
CheckOutlined,
CloseOutlined,
ClockCircleOutlined,
IdcardOutlined,
WechatOutlined,
CoffeeOutlined,
AlipayCircleOutlined
} from '@ant-design/icons-vue';
import { EleProTable, toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import OrderInfo from './components/orderInfo.vue';
import Invoice from './components/invoice.vue';
import {
pageThinkOrder,
removeThinkOrder,
removeBatchThinkOrder
} from '@/api/think/thinkOrder';
import * as InvoiceApi from '@/api/think/thinkInvoice';
import type {
ThinkOrder,
ThinkOrderParam
} from '@/api/think/thinkOrder/model';
import { formatNumber } from 'ele-admin-pro/es';
import type { ThinkInvoice } from '@/api/think/thinkInvoice/model';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import {
ExclamationCircleOutlined,
CheckOutlined,
CloseOutlined,
AlipayCircleOutlined
} from "@ant-design/icons-vue";
import { EleProTable, toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import OrderInfo from "./components/orderInfo.vue";
import Invoice from "./components/invoice.vue";
import {
pageThinkOrder,
removeThinkOrder,
removeBatchThinkOrder
} from "@/api/think/thinkOrder";
import * as InvoiceApi from "@/api/think/thinkInvoice";
import type {
ThinkOrder,
ThinkOrderParam
} from "@/api/think/thinkOrder/model";
import { formatNumber } from "ele-admin-pro/es";
import type { ThinkInvoice } from "@/api/think/thinkInvoice/model";
import Refund from "@/views/think/thinkOrder/components/refund.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkOrder | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 开具发票弹窗
const showInvoice = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格选中数据
const selection = ref<ThinkOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkOrder | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 开具发票弹窗
const showInvoice = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
return pageThinkOrder({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkOrder({
...where,
...orders,
page,
limit
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
},
{
title: "订单号",
dataIndex: "id",
key: "iod",
width: 90
},
{
title: "姓名",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "手机号",
dataIndex: "phone",
key: "phone",
width: 120,
align: "center"
},
{
title: "预约信息",
dataIndex: "dateTime",
key: "dateTime",
width: 120,
align: "center"
},
{
title: "总额",
dataIndex: "totalPrice",
key: "totalPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "减少金额",
dataIndex: "reducePrice",
key: "reducePrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "实付金额",
dataIndex: "payPrice",
key: "payPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "支付方式",
dataIndex: "payType",
key: "payType",
align: "center"
},
{
title: "IC卡号",
dataIndex: "code",
key: "code",
align: "center"
},
{
title: "付款状态",
dataIndex: "payStatus",
key: "payStatus",
sorter: true,
align: "center"
},
{
title: "付款时间",
dataIndex: "payTime",
key: "payTime",
sorter: true,
align: "center",
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
},
{
title: "订单状态",
dataIndex: "orderStatus",
key: "orderStatus",
align: "center"
},
{
title: "优惠类型",
dataIndex: "couponType",
key: "couponType",
align: "center"
},
{
title: "开票状态",
dataIndex: "isInvoice",
key: "isInvoice",
align: "center",
sorter: true
},
// {
// title: '类型',
// dataIndex: 'type',
// key: 'type',
// align: 'center',
// customRender: ({ text }) =>
// ['商城订单', '客户预定', '俱乐部训练场', '活动订场'][text]
// },
// {
// title: '申请退款时间',
// dataIndex: 'refundApplyTime',
// key: 'refundApplyTime',
// align: 'center',
// customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
// },
// {
// title: '备注',
// dataIndex: 'comments',
// key: 'comments',
// align: 'center'
// },
{
title: "操作",
key: "action",
width: 120,
fixed: "right",
align: "center",
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
const showRefund = ref(false);
const refundOrder = ref<ThinkOrder>();
const openRefund = (row: ThinkOrder) => {
refundOrder.value = row;
showRefund.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkOrder) => {
const hide = message.loading("请求中..", 0);
removeThinkOrder(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '订单号',
dataIndex: 'id',
key: 'iod',
width: 90
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: 'center'
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
width: 120,
align: 'center'
},
{
title: '预约信息',
dataIndex: 'dateTime',
key: 'dateTime',
width: 120,
align: 'center'
},
{
title: '总额',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: '减少金额',
dataIndex: 'reducePrice',
key: 'reducePrice',
align: 'center',
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: '实付金额',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center',
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: '支付方式',
dataIndex: 'payType',
key: 'payType',
align: 'center'
},
{
title: 'IC卡号',
dataIndex: 'code',
key: 'code',
align: 'center'
},
{
title: '付款状态',
dataIndex: 'payStatus',
key: 'payStatus',
sorter: true,
align: 'center'
},
{
title: '付款时间',
dataIndex: 'payTime',
key: 'payTime',
sorter: true,
align: 'center',
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '订单状态',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center'
},
{
title: '优惠类型',
dataIndex: 'couponType',
key: 'couponType',
align: 'center'
},
{
title: '开票状态',
dataIndex: 'isInvoice',
key: 'isInvoice',
align: 'center',
sorter: true
},
// {
// title: '类型',
// dataIndex: 'type',
// key: 'type',
// align: 'center',
// customRender: ({ text }) =>
// ['商城订单', '客户预定', '俱乐部训练场', '活动订场'][text]
// },
// {
// title: '申请退款时间',
// dataIndex: 'refundApplyTime',
// key: 'refundApplyTime',
// align: 'center',
// customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
// },
// {
// title: '备注',
// dataIndex: 'comments',
// key: 'comments',
// align: 'center'
// },
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
align: 'center',
hideInSetting: true
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkOrder(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
]);
});
};
/* 搜索 */
const reload = (where?: ThinkOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 开具发票 */
const onInvoice = (row?: ThinkOrder) => {
console.log(row?.payStatus);
if (row?.payStatus != 1) {
return false;
}
current.value = row ?? null;
showInvoice.value = true;
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkOrder) => {
const hide = message.loading('请求中..', 0);
removeThinkOrder(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkOrder(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
const openInvoicePdf = (row?: ThinkInvoice) => {
if (row?.id) {
InvoiceApi.showInvoice(row?.id).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
window.open(pdfUrl);
});
};
}
};
/* 开具发票 */
const onInvoice = (row?: ThinkOrder) => {
console.log(row?.payStatus);
if (row?.payStatus != 1) {
return false;
}
current.value = row ?? null;
showInvoice.value = true;
};
/* 查询 */
const query = () => {
loading.value = true;
};
const openInvoicePdf = (row?: ThinkInvoice) => {
if (row?.id) {
InvoiceApi.showInvoice(row?.id).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
window.open(pdfUrl);
});
/* 自定义行属性 */
const customRow = (record: ThinkOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
};
query();
</script>
<script lang="ts">
import * as MenuIcons from '@/layout/menu-icons';
export default {
name: 'ThinkOrder',
components: MenuIcons
};
import * as MenuIcons from "@/layout/menu-icons";
export default {
name: "ThinkOrder",
components: MenuIcons
};
</script>
<style lang="less" scoped>
.tag-icon {
padding-right: 6px;
}
.tag-icon {
padding-right: 6px;
}
</style>
@@ -0,0 +1,306 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '开具发票2' : '开具发票'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<!-- <a-form-item label="订单编号" name="incoiveNum">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入发票的订单"-->
<!-- v-model:value="form.incoiveNum"-->
<!-- />-->
<!-- </a-form-item>-->
<!-- <a-form-item label="纳税人识别号" name="incoiveCode">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入纳税人识别号"-->
<!-- v-model:value="form.incoiveCode"-->
<!-- />-->
<!-- </a-form-item>-->
<!-- <a-form-item label="订单号" name="orderNum">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入订单号"-->
<!-- v-model:value="form.orderNum"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="发票金额" name="price">
<a-input
allow-clear
placeholder="请输入发票金额"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="单位名称" name="name">
<a-input
allow-clear
placeholder="请输入单位名称"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="税号" name="code">
<a-input
allow-clear
placeholder="请输入税号"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="开户行" name="bank">
<a-input
allow-clear
placeholder="请输入开户行"
v-model:value="form.bank"
/>
</a-form-item>
<a-form-item label="开户账号" name="account">
<a-input
allow-clear
placeholder="请输入开户账号"
v-model:value="form.account"
/>
</a-form-item>
<a-form-item label="单位地址" name="address">
<a-input
allow-clear
placeholder="请输入单位地址"
v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="公司电话" name="tel">
<a-input
allow-clear
placeholder="请输入公司电话"
v-model:value="form.tel"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="电子邮箱" name="email">
<a-input
allow-clear
placeholder="请输入电子邮箱"
v-model:value="form.email"
/>
</a-form-item>
<a-form-item label="备注信息" name="info">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入备注信息"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="发票类型" name="type">
<a-radio-group v-model:value="form.type">
<a-radio :value="1">纸质发票</a-radio>
<a-radio :value="2">电子发票</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="发票类型" name="itype">
<a-radio-group v-model:value="form.itype" :disabled="true">
<a-radio :value="1">场地发票</a-radio>
<a-radio :value="2">vip卡发票</a-radio>
<a-radio :value="2">ic卡发票</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="发票类型" name="invoicetype">
<a-radio-group v-model:value="form.invoicetype">
<a-radio :value="1">普票</a-radio>
<a-radio :value="2">专票</a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import {
addThinkInvoice,
doInvoice,
pageThinkInvoice,
updateThinkInvoice
} from '@/api/think/thinkInvoice';
import { ThinkInvoice } from '@/api/think/thinkInvoice/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { FormInstance } from 'ant-design-vue/es/form';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 用户信息
const form = reactive<ThinkInvoice>({
id: undefined,
incoiveNum: undefined,
incoiveCode: undefined,
orderNum: undefined,
oid: undefined,
uid: undefined,
price: undefined,
name: undefined,
tel: undefined,
address: undefined,
bank: undefined,
account: undefined,
code: undefined,
phone: undefined,
email: undefined,
info: undefined,
isOpen: undefined,
type: 2,
itype: 1,
invoicetype: 1,
createTime: undefined,
updateTime: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
price: [
{
required: true,
type: 'number',
message: '请填写发票金额',
trigger: 'blur'
}
],
name: [
{
required: true,
type: 'string',
message: '请填写单位名称',
trigger: 'blur'
}
],
code: [
{
required: true,
type: 'string',
message: '请填写税号',
trigger: 'blur'
}
]
});
const onChangeInvoice = (data: ThinkInvoice) => {
console.log(data);
console.log(form);
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
// const saveOrUpdate = isUpdate.value
// ? updateThinkInvoice
// : addThinkInvoice;
doInvoice(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
// 第一次开票
isUpdate.value = false;
form.oid = props.data?.id;
form.price = props.data?.totalPrice;
form.incoiveNum = props.data?.orderNum;
form.orderNum = props.data?.orderNum;
form.vid = props.data?.vid;
form.phone = props.data?.phone;
// 开过票
pageThinkInvoice({ uid: props.data?.uid, limit: 1 }).then((res) => {
if (res && res.list.length > 0) {
assignObject(form, res?.list[0]);
isUpdate.value = true;
form.oid = props.data?.id;
form.price = props.data?.payPrice;
form.incoiveNum = props.data?.orderNum;
form.vid = props.data?.vid;
form.phone = props.data?.phone;
}
});
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,429 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="`80%`"
:visible="visible"
:confirm-loading="loading"
:maxable="maxAble"
:title="isUpdate ? '编辑订单' : '订单详情'"
:body-style="{ paddingBottom: '8px', background: '#f3f3f3' }"
@update:visible="updateVisible"
:maskClosable="false"
:footer="null"
@ok="save"
>
<a-card class="order-card" :bordered="false">
<a-descriptions title="基本信息" :column="3">
<a-descriptions-item
label="订单号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.id }}
</a-descriptions-item>
<a-descriptions-item
label="订单编号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.orderNum }}
</a-descriptions-item>
<a-descriptions-item
label="订单状态"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<a-tag v-if="form.orderStatus == 1">已完成</a-tag>
<a-tag v-if="form.orderStatus == 2">未使用</a-tag>
<a-tag v-if="form.orderStatus == 3">已取消</a-tag>
<a-tag v-if="form.orderStatus == 4">退款申请中</a-tag>
<a-tag v-if="form.orderStatus == 5">退款被拒绝</a-tag>
<a-tag v-if="form.orderStatus == 6">退款成功</a-tag>
<a-tag v-if="form.orderStatus == 7">客户端申请退款</a-tag>
</a-descriptions-item>
<a-descriptions-item
label="买家信息"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.name }}
</a-descriptions-item>
<a-descriptions-item
label="手机号码"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.phone }}
</a-descriptions-item>
<a-descriptions-item
label="交易流水号"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ form.wechatOrder }}
</a-descriptions-item>
<a-descriptions-item
label="订单总金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.totalPrice }}
</a-descriptions-item>
<a-descriptions-item
label="实付金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.payPrice }}
</a-descriptions-item>
<a-descriptions-item
label="减少的金额"
:labelStyle="{ width: '90px', color: '#808080' }"
>
¥{{ form.reducePrice }}
</a-descriptions-item>
<a-descriptions-item
label="支付方式"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<template v-if="form.payStatus == 1">
<a-tag v-if="form.payType == 0">余额支付</a-tag>
<a-tag v-if="form.payType == 1">微信支付</a-tag>
<a-tag v-if="form.payType == 2">积分</a-tag>
<a-tag v-if="form.payType == 3">支付宝</a-tag>
<a-tag v-if="form.payType == 4">现金</a-tag>
<a-tag v-if="form.payType == 5">POS机</a-tag>
<a-tag v-if="form.payType == 6">VIP月卡</a-tag>
<a-tag v-if="form.payType == 7">formVIP年卡</a-tag>
<a-tag v-if="form.payType == 8">formVIP次卡</a-tag>
<a-tag v-if="form.payType == 9">formIC月卡</a-tag>
<a-tag v-if="form.payType == 10">formIC年卡</a-tag>
<a-tag v-if="form.payType == 11">formIC次卡</a-tag>
<a-tag v-if="form.payType == 12">form免费</a-tag>
<a-tag v-if="form.payType == 13">formVIP充值卡</a-tag>
<a-tag v-if="form.payType == 14">formIC充值卡</a-tag>
<a-tag v-if="form.payType == 15">form积分支付</a-tag>
<a-tag v-if="form.payType == 16">formVIP季卡</a-tag>
<a-tag v-if="form.payType == 17">formIC季卡</a-tag>
</template>
<template v-else>
<span></span>
</template>
</a-descriptions-item>
<a-descriptions-item
label="支付状态"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<a-tag v-if="form.payStatus == 1" color="green"
><CheckOutlined class="tag-icon" />已付款</a-tag
>
<a-tag v-if="form.payStatus == 0" color="error"
><CloseOutlined class="tag-icon" />未付款</a-tag
>
<a-tag v-if="form.payStatus == 3" color="cyan"
><CoffeeOutlined class="tag-icon" />未付款,占场中</a-tag
>
</a-descriptions-item>
<a-descriptions-item
label="付款时间"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ toDateString(form.payTime, 'yyyy-MM-dd HH:mm') }}
</a-descriptions-item>
<a-descriptions-item
label="下单时间"
:labelStyle="{ width: '90px', color: '#808080' }"
>
{{ toDateString(form.createTime, 'yyyy-MM-dd HH:mm') }}
</a-descriptions-item>
<a-descriptions-item
label="信息备注"
:labelStyle="{ width: '90px', color: '#808080' }"
>
<div
>{{ form.siteName }} {{ form.dateTime }} ¥{{
form.totalPrice
}}元</div
>
</a-descriptions-item>
</a-descriptions>
</a-card>
<a-card class="order-card" :bordered="false">
<a-spin :spinning="loading">
<a-table
:data-source="orderInfo"
:columns="columns"
:pagination="false"
/>
</a-spin>
</a-card>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { ColumnItem } from 'ele-admin-pro/es/ele-pro-table/types';
import {
CheckOutlined,
CloseOutlined,
CoffeeOutlined
} from '@ant-design/icons-vue';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
import { ThinkOrderInfo } from '@/api/think/thinkOrderInfo/model';
import { pageThinkOrderInfo } from '@/api/think/thinkOrderInfo';
import { toDateString } from 'ele-admin-pro';
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
export interface step {
title?: String | undefined;
subTitle?: String | undefined;
description?: String | undefined;
}
// 是否是修改
const isUpdate = ref(false);
// 是否显示最大化切换按钮
const maxAble = ref(true);
// 订单信息
const orderInfo = ref<ThinkOrderInfo[]>([]);
// 步骤条
const steps = ref<step[]>([
{
title: '报餐',
description: undefined
},
{
title: '付款',
description: undefined
},
{
title: '发餐',
description: undefined
},
{
title: '取餐',
description: undefined
},
{
title: '完成',
description: undefined
}
]);
const active = ref(2);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 订单信息
const form = reactive<ThinkOrder>({
id: undefined,
orderNum: undefined,
wechatOrder: undefined,
refundOrder: undefined,
sid: undefined,
uid: undefined,
cid: undefined,
vid: undefined,
aid: undefined,
adminId: undefined,
code: undefined,
name: undefined,
phone: undefined,
totalPrice: undefined,
reducePrice: undefined,
payPrice: undefined,
price: undefined,
money: undefined,
dateTime: undefined,
refundMoney: undefined,
coachPrice: undefined,
coachId: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
type: undefined,
qrcode: undefined,
desc2: undefined,
returnNum: undefined,
returnMoney: undefined,
startTime: undefined,
isInvoice: undefined,
createTime: undefined,
updateTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined,
siteName: undefined
});
// 请求状态
const loading = ref(true);
const { resetFields } = useForm(form);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const columns = ref<ColumnItem[]>([
{
title: '场馆名称',
dataIndex: 'siteName',
key: 'siteName',
align: 'center'
},
{
title: '场地',
dataIndex: 'fieldName',
align: 'center'
},
{
title: '价格',
dataIndex: 'price',
align: 'center'
},
{
title: '儿童价',
dataIndex: 'childrenPrice',
align: 'center'
},
{
title: '成人数',
dataIndex: 'adultNum',
align: 'center'
},
{
title: '儿童数',
dataIndex: 'childrenNum',
align: 'center'
},
{
title: '预定信息',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center'
},
{
title: '是否免费',
dataIndex: 'isFree',
align: 'center',
customRender: ({ text }) => ['', '免费', '付费'][text]
}
]);
/* 制作步骤条 */
const loadSteps = (order) => {
steps.value = [];
steps.value.push({
title: '下单'
});
steps.value.push({
title: '付款'
});
steps.value.push({
title: '发货'
});
steps.value.push({
title: '收货'
});
steps.value.push({
title: '完成'
});
// 下单
if (order.payStatus == 10) {
active.value = 0;
steps.value[0].description = order.createTime;
}
// 付款
if (order.payStatus == 20) {
active.value = 1;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
}
// 发货
if (order.payStatus == 20 && order.deliveryStatus == 20) {
active.value = 2;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
}
// 收货
if (order.payStatus == 20 && order.receiptStatus == 20) {
active.value = 3;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
steps.value[3].description = order.receiptTime;
}
// 完成
if (order.payStatus == 20 && order.orderStatus == 30) {
active.value = 4;
steps.value[0].description = order.createTime;
steps.value[1].description = order.payTime;
steps.value[2].description = order.deliveryTime;
steps.value[3].description = order.receiptTime;
}
// 已取消
if (order.orderStatus == 20) {
active.value = 4;
}
};
// const getOrderInfo = () => {
// const orderId = props.data?.orderId;
// listOrderInfo({ orderId }).then((data) => {
// orderInfo.value = data.filter((d) => d.totalNum > 0);
// });
// };
/* 保存编辑 */
const save = () => {};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
loading.value = true;
assignObject(form, props.data);
pageThinkOrderInfo({ oid: form.id }).then((res) => {
if (res?.list) {
orderInfo.value = res?.list;
}
loading.value = false;
});
loadSteps(props.data);
}
} else {
resetFields();
}
}
);
</script>
<style lang="less" scoped>
.order-card {
margin-bottom: 20px;
}
.ant-form-item {
margin-bottom: 5px;
}
.order-info {
display: flex;
.info {
padding-left: 5px;
display: flex;
flex-direction: column;
}
}
.tag-icon {
padding-right: 6px;
}
</style>
@@ -0,0 +1,112 @@
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
:width="`60%`"
:visible="visible"
:confirm-loading="loading"
title="退款"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
:maskClosable="false"
@ok="save"
>
<a-form>
<a-form-item label="订单金额">
<span>{{ data.totalPrice }}元</span>
</a-form-item>
<a-form-item label="支付金额">
<span>{{ data.payPrice }}元</span>
</a-form-item>
<a-form-item label="退款金额">
<a-input-number placeholder="请输入退款金额" style="width: 300px" v-model:value="form.refundAmount"
:max="data.payPrice" />
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from "vue";
import { ThinkOrder } from "@/api/think/thinkOrder/model";
import { ThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog/model";
import { message } from "ant-design-vue";
import { addThinkOrderRefundLog } from "@/api/think/thinkOrderRefundLog";
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data: ThinkOrder;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
const form = reactive<ThinkOrderRefundLog>({
int: undefined,
uid: undefined,
refundAmount: undefined,
sid: undefined,
oid: undefined,
status: 1,
type: 0
});
// 请求状态
const loading = ref(false);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
const save = async () => {
if (!form.refundAmount) return message.error("请输入退款金额");
loading.value = true;
await addThinkOrderRefundLog(form);
loading.value = false;
message.success("已提交");
updateVisible(false);
emit("done");
};
watch(
() => props.visible,
(visible) => {
if (visible) {
loading.value = false;
if (props.data) {
form.uid = props.data.uid;
form.oid = props.data.id;
form.sid = props.data.sid;
form.refundAmount = 0;
}
}
}
);
</script>
<style lang="less" scoped>
.order-card {
margin-bottom: 20px;
}
.ant-form-item {
margin-bottom: 5px;
}
.order-info {
display: flex;
.info {
padding-left: 5px;
display: flex;
flex-direction: column;
}
}
.tag-icon {
padding-right: 6px;
}
</style>
@@ -0,0 +1,179 @@
<!-- 搜索表单 -->
<template>
<div>
<a-space class="flex items-center" :size="10" style="flex-wrap: wrap">
<ThinkSelectSite
:placeholder="`选择场馆`"
class="input-item"
v-model:value="where.siteName"
@done="chooseSiteId"
/>
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入订单号|编号|手机号"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
</a-space>
<p class="text-red-400 font-bold mt-2">总金额: {{ totalAmount }}元</p>
</div>
</template>
<script lang="ts" setup>
import useSearch from '@/utils/use-search';
import { ref, watch } from 'vue';
import { ThinkOrderInfoParam } from '@/api/think/thinkOrderInfo/model';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
import { toDateString } from 'ele-admin-pro';
import dayjs from 'dayjs';
import { listThinkOrder } from '@/api/think/thinkOrder';
import { ThinkOrder, ThinkOrderParam } from '@/api/think/thinkOrder/model';
import { ThinkSite } from '@/api/think/thinkSite/model';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
totalAmount?: 0;
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkOrderInfoParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'advanced'): void;
}>();
// 表单数据
const { where, resetFields } = useSearch<ThinkOrderParam>({
sid: undefined,
siteName: undefined,
createTimeStart: undefined,
createTimeEnd: undefined,
timeStart: undefined,
timeEnd: undefined,
categoryId: undefined,
keywords: undefined,
payStatus: undefined,
orderStatus: undefined,
payType: undefined,
isInvoice: undefined,
});
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<ThinkOrder[] | any[]>();
const xlsFileName = ref<string>();
/* 搜索 */
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
// where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
// where.createTimeEnd = d2 ? d2 + ' 00:00:00' : undefined;
emit('search', {
...where
});
};
const chooseSiteId = (data: ThinkSite) => {
where.sid = data.id;
where.siteName = data.name;
search();
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'订单号',
'订单编号',
'姓名',
'电话号码',
'预定信息',
'消费金额',
'实付金额',
'下单日期'
]
];
if (!where.timeStart) {
message.error('请选择导出的开始日期、结束日期,每次最多导出5000条记录');
return false;
}
await listThinkOrder(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkOrder) => {
array.push([
`${d.id}`,
`${d.orderNum}`,
`${d.name}`,
`${d.phone}`,
`${d.siteName} ${d.dateTime} ${d.totalPrice}`,
`${d.totalPrice}`,
`${d.payPrice}`,
`${toDateString(d.payTime)}`
]);
});
const sheetName = `订单数据导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {});
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,465 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑' : '添加'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="订单号" name="orderNum">
<a-input
allow-clear
placeholder="请输入订单号"
v-model:value="form.orderNum"
/>
</a-form-item>
<a-form-item label="微信支付订单号" name="wechatOrder">
<a-input
allow-clear
placeholder="请输入微信支付订单号"
v-model:value="form.wechatOrder"
/>
</a-form-item>
<a-form-item label="微信退款订单号" name="refundOrder">
<a-input
allow-clear
placeholder="请输入微信退款订单号"
v-model:value="form.refundOrder"
/>
</a-form-item>
<a-form-item label="场馆id用于权限判断" name="sid">
<a-input
allow-clear
placeholder="请输入场馆id用于权限判断"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="用户id" name="uid">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="使用的优惠券id" name="cid">
<a-input
allow-clear
placeholder="请输入使用的优惠券id"
v-model:value="form.cid"
/>
</a-form-item>
<a-form-item label="使用的会员卡id" name="vid">
<a-input
allow-clear
placeholder="请输入使用的会员卡id"
v-model:value="form.vid"
/>
</a-form-item>
<a-form-item label="关联管理员id" name="aid">
<a-input
allow-clear
placeholder="请输入关联管理员id"
v-model:value="form.aid"
/>
</a-form-item>
<a-form-item label="核销管理员id" name="adminId">
<a-input
allow-clear
placeholder="请输入核销管理员id"
v-model:value="form.adminId"
/>
</a-form-item>
<a-form-item label="IC卡号" name="code">
<a-input
allow-clear
placeholder="请输入IC卡号"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="真实姓名" name="name">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="订单总额" name="totalPrice">
<a-input
allow-clear
placeholder="请输入订单总额"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item
label="减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
name="reducePrice"
>
<a-input
allow-clear
placeholder="请输入减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
v-model:value="form.reducePrice"
/>
</a-form-item>
<a-form-item label="实际付款" name="payPrice">
<a-input
allow-clear
placeholder="请输入实际付款"
v-model:value="form.payPrice"
/>
</a-form-item>
<a-form-item label="用于统计" name="price">
<a-input
allow-clear
placeholder="请输入用于统计"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="价钱,用于积分赠送" name="money">
<a-input
allow-clear
placeholder="请输入价钱,用于积分赠送"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="退款金额" name="refundMoney">
<a-input
allow-clear
placeholder="请输入退款金额"
v-model:value="form.refundMoney"
/>
</a-form-item>
<a-form-item label="教练价格" name="coachPrice">
<a-input
allow-clear
placeholder="请输入教练价格"
v-model:value="form.coachPrice"
/>
</a-form-item>
<a-form-item label="教练id" name="coachId">
<a-input
allow-clear
placeholder="请输入教练id"
v-model:value="form.coachId"
/>
</a-form-item>
<a-form-item
label="1微信支付,2积分,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡"
name="payType"
>
<a-input
allow-clear
placeholder="请输入1微信支付,2积分,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="1已付款,2未付款" name="payStatus">
<a-input
allow-clear
placeholder="请输入1已付款,2未付款"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item
label="1已完成,2未使用,3已取消,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
name="orderStatus"
>
<a-input
allow-clear
placeholder="请输入1已完成,2未使用,3已取消,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item
label="优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
name="type"
>
<a-input
allow-clear
placeholder="请输入优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item
label="二维码地址,保存订单号,支付成功后才生成"
name="qrcode"
>
<a-input
allow-clear
placeholder="请输入二维码地址,保存订单号,支付成功后才生成"
v-model:value="form.qrcode"
/>
</a-form-item>
<a-form-item label="优惠说明" name="desc2">
<a-input
allow-clear
placeholder="请输入优惠说明"
v-model:value="form.desc2"
/>
</a-form-item>
<a-form-item label="vip月卡年卡、ic月卡年卡回退次数" name="returnNum">
<a-input
allow-clear
placeholder="请输入vip月卡年卡、ic月卡年卡回退次数"
v-model:value="form.returnNum"
/>
</a-form-item>
<a-form-item label="vip充值回退金额" name="returnMoney">
<a-input
allow-clear
placeholder="请输入vip充值回退金额"
v-model:value="form.returnMoney"
/>
</a-form-item>
<a-form-item label="预约详情开始时间数组" name="startTime">
<a-input
allow-clear
placeholder="请输入预约详情开始时间数组"
v-model:value="form.startTime"
/>
</a-form-item>
<a-form-item
label="是否已开具发票:1已开发票,2未开发票,3不能开具发票"
name="isInvoice"
>
<a-input
allow-clear
placeholder="请输入是否已开具发票:1已开发票,2未开发票,3不能开具发票"
v-model:value="form.isInvoice"
/>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="付款时间" name="payTime">
<a-input
allow-clear
placeholder="请输入付款时间"
v-model:value="form.payTime"
/>
</a-form-item>
<a-form-item label="退款时间" name="refundTime">
<a-input
allow-clear
placeholder="请输入退款时间"
v-model:value="form.refundTime"
/>
</a-form-item>
<a-form-item label="申请退款时间" name="refundApplyTime">
<a-input
allow-clear
placeholder="请输入申请退款时间"
v-model:value="form.refundApplyTime"
/>
</a-form-item>
<a-form-item
label="对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单"
name="checkBill"
>
<a-input
allow-clear
placeholder="请输入对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单"
v-model:value="form.checkBill"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkOrder, updateThinkOrder } from '@/api/think/thinkOrder';
import { ThinkOrder } from '@/api/think/thinkOrder/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkOrder | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkOrder>({
id: undefined,
orderNum: undefined,
wechatOrder: undefined,
refundOrder: undefined,
sid: undefined,
uid: undefined,
cid: undefined,
vid: undefined,
aid: undefined,
adminId: undefined,
code: undefined,
name: undefined,
phone: undefined,
totalPrice: undefined,
reducePrice: undefined,
payPrice: undefined,
price: undefined,
money: undefined,
refundMoney: undefined,
coachPrice: undefined,
coachId: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
type: undefined,
qrcode: undefined,
desc2: undefined,
returnNum: undefined,
returnMoney: undefined,
startTime: undefined,
isInvoice: undefined,
createTime: undefined,
updateTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkOrder : addThinkOrder;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if (props.data.image) {
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
});
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+527
View File
@@ -0,0 +1,527 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 800 }"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
:totalAmount="totalAmount"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'dateTime'">
<div>{{ record.siteName }}</div>
<div>{{ record.dateTime }} ¥{{ record.totalPrice }}元</div>
</template>
<template v-if="column.key === 'payType'">
<template v-if="record.payStatus == 1">
<a-tag v-if="record.payType == 0">余额支付</a-tag>
<a-tag v-if="record.payType == 1">
<WechatOutlined class="tag-icon" />
微信支付
</a-tag>
<a-tag v-if="record.payType == 2">积分</a-tag>
<a-tag v-if="record.payType == 3">
<AlipayCircleOutlined class="tag-icon" />
支付宝
</a-tag>
<a-tag v-if="record.payType == 4">
<IdcardOutlined class="tag-icon" />
现金
</a-tag>
<a-tag v-if="record.payType == 5">
<IdcardOutlined class="tag-icon" />
POS机
</a-tag>
<a-tag v-if="record.payType == 6">
<IdcardOutlined class="tag-icon" />
VIP月卡
</a-tag>
<a-tag v-if="record.payType == 7">
<IdcardOutlined class="tag-icon" />
VIP年卡
</a-tag>
<a-tag v-if="record.payType == 8">
<IdcardOutlined class="tag-icon" />
VIP次卡
</a-tag>
<a-tag v-if="record.payType == 9">
<IdcardOutlined class="tag-icon" />
IC月卡
</a-tag>
<a-tag v-if="record.payType == 10">
<IdcardOutlined class="tag-icon" />
IC年卡
</a-tag>
<a-tag v-if="record.payType == 11">
<IdcardOutlined class="tag-icon" />
IC次卡
</a-tag>
<a-tag v-if="record.payType == 12">
<IdcardOutlined class="tag-icon" />
免费
</a-tag>
<a-tag v-if="record.payType == 13">
<IdcardOutlined class="tag-icon" />
VIP充值卡
</a-tag>
<a-tag v-if="record.payType == 14">
<IdcardOutlined class="tag-icon" />
IC充值卡
</a-tag>
<a-tag v-if="record.payType == 15">
<IdcardOutlined class="tag-icon" />
积分支付
</a-tag>
<a-tag v-if="record.payType == 16">
<IdcardOutlined class="tag-icon" />
VIP季卡
</a-tag>
<a-tag v-if="record.payType == 17">
<IdcardOutlined class="tag-icon" />
IC季卡
</a-tag>
</template>
<template v-else>
<span></span>
</template>
</template>
<template v-if="column.key === 'couponType'">
<a-tag v-if="record.couponType == 0">无</a-tag>
<a-tag v-if="record.couponType == 1" color="blue">
<IdcardOutlined class="tag-icon" />
抵扣优惠券
</a-tag>
<a-tag v-if="record.couponType == 2" color="blue">
<IdcardOutlined class="tag-icon" />
折扣优惠券
</a-tag>
<a-tag v-if="record.couponType == 3" color="blue">
<IdcardOutlined class="tag-icon" />
VIP月卡
</a-tag>
<a-tag v-if="record.couponType == 4" color="blue">
<IdcardOutlined class="tag-icon" />
VIP年卡
</a-tag>
<a-tag v-if="record.couponType == 5" color="blue">
<IdcardOutlined class="tag-icon" />
VIP次卡
</a-tag>
<a-tag v-if="record.couponType == 6" color="blue">
<IdcardOutlined class="tag-icon" />
VIP会员卡
</a-tag>
<a-tag v-if="record.couponType == 7" color="blue">
<IdcardOutlined class="tag-icon" />
IC月卡
</a-tag>
<a-tag v-if="record.couponType == 8" color="blue">
<IdcardOutlined class="tag-icon" />
IC年卡
</a-tag>
<a-tag v-if="record.couponType == 9" color="blue">
<IdcardOutlined class="tag-icon" />
IC次卡
</a-tag>
<a-tag v-if="record.couponType == 10" color="blue">
<IdcardOutlined class="tag-icon" />
IC会员卡
</a-tag>
<a-tag v-if="record.couponType == 11" color="blue"
>
<IdcardOutlined class="tag-icon" />
免费订单
</a-tag>
<a-tag v-if="record.couponType == 12" color="blue">
<IdcardOutlined class="tag-icon" />
VIP充值卡
</a-tag>
<a-tag v-if="record.couponType == 13" color="blue">
<IdcardOutlined class="tag-icon" />
IC充值卡
</a-tag>
<a-tag v-if="record.couponType == 14" color="blue">
<IdcardOutlined class="tag-icon" />
VIP季卡
</a-tag>
<a-tag v-if="record.couponType == 15" color="blue">
<IdcardOutlined class="tag-icon" />
IC季卡
</a-tag>
</template>
<template v-if="column.key === 'payStatus'">
<a-tag v-if="record.payStatus == 2" color="error">
<CloseOutlined class="tag-icon" />
未付款
</a-tag>
<a-tag v-if="record.payStatus == 1" color="green">
<CheckOutlined class="tag-icon" />
已付款
</a-tag>
<a-tag
v-if="record.payStatus == 3 || record.payStatus == 0"
color="cyan">
<CoffeeOutlined class="tag-icon" />
未付款,占场中
</a-tag>
</template>
<template v-if="column.key === 'orderInfo'">
{{ record.orderInfoList }}
</template>
<template v-if="column.key === 'orderStatus'">
<span v-if="record.orderStatus == 1" class="ele-text-success"
>已完成</span>
<span v-if="record.orderStatus == 2" class="ele-text-placeholder"
>未使用</span>
<span v-if="record.orderStatus == 3" class="ele-text-placeholder"
>已取消</span>
<span v-if="record.orderStatus == 4" class="ele-text-warning"
>退款申请中</span>
<span v-if="record.orderStatus == 5" class="ele-text-danger"
>退款被拒绝</span>
<span v-if="record.orderStatus == 6" class="ele-text-heading">退款成功</span>
<span v-if="record.orderStatus == 7" class="ele-text-warning"
>客户端申请退款</span>
<span v-if="record.orderStatus == 9" class="ele-text-warning"
>未完成</span>
</template>
<template v-if="column.key === 'isInvoice'">
<a-tag
v-if="record.isInvoice == 1"
color="green"
class="cursor-pointer"
@click="openInvoicePdf(record)"
>已开票
</a-tag>
<a-tag
v-if="record.isInvoice == 2"
color="red"
class="cursor-pointer"
@click="onInvoice(record)"
>未开票
</a-tag>
<a-tag v-if="record.isInvoice == 3" color="purple">不能开</a-tag>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">详情</a>
<a-divider type="vertical" />
<a @click="openRefund(record)"
v-if="record.payStatus === 1 && [1, 3].includes(record.payType) && [1, 2].includes(record.orderStatus)">退款</a>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 开具发票 -->
<Invoice v-model:visible="showInvoice" :data="current" @done="reload" />
<Refund v-model:visible="showRefund" :data="refundOrder" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import {
ExclamationCircleOutlined,
CheckOutlined,
CloseOutlined,
AlipayCircleOutlined
} from "@ant-design/icons-vue";
import { EleProTable, toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import OrderInfo from "./components/orderInfo.vue";
import Invoice from "./components/invoice.vue";
import {
pageThinkOrder,
removeThinkOrder,
removeBatchThinkOrder, thinkOrderTotalAmount
} from "@/api/think/thinkOrder";
import * as InvoiceApi from "@/api/think/thinkInvoice";
import type {
ThinkOrder,
ThinkOrderParam
} from "@/api/think/thinkOrder/model";
import { formatNumber } from "ele-admin-pro/es";
import type { ThinkInvoice } from "@/api/think/thinkInvoice/model";
import Refund from "@/views/think/thinkOrder/components/refund.vue";
import { thinkVipCardsBillsTotalAmount } from "@/api/think/thinkVipCardsBills";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkOrder | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 开具发票弹窗
const showInvoice = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
where.payStatus = 1;
getTotalAmount(where);
return pageThinkOrder({
...where,
...orders,
page,
limit
});
};
const totalAmount = ref();
const getTotalAmount = async (where) => {
totalAmount.value = await thinkOrderTotalAmount(where);
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "姓名",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "手机号",
dataIndex: "phone",
key: "phone",
width: 120,
align: "center"
},
{
title: "预约信息",
dataIndex: "dateTime",
key: "dateTime",
width: 120,
align: "center"
},
{
title: "总额",
dataIndex: "totalPrice",
key: "totalPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "减少金额",
dataIndex: "reducePrice",
key: "reducePrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "实付金额",
dataIndex: "payPrice",
key: "payPrice",
align: "center",
sorter: true,
customRender: ({ text }) => `¥${formatNumber(text)}`
},
{
title: "支付方式",
dataIndex: "payType",
key: "payType",
align: "center"
},
{
title: "IC卡号",
dataIndex: "code",
key: "code",
align: "center"
},
{
title: "付款状态",
dataIndex: "payStatus",
key: "payStatus",
sorter: true,
align: "center"
},
{
title: "付款时间",
dataIndex: "payTime",
key: "payTime",
sorter: true,
align: "center",
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
},
{
title: "订单状态",
dataIndex: "orderStatus",
key: "orderStatus",
align: "center"
},
{
title: "优惠类型",
dataIndex: "couponType",
key: "couponType",
align: "center"
}
]);
/* 搜索 */
const reload = (where?: ThinkOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
const showRefund = ref(false);
const refundOrder = ref<ThinkOrder>();
const openRefund = (row: ThinkOrder) => {
refundOrder.value = row;
showRefund.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkOrder) => {
const hide = message.loading("请求中..", 0);
removeThinkOrder(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkOrder(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 开具发票 */
const onInvoice = (row?: ThinkOrder) => {
console.log(row?.payStatus);
if (row?.payStatus != 1) {
return false;
}
current.value = row ?? null;
showInvoice.value = true;
};
const openInvoicePdf = (row?: ThinkInvoice) => {
if (row?.id) {
InvoiceApi.showInvoice(row?.id).then((res) => {
const parse = JSON.parse(res);
const pdfUrl = parse[0].pdfUrl;
window.open(pdfUrl);
});
}
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
import * as MenuIcons from "@/layout/menu-icons";
export default {
name: "ThinkOrder",
components: MenuIcons
};
</script>
<style lang="less" scoped>
.tag-icon {
padding-right: 6px;
}
</style>
@@ -14,10 +14,6 @@
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="场地名称" name="name">
<a-input
@@ -32,23 +28,7 @@
size="120"
shape="square"
/>
<!-- <SelectFile-->
<!-- :placeholder="`请选择图片`"-->
<!-- :limit="1"-->
<!-- :data="images"-->
<!-- @done="chooseImage"-->
<!-- @del="onDeleteItem"-->
<!-- />-->
</a-form-item>
<!-- <a-form-item label="场馆图片" name="files">-->
<!-- <SelectFile-->
<!-- :placeholder="`请选择图片`"-->
<!-- :limit="9"-->
<!-- :data="files"-->
<!-- @done="chooseFiles"-->
<!-- @del="onDeleteFiles"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="每小时价格" name="price">
<a-input-number
allow-clear
@@ -63,6 +43,11 @@
v-model:value="form.businessTime"
/>
</a-form-item>
<a-form-item label="场馆所在区域" name="address">
<a-cascader v-model:value="city" :options="areaList" placeholder="点击选择省市"
:field-names="areaFieldNames"
@change="changeArea" />
</a-form-item>
<a-form-item label="场馆地址" name="address">
<a-input
allow-clear
@@ -70,6 +55,36 @@
v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="场馆面积" name="size">
<a-input
allow-clear
placeholder="请输入场馆面积"
v-model:value="form.size"
>
<template #addonAfter>㎡</template>
</a-input>
</a-form-item>
<a-form-item label="产权证书/不动产权证号" name="realPropertyCertificate">
<a-input
allow-clear
placeholder="请输入产权证书/不动产权证号"
v-model:value="form.realPropertyCertificate"
/>
</a-form-item>
<a-form-item label="租赁开始日期" name="rentStartDate">
<a-date-picker
placeholder="请选择租赁开始日期"
value-format="YYYY-MM-DD"
v-model:value="form.rentStartDate"
/>
</a-form-item>
<a-form-item label="租赁结束日期" name="rentEndDate">
<a-date-picker
placeholder="请选择租赁结束日期"
value-format="YYYY-MM-DD"
v-model:value="form.rentEndDate"
/>
</a-form-item>
<a-form-item label="场馆定位" name="address">
<p>已选经纬度:{{ form.lng }}. {{ form.lat }}</p>
<tdt-map :center="mapState.center" :zoom="mapState.zoom" style="width: 100%; height: 700px" :controls="['Zoom']"
@@ -98,37 +113,59 @@
v-model:value="form.tel"
/>
</a-form-item>
<a-form-item label="类型" name="type">
<a-input
allow-clear
placeholder="请输入类型:1天,2小时"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="天数或小时" name="num">
<a-input
allow-clear
placeholder="请输入天数或小时"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="退款比率" name="proportion">
<a-input
allow-clear
placeholder="请输入退款比率"
v-model:value="form.proportion"
/>
</a-form-item>
<!-- <a-form-item label="退款规则组" name="moneyJson">-->
<!-- <a-form-item label="类型" name="type">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入退款规则组"-->
<!-- v-model:value="form.moneyJson"-->
<!-- placeholder="请输入类型:1天,2小时"-->
<!-- v-model:value="form.type"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="退款规则" name="moneyJson">
<template v-if="form.moneyJson">
<div v-for="(item, index) in moneyJson" :key="index" style="margin-bottom: 1rem">
<a-space>
<a-input-number
allow-clear
v-model:value="item.num"
>
<template #addonBefore>
<a-select v-model:value="item.type" style="width: 120px">
<a-select-option :value="1">天</a-select-option>
<a-select-option :value="2">小时</a-select-option>
</a-select>
</template>
</a-input-number>
<a-input-number
allow-clear
v-model:value="item.proportion"
>
<template #addonBefore>
退款比例
</template>
<template #addonAfter>
%
</template>
</a-input-number>
<a-button danger @click="removeRefund(index)">删除</a-button>
</a-space>
</div>
</template>
<a-space>
<a-button type="primary" @click="addRefund">添加退款规则</a-button>
<span>温馨提示:比例请您输入1-99%,输入0则代表不退款。</span>
</a-space>
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="请输入退款规则组"-->
<!-- v-model:value="form.moneyJson"-->
<!-- />-->
</a-form-item>
<a-form-item label="周末活动订场开关" name="weekendOpen">
<a-switch :checked="form.weekendOpen == 1" />
</a-form-item>
<a-form-item label="每天人数上限" extra="-1为不限制">
<a-input-number v-model:value="form.dailyMaxNum" />
</a-form-item>
<a-form-item label="排序" name="sortNumber">
<a-input
allow-clear
@@ -150,10 +187,11 @@ import { useThemeStore } from "@/store/modules/theme";
import { storeToRefs } from "pinia";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { FormInstance } from "ant-design-vue/es/form";
import { FileRecord } from "@/api/system/file/model";
import TinymceEditor from "@/components/TinymceEditor/index.vue";
import { uploadOss } from "@/api/system/file";
import { TdtMap } from "vue-tianditu";
import { listArea } from "@/api/system/area";
import { Area } from "@/api/system/area/model";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
@@ -192,7 +230,14 @@ const form = reactive<ThinkSite>({
thumb: undefined,
price: undefined,
businessTime: undefined,
province: undefined,
city: undefined,
region: undefined,
address: undefined,
rentStartDate: undefined,
rentEndDate: undefined,
realPropertyCertificate: undefined,
size: undefined,
lat: undefined,
lng: undefined,
info: undefined,
@@ -204,7 +249,8 @@ const form = reactive<ThinkSite>({
moneyJson: undefined,
createTime: undefined,
updateTime: undefined,
weekendOpen: undefined
weekendOpen: undefined,
dailyMaxNum: undefined,
});
/* 更新visible */
@@ -221,35 +267,34 @@ const rules = reactive({
message: "请填写名称",
trigger: "blur"
}
],
realPropertyCertificate: [
{
required: true,
type: "string",
message: "请填写产权证书/不动产权证号",
trigger: "blur"
}
],
rentStartDate: [
{
required: true,
type: "string",
message: "请填写租赁开始日期",
trigger: "blur"
}
],
rentEndDate: [
{
required: true,
type: "string",
message: "请填写租赁结束日期",
trigger: "blur"
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: "done"
});
form.thumb = data.path;
};
const chooseFiles = (data: FileRecord) => {
files.value.push({
uid: data.id,
url: data.path,
status: "done"
});
};
const onDeleteFiles = (index: number) => {
files.value.splice(index, 1);
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.thumb = "";
};
const map = ref();
const mapState = {
center: [108.358150, 22.826820],
@@ -334,6 +379,27 @@ const config = ref({
}
});
const areaFieldNames = {
label: "name",
value: "id"
};
const city = ref<any[]>([]);
const areaList = ref<Area[]>([]);
const getAreaList = async () => {
areaList.value = await listArea({});
};
const changeArea = (value) => {
city.value = value;
const province = areaList.value.find((item) => item.id === value[0]);
const cityItem = province?.children?.find((item) => item.id === value[1]);
const region = cityItem?.children?.find((item) => item.id === value[2]);
if (province) form.province = province.name;
if (cityItem) form.city = cityItem.name;
if (region) form.region = region.name;
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
@@ -367,10 +433,26 @@ const save = () => {
});
};
const moneyJson = ref<any[]>([]);
const addRefund = () => {
moneyJson.value.push({
type: 1,
num: undefined,
proportion: undefined,
text: "天"
});
};
const removeRefund = (index) => {
moneyJson.value.splice(index, 1);
};
watch(
() => props.visible,
(visible) => {
async (visible) => {
if (visible) {
await getAreaList();
city.value = [];
images.value = [];
files.value = [];
content.value = "";
@@ -386,16 +468,18 @@ watch(
status: "done"
});
}
console.log(images.value);
if (props.data.files) {
const arr = JSON.parse(props.data.files);
arr.map((item) => {
files.value.push({
uid: uuid(),
url: item.url,
status: "done"
});
});
if (props.data.moneyJson) {
moneyJson.value = JSON.parse(props.data.moneyJson);
} else {
moneyJson.value = [];
}
if (props.data.province) {
const province = areaList.value.find((item) => item.name === form.province);
const cityItem = province?.children?.find((item) => item.name === form.city);
const region = cityItem?.children?.find((item) => item.name === form.region);
if (province) city.value.push(province.id);
if (cityItem) city.value.push(cityItem.id);
if (region) city.value.push(region.id);
}
isUpdate.value = true;
} else {
@@ -14,239 +14,56 @@
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="sid场馆id集合,适用的场馆" name="sid">
<a-input
allow-clear
placeholder="请输入sid场馆id集合,适用的场馆"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="用户id" name="uid">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="vip卡id" name="vid">
<a-input
allow-clear
placeholder="请输入vip卡id"
v-model:value="form.vid"
/>
</a-form-item>
<a-form-item label="微信订单号" name="wechatOrder">
<a-input
allow-clear
placeholder="请输入微信订单号"
v-model:value="form.wechatOrder"
/>
</a-form-item>
<a-form-item label="虚拟卡号" name="code">
<a-input
allow-clear
placeholder="请输入虚拟卡号"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="会员卡名称" name="name">
<a-input
allow-clear
placeholder="请输入会员卡名称"
v-model:value="form.name"
disabled
/>
</a-form-item>
<a-form-item label="vip购卡价格" name="price">
<a-input
allow-clear
placeholder="请输入vip购卡价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="会员卡介绍" name="desc">
<a-input
allow-clear
placeholder="请输入会员卡介绍"
v-model:value="form.desc"
/>
</a-form-item>
<a-form-item label="会员卡说明" name="info">
<a-input
allow-clear
placeholder="请输入会员卡说明"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="vip卡折扣率" name="discount">
<a-form-item label="vip卡折扣率" name="discount" v-if="form.type === 4">
<a-input
allow-clear
placeholder="请输入vip卡折扣率"
v-model:value="form.discount"
/>
</a-form-item>
<a-form-item label="使用次数" name="count">
<a-input
allow-clear
placeholder="请输入使用次数"
v-model:value="form.count"
/>
</a-form-item>
<a-form-item label="每使用一次减少的金额" name="eachMoney">
<a-form-item label="每使用一次减少的金额" name="eachMoney" v-if="form.type === 4">
<a-input
allow-clear
placeholder="请输入每使用一次减少的金额"
v-model:value="form.eachMoney"
/>
</a-form-item>
<a-form-item label="剩余金额" name="remainingMoney">
<a-form-item label="剩余金额" name="remainingMoney" v-if="form.type === 4">
<a-input
allow-clear
placeholder="请输入剩余金额"
v-model:value="form.remainingMoney"
/>
</a-form-item>
<a-form-item label="剩余次数" name="num">
<a-form-item label="剩余次数" name="num" v-if="form.type === 2">
<a-input
allow-clear
placeholder="请输入剩余次数"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="付款状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否已充值,1已充值,2未充值" name="isRecharge">
<a-input
allow-clear
placeholder="请输入是否已充值,1已充值,2未充值"
v-model:value="form.isRecharge"
/>
</a-form-item>
<a-form-item label="充值金额" name="rechargePrice">
<a-input
allow-clear
placeholder="请输入充值金额"
v-model:value="form.rechargePrice"
/>
</a-form-item>
<a-form-item label="会员卡年限" name="term">
<a-input
allow-clear
placeholder="请输入会员卡年限"
v-model:value="form.term"
/>
</a-form-item>
<a-form-item label="月限" name="month">
<a-input
allow-clear
placeholder="请输入月限"
v-model:value="form.month"
/>
</a-form-item>
<a-form-item label="会员卡类型:1年卡,2次卡,3月卡,4会员VIP" name="type">
<a-input
allow-clear
placeholder="请输入会员卡类型:1年卡,2次卡,3月卡,4会员VIP"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="卡类型:1成人卡,2儿童卡" name="cardType">
<a-input
allow-clear
placeholder="请输入卡类型:1成人卡,2儿童卡"
v-model:value="form.cardType"
/>
</a-form-item>
<a-form-item label="vip卡等级类型:1特殊vip卡,2普通vip卡" name="vipType">
<a-input
allow-clear
placeholder="请输入vip卡等级类型:1特殊vip卡,2普通vip卡"
v-model:value="form.vipType"
/>
</a-form-item>
<a-form-item label="特殊卡开发凭证图" name="pic">
<a-input
allow-clear
placeholder="请输入特殊卡开发凭证图"
v-model:value="form.pic"
/>
</a-form-item>
<a-form-item label="VIP充值卡价格组" name="prices">
<a-input
allow-clear
placeholder="请输入VIP充值卡价格组"
v-model:value="form.prices"
/>
</a-form-item>
<a-form-item label="临时VIP充值卡价格组,用于充值成功赋值给prices" name="tempPrices">
<a-input
allow-clear
placeholder="请输入临时VIP充值卡价格组,用于充值成功赋值给prices"
v-model:value="form.tempPrices"
/>
</a-form-item>
<a-form-item label="是否赠送积分:1赠送,2不赠送" name="isIntegral">
<a-input
allow-clear
placeholder="请输入是否赠送积分:1赠送,2不赠送"
v-model:value="form.isIntegral"
/>
</a-form-item>
<a-form-item label="是否已开具发票:1已开发票,2未开发票" name="isInvoice">
<a-input
allow-clear
placeholder="请输入是否已开具发票:1已开发票,2未开发票"
v-model:value="form.isInvoice"
/>
</a-form-item>
<a-form-item label="使用时间" name="useTime">
<a-input
allow-clear
placeholder="请输入使用时间"
v-model:value="form.useTime"
/>
</a-form-item>
<!-- <a-form-item label="是否赠送积分" name="isIntegral">-->
<!-- <a-select v-model:value="form.isIntegral">-->
<!-- <a-select-option :value="1">赠送</a-select-option>-->
<!-- <a-select-option :value="2">不赠送</a-select-option>-->
<!-- </a-select>-->
<!-- </a-form-item>-->
<a-form-item label="vip卡到期时间" name="expireTime">
<a-input
<a-date-picker show-time
style="width: 300px"
value-format="YYYY-MM-DD HH:mm:ss"
allow-clear
placeholder="请输入vip卡到期时间"
v-model:value="form.expireTime"
/>
</a-form-item>
<a-form-item label="付款时间" name="payTime">
<a-input
allow-clear
placeholder="请输入付款时间"
v-model:value="form.payTime"
/>
</a-form-item>
<a-form-item label="退款时间" name="refundTime">
<a-input
allow-clear
placeholder="请输入退款时间"
v-model:value="form.refundTime"
/>
</a-form-item>
<a-form-item label="申请退款时间" name="refundApplyTime">
<a-input
allow-clear
placeholder="请输入申请退款时间"
v-model:value="form.refundApplyTime"
/>
</a-form-item>
<a-form-item label="对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单" name="checkBill">
<a-input
allow-clear
placeholder="请输入对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单"
v-model:value="form.checkBill"
v-model:value="expireTime"
/>
</a-form-item>
</a-form>
@@ -254,171 +71,140 @@
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkUsersVip, updateThinkUsersVip } from '@/api/think/thinkUsersVip';
import { ThinkUsersVip } from '@/api/think/thinkUsersVip/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
import { ref, reactive, watch } from "vue";
import { Form, message } from "ant-design-vue";
import { assignObject } from "ele-admin-pro";
import { addThinkUsersVip, updateThinkUsersVip } from "@/api/think/thinkUsersVip";
import { ThinkUsersVip } from "@/api/think/thinkUsersVip/model";
import { ItemType } from "ele-admin-pro/es/ele-image-upload/types";
import { FormInstance } from "ant-design-vue/es/form";
import dayjs from "dayjs";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkUsersVip | null;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkUsersVip | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkUsersVip>({
id: undefined,
sid: undefined,
uid: undefined,
vid: undefined,
wechatOrder: undefined,
code: undefined,
name: undefined,
price: undefined,
desc: undefined,
info: undefined,
discount: undefined,
count: undefined,
eachMoney: undefined,
remainingMoney: undefined,
num: undefined,
status: undefined,
isRecharge: undefined,
rechargePrice: undefined,
term: undefined,
month: undefined,
type: undefined,
cardType: undefined,
vipType: undefined,
pic: undefined,
prices: undefined,
tempPrices: undefined,
isIntegral: undefined,
isInvoice: undefined,
useTime: undefined,
expireTime: undefined,
createTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined,
thinkUsersVipId: undefined,
thinkUsersVipName: '',
status: 0,
comments: '',
sortNumber: 100
});
// 用户信息
const form = reactive<ThinkUsersVip>({
id: undefined,
sid: undefined,
uid: undefined,
vid: undefined,
wechatOrder: undefined,
code: undefined,
name: undefined,
price: undefined,
desc: undefined,
info: undefined,
discount: undefined,
count: undefined,
eachMoney: undefined,
remainingMoney: undefined,
num: undefined,
status: undefined,
isRecharge: undefined,
rechargePrice: undefined,
term: undefined,
month: undefined,
type: undefined,
cardType: undefined,
vipType: undefined,
pic: undefined,
prices: undefined,
tempPrices: undefined,
isIntegral: undefined,
isInvoice: undefined,
useTime: undefined,
expireTime: undefined,
createTime: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
checkBill: undefined,
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
// 表单验证规则
const rules = reactive({
thinkUsersVipName: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
// 表单验证规则
const rules = reactive({
});
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
if (!expireTime.value) {
return message.error("请选择到期时间");
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
formData.expireTime = expireTime.value ? dayjs(expireTime.value).unix() : undefined
const saveOrUpdate = isUpdate.value ? updateThinkUsersVip : addThinkUsersVip;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit("done");
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
form.image = data.path;
};
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkUsersVip : addThinkUsersVip;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
const expireTime = ref<string>('');
watch(
() => props.visible,
(visible) => {
if (visible) {
expireTime.value = ''
if (props.data) {
assignObject(form, props.data);
if (form.expireTime) expireTime.value = dayjs(form.expireTime * 1000).format("YYYY-MM-DD HH:mm:ss")
isUpdate.value = true;
} else {
resetFields();
isUpdate.value = false;
}
},
{ immediate: true }
);
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,104 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="'80%'"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
title="使用记录"
:body-style="{ paddingBottom: '28px' }"
:footer="null"
@update:visible="updateVisible"
>
<ele-pro-table
ref="tableRef"
row-key="thinkUsersVipId"
:need-page="false"
:columns="columns"
:datasource="datasource"
tool-class="ele-toolbar-form"
class="sys-org-table"
:loading="loading"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'order'">
<a-tag color="green" v-if="!!record.order">已使用</a-tag>
<a-tag color="red" v-else>未使用</a-tag>
</template>
<template v-if="column.key === 'orderInfo'">
<span v-if="record.order">{{ record.order.thinkOrderInfos.map(item => item.dateTime).join() }}</span>
</template>
</template>
</ele-pro-table>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import { ThinkUsersVip } from "@/api/think/thinkUsersVip/model";
import { EleProTable } from "ele-admin-pro";
import type { ColumnItem, DatasourceFunction } from "ele-admin-pro/es/ele-pro-table/types";
import { thinkUsersVipLog } from "@/api/think/thinkUsersVip";
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkUsersVip | null;
}>();
const emit = defineEmits<{
(e: "done"): void;
(e: "update:visible", visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit("update:visible", value);
};
const datasource: DatasourceFunction = () => {
return thinkUsersVipLog(props?.data?.id);
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "日期",
dataIndex: "date",
align: "center"
},
{
title: "是否已使用",
key: "order",
align: "center",
},
{
title: "使用场馆",
dataIndex: ["order", 'siteName'],
align: "center",
},
{
title: "预定时间",
key: 'orderInfo',
align: "center",
},
]);
watch(
() => props.visible,
(visible) => {
if (visible) {
}
},
{ immediate: true }
);
</script>
+340 -505
View File
@@ -26,8 +26,8 @@
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'isInvoice'">
<a-tag v-if="record.status === 1" color="green">已开票</a-tag>
<a-tag v-if="record.status === 2" color="red">未开票</a-tag>
<a-tag v-if="record.isInvoice === 1" color="green">已开票</a-tag>
<a-tag v-if="record.isInvoice === 2" color="red">未开票</a-tag>
</template>
<template v-if="column.key === 'status'">
<a-space>
@@ -38,22 +38,31 @@
class="cursor-pointer"
v-if="record.remainingMoney === record.price"
color="red"
>全额退款</a-tag
>
>全额退款
</a-tag>
</a-space>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)" class="text-green-600">解绑</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">退卡</a>
</a-popconfirm>
<a-divider type="vertical" />
<a-space v-if="record.status === 1">
<template v-if="record.uid">
<a-popconfirm
title="确定要解绑吗?"
@confirm="release(record)"
>
<a class="text-green-600">解绑</a>
</a-popconfirm>
<a-divider type="vertical" />
<a-popconfirm
title="确定要退卡吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">退卡</a>
</a-popconfirm>
<a-divider type="vertical" />
</template>
<a class="text-fuchsia-600" @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a @click="openLog(record)">使用记录</a>
</a-space>
</template>
</template>
@@ -66,516 +75,342 @@
:data="current"
@done="reload"
/>
<ThinkUsersVipLog v-if="showLog"
v-model:visible="showLog"
:data="current"
@done="reload"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ThinkUsersVipEdit from './components/thinkUsersVipEdit.vue';
import {
pageThinkUsersVip,
removeThinkUsersVip,
removeBatchThinkUsersVip
} from '@/api/think/thinkUsersVip';
import type {
ThinkUsersVip,
ThinkUsersVipParam
} from '@/api/think/thinkUsersVip/model';
import { createVNode, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import type { EleProTable } from "ele-admin-pro";
import { toDateString } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkUsersVipEdit from "./components/thinkUsersVipEdit.vue";
import {
pageThinkUsersVip,
removeThinkUsersVip,
removeBatchThinkUsersVip, updateThinkUsersVip
} from "@/api/think/thinkUsersVip";
import type {
ThinkUsersVip,
ThinkUsersVipParam
} from "@/api/think/thinkUsersVip/model";
import ThinkUsersVipLog from "@/views/think/thinkUsersVip/components/thinkUsersVipLog.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkUsersVip[]>([]);
// 当前编辑数据
const current = ref<ThinkUsersVip | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格选中数据
const selection = ref<ThinkUsersVip[]>([]);
// 当前编辑数据
const current = ref<ThinkUsersVip | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.forAdmin = true;
return pageThinkUsersVip({
...where,
...orders,
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkUsersVip({
...where,
...orders,
page,
limit
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "操作",
key: "action",
width: 250,
fixed: "left",
align: "center",
hideInSetting: true
},
{
title: "手机号码",
dataIndex: "phone",
key: "phone",
fixed: "left",
align: "center"
},
{
title: "真实姓名",
dataIndex: "realName",
key: "realName",
align: "center"
},
{
title: "微信昵称",
dataIndex: "username",
key: "username",
align: "center"
},
{
title: "卡号",
dataIndex: "code",
key: "code",
align: "center"
},
{
title: "VIP卡名称",
dataIndex: "name",
key: "name",
align: "center"
},
{
title: "可用场馆",
dataIndex: "siteNames",
key: "siteNames",
ellipsis: true,
align: "center"
},
{
title: "购卡价格",
dataIndex: "price",
key: "price",
sorter: true,
align: "center"
},
{
title: "支付状态",
dataIndex: "status",
key: "status",
sorter: true,
width: 180,
align: "center"
},
{
title: "折扣率",
dataIndex: "discount",
key: "discount",
sorter: true,
align: "center"
},
{
title: "可使用次数",
dataIndex: "count",
key: "count",
sorter: true,
align: "center"
},
{
title: "剩余次数",
dataIndex: "num",
key: "num",
sorter: true,
align: "center"
},
{
title: "每使用一次减少的金额",
dataIndex: "eachMoney",
key: "eachMoney",
sorter: true,
align: "center"
},
{
title: "剩余金额",
dataIndex: "remainingMoney",
key: "remainingMoney",
sorter: true,
align: "center"
},
{
title: "月限",
dataIndex: "month",
key: "month",
sorter: true,
align: "center"
},
{
title: "年限",
dataIndex: "term",
key: "term",
sorter: true,
align: "center"
},
{
title: "会员卡类型",
dataIndex: "vipType",
key: "vipType",
align: "center",
sorter: true,
customRender: ({ text }) => ["", "特殊VIP卡", "普通VIP卡"][text]
},
{
title: "卡类型",
dataIndex: "cardType",
key: "cardType",
align: "center",
sorter: true,
customRender: ({ text }) => ["", "成人卡", "儿童卡", "不限"][text]
},
{
title: "会员卡类型",
dataIndex: "type",
key: "type",
align: "center",
sorter: true,
customRender: ({ text }) =>
["", "年卡", "次卡", "月卡", "会员VIP", "VIP充值卡"][text]
},
{
title: "是否赠送积分",
dataIndex: "isIntegral",
key: "isIntegral",
sorter: true,
align: "center",
customRender: ({ text }) => ["", "赠送", "不赠送"][text]
},
{
title: "是否已开具发票",
dataIndex: "isInvoice",
key: "isInvoice",
sorter: true,
align: "center",
customRender: ({ text }) => ["", "已开票", "未开票"][text]
},
{
title: "到期时间",
dataIndex: "expireTime",
key: "expireTime",
sorter: true,
align: "center",
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
},
{
title: "购卡时间",
dataIndex: "createTime",
key: "createTime",
sorter: true,
align: "center",
customRender: ({ text }) => toDateString(text, "yyyy-MM-dd HH:mm:ss")
}
]);
/* 搜索 */
const reload = (where?: ThinkUsersVipParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkUsersVip) => {
current.value = row ?? null;
showEdit.value = true;
};
const release = async (row?: ThinkUsersVip) => {
await updateThinkUsersVip({
id: row?.id,
uid: 0
});
message.success("解绑成功");
reload();
};
const showLog = ref(false);
const openLog = (row?: ThinkUsersVip) => {
current.value = row ?? null;
showLog.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkUsersVip) => {
const hide = message.loading("请求中..", 0);
removeThinkUsersVip(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '操作',
key: 'action',
width: 180,
fixed: 'left',
align: 'center',
hideInSetting: true
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
fixed: 'left',
align: 'center'
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center'
},
{
title: '微信昵称',
dataIndex: 'username',
key: 'username',
align: 'center'
},
{
title: '卡号',
dataIndex: 'code',
key: 'code',
align: 'center'
},
{
title: 'VIP卡名称',
dataIndex: 'name',
key: 'name',
align: 'center'
},
{
title: '可用场馆',
dataIndex: 'siteNames',
key: 'siteNames',
ellipsis: true,
align: 'center'
},
{
title: '购卡价格',
dataIndex: 'price',
key: 'price',
sorter: true,
align: 'center'
},
{
title: '支付状态',
dataIndex: 'status',
key: 'status',
sorter: true,
width: 180,
align: 'center'
},
{
title: '折扣率',
dataIndex: 'discount',
key: 'discount',
sorter: true,
align: 'center'
},
{
title: '可使用次数',
dataIndex: 'count',
key: 'count',
sorter: true,
align: 'center'
},
{
title: '剩余次数',
dataIndex: 'num',
key: 'num',
sorter: true,
align: 'center'
},
{
title: '每使用一次减少的金额',
dataIndex: 'eachMoney',
key: 'eachMoney',
sorter: true,
align: 'center'
},
{
title: '剩余金额',
dataIndex: 'remainingMoney',
key: 'remainingMoney',
sorter: true,
align: 'center'
},
{
title: '月限',
dataIndex: 'month',
key: 'month',
sorter: true,
align: 'center'
},
{
title: '年限',
dataIndex: 'term',
key: 'term',
sorter: true,
align: 'center'
},
{
title: '会员卡类型',
dataIndex: 'vipType',
key: 'vipType',
align: 'center',
sorter: true,
customRender: ({ text }) => ['', '特殊VIP卡', '普通VIP卡'][text]
},
{
title: '卡类型',
dataIndex: 'cardType',
key: 'cardType',
align: 'center',
sorter: true,
customRender: ({ text }) => ['', '成人卡', '儿童卡', '不限'][text]
},
{
title: '会员卡类型',
dataIndex: 'type',
key: 'type',
align: 'center',
sorter: true,
customRender: ({ text }) =>
['', '年卡', '次卡', '月卡', '会员VIP', 'VIP充值卡'][text]
},
{
title: '是否赠送积分',
dataIndex: 'isIntegral',
key: 'isIntegral',
sorter: true,
align: 'center',
customRender: ({ text }) => ['', '赠送', '不赠送'][text]
},
{
title: '是否已开具发票',
dataIndex: 'isInvoice',
key: 'isInvoice',
sorter: true,
align: 'center',
customRender: ({ text }) => ['', '已开票', '未开票'][text]
},
{
title: '到期时间',
dataIndex: 'expireTime',
key: 'expireTime',
sorter: true,
align: 'center',
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '购卡时间',
dataIndex: 'createTime',
key: 'createTime',
sorter: true,
align: 'center',
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error("请至少选择一条数据");
return;
}
Modal.confirm({
title: "提示",
content: "确定要删除选中的记录吗?",
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading("请求中..", 0);
removeBatchThinkUsersVip(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// {
// title: 'vip卡id',
// dataIndex: 'vid',
// key: 'vid',
// align: 'center',
// },
// {
// title: '微信订单号',
// dataIndex: 'wechatOrder',
// key: 'wechatOrder',
// align: 'center',
// },
// {
// title: '虚拟卡号',
// dataIndex: 'code',
// key: 'code',
// align: 'center',
// },
// {
// title: '会员卡名称',
// dataIndex: 'name',
// key: 'name',
// align: 'center',
// },
// {
// title: 'vip购卡价格',
// dataIndex: 'price',
// key: 'price',
// align: 'center',
// },
// {
// title: '会员卡介绍',
// dataIndex: 'desc',
// key: 'desc',
// align: 'center',
// },
// {
// title: '会员卡说明',
// dataIndex: 'info',
// key: 'info',
// align: 'center',
// },
// {
// title: 'vip卡折扣率',
// dataIndex: 'discount',
// key: 'discount',
// align: 'center',
// },
// {
// title: '使用次数',
// dataIndex: 'count',
// key: 'count',
// align: 'center',
// },
// {
// title: '每使用一次减少的金额',
// dataIndex: 'eachMoney',
// key: 'eachMoney',
// align: 'center',
// },
// {
// title: '剩余金额',
// dataIndex: 'remainingMoney',
// key: 'remainingMoney',
// align: 'center',
// },
// {
// title: '剩余次数',
// dataIndex: 'num',
// key: 'num',
// align: 'center',
// },
// {
// title: '付款状态',
// dataIndex: 'status',
// key: 'status',
// align: 'center',
// },
// {
// title: '是否已充值,1已充值,2未充值',
// dataIndex: 'isRecharge',
// key: 'isRecharge',
// align: 'center',
// },
// {
// title: '充值金额',
// dataIndex: 'rechargePrice',
// key: 'rechargePrice',
// align: 'center',
// },
// {
// title: '会员卡年限',
// dataIndex: 'term',
// key: 'term',
// align: 'center',
// },
// {
// title: '月限',
// dataIndex: 'month',
// key: 'month',
// align: 'center',
// },
// {
// title: '会员卡类型:1年卡,2次卡,3月卡,4会员VIP',
// dataIndex: 'type',
// key: 'type',
// align: 'center',
// },
// {
// title: '卡类型:1成人卡,2儿童卡',
// dataIndex: 'cardType',
// key: 'cardType',
// align: 'center',
// },
// {
// title: 'vip卡等级类型:1特殊vip卡,2普通vip卡',
// dataIndex: 'vipType',
// key: 'vipType',
// align: 'center',
// },
// {
// title: '特殊卡开发凭证图',
// dataIndex: 'pic',
// key: 'pic',
// align: 'center',
// },
// {
// title: 'VIP充值卡价格组',
// dataIndex: 'prices',
// key: 'prices',
// align: 'center',
// },
// {
// title: '临时VIP充值卡价格组,用于充值成功赋值给prices',
// dataIndex: 'tempPrices',
// key: 'tempPrices',
// align: 'center',
// },
// {
// title: '是否赠送积分:1赠送,2不赠送',
// dataIndex: 'isIntegral',
// key: 'isIntegral',
// align: 'center',
// },
// {
// title: '是否已开具发票:1已开发票,2未开发票',
// dataIndex: 'isInvoice',
// key: 'isInvoice',
// align: 'center',
// },
// {
// title: '使用时间',
// dataIndex: 'useTime',
// key: 'useTime',
// align: 'center',
// },
// {
// title: 'vip卡到期时间',
// dataIndex: 'expireTime',
// key: 'expireTime',
// align: 'center',
// },
// {
// title: '购买时间',
// dataIndex: 'createTime',
// key: 'createTime',
// align: 'center',
// sorter: true,
// ellipsis: true,
// customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
// },
// {
// title: '付款时间',
// dataIndex: 'payTime',
// key: 'payTime',
// align: 'center',
// },
// {
// title: '退款时间',
// dataIndex: 'refundTime',
// key: 'refundTime',
// align: 'center',
// },
// {
// title: '申请退款时间',
// dataIndex: 'refundApplyTime',
// key: 'refundApplyTime',
// align: 'center',
// },
// {
// title: '对账情况:1=已对账;2=未对账;3=已对账,金额对不上;4=未查询到该订单',
// dataIndex: 'checkBill',
// key: 'checkBill',
// align: 'center',
// },
]);
/* 查询 */
const query = () => {
loading.value = true;
};
/* 搜索 */
const reload = (where?: ThinkUsersVipParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkUsersVip) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkUsersVip) => {
const hide = message.loading('请求中..', 0);
removeThinkUsersVip(row.thinkUsersVipId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
/* 自定义行属性 */
const customRow = (record: ThinkUsersVip) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkUsersVip(selection.value.map((d) => d.thinkUsersVipId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkUsersVip) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkUsersVip'
};
export default {
name: "ThinkUsersVip"
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,56 @@
<!-- 搜索表单 -->
<template>
<div>
<a-space :size="10" style="flex-wrap: wrap">
<a-range-picker
allow-clear
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
</a-space>
<p class="ele-text-danger font-bold mt-2">总金额:{{totalAmount }}元</p>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import { ThinkVipCardsBillsParam } from "@/api/think/thinkVipCardsBills/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
totalAmount?: number;
}>(),
{}
);
const dateRange = ref<[string, string] | null>();
const emit = defineEmits<{
(e: "search", where?: ThinkVipCardsBillsParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "batchMove"): void;
}>();
// 新增
const search = () => {
let dateStart: string = "", dateEnd: string = "";
if (dateRange.value && dateRange.value?.length > 0 && dateRange.value[0]) {
[dateStart, dateEnd] = dateRange.value;
}
emit("search", {
dateStart,
dateEnd
});
};
watch(
() => props.selection,
() => {
}
);
</script>
@@ -0,0 +1,217 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑Vip卡每日账单' : '添加Vip卡每日账单'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="" name="uid">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="" name="vid">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.vid"
/>
</a-form-item>
<a-form-item label="" name="date">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.date"
/>
</a-form-item>
<a-form-item label="" name="amount">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.amount"
/>
</a-form-item>
<a-form-item label="状态, 0已发布, 1待审核 2已驳回 3违规内容" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkVipCardsBills, updateThinkVipCardsBills } from '@/api/think/thinkVipCardsBills';
import { ThinkVipCardsBills } from '@/api/think/thinkVipCardsBills/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkVipCardsBills | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkVipCardsBills>({
id: undefined,
uid: undefined,
vid: undefined,
date: undefined,
amount: undefined,
tenantId: undefined,
status: undefined,
deleted: undefined,
createTime: undefined,
updateTime: undefined,
thinkVipCardsBillsId: undefined,
thinkVipCardsBillsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkVipCardsBillsName: [
{
required: true,
type: 'string',
message: '请填写Vip卡每日账单名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkVipCardsBills : addThinkVipCardsBills;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,179 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkVipCardsBillsId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
:totalAmount="totalAmount"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'user'">
<template v-if="record.user">
<p>{{ record.user.username }}</p>
<p>{{ record.user.phone }}</p>
</template>
<p v-else>散客</p>
</template>
<template v-if="column.key === 'vip'">
<p v-if="record.vip">{{ record.vip.name }}</p>
<p v-if="record.card">{{ record.card.name }}</p>
</template>
<template v-if="column.key === 'used'">
<a-tag v-if="record.used === 1" color="green">已使用</a-tag>
<a-tag v-if="record.used === 0" color="red">未使用</a-tag>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ThinkVipCardsBillsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from "vue";
import type { EleProTable } from "ele-admin-pro";
import type {
DatasourceFunction,
ColumnItem
} from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import ThinkVipCardsBillsEdit from "./components/thinkVipCardsBillsEdit.vue";
import {
pageThinkVipCardsBills, thinkVipCardsBillsTotalAmount
} from "@/api/think/thinkVipCardsBills";
import type { ThinkVipCardsBills, ThinkVipCardsBillsParam } from "@/api/think/thinkVipCardsBills/model";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkVipCardsBills[]>([]);
// 当前编辑数据
const current = ref<ThinkVipCardsBills | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
getTotalAmount(where);
return pageThinkVipCardsBills({
...where,
...orders,
page,
limit
});
};
const totalAmount = ref();
const getTotalAmount = async (where) => {
totalAmount.value = await thinkVipCardsBillsTotalAmount(where);
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: "用户",
key: "user",
align: "center"
},
{
title: "VIP卡",
key: "vip",
align: "center"
},
{
title: "日期",
dataIndex: "date",
key: "date",
align: "center"
},
{
title: "金额",
dataIndex: "amount",
key: "amount",
align: "center"
},
{
title: "是否使用",
key: "used",
align: "center"
}
]);
/* 搜索 */
const reload = (where?: ThinkVipCardsBillsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkVipCardsBills) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkVipCardsBills) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: "ThinkVipCardsBills"
};
</script>
<style lang="less" scoped></style>
@@ -1,188 +1,59 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<!-- <a-button type="primary" class="ele-btn-icon" @click="add">-->
<!-- <template #icon>-->
<!-- <PlusOutlined />-->
<!-- </template>-->
<!-- <span>添加</span>-->
<!-- </a-button>-->
<!-- <a-radio-group v-model:value="where.isExpireTime" @change="search">-->
<!-- <a-radio-button :value="1">未过期</a-radio-button>-->
<!-- <a-radio-button :value="2">已过期</a-radio-button>-->
<!-- </a-radio-group>-->
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
allow-clear
/>
<!-- <a-input-search-->
<!-- allow-clear-->
<!-- placeholder="请输入关键词"-->
<!-- v-model:value="where.keywords"-->
<!-- @pressEnter="search"-->
<!-- @search="search"-->
<!-- style="width: 380px"-->
<!-- />-->
<!-- <a-button @click="reset">重置</a-button>-->
<a-button class="ele-btn-icon" :disabled="loading" @click="handleExport">
<template #icon>
<download-outlined />
</template>
<span>导出充值记录</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import { watch, ref } from 'vue';
import useSearch from '@/utils/use-search';
import dayjs from 'dayjs';
import { toDateString } from 'ele-admin-pro';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
import {
ThinkCardLog,
ThinkCardLogParam
} from '@/api/think/thinkCardLog/model';
import { listThinkCardLog } from '@/api/think/thinkCardLog';
import { watch, ref } from "vue";
import useSearch from "@/utils/use-search";
import dayjs from "dayjs";
import { ThinkVipParam } from "@/api/think/thinkVip/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkCardLogParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
const emit = defineEmits<{
(e: "search", where?: ThinkVipParam): void;
(e: "add"): void;
(e: "remove"): void;
(e: "batchMove"): void;
}>();
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<ThinkCardLog[] | any[]>();
const xlsFileName = ref<string>();
const payType = ref<string[]>([
'',
'微信支付',
'支付宝支付',
'现金支付',
'POS机支付'
]);
// 日期范围选择
const dateRange = ref<[string, string]>(["", ""]);
// 表单数据
const { where, resetFields } = useSearch<ThinkCardLogParam>({
code: undefined,
timeStart: undefined,
timeEnd: undefined,
isExpireTime: undefined,
keywords: undefined
// 表单数据
const { where, } = useSearch<ThinkVipParam>({
createTimeStart: undefined,
createTimeEnd: undefined,
});
const search = () => {
const [d1, d2] = dateRange.value ?? [];
where.createTimeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.createTimeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
emit("search", {
...where
});
};
// 新增
const add = () => {
emit('add');
};
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
emit('search', {
...where
});
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'卡号',
'姓名',
'手机号',
'会员卡名称',
'支付方式',
'充值金额',
'充值次数',
'操作员',
'第三方订单号',
'充值时间'
]
];
if (!where.timeStart) {
message.error('请选择导出的开始日期、结束日期,每次最多导出5000条记录');
return false;
}
await listThinkCardLog(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkCardLog) => {
array.push([
`${d.code}`,
`${d.username}`,
`${d.phone}`,
`${d.cardName}`,
`${payType.value[Number(d.payType)]}`,
`${d.money}`,
`${d.count}`,
`${d.adminName || d.aid}`,
`${d.wechatOrder}`,
`${toDateString(d.createTime)}`
]);
});
const sheetName = `充值记录导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {});
};
watch(
() => props.selection,
() => {}
);
watch(
() => props.selection,
() => {
}
);
</script>
+114 -54
View File
@@ -10,10 +10,12 @@
row-key="id"
:dataSource="list"
:columns="columns"
:pagination="false"
:needPage="false"
:datasource="datasource"
bordered
>
<template #toolbar>
<search />
<search @search="reload"/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'avatar'">
@@ -39,58 +41,116 @@
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import type { ColumnItem } from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
const list = ref<any[]>();
const columns = ref<ColumnItem[]>([
// {
// key: 'index',
// width: 48,
// align: 'center',
// fixed: 'left',
// hideInSetting: true,
// customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
// },
{
title: '会员卡名称',
dataIndex: 'title',
key: 'title'
},
{
title: '卡类型',
dataIndex: 'actualViews',
hideInTable: true,
sorter: true
},
{
title: '数量',
dataIndex: 'sortNumber',
align: 'center',
sorter: true
},
{
title: '数量统计',
key: 'status',
hideInTable: true,
filterMultiple: false,
align: 'center'
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 120,
align: 'center',
sorter: true
},
{
title: '操作',
key: 'action',
width: 100,
align: 'center'
}
]);
import { ref } from "vue";
import type { ColumnItem, DatasourceFunction } from "ele-admin-pro/es/ele-pro-table/types";
import Search from "./components/search.vue";
import { thinkVipTotal } from "@/api/think/thinkVip";
import { ThinkVipParam } from "@/api/think/thinkVip/model";
const list = ref<any[]>();
const columns = ref<ColumnItem[]>([
{
title: "数量统计",
children: [
{
title: "会员卡名称",
dataIndex: "name",
align: "center"
},
{
title: "卡类型",
dataIndex: "type",
align: "center",
customRender: ({ text }) => {
return ["年卡", "次卡", "月卡", "会员VIP", "VIP充值卡", "VIP充值卡"][text];
}
},
{
title: "数量",
dataIndex: "totalNum",
align: "center"
}
]
},
{
title: "费用统计",
children: [
{
title: "微信支付",
children: [
{
title: "用户支付",
dataIndex: "wechatAmount",
align: "center"
},
{
title: "实际到账",
dataIndex: "wechatActual",
align: "center"
},
{
title: "退款",
dataIndex: "wechatRefund",
align: "center"
}
]
},
{
title: "POS机",
children: [
{
title: "用户支付",
dataIndex: "posAmount",
align: "center"
},
{
title: "实际到账",
dataIndex: "posActual",
align: "center"
},
{
title: "退款",
dataIndex: "posRefund",
align: "center"
}
]
},
{
title: "现金",
children: [
{
title: "用户支付",
dataIndex: "cashAmount",
align: "center"
},
{
title: "实际到账",
dataIndex: "cashActual",
align: "center"
},
{
title: "退款",
dataIndex: "cashRefund",
align: "center"
}
]
}
]
}
]);
const datasource: DatasourceFunction = ({
where
}) => {
return thinkVipTotal({
...where
});
};
const tableRef = ref();
const reload = (where?: ThinkVipParam) => {
tableRef?.value?.reload({ where: where });
};
</script>
<style scoped lang="less"></style>