Browse Source

优化:修复已知问题

dev
科技小王子 6 months ago
parent
commit
f568c71026
  1. 4
      .env.development
  2. 20
      src/api/bszx/bszxOrder/index.ts
  3. 106
      src/api/shop/shopOrder/index.ts
  4. 147
      src/api/shop/shopOrder/model/index.ts
  5. 2
      src/store/modules/user.ts
  6. 6
      src/views/bszx/bszxBm/index.vue
  7. 249
      src/views/bszx/bszxOrder/components/bszxPayEdit.vue
  8. 158
      src/views/bszx/bszxOrder/components/search.vue
  9. 229
      src/views/bszx/bszxOrder/index.vue
  10. 14
      src/views/bszx/bszxPay/index.vue
  11. 4
      src/views/cms/cmsWebsiteField/components/edit.vue
  12. 336
      src/views/shop/shopOrder/components/cmsOrderEdit.vue
  13. 59
      src/views/shop/shopOrder/components/extra.vue
  14. 153
      src/views/shop/shopOrder/components/search.vue
  15. 288
      src/views/shop/shopOrder/index.vue

4
.env.development

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

20
src/api/bszx/bszxOrder/index.ts

@ -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));
}

106
src/api/shop/shopOrder/index.ts

@ -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));
}

147
src/api/shop/shopOrder/model/index.ts

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

2
src/store/modules/user.ts

@ -45,7 +45,7 @@ export const useUserStore = defineStore({
if (!result) {
Modal.info({
title: '系统提示',
content: '该应用已欠费,请先续费后访问!',
content: '网站已被关停,请登录控制台查看具体原因!',
okText: '重新登录',
onOk: () => {
logout(false, '/login');

6
src/views/bszx/bszxBm/index.vue

@ -100,9 +100,9 @@ const datasource: DatasourceFunction = ({
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
// if (filters) {
// where.status = filters.status;
// }
return pageBszxBm({
...where,
...orders,

249
src/views/bszx/bszxOrder/components/bszxPayEdit.vue

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

158
src/views/bszx/bszxOrder/components/search.vue

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

229
src/views/bszx/bszxOrder/index.vue

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

14
src/views/bszx/bszxPay/index.vue

@ -24,7 +24,7 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<div @click="onSearch(record)" class="cursor-pointer">{{ record.name }}</div>
<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>
@ -188,12 +188,12 @@ const columns = ref<ColumnItem[]>([
// key: 'certificate',
// align: 'center',
// },
// {
// title: '',
// dataIndex: 'comments',
// key: 'comments',
// align: 'center',
// },
{
title: '心愿',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
// {
// title: '',
// dataIndex: 'status',

4
src/views/cms/cmsWebsiteField/components/edit.vue

@ -28,7 +28,7 @@
<SelectWebsiteField
:placeholder="`从模板选择`"
class="input-item"
v-model:value="form.template"
v-model:value="form.name"
@done="chooseData"
/>
</div>
@ -213,7 +213,7 @@
};
const chooseData = (data: CmsWebsiteField) => {
assignFields(data);
form.name = data.name;
form.value = data.defaultValue;
if (data.type == 1) {
images.value.push({

336
src/views/shop/shopOrder/components/cmsOrderEdit.vue

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

59
src/views/shop/shopOrder/components/extra.vue

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

153
src/views/shop/shopOrder/components/search.vue

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

288
src/views/shop/shopOrder/index.vue

@ -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…
Cancel
Save