15 changed files with 1760 additions and 15 deletions
@ -1,11 +1,11 @@ |
|||||
VITE_APP_NAME=后台管理系统 |
VITE_APP_NAME=后台管理系统 |
||||
VITE_SOCKET_URL=wss://server.gxwebsoft.com |
VITE_SOCKET_URL=wss://server.gxwebsoft.com |
||||
#VITE_SERVER_URL=https://server.gxwebsoft.com/api |
|
||||
|
VITE_SERVER_URL=https://server.gxwebsoft.com/api |
||||
#VITE_API_URL=https://cms-api.websoft.top/api |
#VITE_API_URL=https://cms-api.websoft.top/api |
||||
|
|
||||
|
|
||||
#VITE_SOCKET_URL=ws://127.0.0.1:9191 |
#VITE_SOCKET_URL=ws://127.0.0.1:9191 |
||||
VITE_SERVER_URL=http://127.0.0.1:8000/api |
|
||||
|
#VITE_SERVER_URL=http://127.0.0.1:8000/api |
||||
VITE_API_URL=http://127.0.0.1:9000/api |
VITE_API_URL=http://127.0.0.1:9000/api |
||||
#VITE_THINK_URL=http://127.0.0.1:9099/api |
#VITE_THINK_URL=http://127.0.0.1:9099/api |
||||
#/booking/bookingItem |
#/booking/bookingItem |
||||
|
@ -0,0 +1,20 @@ |
|||||
|
import request from '@/utils/request'; |
||||
|
import type { ApiResult, PageResult } from '@/api'; |
||||
|
import { MODULES_API_URL } from '@/config/setting'; |
||||
|
import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model"; |
||||
|
|
||||
|
/** |
||||
|
* 分页查询百色中学-捐款记录 |
||||
|
*/ |
||||
|
export async function pageBszxOrder(params: ShopOrderParam) { |
||||
|
const res = await request.get<ApiResult<PageResult<ShopOrder>>>( |
||||
|
MODULES_API_URL + '/bszx/bszx-order/page', |
||||
|
{ |
||||
|
params |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
@ -0,0 +1,106 @@ |
|||||
|
import request from '@/utils/request'; |
||||
|
import type { ApiResult, PageResult } from '@/api'; |
||||
|
import type { ShopOrder, ShopOrderParam } from './model'; |
||||
|
import { MODULES_API_URL } from '@/config/setting'; |
||||
|
|
||||
|
/** |
||||
|
* 分页查询订单 |
||||
|
*/ |
||||
|
export async function pageShopOrder(params: ShopOrderParam) { |
||||
|
const res = await request.get<ApiResult<PageResult<ShopOrder>>>( |
||||
|
MODULES_API_URL + '/shop/shop-order/page', |
||||
|
{ |
||||
|
params |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询订单列表 |
||||
|
*/ |
||||
|
export async function listShopOrder(params?: ShopOrderParam) { |
||||
|
const res = await request.get<ApiResult<ShopOrder[]>>( |
||||
|
MODULES_API_URL + '/shop/shop-order', |
||||
|
{ |
||||
|
params |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0 && res.data.data) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加订单 |
||||
|
*/ |
||||
|
export async function addShopOrder(data: ShopOrder) { |
||||
|
const res = await request.post<ApiResult<unknown>>( |
||||
|
MODULES_API_URL + '/shop/shop-order', |
||||
|
data |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 修改订单 |
||||
|
*/ |
||||
|
export async function updateShopOrder(data: ShopOrder) { |
||||
|
const res = await request.put<ApiResult<unknown>>( |
||||
|
MODULES_API_URL + '/shop/shop-order', |
||||
|
data |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除订单 |
||||
|
*/ |
||||
|
export async function removeShopOrder(id?: number) { |
||||
|
const res = await request.delete<ApiResult<unknown>>( |
||||
|
MODULES_API_URL + '/shop/shop-order/' + id |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量删除订单 |
||||
|
*/ |
||||
|
export async function removeBatchShopOrder(data: (number | undefined)[]) { |
||||
|
const res = await request.delete<ApiResult<unknown>>( |
||||
|
MODULES_API_URL + '/shop/shop-order/batch', |
||||
|
{ |
||||
|
data |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据id查询订单 |
||||
|
*/ |
||||
|
export async function getShopOrder(id: number) { |
||||
|
const res = await request.get<ApiResult<ShopOrder>>( |
||||
|
MODULES_API_URL + '/shop/shop-order/' + id |
||||
|
); |
||||
|
if (res.data.code === 0 && res.data.data) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
@ -0,0 +1,147 @@ |
|||||
|
import type { PageParam } from '@/api'; |
||||
|
|
||||
|
/** |
||||
|
* 订单 |
||||
|
*/ |
||||
|
export interface ShopOrder { |
||||
|
// 订单号
|
||||
|
orderId?: number; |
||||
|
// 订单编号
|
||||
|
orderNo?: string; |
||||
|
// 订单类型,0商城订单 1预定订单/外卖 2会员卡
|
||||
|
type?: number; |
||||
|
// 快递/自提
|
||||
|
deliveryType?: number; |
||||
|
// 下单渠道,0小程序预定 1俱乐部训练场 3活动订场
|
||||
|
channel?: number; |
||||
|
// 微信支付订单号
|
||||
|
transactionId?: string; |
||||
|
// 微信退款订单号
|
||||
|
refundOrder?: string; |
||||
|
// 商户ID
|
||||
|
merchantId?: number; |
||||
|
// 商户名称
|
||||
|
merchantName?: string; |
||||
|
// 商户编号
|
||||
|
merchantCode?: string; |
||||
|
// 使用的优惠券id
|
||||
|
couponId?: number; |
||||
|
// 使用的会员卡id
|
||||
|
cardId?: string; |
||||
|
// 关联管理员id
|
||||
|
adminId?: number; |
||||
|
// 核销管理员id
|
||||
|
confirmId?: number; |
||||
|
// IC卡号
|
||||
|
icCard?: string; |
||||
|
// 真实姓名
|
||||
|
realName?: string; |
||||
|
// 手机号码
|
||||
|
phone?: string; |
||||
|
// 收货地址
|
||||
|
address?: string; |
||||
|
//
|
||||
|
addressLat?: string; |
||||
|
//
|
||||
|
addressLng?: string; |
||||
|
// 自提店铺id
|
||||
|
selfTakeMerchantId?: number; |
||||
|
// 自提店铺
|
||||
|
selfTakeMerchantName?: string; |
||||
|
// 配送开始时间
|
||||
|
sendStartTime?: string; |
||||
|
// 配送结束时间
|
||||
|
sendEndTime?: string; |
||||
|
// 发货店铺id
|
||||
|
expressMerchantId?: number; |
||||
|
// 发货店铺
|
||||
|
expressMerchantName?: string; |
||||
|
// 订单总额
|
||||
|
totalPrice?: string; |
||||
|
// 减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格
|
||||
|
reducePrice?: string; |
||||
|
// 实际付款
|
||||
|
payPrice?: string; |
||||
|
// 用于统计
|
||||
|
price?: string; |
||||
|
// 价钱,用于积分赠送
|
||||
|
money?: string; |
||||
|
// 退款金额
|
||||
|
refundMoney?: string; |
||||
|
// 教练价格
|
||||
|
coachPrice?: string; |
||||
|
// 购买数量
|
||||
|
totalNum?: number; |
||||
|
// 教练id
|
||||
|
coachId?: number; |
||||
|
// 支付的用户id
|
||||
|
payUserId?: number; |
||||
|
// 0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
|
payType?: number; |
||||
|
// 代付支付方式,0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
|
friendPayType?: number; |
||||
|
// 0未付款,1已付款
|
||||
|
payStatus?: string; |
||||
|
// 0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款
|
||||
|
orderStatus?: number; |
||||
|
// 发货状态(10未发货 20已发货 30部分发货)
|
||||
|
deliveryStatus?: number; |
||||
|
// 发货时间
|
||||
|
deliveryTime?: string; |
||||
|
// 优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡
|
||||
|
couponType?: number; |
||||
|
// 优惠说明
|
||||
|
couponDesc?: string; |
||||
|
// 二维码地址,保存订单号,支付成功后才生成
|
||||
|
qrcode?: string; |
||||
|
// vip月卡年卡、ic月卡年卡回退次数
|
||||
|
returnNum?: number; |
||||
|
// vip充值回退金额
|
||||
|
returnMoney?: string; |
||||
|
// 预约详情开始时间数组
|
||||
|
startTime?: string; |
||||
|
// 是否已开具发票:0未开发票,1已开发票,2不能开具发票
|
||||
|
isInvoice?: string; |
||||
|
// 发票流水号
|
||||
|
invoiceNo?: string; |
||||
|
// 支付时间
|
||||
|
payTime?: string; |
||||
|
// 退款时间
|
||||
|
refundTime?: string; |
||||
|
// 申请退款时间
|
||||
|
refundApplyTime?: string; |
||||
|
// 过期时间
|
||||
|
expirationTime?: string; |
||||
|
// 对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单
|
||||
|
checkBill?: number; |
||||
|
// 订单是否已结算(0未结算 1已结算)
|
||||
|
isSettled?: number; |
||||
|
// 系统版本号 0当前版本 value=其他版本
|
||||
|
version?: number; |
||||
|
// 用户id
|
||||
|
userId?: number; |
||||
|
// 备注
|
||||
|
comments?: string; |
||||
|
// 排序号
|
||||
|
sortNumber?: number; |
||||
|
// 是否删除, 0否, 1是
|
||||
|
deleted?: number; |
||||
|
// 租户id
|
||||
|
tenantId?: number; |
||||
|
// 修改时间
|
||||
|
updateTime?: string; |
||||
|
// 创建时间
|
||||
|
createTime?: string; |
||||
|
// 自提码
|
||||
|
selfTakeCode?: string; |
||||
|
// 是否已收到赠品
|
||||
|
hasTakeGift?: string; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 订单搜索条件 |
||||
|
*/ |
||||
|
export interface ShopOrderParam extends PageParam { |
||||
|
orderId?: number; |
||||
|
keywords?: string; |
||||
|
} |
@ -0,0 +1,249 @@ |
|||||
|
<!-- 编辑弹窗 --> |
||||
|
<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="age"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入年龄" |
||||
|
v-model:value="form.age" |
||||
|
/> |
||||
|
</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="性别 1男 2女" name="sex"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入性别 1男 2女" |
||||
|
v-model:value="form.sex" |
||||
|
/> |
||||
|
</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="className"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入班级" |
||||
|
v-model:value="form.className" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="年级" name="gradeName"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入年级" |
||||
|
v-model:value="form.gradeName" |
||||
|
/> |
||||
|
</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="workUnit"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入工作单位" |
||||
|
v-model:value="form.workUnit" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="职务" name="position"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入职务" |
||||
|
v-model:value="form.position" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="捐赠证书" name="certificate"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入捐赠证书" |
||||
|
v-model:value="form.certificate" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="排序(数字越小越靠前)" name="sortNumber"> |
||||
|
<a-input-number |
||||
|
:min="0" |
||||
|
:max="9999" |
||||
|
class="ele-fluid" |
||||
|
placeholder="请输入排序号" |
||||
|
v-model:value="form.sortNumber" |
||||
|
/> |
||||
|
</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="状态" 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> |
||||
|
</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 { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay'; |
||||
|
import { BszxPay } from '@/api/bszx/bszxPay/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?: BszxPay | 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<BszxPay>({ |
||||
|
id: undefined, |
||||
|
age: undefined, |
||||
|
name: undefined, |
||||
|
sex: undefined, |
||||
|
phone: undefined, |
||||
|
className: undefined, |
||||
|
gradeName: undefined, |
||||
|
address: undefined, |
||||
|
workUnit: undefined, |
||||
|
position: undefined, |
||||
|
number: undefined, |
||||
|
extra: undefined, |
||||
|
dateTime: undefined, |
||||
|
certificate: undefined, |
||||
|
formData: undefined, |
||||
|
formId: undefined, |
||||
|
userId: undefined, |
||||
|
comments: undefined, |
||||
|
status: undefined, |
||||
|
deleted: undefined, |
||||
|
tenantId: undefined, |
||||
|
createTime: undefined, |
||||
|
sortNumber: 100 |
||||
|
}); |
||||
|
|
||||
|
/* 更新visible */ |
||||
|
const updateVisible = (value: boolean) => { |
||||
|
emit('update:visible', value); |
||||
|
}; |
||||
|
|
||||
|
// 表单验证规则 |
||||
|
const rules = reactive({ |
||||
|
appBszxPayName: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写应用-百色中学-捐款记录名称', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
|
||||
|
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 ? updateBszxPay : addBszxPay; |
||||
|
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> |
@ -0,0 +1,158 @@ |
|||||
|
<!-- 搜索表单 --> |
||||
|
<template> |
||||
|
<a-space :size="10" style="flex-wrap: wrap"> |
||||
|
<a-input-search |
||||
|
allow-clear |
||||
|
placeholder="请输入关键词" |
||||
|
style="width: 280px" |
||||
|
v-model:value="where.keywords" |
||||
|
@search="reload" |
||||
|
/> |
||||
|
<a-range-picker |
||||
|
v-model:value="dateRange" |
||||
|
@change="search" |
||||
|
value-format="YYYY-MM-DD" |
||||
|
/> |
||||
|
<a-button @click="handleExport">导出</a-button> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { ref, watch } from 'vue'; |
||||
|
import { utils, writeFile } from 'xlsx'; |
||||
|
import dayjs from 'dayjs'; |
||||
|
import { message } from 'ant-design-vue'; |
||||
|
import useSearch from "@/utils/use-search"; |
||||
|
import {BszxPayParam} from "@/api/bszx/bszxPay/model"; |
||||
|
import {BszxBm} from "@/api/bszx/bszxBm/model"; |
||||
|
import {listBszxPay} from "@/api/bszx/bszxPay"; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
// 选中的角色 |
||||
|
selection?: []; |
||||
|
}>(), |
||||
|
{} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'search', where?: BszxPayParam): void; |
||||
|
(e: 'add'): void; |
||||
|
(e: 'remove'): void; |
||||
|
(e: 'batchMove'): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 表单数据 |
||||
|
const { where } = useSearch<BszxPayParam>({ |
||||
|
id: undefined, |
||||
|
keywords: '', |
||||
|
createTimeStart: undefined, |
||||
|
createTimeEnd: undefined, |
||||
|
userId: undefined |
||||
|
}); |
||||
|
|
||||
|
const reload = () => { |
||||
|
emit('search', where); |
||||
|
}; |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const search = () => { |
||||
|
const [d1, d2] = dateRange.value ?? []; |
||||
|
where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined; |
||||
|
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : undefined; |
||||
|
emit('search', { |
||||
|
...where |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
const dateRange = ref<[string, string]>(['', '']); |
||||
|
// 变量 |
||||
|
const loading = ref(false); |
||||
|
const bmList = ref<BszxBm[]>([]) |
||||
|
const xlsFileName = ref<string>(); |
||||
|
|
||||
|
// 导出 |
||||
|
const handleExport = async () => { |
||||
|
loading.value = true; |
||||
|
const array: (string | number)[][] = [ |
||||
|
[ |
||||
|
'订单编号', |
||||
|
'姓名', |
||||
|
'手机号码', |
||||
|
'捐款金额', |
||||
|
'性别', |
||||
|
'年级', |
||||
|
'班级', |
||||
|
'居住地址', |
||||
|
'工作单位', |
||||
|
'职务', |
||||
|
'捐款时间' |
||||
|
] |
||||
|
]; |
||||
|
|
||||
|
// 按搜索结果导出 |
||||
|
where.sceneType = 'Content'; |
||||
|
await listBszxPay(where) |
||||
|
.then((list) => { |
||||
|
bmList.value = list; |
||||
|
list?.forEach((d: BszxBm) => { |
||||
|
array.push([ |
||||
|
`${d.orderNo}`, |
||||
|
`${d.name}`, |
||||
|
`${d.mobile}`, |
||||
|
`${d.price}`, |
||||
|
`${d.sex == 1 ? '男' : ''}${d.sex == 2 ? '女' : '-'}`, |
||||
|
`${d.gradeName ? d.gradeName : '-'}`, |
||||
|
`${d.className ? d.className : '-'}`, |
||||
|
`${d.address ? d.address : '-'}`, |
||||
|
`${d.workUnit ? d.workUnit : '-'}`, |
||||
|
`${d.position ? d.position : '-'}`, |
||||
|
`${d.createTime}` |
||||
|
]); |
||||
|
}); |
||||
|
const sheetName = `导出捐款记录${dayjs(new Date()).format('YYYYMMDD')}`; |
||||
|
const workbook = { |
||||
|
SheetNames: [sheetName], |
||||
|
Sheets: {} |
||||
|
}; |
||||
|
const sheet = utils.aoa_to_sheet(array); |
||||
|
workbook.Sheets[sheetName] = sheet; |
||||
|
// 设置列宽 |
||||
|
sheet['!cols'] = [ |
||||
|
{ wch: 10 }, |
||||
|
{ wch: 40 }, |
||||
|
{ wch: 20 }, |
||||
|
{ wch: 20 }, |
||||
|
{ wch: 60 }, |
||||
|
{ wch: 15 }, |
||||
|
{ wch: 10 }, |
||||
|
{ wch: 10 }, |
||||
|
{ wch: 20 }, |
||||
|
{ wch: 10 }, |
||||
|
{ wch: 20 } |
||||
|
]; |
||||
|
message.loading('正在导出...'); |
||||
|
setTimeout(() => { |
||||
|
writeFile( |
||||
|
workbook, |
||||
|
`${ |
||||
|
where.createTimeEnd ? xlsFileName.value + '_' : '' |
||||
|
}${sheetName}.xlsx` |
||||
|
); |
||||
|
loading.value = false; |
||||
|
}, 1000); |
||||
|
}) |
||||
|
.catch((msg) => { |
||||
|
message.error(msg); |
||||
|
loading.value = false; |
||||
|
}) |
||||
|
.finally(() => {}); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.selection, |
||||
|
() => {} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,229 @@ |
|||||
|
<template> |
||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)"> |
||||
|
<template #extra> |
||||
|
<Extra/> |
||||
|
</template> |
||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }"> |
||||
|
<ele-pro-table |
||||
|
ref="tableRef" |
||||
|
row-key="orderId" |
||||
|
: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 === 'name'"> |
||||
|
<div @click="onSearch(record)" class="cursor-pointer">{{ record.name || '匿名' }}</div> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'phone'"> |
||||
|
<div v-if="record.mobile" class="text-gray-400">{{ record.mobile }}</div> |
||||
|
<div v-else class="text-gray-600">{{ record.phone }}</div> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'payStatus'"> |
||||
|
<a-tag color="green" v-if="record.payStatus">已支付</a-tag> |
||||
|
<a-tag v-else color="red">未支付</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'image'"> |
||||
|
<a-image :src="record.image" :width="50"/> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'sex'"> |
||||
|
<a-tag v-if="record.sex === 1">男</a-tag> |
||||
|
<a-tag v-if="record.sex === 2">女</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'present'"> |
||||
|
<a-tag v-if="record.present">能</a-tag> |
||||
|
<a-tag v-else>不能</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-popconfirm |
||||
|
title="确定要删除此记录吗?" |
||||
|
@confirm="remove(record)" |
||||
|
> |
||||
|
<a class="ele-text-danger">删除</a> |
||||
|
</a-popconfirm> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
</template> |
||||
|
</ele-pro-table> |
||||
|
</a-card> |
||||
|
|
||||
|
<!-- 编辑弹窗 --> |
||||
|
<BszxPayEdit v-model:visible="showEdit" :data="current" @done="reload"/> |
||||
|
</a-page-header> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import {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 BszxPayEdit from './components/bszxPayEdit.vue'; |
||||
|
import {getPageTitle} from "@/utils/common"; |
||||
|
import Extra from "@/views/bszx/extra.vue"; |
||||
|
import {pageBszxOrder} from "@/api/bszx/bszxOrder"; |
||||
|
import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model"; |
||||
|
|
||||
|
// 表格实例 |
||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); |
||||
|
|
||||
|
// 表格选中数据 |
||||
|
const selection = ref<ShopOrder[]>([]); |
||||
|
// 当前编辑数据 |
||||
|
const current = ref<ShopOrder | 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 pageBszxOrder({ |
||||
|
...where, |
||||
|
...orders, |
||||
|
page, |
||||
|
limit |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 表格列配置 |
||||
|
const columns = ref<ColumnItem[]>([ |
||||
|
{ |
||||
|
title: '订单号', |
||||
|
dataIndex: 'orderNo', |
||||
|
key: 'orderNo', |
||||
|
align: 'center', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '姓名', |
||||
|
dataIndex: 'realName', |
||||
|
key: 'realName', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '手机号码', |
||||
|
dataIndex: 'phone', |
||||
|
key: 'phone', |
||||
|
align: 'center', |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '捐款金额', |
||||
|
dataIndex: 'payPrice', |
||||
|
key: 'payPrice', |
||||
|
width: 120, |
||||
|
align: 'center', |
||||
|
customRender: ({text}) => '¥' + text |
||||
|
}, |
||||
|
{ |
||||
|
title: '支付状态', |
||||
|
dataIndex: 'payStatus', |
||||
|
key: 'payStatus', |
||||
|
align: 'center' |
||||
|
}, |
||||
|
// { |
||||
|
// title: '状态', |
||||
|
// dataIndex: 'status', |
||||
|
// key: 'status', |
||||
|
// align: 'center', |
||||
|
// }, |
||||
|
{ |
||||
|
title: '下单时间', |
||||
|
dataIndex: 'createTime', |
||||
|
key: 'createTime', |
||||
|
align: 'center', |
||||
|
width: 180, |
||||
|
sorter: true, |
||||
|
ellipsis: true |
||||
|
}, |
||||
|
// { |
||||
|
// title: '操作', |
||||
|
// key: 'action', |
||||
|
// width: 180, |
||||
|
// fixed: 'right', |
||||
|
// align: 'center', |
||||
|
// hideInSetting: true |
||||
|
// } |
||||
|
]); |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const reload = (where?: ShopOrderParam) => { |
||||
|
selection.value = []; |
||||
|
tableRef?.value?.reload({where: where}); |
||||
|
}; |
||||
|
|
||||
|
const onSearch = (item: ShopOrder) => { |
||||
|
reload({userId: item.userId}) |
||||
|
} |
||||
|
|
||||
|
/* 打开编辑弹窗 */ |
||||
|
const openEdit = (row?: ShopOrder) => { |
||||
|
current.value = row ?? null; |
||||
|
showEdit.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 打开批量移动弹窗 */ |
||||
|
const openMove = () => { |
||||
|
showMove.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 查询 */ |
||||
|
const query = () => { |
||||
|
loading.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 自定义行属性 */ |
||||
|
const customRow = (record: ShopOrder) => { |
||||
|
return { |
||||
|
// 行点击事件 |
||||
|
onClick: () => { |
||||
|
// console.log(record); |
||||
|
}, |
||||
|
// 行双击事件 |
||||
|
onDblclick: () => { |
||||
|
// openEdit(record); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
query(); |
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'BszxOrder' |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped></style> |
@ -0,0 +1,336 @@ |
|||||
|
<!-- 编辑弹窗 --> |
||||
|
<template> |
||||
|
<ele-modal |
||||
|
:width="1000" |
||||
|
:visible="visible" |
||||
|
:maskClosable="false" |
||||
|
:maxable="maxable" |
||||
|
:title="isUpdate ? '编辑订单' : '订单详情'" |
||||
|
:body-style="{ paddingBottom: '28px' }" |
||||
|
@update:visible="updateVisible" |
||||
|
@ok="save" |
||||
|
> |
||||
|
<a-tabs type="card"> |
||||
|
<a-tab-pane key="1" tab="订单信息"> |
||||
|
<a-form |
||||
|
ref="formRef" |
||||
|
:model="form" |
||||
|
:rules="rules" |
||||
|
:label-col="styleResponsive ? { md: 2, sm: 5, xs: 24 } : { flex: '90px' }" |
||||
|
:wrapper-col=" |
||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' } |
||||
|
" |
||||
|
> |
||||
|
<a-form-item label="订单编号" name="orderNo"> |
||||
|
{{ form.orderNo }} |
||||
|
</a-form-item> |
||||
|
<a-form-item label="留言内容" name="content"> |
||||
|
<a-textarea |
||||
|
:rows="8" |
||||
|
:maxlength="300" |
||||
|
placeholder="请输入留言内容" |
||||
|
v-model:value="form.content" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item |
||||
|
label="上传附件" |
||||
|
name="files" |
||||
|
:wrapper-col="{ flex: '1 1 auto' }" |
||||
|
:style="{ width: '100%' }" |
||||
|
> |
||||
|
<SelectFile |
||||
|
:placeholder="`请选择图片`" |
||||
|
:limit="6" |
||||
|
:data="files" |
||||
|
disabled |
||||
|
@done="chooseFile" |
||||
|
@del="onDeleteFile" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<!-- <a-form-item label="产品名称" name="title">--> |
||||
|
<!-- <a-input--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入产品名称"--> |
||||
|
<!-- v-model:value="form.title"--> |
||||
|
<!-- />--> |
||||
|
<!-- </a-form-item>--> |
||||
|
<a-form-item label="客户姓名" name="realName"> |
||||
|
{{ form.realName }} |
||||
|
<!-- <a-input--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入真实姓名"--> |
||||
|
<!-- :maxlength="10"--> |
||||
|
<!-- disabled--> |
||||
|
<!-- v-model:value="form.realName"--> |
||||
|
<!-- />--> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="手机号码" name="phone"> |
||||
|
{{ form.phone }} |
||||
|
<!-- <a-input--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入手机号码"--> |
||||
|
<!-- :maxlength="11"--> |
||||
|
<!-- disabled--> |
||||
|
<!-- v-model:value="form.phone"--> |
||||
|
<!-- />--> |
||||
|
</a-form-item> |
||||
|
<!-- <a-form-item label="电子邮箱" name="email">--> |
||||
|
<!-- {{ form.email }}--> |
||||
|
<!-- <a-input--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入电子邮箱"--> |
||||
|
<!-- v-model:value="form.email"--> |
||||
|
<!-- />--> |
||||
|
<!-- </a-form-item>--> |
||||
|
<!-- <a-form-item label="联系地址" name="address">--> |
||||
|
<!-- {{ form.address }}--> |
||||
|
<!-- <a-input--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入联系地址"--> |
||||
|
<!-- v-model:value="form.address"--> |
||||
|
<!-- />--> |
||||
|
<!-- </a-form-item>--> |
||||
|
<!-- <a-form-item label="报价金额" name="price">--> |
||||
|
<!-- <a-input-number--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入报价金额"--> |
||||
|
<!-- v-model:value="form.price"--> |
||||
|
<!-- />--> |
||||
|
<!-- </a-form-item>--> |
||||
|
<!-- <a-form-item label="购买数量" name="totalNum">--> |
||||
|
<!-- <a-input-number--> |
||||
|
<!-- allow-clear--> |
||||
|
<!-- placeholder="请输入购买数量"--> |
||||
|
<!-- v-model:value="form.totalNum"--> |
||||
|
<!-- />--> |
||||
|
<!-- </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="isSettled"> |
||||
|
<a-switch v-model:checked="form.isSettled" checked-children="已处理" un-checked-children="待处理"/> |
||||
|
</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> |
||||
|
</a-tab-pane> |
||||
|
</a-tabs> |
||||
|
</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 {addCmsOrder, updateCmsOrder} from '@/api/cms/cmsOrder'; |
||||
|
import {CmsOrder} from '@/api/cms/cmsOrder/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?: CmsOrder | 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 files = ref<ItemType[]>([]); |
||||
|
|
||||
|
// 用户信息 |
||||
|
const form = reactive<CmsOrder>({ |
||||
|
orderId: undefined, |
||||
|
title: undefined, |
||||
|
orderNo: undefined, |
||||
|
type: undefined, |
||||
|
itemId: undefined, |
||||
|
realName: undefined, |
||||
|
phone: undefined, |
||||
|
email: undefined, |
||||
|
address: undefined, |
||||
|
content: undefined, |
||||
|
files: undefined, |
||||
|
totalPrice: '0.00', |
||||
|
payPrice: '0.00', |
||||
|
price: '0.00', |
||||
|
totalNum: undefined, |
||||
|
qrcode: undefined, |
||||
|
channel: undefined, |
||||
|
expirationTime: undefined, |
||||
|
isSettled: undefined, |
||||
|
userId: undefined, |
||||
|
deleted: undefined, |
||||
|
tenantId: undefined, |
||||
|
createTime: undefined, |
||||
|
comments: '', |
||||
|
sortNumber: 100 |
||||
|
}); |
||||
|
|
||||
|
/* 更新visible */ |
||||
|
const updateVisible = (value: boolean) => { |
||||
|
emit('update:visible', value); |
||||
|
}; |
||||
|
|
||||
|
// 表单验证规则 |
||||
|
const rules = reactive({ |
||||
|
title: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写产品名称', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
], |
||||
|
realName: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写联系人姓名', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
], |
||||
|
phone: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写联系电话', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
], |
||||
|
isSettled: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'boolean', |
||||
|
message: '请选择处理状态', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
], |
||||
|
content: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写备注信息', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
], |
||||
|
comments: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写备注信息', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
|
||||
|
const chooseFile = (data: FileRecord) => { |
||||
|
files.value.push({ |
||||
|
uid: data.id, |
||||
|
url: data.url, |
||||
|
status: 'done' |
||||
|
}); |
||||
|
form.files = JSON.stringify(files.value.map(d => d.url)) |
||||
|
}; |
||||
|
|
||||
|
const onDeleteFile = (index: number) => { |
||||
|
files.value.splice(index, 1); |
||||
|
}; |
||||
|
|
||||
|
const updateIsSettled = () => { |
||||
|
form.isSettled = !form.isSettled |
||||
|
updateCmsOrder(form).then(res => { |
||||
|
message.success('操作成功') |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
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 ? updateCmsOrder : addCmsOrder; |
||||
|
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?.files) { |
||||
|
const arr = JSON.parse(props.data?.files) |
||||
|
files.value = [] |
||||
|
arr.forEach((url: string) => { |
||||
|
files.value.push({ |
||||
|
uid: uuid(), |
||||
|
url: url, |
||||
|
status: 'done' |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
isUpdate.value = true; |
||||
|
} else { |
||||
|
isUpdate.value = false; |
||||
|
} |
||||
|
} else { |
||||
|
resetFields(); |
||||
|
} |
||||
|
}, |
||||
|
{immediate: true} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,59 @@ |
|||||
|
<!-- 搜索表单 --> |
||||
|
<template> |
||||
|
<a-space style="flex-wrap: wrap"> |
||||
|
<a-button |
||||
|
type="text" |
||||
|
@click="openUrl(`/website/order`)" |
||||
|
>商城订单 |
||||
|
</a-button> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import {watch,nextTick} from 'vue'; |
||||
|
import {CmsWebsite} from '@/api/cms/cmsWebsite/model'; |
||||
|
import {openUrl} from "@/utils/common"; |
||||
|
import {message} from 'ant-design-vue'; |
||||
|
import {removeSiteInfoCache} from "@/api/cms/cmsWebsite"; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
// 选中的角色 |
||||
|
selection?: []; |
||||
|
website?: CmsWebsite; |
||||
|
count?: 0; |
||||
|
}>(), |
||||
|
{} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'add'): void; |
||||
|
}>(); |
||||
|
|
||||
|
const add = () => { |
||||
|
emit('add'); |
||||
|
}; |
||||
|
|
||||
|
// 清除缓存 |
||||
|
const clearSiteInfoCache = () => { |
||||
|
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId') + "*").then( |
||||
|
(msg) => { |
||||
|
if (msg) { |
||||
|
message.success(msg); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
nextTick(() => { |
||||
|
if(localStorage.getItem('NotActive')){ |
||||
|
// IsActive.value = false |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
watch( |
||||
|
() => props.selection, |
||||
|
() => { |
||||
|
} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,153 @@ |
|||||
|
<!-- 搜索表单 --> |
||||
|
<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 |
||||
|
danger |
||||
|
type="primary" |
||||
|
class="ele-btn-icon" |
||||
|
:disabled="selection?.length === 0" |
||||
|
@click="removeBatch" |
||||
|
> |
||||
|
<template #icon> |
||||
|
<DeleteOutlined /> |
||||
|
</template> |
||||
|
<span>批量删除</span> |
||||
|
</a-button> |
||||
|
<a-radio-group v-model:value="where.isSettled" @change="reload"> |
||||
|
<a-radio-button :value="0">待处理</a-radio-button> |
||||
|
<a-radio-button :value="1">已完成</a-radio-button> |
||||
|
</a-radio-group> |
||||
|
<a-input-search |
||||
|
allow-clear |
||||
|
placeholder="请输入关键词" |
||||
|
style="width: 280px" |
||||
|
v-model:value="where.keywords" |
||||
|
@pressEnter="reload" |
||||
|
@search="reload" |
||||
|
/> |
||||
|
<a-button type="text" @click="handleExport">导出xls表</a-button> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { PlusOutlined } from '@ant-design/icons-vue'; |
||||
|
import { watch, ref } from 'vue'; |
||||
|
import { utils, writeFile } from 'xlsx'; |
||||
|
import { message } from 'ant-design-vue'; |
||||
|
import useSearch from "@/utils/use-search"; |
||||
|
import {CmsOrder, CmsOrderParam} from "@/api/cms/cmsOrder/model"; |
||||
|
import type {CmsArticle} from "@/api/cms/cmsArticle/model"; |
||||
|
import {listCmsOrder} from "@/api/cms/cmsOrder"; |
||||
|
import dayjs from 'dayjs'; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
// 选中的角色 |
||||
|
selection?: []; |
||||
|
}>(), |
||||
|
{} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'search', where?: CmsOrderParam): void; |
||||
|
(e: 'add'): void; |
||||
|
(e: 'remove'): void; |
||||
|
(e: 'batchMove'): void; |
||||
|
}>(); |
||||
|
|
||||
|
const articleList = ref<CmsArticle[]>([]); |
||||
|
// 请求状态 |
||||
|
const loading = ref(false); |
||||
|
const xlsFileName = ref<string>(); |
||||
|
|
||||
|
// 表单数据 |
||||
|
const { where } = useSearch<CmsOrderParam>({ |
||||
|
keywords: '' |
||||
|
}); |
||||
|
|
||||
|
// 新增 |
||||
|
const add = () => { |
||||
|
emit('add'); |
||||
|
}; |
||||
|
|
||||
|
// 导出 |
||||
|
const handleExport = async () => { |
||||
|
loading.value = true; |
||||
|
const array: (string | number)[][] = [ |
||||
|
[ |
||||
|
'订单编号', |
||||
|
'姓名', |
||||
|
'手机号码', |
||||
|
'详细地址', |
||||
|
'留言内容', |
||||
|
'上传附件', |
||||
|
'处理状态', |
||||
|
'创建时间' |
||||
|
] |
||||
|
]; |
||||
|
|
||||
|
// 按搜索结果导出 |
||||
|
where.sceneType = 'Content'; |
||||
|
await listCmsOrder(where) |
||||
|
.then((list) => { |
||||
|
articleList.value = list; |
||||
|
list?.forEach((d: CmsOrder) => { |
||||
|
array.push([ |
||||
|
`${d.orderNo}`, |
||||
|
`${d.realName}`, |
||||
|
`${d.phone}`, |
||||
|
`${d.address}`, |
||||
|
`${d.content}`, |
||||
|
`${d.files}`, |
||||
|
`${d.isSettled ? '已完成' : '待处理'}`, |
||||
|
`${d.createTime}` |
||||
|
]); |
||||
|
}); |
||||
|
const sheetName = `导出订单xls - ${dayjs(new Date()).format('YYYYMMDD')}`; |
||||
|
const workbook = { |
||||
|
SheetNames: [sheetName], |
||||
|
Sheets: {} |
||||
|
}; |
||||
|
const sheet = utils.aoa_to_sheet(array); |
||||
|
workbook.Sheets[sheetName] = sheet; |
||||
|
// 设置列宽 |
||||
|
sheet['!cols'] = []; |
||||
|
message.loading('正在导出...'); |
||||
|
setTimeout(() => { |
||||
|
writeFile( |
||||
|
workbook, |
||||
|
`${ |
||||
|
where.createTimeEnd ? xlsFileName.value + '_' : '' |
||||
|
}${sheetName}.xlsx` |
||||
|
); |
||||
|
loading.value = false; |
||||
|
}, 1000); |
||||
|
}) |
||||
|
.catch((msg) => { |
||||
|
message.error(msg); |
||||
|
loading.value = false; |
||||
|
}) |
||||
|
.finally(() => {}); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
const reload = () => { |
||||
|
emit('search', where); |
||||
|
}; |
||||
|
|
||||
|
// 批量删除 |
||||
|
const removeBatch = () => { |
||||
|
emit('remove'); |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.selection, |
||||
|
() => {} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,288 @@ |
|||||
|
<template> |
||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)"> |
||||
|
<template #extra> |
||||
|
<Extra /> |
||||
|
</template> |
||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }"> |
||||
|
<ele-pro-table |
||||
|
ref="tableRef" |
||||
|
row-key="orderId" |
||||
|
:columns="columns" |
||||
|
:datasource="datasource" |
||||
|
v-model:selection="selection" |
||||
|
: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 === 'type'"> |
||||
|
<a-tag v-if="record.type === 1">询价</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'title'"> |
||||
|
<a :href="navTo(record,`/item/${record.articleId}.html`)" class="text-black" target="_blank">{{ |
||||
|
record.title |
||||
|
}}</a> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'comments'"> |
||||
|
<div class="flex flex-col text-left bg-blue-50 p-2 rounded-sm h-full"> |
||||
|
{{ record.comments }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'price'"> |
||||
|
<div class="">¥{{ record.price }}</div> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'isSettled'"> |
||||
|
<a-tag v-if="!record.isSettled" color="red">待处理</a-tag> |
||||
|
<a-tag v-if="record.isSettled" color="green">已完成</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'action'"> |
||||
|
<a-space> |
||||
|
<a @click="openEdit(record)">修改</a> |
||||
|
<a-divider type="vertical"/> |
||||
|
<a-popconfirm |
||||
|
v-if="!record.isSettled" |
||||
|
title="确定要删除此记录吗?" |
||||
|
@confirm="remove(record)" |
||||
|
> |
||||
|
<a class="ele-text-danger">删除</a> |
||||
|
</a-popconfirm> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
</template> |
||||
|
</ele-pro-table> |
||||
|
</a-card> |
||||
|
|
||||
|
<!-- 编辑弹窗 --> |
||||
|
<CmsOrderEdit v-model:visible="showEdit" :data="current" @done="reload"/> |
||||
|
</a-page-header> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import {createVNode, ref} from 'vue'; |
||||
|
import {message, Modal} from 'ant-design-vue'; |
||||
|
import {useI18n} from 'vue-i18n'; |
||||
|
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 CmsOrderEdit from './components/cmsOrderEdit.vue'; |
||||
|
import type {CmsOrder, CmsOrderParam} from '@/api/cms/cmsOrder/model'; |
||||
|
import {getPageTitle, navTo} from "@/utils/common"; |
||||
|
import Extra from "./components/extra.vue"; |
||||
|
import {pageShopOrder, removeBatchShopOrder, removeShopOrder} from "@/api/shop/shopOrder"; |
||||
|
|
||||
|
const {locale} = useI18n(); |
||||
|
|
||||
|
// 表格实例 |
||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); |
||||
|
|
||||
|
// 表格选中数据 |
||||
|
const selection = ref<CmsOrder[]>([]); |
||||
|
// 当前编辑数据 |
||||
|
const current = ref<CmsOrder | 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; |
||||
|
} |
||||
|
where.lang = locale.value || undefined; |
||||
|
return pageShopOrder({ |
||||
|
...where, |
||||
|
...orders, |
||||
|
page, |
||||
|
limit |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 表格列配置 |
||||
|
const columns = ref<ColumnItem[]>([ |
||||
|
{ |
||||
|
title: '订单编号', |
||||
|
dataIndex: 'orderNo', |
||||
|
key: 'orderNo', |
||||
|
align: 'center', |
||||
|
width: 190, |
||||
|
}, |
||||
|
// { |
||||
|
// title: '订单类型', |
||||
|
// dataIndex: 'type', |
||||
|
// key: 'type', |
||||
|
// align: 'center', |
||||
|
// }, |
||||
|
{ |
||||
|
title: '产品名称', |
||||
|
dataIndex: 'title', |
||||
|
key: 'title', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '姓名', |
||||
|
dataIndex: 'realName', |
||||
|
key: 'realName', |
||||
|
width: 150, |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '电话', |
||||
|
dataIndex: 'phone', |
||||
|
key: 'phone', |
||||
|
width: 150, |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '备注', |
||||
|
dataIndex: 'comments', |
||||
|
key: 'comments', |
||||
|
align: 'center', |
||||
|
width: 320 |
||||
|
}, |
||||
|
{ |
||||
|
title: '报价金额', |
||||
|
dataIndex: 'price', |
||||
|
key: 'price', |
||||
|
align: 'center', |
||||
|
hideInTable: true |
||||
|
}, |
||||
|
{ |
||||
|
title: '购买数量', |
||||
|
dataIndex: 'totalNum', |
||||
|
key: 'totalNum', |
||||
|
align: 'center', |
||||
|
hideInTable: true |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单状态', |
||||
|
dataIndex: 'isSettled', |
||||
|
key: 'isSettled', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '创建时间', |
||||
|
dataIndex: 'createTime', |
||||
|
key: 'createTime', |
||||
|
align: 'center', |
||||
|
sorter: true, |
||||
|
ellipsis: true |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'action', |
||||
|
width: 180, |
||||
|
fixed: 'right', |
||||
|
align: 'center', |
||||
|
hideInSetting: true |
||||
|
} |
||||
|
]); |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const reload = (where?: CmsOrderParam) => { |
||||
|
selection.value = []; |
||||
|
tableRef?.value?.reload({where: where}); |
||||
|
}; |
||||
|
|
||||
|
/* 打开编辑弹窗 */ |
||||
|
const openEdit = (row?: CmsOrder) => { |
||||
|
current.value = row ?? null; |
||||
|
showEdit.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 打开批量移动弹窗 */ |
||||
|
const openMove = () => { |
||||
|
showMove.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 删除单个 */ |
||||
|
const remove = (row: CmsOrder) => { |
||||
|
const hide = message.loading('请求中..', 0); |
||||
|
removeShopOrder(row.orderId) |
||||
|
.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); |
||||
|
removeBatchShopOrder(selection.value.map((d) => d.orderId)) |
||||
|
.then((msg) => { |
||||
|
hide(); |
||||
|
message.success(msg); |
||||
|
reload(); |
||||
|
}) |
||||
|
.catch((e) => { |
||||
|
hide(); |
||||
|
message.error(e.message); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/* 查询 */ |
||||
|
const query = () => { |
||||
|
loading.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 自定义行属性 */ |
||||
|
const customRow = (record: CmsOrder) => { |
||||
|
return { |
||||
|
// 行点击事件 |
||||
|
onClick: () => { |
||||
|
// console.log(record); |
||||
|
}, |
||||
|
// 行双击事件 |
||||
|
onDblclick: () => { |
||||
|
openEdit(record); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
query(); |
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'CmsOrder' |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped></style> |
Loading…
Reference in new issue