15 changed files with 1760 additions and 15 deletions
@ -1,11 +1,11 @@ |
|||
VITE_APP_NAME=后台管理系统 |
|||
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_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_THINK_URL=http://127.0.0.1:9099/api |
|||
#/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