新增:并入shop、cms、oa三大模块代码

This commit is contained in:
2024-09-13 00:10:29 +08:00
parent 0068553e35
commit ea5a48fa29
424 changed files with 64497 additions and 67 deletions

View File

@@ -26,13 +26,11 @@
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="商户图标" name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
<a-form-item label="店铺类型" name="shopType">
<SelectMerchantType
:placeholder="`请选择店铺类型`"
v-model:value="form.shopType"
@done="chooseShopType"
/>
</a-form-item>
<a-form-item label="商户手机号" name="phone">
@@ -50,13 +48,6 @@
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="工作负责人" name="name2">
<a-input
allow-clear
placeholder="工作负责人名称"
v-model:value="form.name2"
/>
</a-form-item>
<a-form-item label="店铺类型" name="shopType">
<SelectMerchantType
:placeholder="`请选择店铺类型`"
@@ -73,7 +64,42 @@
@change="onIndustry"
/>
</a-form-item>
<a-form-item label="资质图片" name="files">
<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="yyzz">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="yyzz"
@done="chooseFiles"
@del="onDeleteFiles"
/>
</a-form-item>
<a-form-item label="身份证" name="sfz">
<a-space>
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="sfz1"
@done="chooseFiles"
@del="onDeleteFiles"
/>
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="sfz2"
@done="chooseFiles"
@del="onDeleteFiles"
/>
</a-space>
</a-form-item>
<a-form-item label="其他资质" name="files">
<SelectFile
:placeholder="`请选择图片`"
:limit="9"
@@ -82,12 +108,13 @@
@del="onDeleteFiles"
/>
</a-form-item>
<a-form-item label="产品介绍" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
<a-form-item label="门店照片" name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="审核状态" name="status">
@@ -152,6 +179,9 @@
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
const files = ref<ItemType[]>([]);
const yyzz = ref<ItemType[]>([]);
const sfz1 = ref<ItemType[]>([]);
const sfz2 = ref<ItemType[]>([]);
// 用户信息
const form = reactive<MerchantApply>({
@@ -278,6 +308,10 @@
(visible) => {
if (visible) {
images.value = [];
yyzz.value = [];
sfz1.value = [];
sfz2.value = [];
files.value = [];
if (props.data) {
assignObject(form, props.data);
form.status = 1;
@@ -288,6 +322,43 @@
status: 'done'
});
}
if (props.data.yyzz) {
yyzz.value.push({
uid: uuid(),
url: props.data.yyzz,
status: 'done'
});
}
if (props.data.sfz1) {
sfz1.value.push({
uid: uuid(),
url: props.data.sfz1,
status: 'done'
});
}
if (props.data.sfz2) {
sfz2.value.push({
uid: uuid(),
url: props.data.sfz2,
status: 'done'
});
}
if (props.data.files) {
const arr = JSON.parse(props.data.files);
arr.map((url) => {
files.value.push({
uid: uuid(),
url: url,
status: 'done'
});
});
}
// yyzz.value.push({
// uid: uuid(),
// url: `.url;`,
// status: 'done'
// });
isUpdate.value = true;
} else {
isUpdate.value = false;

View File

@@ -29,6 +29,9 @@
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'shopType'">
<a-tag>{{ record.shopType }}</a-tag>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="orange">待审核</a-tag>
<a-tag v-if="record.status === 1" color="green">审核通过</a-tag>
@@ -121,10 +124,12 @@
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'applyId',
key: 'applyId',
width: 90
key: 'index',
width: 48,
align: 'center',
fixed: 'left',
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: '商户名称',
@@ -132,6 +137,12 @@
key: 'merchantName',
align: 'center'
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center'
},
{
title: '商户姓名',
dataIndex: 'realName',
@@ -144,12 +155,6 @@
key: 'phone',
align: 'center'
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center'
},
{
title: '申请时间',
dataIndex: 'createTime',

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,208 @@
<!-- 编辑弹窗 -->
<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="brandName">
<a-input
allow-clear
placeholder="请输入品牌名称"
v-model:value="form.brandName"
/>
</a-form-item>
<a-form-item
label="图标"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="备注" 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-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>
</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 { addShopBrand, updateShopBrand } from '@/api/shop/shopBrand';
import { ShopBrand } from '@/api/shop/shopBrand/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?: ShopBrand | 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<ShopBrand>({
brandId: undefined,
brandName: undefined,
image: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopBrandId: undefined,
shopBrandName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopBrandName: [
{
required: true,
type: 'string',
message: '请填写品牌名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopBrand : addShopBrand;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopBrandId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopBrandEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopBrandEdit from './components/shopBrandEdit.vue';
import { pageShopBrand, removeShopBrand, removeBatchShopBrand } from '@/api/shop/shopBrand';
import type { ShopBrand, ShopBrandParam } from '@/api/shop/shopBrand/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopBrand[]>([]);
// 当前编辑数据
const current = ref<ShopBrand | 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 pageShopBrand({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'brandId',
key: 'brandId',
align: 'center',
width: 90,
},
{
title: '品牌名称',
dataIndex: 'brandName',
key: 'brandName',
align: 'center',
},
{
title: '图标',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopBrandParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopBrand) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopBrand) => {
const hide = message.loading('请求中..', 0);
removeShopBrand(row.shopBrandId)
.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);
removeBatchShopBrand(selection.value.map((d) => d.shopBrandId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopBrand) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopBrand'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,290 @@
<!-- 编辑弹窗 -->
<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="类型 0商城 1外卖" name="type">
<a-input
allow-clear
placeholder="请输入类型 0商城 1外卖"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="唯一标识" name="code">
<a-input
allow-clear
placeholder="请输入唯一标识"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="商品规格" name="spec">
<a-input
allow-clear
placeholder="请输入商品规格"
v-model:value="form.spec"
/>
</a-form-item>
<a-form-item label="商品价格" name="price">
<a-input
allow-clear
placeholder="请输入商品价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="商品数量" name="cartNum">
<a-input
allow-clear
placeholder="请输入商品数量"
v-model:value="form.cartNum"
/>
</a-form-item>
<a-form-item label="单商品合计" name="totalPrice">
<a-input
allow-clear
placeholder="请输入单商品合计"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item label="0 = 未购买 1 = 已购买" name="isPay">
<a-input
allow-clear
placeholder="请输入0 = 未购买 1 = 已购买"
v-model:value="form.isPay"
/>
</a-form-item>
<a-form-item label="是否为立即购买" name="isNew">
<a-input
allow-clear
placeholder="请输入是否为立即购买"
v-model:value="form.isNew"
/>
</a-form-item>
<a-form-item label="拼团id" name="combinationId">
<a-input
allow-clear
placeholder="请输入拼团id"
v-model:value="form.combinationId"
/>
</a-form-item>
<a-form-item label="秒杀产品ID" name="seckillId">
<a-input
allow-clear
placeholder="请输入秒杀产品ID"
v-model:value="form.seckillId"
/>
</a-form-item>
<a-form-item label="砍价id" name="bargainId">
<a-input
allow-clear
placeholder="请输入砍价id"
v-model:value="form.bargainId"
/>
</a-form-item>
<a-form-item label="是否选中" name="selected">
<a-input
allow-clear
placeholder="请输入是否选中"
v-model:value="form.selected"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopCart, updateShopCart } from '@/api/shop/shopCart';
import { ShopCart } from '@/api/shop/shopCart/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?: ShopCart | 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<ShopCart>({
id: undefined,
type: undefined,
code: undefined,
goodsId: undefined,
spec: undefined,
price: undefined,
cartNum: undefined,
totalPrice: undefined,
isPay: undefined,
isNew: undefined,
combinationId: undefined,
seckillId: undefined,
bargainId: undefined,
selected: undefined,
merchantId: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopCartId: undefined,
shopCartName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopCartName: [
{
required: true,
type: 'string',
message: '请填写购物车名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopCart : addShopCart;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,311 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopCartId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopCartEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopCartEdit from './components/shopCartEdit.vue';
import { pageShopCart, removeShopCart, removeBatchShopCart } from '@/api/shop/shopCart';
import type { ShopCart, ShopCartParam } from '@/api/shop/shopCart/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopCart[]>([]);
// 当前编辑数据
const current = ref<ShopCart | 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 pageShopCart({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '购物车表ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '类型 0商城 1外卖',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '唯一标识',
dataIndex: 'code',
key: 'code',
align: 'center',
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '商品规格',
dataIndex: 'spec',
key: 'spec',
align: 'center',
},
{
title: '商品价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '商品数量',
dataIndex: 'cartNum',
key: 'cartNum',
align: 'center',
},
{
title: '单商品合计',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
},
{
title: '0 = 未购买 1 = 已购买',
dataIndex: 'isPay',
key: 'isPay',
align: 'center',
},
{
title: '是否为立即购买',
dataIndex: 'isNew',
key: 'isNew',
align: 'center',
},
{
title: '拼团id',
dataIndex: 'combinationId',
key: 'combinationId',
align: 'center',
},
{
title: '秒杀产品ID',
dataIndex: 'seckillId',
key: 'seckillId',
align: 'center',
},
{
title: '砍价id',
dataIndex: 'bargainId',
key: 'bargainId',
align: 'center',
},
{
title: '是否选中',
dataIndex: 'selected',
key: 'selected',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopCartParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopCart) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopCart) => {
const hide = message.loading('请求中..', 0);
removeShopCart(row.shopCartId)
.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);
removeBatchShopCart(selection.value.map((d) => d.shopCartId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopCart) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopCart'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,299 @@
<!-- 编辑弹窗 -->
<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="类型 0商城 1外卖" name="type">
<a-input
allow-clear
placeholder="请输入类型 0商城 1外卖"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="唯一标识" name="code">
<a-input
allow-clear
placeholder="请输入唯一标识"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="商品名称" name="name">
<a-input
allow-clear
placeholder="请输入商品名称"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="商品规格" name="spec">
<a-input
allow-clear
placeholder="请输入商品规格"
v-model:value="form.spec"
/>
</a-form-item>
<a-form-item label="商品价格" name="price">
<a-input
allow-clear
placeholder="请输入商品价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="商品数量" name="cartNum">
<a-input
allow-clear
placeholder="请输入商品数量"
v-model:value="form.cartNum"
/>
</a-form-item>
<a-form-item label="单商品合计" name="totalPrice">
<a-input
allow-clear
placeholder="请输入单商品合计"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item label="0 = 未购买 1 = 已购买" name="isPay">
<a-input
allow-clear
placeholder="请输入0 = 未购买 1 = 已购买"
v-model:value="form.isPay"
/>
</a-form-item>
<a-form-item label="是否为立即购买" name="isNew">
<a-input
allow-clear
placeholder="请输入是否为立即购买"
v-model:value="form.isNew"
/>
</a-form-item>
<a-form-item label="是否选中" name="selected">
<a-input
allow-clear
placeholder="请输入是否选中"
v-model:value="form.selected"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</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="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="收银员ID" name="cashierId">
<a-input
allow-clear
placeholder="请输入收银员ID"
v-model:value="form.cashierId"
/>
</a-form-item>
<a-form-item label="分组取单" name="groupId">
<a-input
allow-clear
placeholder="请输入分组取单"
v-model:value="form.groupId"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopCashier, updateShopCashier } from '@/api/shop/shopCashier';
import { ShopCashier } from '@/api/shop/shopCashier/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?: ShopCashier | 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<ShopCashier>({
id: undefined,
type: undefined,
code: undefined,
goodsId: undefined,
name: undefined,
spec: undefined,
price: undefined,
cartNum: undefined,
totalPrice: undefined,
isPay: undefined,
isNew: undefined,
selected: undefined,
merchantId: undefined,
comments: undefined,
userId: undefined,
cashierId: undefined,
groupId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopCashierId: undefined,
shopCashierName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopCashierName: [
{
required: true,
type: 'string',
message: '请填写收银名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopCashier : addShopCashier;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,317 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopCashierId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopCashierEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopCashierEdit from './components/shopCashierEdit.vue';
import { pageShopCashier, removeShopCashier, removeBatchShopCashier } from '@/api/shop/shopCashier';
import type { ShopCashier, ShopCashierParam } from '@/api/shop/shopCashier/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopCashier[]>([]);
// 当前编辑数据
const current = ref<ShopCashier | 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 pageShopCashier({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '收银单ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '类型 0商城 1外卖',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '唯一标识',
dataIndex: 'code',
key: 'code',
align: 'center',
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '商品名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '商品规格',
dataIndex: 'spec',
key: 'spec',
align: 'center',
},
{
title: '商品价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '商品数量',
dataIndex: 'cartNum',
key: 'cartNum',
align: 'center',
},
{
title: '单商品合计',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
},
{
title: '0 = 未购买 1 = 已购买',
dataIndex: 'isPay',
key: 'isPay',
align: 'center',
},
{
title: '是否为立即购买',
dataIndex: 'isNew',
key: 'isNew',
align: 'center',
},
{
title: '是否选中',
dataIndex: 'selected',
key: 'selected',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '收银员ID',
dataIndex: 'cashierId',
key: 'cashierId',
align: 'center',
},
{
title: '分组取单',
dataIndex: 'groupId',
key: 'groupId',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopCashierParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopCashier) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopCashier) => {
const hide = message.loading('请求中..', 0);
removeShopCashier(row.shopCashierId)
.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);
removeBatchShopCashier(selection.value.map((d) => d.shopCashierId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopCashier) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopCashier'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,234 @@
<!-- 编辑弹窗 -->
<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="dateTime">
<a-input
allow-clear
placeholder="请输入统计日期"
v-model:value="form.dateTime"
/>
</a-form-item>
<a-form-item label="总销售额" name="totalPrice">
<a-input
allow-clear
placeholder="请输入总销售额"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item label="今日销售额" name="todayPrice">
<a-input
allow-clear
placeholder="请输入今日销售额"
v-model:value="form.todayPrice"
/>
</a-form-item>
<a-form-item label="总会员数" name="totalUsers">
<a-input
allow-clear
placeholder="请输入总会员数"
v-model:value="form.totalUsers"
/>
</a-form-item>
<a-form-item label="今日新增" name="todayUsers">
<a-input
allow-clear
placeholder="请输入今日新增"
v-model:value="form.todayUsers"
/>
</a-form-item>
<a-form-item label="总订单笔数" name="totalOrders">
<a-input
allow-clear
placeholder="请输入总订单笔数"
v-model:value="form.totalOrders"
/>
</a-form-item>
<a-form-item label="今日订单笔数" name="todayOrders">
<a-input
allow-clear
placeholder="请输入今日订单笔数"
v-model:value="form.todayOrders"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1冻结" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</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 { addShopCount, updateShopCount } from '@/api/shop/shopCount';
import { ShopCount } from '@/api/shop/shopCount/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?: ShopCount | 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<ShopCount>({
id: undefined,
dateTime: undefined,
totalPrice: undefined,
todayPrice: undefined,
totalUsers: undefined,
todayUsers: undefined,
totalOrders: undefined,
todayOrders: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
createTime: undefined,
shopCountId: undefined,
shopCountName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopCountName: [
{
required: true,
type: 'string',
message: '请填写商城销售统计表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopCount : addShopCount;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,269 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopCountId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopCountEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopCountEdit from './components/shopCountEdit.vue';
import { pageShopCount, removeShopCount, removeBatchShopCount } from '@/api/shop/shopCount';
import type { ShopCount, ShopCountParam } from '@/api/shop/shopCount/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopCount[]>([]);
// 当前编辑数据
const current = ref<ShopCount | 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 pageShopCount({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '统计日期',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center',
},
{
title: '总销售额',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
},
{
title: '今日销售额',
dataIndex: 'todayPrice',
key: 'todayPrice',
align: 'center',
},
{
title: '总会员数',
dataIndex: 'totalUsers',
key: 'totalUsers',
align: 'center',
},
{
title: '今日新增',
dataIndex: 'todayUsers',
key: 'todayUsers',
align: 'center',
},
{
title: '总订单笔数',
dataIndex: 'totalOrders',
key: 'totalOrders',
align: 'center',
},
{
title: '今日订单笔数',
dataIndex: 'todayOrders',
key: 'todayOrders',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopCountParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopCount) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopCount) => {
const hide = message.loading('请求中..', 0);
removeShopCount(row.shopCountId)
.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);
removeBatchShopCount(selection.value.map((d) => d.shopCountId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopCount) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopCount'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,242 @@
<!-- 编辑弹窗 -->
<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="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="姓名" name="realName">
<a-input
allow-clear
placeholder="请输入姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="手机号" name="mobile">
<a-input
allow-clear
placeholder="请输入手机号"
v-model:value="form.mobile"
/>
</a-form-item>
<a-form-item label="推荐人用户ID" name="refereeId">
<a-input
allow-clear
placeholder="请输入推荐人用户ID"
v-model:value="form.refereeId"
/>
</a-form-item>
<a-form-item label="申请方式(10需后台审核 20无需审核)" name="applyType">
<a-input
allow-clear
placeholder="请输入申请方式(10需后台审核 20无需审核)"
v-model:value="form.applyType"
/>
</a-form-item>
<a-form-item label="申请时间" name="applyTime">
<a-input
allow-clear
placeholder="请输入申请时间"
v-model:value="form.applyTime"
/>
</a-form-item>
<a-form-item label="审核状态 (10待审核 20审核通过 30驳回)" name="applyStatus">
<a-input
allow-clear
placeholder="请输入审核状态 (10待审核 20审核通过 30驳回)"
v-model:value="form.applyStatus"
/>
</a-form-item>
<a-form-item label="审核时间" name="auditTime">
<a-input
allow-clear
placeholder="请输入审核时间"
v-model:value="form.auditTime"
/>
</a-form-item>
<a-form-item label="驳回原因" name="rejectReason">
<a-input
allow-clear
placeholder="请输入驳回原因"
v-model:value="form.rejectReason"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerApply, updateShopDealerApply } from '@/api/shop/shopDealerApply';
import { ShopDealerApply } from '@/api/shop/shopDealerApply/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?: ShopDealerApply | 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<ShopDealerApply>({
applyId: undefined,
userId: undefined,
realName: undefined,
mobile: undefined,
refereeId: undefined,
applyType: undefined,
applyTime: undefined,
applyStatus: undefined,
auditTime: undefined,
rejectReason: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerApplyId: undefined,
shopDealerApplyName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerApplyName: [
{
required: true,
type: 'string',
message: '请填写分销商申请记录表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerApply : addShopDealerApply;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,275 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerApplyId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerApplyEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerApplyEdit from './components/shopDealerApplyEdit.vue';
import { pageShopDealerApply, removeShopDealerApply, removeBatchShopDealerApply } from '@/api/shop/shopDealerApply';
import type { ShopDealerApply, ShopDealerApplyParam } from '@/api/shop/shopDealerApply/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerApply[]>([]);
// 当前编辑数据
const current = ref<ShopDealerApply | 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 pageShopDealerApply({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'applyId',
key: 'applyId',
align: 'center',
width: 90,
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '手机号',
dataIndex: 'mobile',
key: 'mobile',
align: 'center',
},
{
title: '推荐人用户ID',
dataIndex: 'refereeId',
key: 'refereeId',
align: 'center',
},
{
title: '申请方式(10需后台审核 20无需审核)',
dataIndex: 'applyType',
key: 'applyType',
align: 'center',
},
{
title: '申请时间',
dataIndex: 'applyTime',
key: 'applyTime',
align: 'center',
},
{
title: '审核状态 (10待审核 20审核通过 30驳回)',
dataIndex: 'applyStatus',
key: 'applyStatus',
align: 'center',
},
{
title: '审核时间',
dataIndex: 'auditTime',
key: 'auditTime',
align: 'center',
},
{
title: '驳回原因',
dataIndex: 'rejectReason',
key: 'rejectReason',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerApplyParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerApply) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerApply) => {
const hide = message.loading('请求中..', 0);
removeShopDealerApply(row.shopDealerApplyId)
.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);
removeBatchShopDealerApply(selection.value.map((d) => d.shopDealerApplyId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerApply) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerApply'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,218 @@
<!-- 编辑弹窗 -->
<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="分销商用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入分销商用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="订单ID" name="orderId">
<a-input
allow-clear
placeholder="请输入订单ID"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="资金流动类型 (10佣金收入 20提现支出 30转账支出 40转账收入)" name="flowType">
<a-input
allow-clear
placeholder="请输入资金流动类型 (10佣金收入 20提现支出 30转账支出 40转账收入)"
v-model:value="form.flowType"
/>
</a-form-item>
<a-form-item label="金额" name="money">
<a-input
allow-clear
placeholder="请输入金额"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="描述" name="describe">
<a-input
allow-clear
placeholder="请输入描述"
v-model:value="form.describe"
/>
</a-form-item>
<a-form-item label="对方用户ID" name="toUserId">
<a-input
allow-clear
placeholder="请输入对方用户ID"
v-model:value="form.toUserId"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerCapital, updateShopDealerCapital } from '@/api/shop/shopDealerCapital';
import { ShopDealerCapital } from '@/api/shop/shopDealerCapital/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?: ShopDealerCapital | 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<ShopDealerCapital>({
id: undefined,
userId: undefined,
orderId: undefined,
flowType: undefined,
money: undefined,
describe: undefined,
toUserId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerCapitalId: undefined,
shopDealerCapitalName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerCapitalName: [
{
required: true,
type: 'string',
message: '请填写分销商资金明细表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerCapital : addShopDealerCapital;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,257 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerCapitalId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerCapitalEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerCapitalEdit from './components/shopDealerCapitalEdit.vue';
import { pageShopDealerCapital, removeShopDealerCapital, removeBatchShopDealerCapital } from '@/api/shop/shopDealerCapital';
import type { ShopDealerCapital, ShopDealerCapitalParam } from '@/api/shop/shopDealerCapital/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerCapital[]>([]);
// 当前编辑数据
const current = ref<ShopDealerCapital | 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 pageShopDealerCapital({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '分销商用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '订单ID',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '资金流动类型 (10佣金收入 20提现支出 30转账支出 40转账收入)',
dataIndex: 'flowType',
key: 'flowType',
align: 'center',
},
{
title: '金额',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '描述',
dataIndex: 'describe',
key: 'describe',
align: 'center',
},
{
title: '对方用户ID',
dataIndex: 'toUserId',
key: 'toUserId',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerCapitalParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerCapital) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerCapital) => {
const hide = message.loading('请求中..', 0);
removeShopDealerCapital(row.shopDealerCapitalId)
.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);
removeBatchShopDealerCapital(selection.value.map((d) => d.shopDealerCapitalId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerCapital) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerCapital'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,266 @@
<!-- 编辑弹窗 -->
<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="买家用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入买家用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="订单ID" name="orderId">
<a-input
allow-clear
placeholder="请输入订单ID"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="订单总金额(不含运费)" name="orderPrice">
<a-input
allow-clear
placeholder="请输入订单总金额(不含运费)"
v-model:value="form.orderPrice"
/>
</a-form-item>
<a-form-item label="分销商用户id(一级)" name="firstUserId">
<a-input
allow-clear
placeholder="请输入分销商用户id(一级)"
v-model:value="form.firstUserId"
/>
</a-form-item>
<a-form-item label="分销商用户id(二级)" name="secondUserId">
<a-input
allow-clear
placeholder="请输入分销商用户id(二级)"
v-model:value="form.secondUserId"
/>
</a-form-item>
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
<a-input
allow-clear
placeholder="请输入分销商用户id(三级)"
v-model:value="form.thirdUserId"
/>
</a-form-item>
<a-form-item label="分销佣金(一级)" name="firstMoney">
<a-input
allow-clear
placeholder="请输入分销佣金(一级)"
v-model:value="form.firstMoney"
/>
</a-form-item>
<a-form-item label="分销佣金(二级)" name="secondMoney">
<a-input
allow-clear
placeholder="请输入分销佣金(二级)"
v-model:value="form.secondMoney"
/>
</a-form-item>
<a-form-item label="分销佣金(三级)" name="thirdMoney">
<a-input
allow-clear
placeholder="请输入分销佣金(三级)"
v-model:value="form.thirdMoney"
/>
</a-form-item>
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
<a-input
allow-clear
placeholder="请输入订单是否失效(0未失效 1已失效)"
v-model:value="form.isInvalid"
/>
</a-form-item>
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
<a-input
allow-clear
placeholder="请输入佣金结算(0未结算 1已结算)"
v-model:value="form.isSettled"
/>
</a-form-item>
<a-form-item label="结算时间" name="settleTime">
<a-input
allow-clear
placeholder="请输入结算时间"
v-model:value="form.settleTime"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerOrder, updateShopDealerOrder } from '@/api/shop/shopDealerOrder';
import { ShopDealerOrder } from '@/api/shop/shopDealerOrder/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?: ShopDealerOrder | 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<ShopDealerOrder>({
id: undefined,
userId: undefined,
orderId: undefined,
orderPrice: undefined,
firstUserId: undefined,
secondUserId: undefined,
thirdUserId: undefined,
firstMoney: undefined,
secondMoney: undefined,
thirdMoney: undefined,
isInvalid: undefined,
isSettled: undefined,
settleTime: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerOrderId: undefined,
shopDealerOrderName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerOrderName: [
{
required: true,
type: 'string',
message: '请填写分销商订单记录表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerOrder : addShopDealerOrder;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,293 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerOrderId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerOrderEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerOrderEdit from './components/shopDealerOrderEdit.vue';
import { pageShopDealerOrder, removeShopDealerOrder, removeBatchShopDealerOrder } from '@/api/shop/shopDealerOrder';
import type { ShopDealerOrder, ShopDealerOrderParam } from '@/api/shop/shopDealerOrder/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerOrder[]>([]);
// 当前编辑数据
const current = ref<ShopDealerOrder | 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 pageShopDealerOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '买家用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '订单ID',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '订单总金额(不含运费)',
dataIndex: 'orderPrice',
key: 'orderPrice',
align: 'center',
},
{
title: '分销商用户id(一级)',
dataIndex: 'firstUserId',
key: 'firstUserId',
align: 'center',
},
{
title: '分销商用户id(二级)',
dataIndex: 'secondUserId',
key: 'secondUserId',
align: 'center',
},
{
title: '分销商用户id(三级)',
dataIndex: 'thirdUserId',
key: 'thirdUserId',
align: 'center',
},
{
title: '分销佣金(一级)',
dataIndex: 'firstMoney',
key: 'firstMoney',
align: 'center',
},
{
title: '分销佣金(二级)',
dataIndex: 'secondMoney',
key: 'secondMoney',
align: 'center',
},
{
title: '分销佣金(三级)',
dataIndex: 'thirdMoney',
key: 'thirdMoney',
align: 'center',
},
{
title: '订单是否失效(0未失效 1已失效)',
dataIndex: 'isInvalid',
key: 'isInvalid',
align: 'center',
},
{
title: '佣金结算(0未结算 1已结算)',
dataIndex: 'isSettled',
key: 'isSettled',
align: 'center',
},
{
title: '结算时间',
dataIndex: 'settleTime',
key: 'settleTime',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerOrder) => {
const hide = message.loading('请求中..', 0);
removeShopDealerOrder(row.shopDealerOrderId)
.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);
removeBatchShopDealerOrder(selection.value.map((d) => d.shopDealerOrderId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerOrder'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,194 @@
<!-- 编辑弹窗 -->
<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="分销商用户ID" name="dealerId">
<a-input
allow-clear
placeholder="请输入分销商用户ID"
v-model:value="form.dealerId"
/>
</a-form-item>
<a-form-item label="用户id(被推荐人)" name="userId">
<a-input
allow-clear
placeholder="请输入用户id(被推荐人)"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="推荐关系层级(1,2,3)" name="level">
<a-input
allow-clear
placeholder="请输入推荐关系层级(1,2,3)"
v-model:value="form.level"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerReferee, updateShopDealerReferee } from '@/api/shop/shopDealerReferee';
import { ShopDealerReferee } from '@/api/shop/shopDealerReferee/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?: ShopDealerReferee | 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<ShopDealerReferee>({
id: undefined,
dealerId: undefined,
userId: undefined,
level: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerRefereeId: undefined,
shopDealerRefereeName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerRefereeName: [
{
required: true,
type: 'string',
message: '请填写分销商推荐关系表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerReferee : addShopDealerReferee;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerRefereeId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerRefereeEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerRefereeEdit from './components/shopDealerRefereeEdit.vue';
import { pageShopDealerReferee, removeShopDealerReferee, removeBatchShopDealerReferee } from '@/api/shop/shopDealerReferee';
import type { ShopDealerReferee, ShopDealerRefereeParam } from '@/api/shop/shopDealerReferee/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerReferee[]>([]);
// 当前编辑数据
const current = ref<ShopDealerReferee | 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 pageShopDealerReferee({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '分销商用户ID',
dataIndex: 'dealerId',
key: 'dealerId',
align: 'center',
},
{
title: '用户id(被推荐人)',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '推荐关系层级(1,2,3)',
dataIndex: 'level',
key: 'level',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerRefereeParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerReferee) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerReferee) => {
const hide = message.loading('请求中..', 0);
removeShopDealerReferee(row.shopDealerRefereeId)
.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);
removeBatchShopDealerReferee(selection.value.map((d) => d.shopDealerRefereeId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerReferee) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerReferee'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,185 @@
<!-- 编辑弹窗 -->
<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="describe">
<a-input
allow-clear
placeholder="请输入设置项描述"
v-model:value="form.describe"
/>
</a-form-item>
<a-form-item label="设置内容(json格式)" name="values">
<a-input
allow-clear
placeholder="请输入设置内容(json格式)"
v-model:value="form.values"
/>
</a-form-item>
<a-form-item label="更新时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入更新时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerSetting, updateShopDealerSetting } from '@/api/shop/shopDealerSetting';
import { ShopDealerSetting } from '@/api/shop/shopDealerSetting/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?: ShopDealerSetting | 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<ShopDealerSetting>({
key: undefined,
describe: undefined,
values: undefined,
tenantId: undefined,
updateTime: undefined,
shopDealerSettingId: undefined,
shopDealerSettingName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerSettingName: [
{
required: true,
type: 'string',
message: '请填写分销商设置表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerSetting : addShopDealerSetting;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,224 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerSettingId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerSettingEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerSettingEdit from './components/shopDealerSettingEdit.vue';
import { pageShopDealerSetting, removeShopDealerSetting, removeBatchShopDealerSetting } from '@/api/shop/shopDealerSetting';
import type { ShopDealerSetting, ShopDealerSettingParam } from '@/api/shop/shopDealerSetting/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerSetting[]>([]);
// 当前编辑数据
const current = ref<ShopDealerSetting | 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 pageShopDealerSetting({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '设置项标示',
dataIndex: 'key',
key: 'key',
align: 'center',
width: 90,
},
{
title: '设置项描述',
dataIndex: 'describe',
key: 'describe',
align: 'center',
},
{
title: '设置内容(json格式)',
dataIndex: 'values',
key: 'values',
align: 'center',
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerSettingParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerSetting) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerSetting) => {
const hide = message.loading('请求中..', 0);
removeShopDealerSetting(row.shopDealerSettingId)
.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);
removeBatchShopDealerSetting(selection.value.map((d) => d.shopDealerSettingId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerSetting) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerSetting'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,274 @@
<!-- 编辑弹窗 -->
<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="自增ID" name="userId">
<a-input
allow-clear
placeholder="请输入自增ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="姓名" name="realName">
<a-input
allow-clear
placeholder="请输入姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="手机号" name="mobile">
<a-input
allow-clear
placeholder="请输入手机号"
v-model:value="form.mobile"
/>
</a-form-item>
<a-form-item label="支付密码" name="payPassword">
<a-input
allow-clear
placeholder="请输入支付密码"
v-model:value="form.payPassword"
/>
</a-form-item>
<a-form-item label="当前可提现佣金" name="money">
<a-input
allow-clear
placeholder="请输入当前可提现佣金"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="已冻结佣金" name="freezeMoney">
<a-input
allow-clear
placeholder="请输入已冻结佣金"
v-model:value="form.freezeMoney"
/>
</a-form-item>
<a-form-item label="累积提现佣金" name="totalMoney">
<a-input
allow-clear
placeholder="请输入累积提现佣金"
v-model:value="form.totalMoney"
/>
</a-form-item>
<a-form-item label="推荐人用户ID" name="refereeId">
<a-input
allow-clear
placeholder="请输入推荐人用户ID"
v-model:value="form.refereeId"
/>
</a-form-item>
<a-form-item label="成员数量(一级)" name="firstNum">
<a-input
allow-clear
placeholder="请输入成员数量(一级)"
v-model:value="form.firstNum"
/>
</a-form-item>
<a-form-item label="成员数量(二级)" name="secondNum">
<a-input
allow-clear
placeholder="请输入成员数量(二级)"
v-model:value="form.secondNum"
/>
</a-form-item>
<a-form-item label="成员数量(三级)" name="thirdNum">
<a-input
allow-clear
placeholder="请输入成员数量(三级)"
v-model:value="form.thirdNum"
/>
</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="isDelete">
<a-input
allow-clear
placeholder="请输入是否删除"
v-model:value="form.isDelete"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerUser, updateShopDealerUser } from '@/api/shop/shopDealerUser';
import { ShopDealerUser } from '@/api/shop/shopDealerUser/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?: ShopDealerUser | 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<ShopDealerUser>({
id: undefined,
userId: undefined,
realName: undefined,
mobile: undefined,
payPassword: undefined,
money: undefined,
freezeMoney: undefined,
totalMoney: undefined,
refereeId: undefined,
firstNum: undefined,
secondNum: undefined,
thirdNum: undefined,
qrcode: undefined,
isDelete: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerUserId: undefined,
shopDealerUserName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerUserName: [
{
required: true,
type: 'string',
message: '请填写分销商用户记录表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerUser : addShopDealerUser;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,299 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerUserId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerUserEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerUserEdit from './components/shopDealerUserEdit.vue';
import { pageShopDealerUser, removeShopDealerUser, removeBatchShopDealerUser } from '@/api/shop/shopDealerUser';
import type { ShopDealerUser, ShopDealerUserParam } from '@/api/shop/shopDealerUser/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerUser[]>([]);
// 当前编辑数据
const current = ref<ShopDealerUser | 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 pageShopDealerUser({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '自增ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '手机号',
dataIndex: 'mobile',
key: 'mobile',
align: 'center',
},
{
title: '支付密码',
dataIndex: 'payPassword',
key: 'payPassword',
align: 'center',
},
{
title: '当前可提现佣金',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '已冻结佣金',
dataIndex: 'freezeMoney',
key: 'freezeMoney',
align: 'center',
},
{
title: '累积提现佣金',
dataIndex: 'totalMoney',
key: 'totalMoney',
align: 'center',
},
{
title: '推荐人用户ID',
dataIndex: 'refereeId',
key: 'refereeId',
align: 'center',
},
{
title: '成员数量(一级)',
dataIndex: 'firstNum',
key: 'firstNum',
align: 'center',
},
{
title: '成员数量(二级)',
dataIndex: 'secondNum',
key: 'secondNum',
align: 'center',
},
{
title: '成员数量(三级)',
dataIndex: 'thirdNum',
key: 'thirdNum',
align: 'center',
},
{
title: '专属二维码',
dataIndex: 'qrcode',
key: 'qrcode',
align: 'center',
},
{
title: '是否删除',
dataIndex: 'isDelete',
key: 'isDelete',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerUserParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerUser) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerUser) => {
const hide = message.loading('请求中..', 0);
removeShopDealerUser(row.shopDealerUserId)
.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);
removeBatchShopDealerUser(selection.value.map((d) => d.shopDealerUserId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerUser) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerUser'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,266 @@
<!-- 编辑弹窗 -->
<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="分销商用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入分销商用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="提现金额" name="money">
<a-input
allow-clear
placeholder="请输入提现金额"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="打款方式 (10微信 20支付宝 30银行卡)" name="payType">
<a-input
allow-clear
placeholder="请输入打款方式 (10微信 20支付宝 30银行卡)"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="支付宝姓名" name="alipayName">
<a-input
allow-clear
placeholder="请输入支付宝姓名"
v-model:value="form.alipayName"
/>
</a-form-item>
<a-form-item label="支付宝账号" name="alipayAccount">
<a-input
allow-clear
placeholder="请输入支付宝账号"
v-model:value="form.alipayAccount"
/>
</a-form-item>
<a-form-item label="开户行名称" name="bankName">
<a-input
allow-clear
placeholder="请输入开户行名称"
v-model:value="form.bankName"
/>
</a-form-item>
<a-form-item label="银行开户名" name="bankAccount">
<a-input
allow-clear
placeholder="请输入银行开户名"
v-model:value="form.bankAccount"
/>
</a-form-item>
<a-form-item label="银行卡号" name="bankCard">
<a-input
allow-clear
placeholder="请输入银行卡号"
v-model:value="form.bankCard"
/>
</a-form-item>
<a-form-item label="申请状态 (10待审核 20审核通过 30驳回 40已打款)" name="applyStatus">
<a-input
allow-clear
placeholder="请输入申请状态 (10待审核 20审核通过 30驳回 40已打款)"
v-model:value="form.applyStatus"
/>
</a-form-item>
<a-form-item label="审核时间" name="auditTime">
<a-input
allow-clear
placeholder="请输入审核时间"
v-model:value="form.auditTime"
/>
</a-form-item>
<a-form-item label="驳回原因" name="rejectReason">
<a-input
allow-clear
placeholder="请输入驳回原因"
v-model:value="form.rejectReason"
/>
</a-form-item>
<a-form-item label="来源客户端(APP、H5、小程序等)" name="platform">
<a-input
allow-clear
placeholder="请输入来源客户端(APP、H5、小程序等)"
v-model:value="form.platform"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopDealerWithdraw, updateShopDealerWithdraw } from '@/api/shop/shopDealerWithdraw';
import { ShopDealerWithdraw } from '@/api/shop/shopDealerWithdraw/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?: ShopDealerWithdraw | 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<ShopDealerWithdraw>({
id: undefined,
userId: undefined,
money: undefined,
payType: undefined,
alipayName: undefined,
alipayAccount: undefined,
bankName: undefined,
bankAccount: undefined,
bankCard: undefined,
applyStatus: undefined,
auditTime: undefined,
rejectReason: undefined,
platform: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopDealerWithdrawId: undefined,
shopDealerWithdrawName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopDealerWithdrawName: [
{
required: true,
type: 'string',
message: '请填写分销商提现明细表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopDealerWithdraw : addShopDealerWithdraw;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,293 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopDealerWithdrawId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopDealerWithdrawEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopDealerWithdrawEdit from './components/shopDealerWithdrawEdit.vue';
import { pageShopDealerWithdraw, removeShopDealerWithdraw, removeBatchShopDealerWithdraw } from '@/api/shop/shopDealerWithdraw';
import type { ShopDealerWithdraw, ShopDealerWithdrawParam } from '@/api/shop/shopDealerWithdraw/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopDealerWithdraw[]>([]);
// 当前编辑数据
const current = ref<ShopDealerWithdraw | 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 pageShopDealerWithdraw({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '分销商用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '提现金额',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '打款方式 (10微信 20支付宝 30银行卡)',
dataIndex: 'payType',
key: 'payType',
align: 'center',
},
{
title: '支付宝姓名',
dataIndex: 'alipayName',
key: 'alipayName',
align: 'center',
},
{
title: '支付宝账号',
dataIndex: 'alipayAccount',
key: 'alipayAccount',
align: 'center',
},
{
title: '开户行名称',
dataIndex: 'bankName',
key: 'bankName',
align: 'center',
},
{
title: '银行开户名',
dataIndex: 'bankAccount',
key: 'bankAccount',
align: 'center',
},
{
title: '银行卡号',
dataIndex: 'bankCard',
key: 'bankCard',
align: 'center',
},
{
title: '申请状态 (10待审核 20审核通过 30驳回 40已打款)',
dataIndex: 'applyStatus',
key: 'applyStatus',
align: 'center',
},
{
title: '审核时间',
dataIndex: 'auditTime',
key: 'auditTime',
align: 'center',
},
{
title: '驳回原因',
dataIndex: 'rejectReason',
key: 'rejectReason',
align: 'center',
},
{
title: '来源客户端(APP、H5、小程序等)',
dataIndex: 'platform',
key: 'platform',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopDealerWithdrawParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopDealerWithdraw) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopDealerWithdraw) => {
const hide = message.loading('请求中..', 0);
removeShopDealerWithdraw(row.shopDealerWithdrawId)
.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);
removeBatchShopDealerWithdraw(selection.value.map((d) => d.shopDealerWithdrawId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopDealerWithdraw) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopDealerWithdraw'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,416 @@
<!-- 编辑弹窗 -->
<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="类型 1实物商品 2虚拟商品" name="type">
<a-input
allow-clear
placeholder="请输入类型 1实物商品 2虚拟商品"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="商品编码" name="code">
<a-input
allow-clear
placeholder="请输入商品编码"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="商品标题" name="goodsName">
<a-input
allow-clear
placeholder="请输入商品标题"
v-model:value="form.goodsName"
/>
</a-form-item>
<a-form-item
label="商品封面图"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商品详情" name="content">
<a-input
allow-clear
placeholder="请输入商品详情"
v-model:value="form.content"
/>
</a-form-item>
<a-form-item label="父级分类ID" name="parentId">
<a-input
allow-clear
placeholder="请输入父级分类ID"
v-model:value="form.parentId"
/>
</a-form-item>
<a-form-item label="商品分类ID" name="categoryId">
<a-input
allow-clear
placeholder="请输入商品分类ID"
v-model:value="form.categoryId"
/>
</a-form-item>
<a-form-item label="父级分类" name="parentName">
<a-input
allow-clear
placeholder="请输入父级分类"
v-model:value="form.parentName"
/>
</a-form-item>
<a-form-item label="当前分类" name="categoryName">
<a-input
allow-clear
placeholder="请输入当前分类"
v-model:value="form.categoryName"
/>
</a-form-item>
<a-form-item label="三级分类" name="childrenName">
<a-input
allow-clear
placeholder="请输入三级分类"
v-model:value="form.childrenName"
/>
</a-form-item>
<a-form-item label="商品规格 0单规格 1多规格" name="specs">
<a-input
allow-clear
placeholder="请输入商品规格 0单规格 1多规格"
v-model:value="form.specs"
/>
</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="unitName">
<a-input
allow-clear
placeholder="请输入单位名称 (个)"
v-model:value="form.unitName"
/>
</a-form-item>
<a-form-item label="进货价格" name="price">
<a-input
allow-clear
placeholder="请输入进货价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="销售价格" name="salePrice">
<a-input
allow-clear
placeholder="请输入销售价格"
v-model:value="form.salePrice"
/>
</a-form-item>
<a-form-item label="库存计算方式(10下单减库存 20付款减库存)" name="deductStockType">
<a-input
allow-clear
placeholder="请输入库存计算方式(10下单减库存 20付款减库存)"
v-model:value="form.deductStockType"
/>
</a-form-item>
<a-form-item label="封面图" name="files">
<a-input
allow-clear
placeholder="请输入封面图"
v-model:value="form.files"
/>
</a-form-item>
<a-form-item label="销量" name="sales">
<a-input
allow-clear
placeholder="请输入销量"
v-model:value="form.sales"
/>
</a-form-item>
<a-form-item label="库存" name="stock">
<a-input
allow-clear
placeholder="请输入库存"
v-model:value="form.stock"
/>
</a-form-item>
<a-form-item label="商品重量" name="goodsWeight">
<a-input
allow-clear
placeholder="请输入商品重量"
v-model:value="form.goodsWeight"
/>
</a-form-item>
<a-form-item label="消费赚取积分" name="gainIntegral">
<a-input
allow-clear
placeholder="请输入消费赚取积分"
v-model:value="form.gainIntegral"
/>
</a-form-item>
<a-form-item label="推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="状态0未上架1上架" name="isShow">
<a-input
allow-clear
placeholder="请输入状态0未上架1上架"
v-model:value="form.isShow"
/>
</a-form-item>
<a-form-item label="状态, 0上架 1待上架 2待审核 3审核不通过" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</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="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoods, updateShopGoods } from '@/api/shop/shopGoods';
import { ShopGoods } from '@/api/shop/shopGoods/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?: ShopGoods | 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<ShopGoods>({
goodsId: undefined,
type: undefined,
code: undefined,
goodsName: undefined,
image: undefined,
content: undefined,
parentId: undefined,
categoryId: undefined,
parentName: undefined,
categoryName: undefined,
childrenName: undefined,
specs: undefined,
position: undefined,
unitName: undefined,
price: undefined,
salePrice: undefined,
deductStockType: undefined,
files: undefined,
sales: undefined,
stock: undefined,
goodsWeight: undefined,
gainIntegral: undefined,
recommend: undefined,
merchantId: undefined,
merchantName: undefined,
isShow: undefined,
status: undefined,
comments: undefined,
sortNumber: undefined,
userId: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsId: undefined,
shopGoodsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsName: [
{
required: true,
type: 'string',
message: '请填写商品记录表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoods : addShopGoods;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,401 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsEdit from './components/shopGoodsEdit.vue';
import { pageShopGoods, removeShopGoods, removeBatchShopGoods } from '@/api/shop/shopGoods';
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoods[]>([]);
// 当前编辑数据
const current = ref<ShopGoods | 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 pageShopGoods({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '自增ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
width: 90,
},
{
title: '类型 1实物商品 2虚拟商品',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '商品编码',
dataIndex: 'code',
key: 'code',
align: 'center',
},
{
title: '商品标题',
dataIndex: 'goodsName',
key: 'goodsName',
align: 'center',
},
{
title: '商品封面图',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商品详情',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '父级分类ID',
dataIndex: 'parentId',
key: 'parentId',
align: 'center',
},
{
title: '商品分类ID',
dataIndex: 'categoryId',
key: 'categoryId',
align: 'center',
},
{
title: '父级分类',
dataIndex: 'parentName',
key: 'parentName',
align: 'center',
},
{
title: '当前分类',
dataIndex: 'categoryName',
key: 'categoryName',
align: 'center',
},
{
title: '三级分类',
dataIndex: 'childrenName',
key: 'childrenName',
align: 'center',
},
{
title: '商品规格 0单规格 1多规格',
dataIndex: 'specs',
key: 'specs',
align: 'center',
},
{
title: '货架',
dataIndex: 'position',
key: 'position',
align: 'center',
},
{
title: '单位名称 (个)',
dataIndex: 'unitName',
key: 'unitName',
align: 'center',
},
{
title: '进货价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '销售价格',
dataIndex: 'salePrice',
key: 'salePrice',
align: 'center',
},
{
title: '库存计算方式(10下单减库存 20付款减库存)',
dataIndex: 'deductStockType',
key: 'deductStockType',
align: 'center',
},
{
title: '封面图',
dataIndex: 'files',
key: 'files',
align: 'center',
},
{
title: '销量',
dataIndex: 'sales',
key: 'sales',
align: 'center',
},
{
title: '库存',
dataIndex: 'stock',
key: 'stock',
align: 'center',
},
{
title: '商品重量',
dataIndex: 'goodsWeight',
key: 'goodsWeight',
align: 'center',
},
{
title: '消费赚取积分',
dataIndex: 'gainIntegral',
key: 'gainIntegral',
align: 'center',
},
{
title: '推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '状态0未上架1上架',
dataIndex: 'isShow',
key: 'isShow',
align: 'center',
},
{
title: '状态, 0上架 1待上架 2待审核 3审核不通过',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoods) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoods) => {
const hide = message.loading('请求中..', 0);
removeShopGoods(row.shopGoodsId)
.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);
removeBatchShopGoods(selection.value.map((d) => d.shopGoodsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoods) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoods'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,320 @@
<!-- 编辑弹窗 -->
<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="categoryCode">
<a-input
allow-clear
placeholder="请输入分类标识"
v-model:value="form.categoryCode"
/>
</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="类型 0商城分类 1外卖分类" name="type">
<a-input
allow-clear
placeholder="请输入类型 0商城分类 1外卖分类"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item
label="分类图片"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="上级分类ID" name="parentId">
<a-input
allow-clear
placeholder="请输入上级分类ID"
v-model:value="form.parentId"
/>
</a-form-item>
<a-form-item label="路由/链接地址" name="path">
<a-input
allow-clear
placeholder="请输入路由/链接地址"
v-model:value="form.path"
/>
</a-form-item>
<a-form-item label="组件路径" name="component">
<a-input
allow-clear
placeholder="请输入组件路径"
v-model:value="form.component"
/>
</a-form-item>
<a-form-item label="绑定的页面" name="pageId">
<a-input
allow-clear
placeholder="请输入绑定的页面"
v-model:value="form.pageId"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="商品数量" name="count">
<a-input
allow-clear
placeholder="请输入商品数量"
v-model:value="form.count"
/>
</a-form-item>
<a-form-item label="排序(数字越小越靠前)" name="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="是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)" name="hide">
<a-input
allow-clear
placeholder="请输入是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)"
v-model:value="form.hide"
/>
</a-form-item>
<a-form-item label="是否推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入是否推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="是否显示在首页" name="showIndex">
<a-input
allow-clear
placeholder="请输入是否显示在首页"
v-model:value="form.showIndex"
/>
</a-form-item>
<a-form-item label="商铺ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商铺ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1禁用" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsCategory, updateShopGoodsCategory } from '@/api/shop/shopGoodsCategory';
import { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/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?: ShopGoodsCategory | 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<ShopGoodsCategory>({
categoryId: undefined,
categoryCode: undefined,
title: undefined,
type: undefined,
image: undefined,
parentId: undefined,
path: undefined,
component: undefined,
pageId: undefined,
userId: undefined,
count: undefined,
sortNumber: undefined,
comments: undefined,
hide: undefined,
recommend: undefined,
showIndex: undefined,
merchantId: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsCategoryId: undefined,
shopGoodsCategoryName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsCategoryName: [
{
required: true,
type: 'string',
message: '请填写商品分类名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsCategory : addShopGoodsCategory;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,329 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsCategoryId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsCategoryEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsCategoryEdit from './components/shopGoodsCategoryEdit.vue';
import { pageShopGoodsCategory, removeShopGoodsCategory, removeBatchShopGoodsCategory } from '@/api/shop/shopGoodsCategory';
import type { ShopGoodsCategory, ShopGoodsCategoryParam } from '@/api/shop/shopGoodsCategory/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsCategory[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsCategory | 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 pageShopGoodsCategory({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '商品分类ID',
dataIndex: 'categoryId',
key: 'categoryId',
align: 'center',
width: 90,
},
{
title: '分类标识',
dataIndex: 'categoryCode',
key: 'categoryCode',
align: 'center',
},
{
title: '分类名称',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '类型 0商城分类 1外卖分类',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '分类图片',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '上级分类ID',
dataIndex: 'parentId',
key: 'parentId',
align: 'center',
},
{
title: '路由/链接地址',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '组件路径',
dataIndex: 'component',
key: 'component',
align: 'center',
},
{
title: '绑定的页面',
dataIndex: 'pageId',
key: 'pageId',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '商品数量',
dataIndex: 'count',
key: 'count',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)',
dataIndex: 'hide',
key: 'hide',
align: 'center',
},
{
title: '是否推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center',
},
{
title: '是否显示在首页',
dataIndex: 'showIndex',
key: 'showIndex',
align: 'center',
},
{
title: '商铺ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '状态, 0正常, 1禁用',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsCategoryParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsCategory) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsCategory) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsCategory(row.shopGoodsCategoryId)
.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);
removeBatchShopGoodsCategory(selection.value.map((d) => d.shopGoodsCategoryId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsCategory) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsCategory'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,321 @@
<!-- 编辑弹窗 -->
<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="用户ID" name="uid">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="订单ID" name="oid">
<a-input
allow-clear
placeholder="请输入订单ID"
v-model:value="form.oid"
/>
</a-form-item>
<a-form-item label="商品唯一id" name="unique">
<a-input
allow-clear
placeholder="请输入商品唯一id"
v-model:value="form.unique"
/>
</a-form-item>
<a-form-item label="商品id" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品id"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="某种商品类型(普通商品、秒杀商品)" name="replyType">
<a-input
allow-clear
placeholder="请输入某种商品类型(普通商品、秒杀商品)"
v-model:value="form.replyType"
/>
</a-form-item>
<a-form-item label="商品分数" name="goodsScore">
<a-input
allow-clear
placeholder="请输入商品分数"
v-model:value="form.goodsScore"
/>
</a-form-item>
<a-form-item label="服务分数" name="serviceScore">
<a-input
allow-clear
placeholder="请输入服务分数"
v-model:value="form.serviceScore"
/>
</a-form-item>
<a-form-item label="评论内容" name="comment">
<a-input
allow-clear
placeholder="请输入评论内容"
v-model:value="form.comment"
/>
</a-form-item>
<a-form-item label="评论图片" name="pics">
<a-input
allow-clear
placeholder="请输入评论图片"
v-model:value="form.pics"
/>
</a-form-item>
<a-form-item label="管理员回复内容" name="merchantReplyContent">
<a-input
allow-clear
placeholder="请输入管理员回复内容"
v-model:value="form.merchantReplyContent"
/>
</a-form-item>
<a-form-item label="管理员回复时间" name="merchantReplyTime">
<a-input
allow-clear
placeholder="请输入管理员回复时间"
v-model:value="form.merchantReplyTime"
/>
</a-form-item>
<a-form-item label="0未删除1已删除" name="isDel">
<a-input
allow-clear
placeholder="请输入0未删除1已删除"
v-model:value="form.isDel"
/>
</a-form-item>
<a-form-item label="0未回复1已回复" name="isReply">
<a-input
allow-clear
placeholder="请输入0未回复1已回复"
v-model:value="form.isReply"
/>
</a-form-item>
<a-form-item label="用户名称" name="nickname">
<a-input
allow-clear
placeholder="请输入用户名称"
v-model:value="form.nickname"
/>
</a-form-item>
<a-form-item label="用户头像" name="avatar">
<a-input
allow-clear
placeholder="请输入用户头像"
v-model:value="form.avatar"
/>
</a-form-item>
<a-form-item label="商品规格属性值,多个,号隔开" name="sku">
<a-input
allow-clear
placeholder="请输入商品规格属性值,多个,号隔开"
v-model:value="form.sku"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1冻结" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="更新时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入更新时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsComment, updateShopGoodsComment } from '@/api/shop/shopGoodsComment';
import { ShopGoodsComment } from '@/api/shop/shopGoodsComment/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?: ShopGoodsComment | 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<ShopGoodsComment>({
id: undefined,
uid: undefined,
oid: undefined,
unique: undefined,
goodsId: undefined,
replyType: undefined,
goodsScore: undefined,
serviceScore: undefined,
comment: undefined,
pics: undefined,
merchantReplyContent: undefined,
merchantReplyTime: undefined,
isDel: undefined,
isReply: undefined,
nickname: undefined,
avatar: undefined,
sku: undefined,
status: undefined,
deleted: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsCommentId: undefined,
shopGoodsCommentName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsCommentName: [
{
required: true,
type: 'string',
message: '请填写评论表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsComment : addShopGoodsComment;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,335 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsCommentId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsCommentEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsCommentEdit from './components/shopGoodsCommentEdit.vue';
import { pageShopGoodsComment, removeShopGoodsComment, removeBatchShopGoodsComment } from '@/api/shop/shopGoodsComment';
import type { ShopGoodsComment, ShopGoodsCommentParam } from '@/api/shop/shopGoodsComment/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsComment[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsComment | 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 pageShopGoodsComment({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '评论ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户ID',
dataIndex: 'uid',
key: 'uid',
align: 'center',
},
{
title: '订单ID',
dataIndex: 'oid',
key: 'oid',
align: 'center',
},
{
title: '商品唯一id',
dataIndex: 'unique',
key: 'unique',
align: 'center',
},
{
title: '商品id',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '某种商品类型(普通商品、秒杀商品)',
dataIndex: 'replyType',
key: 'replyType',
align: 'center',
},
{
title: '商品分数',
dataIndex: 'goodsScore',
key: 'goodsScore',
align: 'center',
},
{
title: '服务分数',
dataIndex: 'serviceScore',
key: 'serviceScore',
align: 'center',
},
{
title: '评论内容',
dataIndex: 'comment',
key: 'comment',
align: 'center',
},
{
title: '评论图片',
dataIndex: 'pics',
key: 'pics',
align: 'center',
},
{
title: '管理员回复内容',
dataIndex: 'merchantReplyContent',
key: 'merchantReplyContent',
align: 'center',
},
{
title: '管理员回复时间',
dataIndex: 'merchantReplyTime',
key: 'merchantReplyTime',
align: 'center',
},
{
title: '0未删除1已删除',
dataIndex: 'isDel',
key: 'isDel',
align: 'center',
},
{
title: '0未回复1已回复',
dataIndex: 'isReply',
key: 'isReply',
align: 'center',
},
{
title: '用户名称',
dataIndex: 'nickname',
key: 'nickname',
align: 'center',
},
{
title: '用户头像',
dataIndex: 'avatar',
key: 'avatar',
align: 'center',
},
{
title: '商品规格属性值,多个,号隔开',
dataIndex: 'sku',
key: 'sku',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsCommentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsComment) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsComment) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsComment(row.shopGoodsCommentId)
.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);
removeBatchShopGoodsComment(selection.value.map((d) => d.shopGoodsCommentId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsComment) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsComment'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,219 @@
<!-- 编辑弹窗 -->
<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="商品id" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品id"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="优惠劵id" name="issueCouponId">
<a-input
allow-clear
placeholder="请输入优惠劵id"
v-model:value="form.issueCouponId"
/>
</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="状态, 0正常, 1冻结" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsCoupon, updateShopGoodsCoupon } from '@/api/shop/shopGoodsCoupon';
import { ShopGoodsCoupon } from '@/api/shop/shopGoodsCoupon/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?: ShopGoodsCoupon | 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<ShopGoodsCoupon>({
id: undefined,
goodsId: undefined,
issueCouponId: undefined,
sortNumber: undefined,
status: undefined,
deleted: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsCouponId: undefined,
shopGoodsCouponName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsCouponName: [
{
required: true,
type: 'string',
message: '请填写商品优惠券表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsCoupon : addShopGoodsCoupon;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,257 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsCouponId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsCouponEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsCouponEdit from './components/shopGoodsCouponEdit.vue';
import { pageShopGoodsCoupon, removeShopGoodsCoupon, removeBatchShopGoodsCoupon } from '@/api/shop/shopGoodsCoupon';
import type { ShopGoodsCoupon, ShopGoodsCouponParam } from '@/api/shop/shopGoodsCoupon/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsCoupon[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsCoupon | 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 pageShopGoodsCoupon({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商品id',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '优惠劵id',
dataIndex: 'issueCouponId',
key: 'issueCouponId',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsCouponParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsCoupon) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsCoupon) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsCoupon(row.shopGoodsCouponId)
.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);
removeBatchShopGoodsCoupon(selection.value.map((d) => d.shopGoodsCouponId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsCoupon) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsCoupon'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,291 @@
<!-- 编辑弹窗 -->
<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="类型visit,cart,order,pay,collect,refund" name="type">
<a-input
allow-clear
placeholder="请输入类型visit,cart,order,pay,collect,refund"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="是否浏览" name="visitNum">
<a-input
allow-clear
placeholder="请输入是否浏览"
v-model:value="form.visitNum"
/>
</a-form-item>
<a-form-item label="加入购物车数量" name="cartNum">
<a-input
allow-clear
placeholder="请输入加入购物车数量"
v-model:value="form.cartNum"
/>
</a-form-item>
<a-form-item label="下单数量" name="orderNum">
<a-input
allow-clear
placeholder="请输入下单数量"
v-model:value="form.orderNum"
/>
</a-form-item>
<a-form-item label="支付数量" name="payNum">
<a-input
allow-clear
placeholder="请输入支付数量"
v-model:value="form.payNum"
/>
</a-form-item>
<a-form-item label="支付金额" name="payPrice">
<a-input
allow-clear
placeholder="请输入支付金额"
v-model:value="form.payPrice"
/>
</a-form-item>
<a-form-item label="商品成本价" name="costPrice">
<a-input
allow-clear
placeholder="请输入商品成本价"
v-model:value="form.costPrice"
/>
</a-form-item>
<a-form-item label="支付用户ID" name="payUid">
<a-input
allow-clear
placeholder="请输入支付用户ID"
v-model:value="form.payUid"
/>
</a-form-item>
<a-form-item label="退款数量" name="refundNum">
<a-input
allow-clear
placeholder="请输入退款数量"
v-model:value="form.refundNum"
/>
</a-form-item>
<a-form-item label="退款金额" name="refundPrice">
<a-input
allow-clear
placeholder="请输入退款金额"
v-model:value="form.refundPrice"
/>
</a-form-item>
<a-form-item label="收藏" name="collectNum">
<a-input
allow-clear
placeholder="请输入收藏"
v-model:value="form.collectNum"
/>
</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="状态, 0正常, 1冻结" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsLog, updateShopGoodsLog } from '@/api/shop/shopGoodsLog';
import { ShopGoodsLog } from '@/api/shop/shopGoodsLog/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?: ShopGoodsLog | 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<ShopGoodsLog>({
id: undefined,
type: undefined,
goodsId: undefined,
visitNum: undefined,
cartNum: undefined,
orderNum: undefined,
payNum: undefined,
payPrice: undefined,
costPrice: undefined,
payUid: undefined,
refundNum: undefined,
refundPrice: undefined,
collectNum: undefined,
sortNumber: undefined,
status: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsLogId: undefined,
shopGoodsLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsLogName: [
{
required: true,
type: 'string',
message: '请填写商品日志表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsLog : addShopGoodsLog;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,311 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsLogId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsLogEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsLogEdit from './components/shopGoodsLogEdit.vue';
import { pageShopGoodsLog, removeShopGoodsLog, removeBatchShopGoodsLog } from '@/api/shop/shopGoodsLog';
import type { ShopGoodsLog, ShopGoodsLogParam } from '@/api/shop/shopGoodsLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsLog[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsLog | 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 pageShopGoodsLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '统计ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '类型visit,cart,order,pay,collect,refund',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '是否浏览',
dataIndex: 'visitNum',
key: 'visitNum',
align: 'center',
},
{
title: '加入购物车数量',
dataIndex: 'cartNum',
key: 'cartNum',
align: 'center',
},
{
title: '下单数量',
dataIndex: 'orderNum',
key: 'orderNum',
align: 'center',
},
{
title: '支付数量',
dataIndex: 'payNum',
key: 'payNum',
align: 'center',
},
{
title: '支付金额',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center',
},
{
title: '商品成本价',
dataIndex: 'costPrice',
key: 'costPrice',
align: 'center',
},
{
title: '支付用户ID',
dataIndex: 'payUid',
key: 'payUid',
align: 'center',
},
{
title: '退款数量',
dataIndex: 'refundNum',
key: 'refundNum',
align: 'center',
},
{
title: '退款金额',
dataIndex: 'refundPrice',
key: 'refundPrice',
align: 'center',
},
{
title: '收藏',
dataIndex: 'collectNum',
key: 'collectNum',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsLog) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsLog(row.shopGoodsLogId)
.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);
removeBatchShopGoodsLog(selection.value.map((d) => d.shopGoodsLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsLog'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,202 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑商品点赞和收藏表' : '添加商品点赞和收藏表'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="类型(收藏(collect、点赞(like))" name="type">
<a-input
allow-clear
placeholder="请输入类型(收藏(collect、点赞(like))"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="某种类型的商品(普通商品、秒杀商品)" name="category">
<a-input
allow-clear
placeholder="请输入某种类型的商品(普通商品、秒杀商品)"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="更新时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入更新时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsRelation, updateShopGoodsRelation } from '@/api/shop/shopGoodsRelation';
import { ShopGoodsRelation } from '@/api/shop/shopGoodsRelation/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?: ShopGoodsRelation | 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<ShopGoodsRelation>({
id: undefined,
userId: undefined,
goodsId: undefined,
type: undefined,
category: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
shopGoodsRelationId: undefined,
shopGoodsRelationName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsRelationName: [
{
required: true,
type: 'string',
message: '请填写商品点赞和收藏表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsRelation : addShopGoodsRelation;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsRelationId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsRelationEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsRelationEdit from './components/shopGoodsRelationEdit.vue';
import { pageShopGoodsRelation, removeShopGoodsRelation, removeBatchShopGoodsRelation } from '@/api/shop/shopGoodsRelation';
import type { ShopGoodsRelation, ShopGoodsRelationParam } from '@/api/shop/shopGoodsRelation/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsRelation[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsRelation | 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 pageShopGoodsRelation({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'id',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '类型(收藏(collect、点赞(like))',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '某种类型的商品(普通商品、秒杀商品)',
dataIndex: 'category',
key: 'category',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsRelationParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsRelation) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsRelation) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsRelation(row.shopGoodsRelationId)
.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);
removeBatchShopGoodsRelation(selection.value.map((d) => d.shopGoodsRelationId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsRelation) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsRelation'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,278 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑商品sku列表' : '添加商品sku列表'"
: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="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="商品属性索引值 (attr_value|attr_value[|....])" name="sku">
<a-input
allow-clear
placeholder="请输入商品属性索引值 (attr_value|attr_value[|....])"
v-model:value="form.sku"
/>
</a-form-item>
<a-form-item
label="商品图片"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商品价格" name="price">
<a-input
allow-clear
placeholder="请输入商品价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="市场价格" name="salePrice">
<a-input
allow-clear
placeholder="请输入市场价格"
v-model:value="form.salePrice"
/>
</a-form-item>
<a-form-item label="成本价" name="cost">
<a-input
allow-clear
placeholder="请输入成本价"
v-model:value="form.cost"
/>
</a-form-item>
<a-form-item label="库存" name="stock">
<a-input
allow-clear
placeholder="请输入库存"
v-model:value="form.stock"
/>
</a-form-item>
<a-form-item label="sku编码" name="skuNo">
<a-input
allow-clear
placeholder="请输入sku编码"
v-model:value="form.skuNo"
/>
</a-form-item>
<a-form-item label="商品条码" name="barCode">
<a-input
allow-clear
placeholder="请输入商品条码"
v-model:value="form.barCode"
/>
</a-form-item>
<a-form-item label="重量" name="weight">
<a-input
allow-clear
placeholder="请输入重量"
v-model:value="form.weight"
/>
</a-form-item>
<a-form-item label="体积" name="volume">
<a-input
allow-clear
placeholder="请输入体积"
v-model:value="form.volume"
/>
</a-form-item>
<a-form-item label="唯一值" name="uuid">
<a-input
allow-clear
placeholder="请输入唯一值"
v-model:value="form.uuid"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1异常" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopGoodsSku, updateShopGoodsSku } from '@/api/shop/shopGoodsSku';
import { ShopGoodsSku } from '@/api/shop/shopGoodsSku/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?: ShopGoodsSku | 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<ShopGoodsSku>({
id: undefined,
goodsId: undefined,
sku: undefined,
image: undefined,
price: undefined,
salePrice: undefined,
cost: undefined,
stock: undefined,
skuNo: undefined,
barCode: undefined,
weight: undefined,
volume: undefined,
uuid: undefined,
status: undefined,
comments: undefined,
tenantId: undefined,
createTime: undefined,
shopGoodsSkuId: undefined,
shopGoodsSkuName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsSkuName: [
{
required: true,
type: 'string',
message: '请填写商品sku列表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsSku : addShopGoodsSku;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,299 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsSkuId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsSkuEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsSkuEdit from './components/shopGoodsSkuEdit.vue';
import { pageShopGoodsSku, removeShopGoodsSku, removeBatchShopGoodsSku } from '@/api/shop/shopGoodsSku';
import type { ShopGoodsSku, ShopGoodsSkuParam } from '@/api/shop/shopGoodsSku/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsSku[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsSku | 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 pageShopGoodsSku({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '商品属性索引值 (attr_value|attr_value[|....])',
dataIndex: 'sku',
key: 'sku',
align: 'center',
},
{
title: '商品图片',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商品价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '市场价格',
dataIndex: 'salePrice',
key: 'salePrice',
align: 'center',
},
{
title: '成本价',
dataIndex: 'cost',
key: 'cost',
align: 'center',
},
{
title: '库存',
dataIndex: 'stock',
key: 'stock',
align: 'center',
},
{
title: 'sku编码',
dataIndex: 'skuNo',
key: 'skuNo',
align: 'center',
},
{
title: '商品条码',
dataIndex: 'barCode',
key: 'barCode',
align: 'center',
},
{
title: '重量',
dataIndex: 'weight',
key: 'weight',
align: 'center',
},
{
title: '体积',
dataIndex: 'volume',
key: 'volume',
align: 'center',
},
{
title: '唯一值',
dataIndex: 'uuid',
key: 'uuid',
align: 'center',
},
{
title: '状态, 0正常, 1异常',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsSkuParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsSku) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsSku) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsSku(row.shopGoodsSkuId)
.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);
removeBatchShopGoodsSku(selection.value.map((d) => d.shopGoodsSkuId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsSku) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsSku'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,201 @@
<!-- 编辑弹窗 -->
<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="商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="规格ID" name="specId">
<a-input
allow-clear
placeholder="请输入规格ID"
v-model:value="form.specId"
/>
</a-form-item>
<a-form-item label="规格名称" name="specName">
<a-input
allow-clear
placeholder="请输入规格名称"
v-model:value="form.specName"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
/>
</a-form-item>
<a-form-item label="活动类型 0=商品1=秒杀2=砍价3=拼团" name="type">
<a-input
allow-clear
placeholder="请输入活动类型 0=商品1=秒杀2=砍价3=拼团"
v-model:value="form.type"
/>
</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 { addShopGoodsSpec, updateShopGoodsSpec } from '@/api/shop/shopGoodsSpec';
import { ShopGoodsSpec } from '@/api/shop/shopGoodsSpec/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?: ShopGoodsSpec | 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<ShopGoodsSpec>({
id: undefined,
goodsId: undefined,
specId: undefined,
specName: undefined,
specValue: undefined,
type: undefined,
tenantId: undefined,
shopGoodsSpecId: undefined,
shopGoodsSpecName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopGoodsSpecName: [
{
required: true,
type: 'string',
message: '请填写商品多规格名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopGoodsSpec : addShopGoodsSpec;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,236 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopGoodsSpecId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopGoodsSpecEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopGoodsSpecEdit from './components/shopGoodsSpecEdit.vue';
import { pageShopGoodsSpec, removeShopGoodsSpec, removeBatchShopGoodsSpec } from '@/api/shop/shopGoodsSpec';
import type { ShopGoodsSpec, ShopGoodsSpecParam } from '@/api/shop/shopGoodsSpec/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopGoodsSpec[]>([]);
// 当前编辑数据
const current = ref<ShopGoodsSpec | 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 pageShopGoodsSpec({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '规格ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
},
{
title: '规格名称',
dataIndex: 'specName',
key: 'specName',
align: 'center',
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
},
{
title: '活动类型 0=商品1=秒杀2=砍价3=拼团',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopGoodsSpecParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopGoodsSpec) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopGoodsSpec) => {
const hide = message.loading('请求中..', 0);
removeShopGoodsSpec(row.shopGoodsSpecId)
.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);
removeBatchShopGoodsSpec(selection.value.map((d) => d.shopGoodsSpecId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopGoodsSpec) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopGoodsSpec'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,400 @@
<!-- 编辑弹窗 -->
<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="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="商户编号" name="merchantCode">
<a-input
allow-clear
placeholder="请输入商户编号"
v-model:value="form.merchantCode"
/>
</a-form-item>
<a-form-item label="商户类型" name="type">
<a-input
allow-clear
placeholder="请输入商户类型"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item
label="商户图标"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商户手机号" name="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="商户姓名" name="realName">
<a-input
allow-clear
placeholder="请输入商户姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="店铺类型" name="shopType">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.shopType"
/>
</a-form-item>
<a-form-item label="项目分类" name="itemType">
<a-input
allow-clear
placeholder="请输入项目分类"
v-model:value="form.itemType"
/>
</a-form-item>
<a-form-item label="商户分类" name="category">
<a-input
allow-clear
placeholder="请输入商户分类"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="经纬度" name="lngAndLat">
<a-input
allow-clear
placeholder="请输入经纬度"
v-model:value="form.lngAndLat"
/>
</a-form-item>
<a-form-item label="所在省份" name="province">
<a-input
allow-clear
placeholder="请输入所在省份"
v-model:value="form.province"
/>
</a-form-item>
<a-form-item label="所在城市" name="city">
<a-input
allow-clear
placeholder="请输入所在城市"
v-model:value="form.city"
/>
</a-form-item>
<a-form-item label="所在辖区" name="region">
<a-input
allow-clear
placeholder="请输入所在辖区"
v-model:value="form.region"
/>
</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="commission">
<a-input
allow-clear
placeholder="请输入手续费"
v-model:value="form.commission"
/>
</a-form-item>
<a-form-item label="关键字" name="keywords">
<a-input
allow-clear
placeholder="请输入关键字"
v-model:value="form.keywords"
/>
</a-form-item>
<a-form-item label="资质图片" name="files">
<a-input
allow-clear
placeholder="请输入资质图片"
v-model:value="form.files"
/>
</a-form-item>
<a-form-item label="营业时间" name="businessTime">
<a-input
allow-clear
placeholder="请输入营业时间"
v-model:value="form.businessTime"
/>
</a-form-item>
<a-form-item label="文章内容" name="content">
<a-input
allow-clear
placeholder="请输入文章内容"
v-model:value="form.content"
/>
</a-form-item>
<a-form-item label="每小时价格" name="price">
<a-input
allow-clear
placeholder="请输入每小时价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="是否自营" name="ownStore">
<a-input
allow-clear
placeholder="请输入是否自营"
v-model:value="form.ownStore"
/>
</a-form-item>
<a-form-item label="是否推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入是否推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="是否需要审核" name="goodsReview">
<a-input
allow-clear
placeholder="请输入是否需要审核"
v-model:value="form.goodsReview"
/>
</a-form-item>
<a-form-item label="管理入口" name="adminUrl">
<a-input
allow-clear
placeholder="请输入管理入口"
v-model:value="form.adminUrl"
/>
</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="userId">
<a-input
allow-clear
placeholder="请输入所有人"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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 { addShopMerchant, updateShopMerchant } from '@/api/shop/shopMerchant';
import { ShopMerchant } from '@/api/shop/shopMerchant/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?: ShopMerchant | 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<ShopMerchant>({
merchantId: undefined,
merchantName: undefined,
merchantCode: undefined,
type: undefined,
image: undefined,
phone: undefined,
realName: undefined,
shopType: undefined,
itemType: undefined,
category: undefined,
lngAndLat: undefined,
province: undefined,
city: undefined,
region: undefined,
address: undefined,
commission: undefined,
keywords: undefined,
files: undefined,
businessTime: undefined,
content: undefined,
price: undefined,
ownStore: undefined,
recommend: undefined,
goodsReview: undefined,
adminUrl: undefined,
comments: undefined,
userId: undefined,
deleted: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantId: undefined,
shopMerchantName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantName: [
{
required: true,
type: 'string',
message: '请填写商户名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopMerchant : addShopMerchant;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,389 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopMerchantEdit from './components/shopMerchantEdit.vue';
import { pageShopMerchant, removeShopMerchant, removeBatchShopMerchant } from '@/api/shop/shopMerchant';
import type { ShopMerchant, ShopMerchantParam } from '@/api/shop/shopMerchant/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchant[]>([]);
// 当前编辑数据
const current = ref<ShopMerchant | 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 pageShopMerchant({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
width: 90,
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '商户编号',
dataIndex: 'merchantCode',
key: 'merchantCode',
align: 'center',
},
{
title: '商户类型',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '商户图标',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '商户姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center',
},
{
title: '项目分类',
dataIndex: 'itemType',
key: 'itemType',
align: 'center',
},
{
title: '商户分类',
dataIndex: 'category',
key: 'category',
align: 'center',
},
{
title: '经纬度',
dataIndex: 'lngAndLat',
key: 'lngAndLat',
align: 'center',
},
{
title: '所在省份',
dataIndex: 'province',
key: 'province',
align: 'center',
},
{
title: '所在城市',
dataIndex: 'city',
key: 'city',
align: 'center',
},
{
title: '所在辖区',
dataIndex: 'region',
key: 'region',
align: 'center',
},
{
title: '详细地址',
dataIndex: 'address',
key: 'address',
align: 'center',
},
{
title: '手续费',
dataIndex: 'commission',
key: 'commission',
align: 'center',
},
{
title: '关键字',
dataIndex: 'keywords',
key: 'keywords',
align: 'center',
},
{
title: '资质图片',
dataIndex: 'files',
key: 'files',
align: 'center',
},
{
title: '营业时间',
dataIndex: 'businessTime',
key: 'businessTime',
align: 'center',
},
{
title: '文章内容',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '每小时价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '是否自营',
dataIndex: 'ownStore',
key: 'ownStore',
align: 'center',
},
{
title: '是否推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center',
},
{
title: '是否需要审核',
dataIndex: 'goodsReview',
key: 'goodsReview',
align: 'center',
},
{
title: '管理入口',
dataIndex: 'adminUrl',
key: 'adminUrl',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '所有人',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopMerchantParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchant) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchant) => {
const hide = message.loading('请求中..', 0);
removeShopMerchant(row.shopMerchantId)
.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);
removeBatchShopMerchant(selection.value.map((d) => d.shopMerchantId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchant) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchant'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,236 @@
<!-- 编辑弹窗 -->
<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="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="真实姓名" name="realName">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="角色ID" name="roleId">
<a-input
allow-clear
placeholder="请输入角色ID"
v-model:value="form.roleId"
/>
</a-form-item>
<a-form-item label="角色名称" name="roleName">
<a-input
allow-clear
placeholder="请输入角色名称"
v-model:value="form.roleName"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</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-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>
</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 { addShopMerchantAccount, updateShopMerchantAccount } from '@/api/shop/shopMerchantAccount';
import { ShopMerchantAccount } from '@/api/shop/shopMerchantAccount/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?: ShopMerchantAccount | 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<ShopMerchantAccount>({
id: undefined,
phone: undefined,
realName: undefined,
merchantId: undefined,
roleId: undefined,
roleName: undefined,
userId: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantAccountId: undefined,
shopMerchantAccountName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantAccountName: [
{
required: true,
type: 'string',
message: '请填写商户账号名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopMerchantAccount : addShopMerchantAccount;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,269 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantAccountId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantAccountEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopMerchantAccountEdit from './components/shopMerchantAccountEdit.vue';
import { pageShopMerchantAccount, removeShopMerchantAccount, removeBatchShopMerchantAccount } from '@/api/shop/shopMerchantAccount';
import type { ShopMerchantAccount, ShopMerchantAccountParam } from '@/api/shop/shopMerchantAccount/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantAccount[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantAccount | 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 pageShopMerchantAccount({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '角色ID',
dataIndex: 'roleId',
key: 'roleId',
align: 'center',
},
{
title: '角色名称',
dataIndex: 'roleName',
key: 'roleName',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopMerchantAccountParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantAccount) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantAccount) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantAccount(row.shopMerchantAccountId)
.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);
removeBatchShopMerchantAccount(selection.value.map((d) => d.shopMerchantAccountId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantAccount) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantAccount'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,312 @@
<!-- 编辑弹窗 -->
<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="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item
label="商户图标"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商户手机号" name="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="商户姓名" name="realName">
<a-input
allow-clear
placeholder="请输入商户姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="店铺类型" name="shopType">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.shopType"
/>
</a-form-item>
<a-form-item label="商户分类" name="category">
<a-input
allow-clear
placeholder="请输入商户分类"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="手续费" name="commission">
<a-input
allow-clear
placeholder="请输入手续费"
v-model:value="form.commission"
/>
</a-form-item>
<a-form-item label="关键字" name="keywords">
<a-input
allow-clear
placeholder="请输入关键字"
v-model:value="form.keywords"
/>
</a-form-item>
<a-form-item label="资质图片" name="files">
<a-input
allow-clear
placeholder="请输入资质图片"
v-model:value="form.files"
/>
</a-form-item>
<a-form-item label="所有人" name="userId">
<a-input
allow-clear
placeholder="请输入所有人"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否自营" name="ownStore">
<a-input
allow-clear
placeholder="请输入是否自营"
v-model:value="form.ownStore"
/>
</a-form-item>
<a-form-item label="是否推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入是否推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="是否需要审核" name="goodsReview">
<a-input
allow-clear
placeholder="请输入是否需要审核"
v-model:value="form.goodsReview"
/>
</a-form-item>
<a-form-item label="工作负责人" name="name2">
<a-input
allow-clear
placeholder="请输入工作负责人"
v-model:value="form.name2"
/>
</a-form-item>
<a-form-item label="驳回原因" name="reason">
<a-input
allow-clear
placeholder="请输入驳回原因"
v-model:value="form.reason"
/>
</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-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>
</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 { addShopMerchantApply, updateShopMerchantApply } from '@/api/shop/shopMerchantApply';
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/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?: ShopMerchantApply | 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<ShopMerchantApply>({
applyId: undefined,
merchantName: undefined,
image: undefined,
phone: undefined,
realName: undefined,
shopType: undefined,
category: undefined,
commission: undefined,
keywords: undefined,
files: undefined,
userId: undefined,
ownStore: undefined,
recommend: undefined,
goodsReview: undefined,
name2: undefined,
reason: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantApplyId: undefined,
shopMerchantApplyName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantApplyName: [
{
required: true,
type: 'string',
message: '请填写商户入驻申请名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopMerchantApply : addShopMerchantApply;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,336 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantApplyId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantApplyEdit
v-model:visible="showEdit"
:data="current"
@done="reload"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopMerchantApplyEdit from './components/shopMerchantApplyEdit.vue';
import {
pageShopMerchantApply,
removeShopMerchantApply,
removeBatchShopMerchantApply
} from '@/api/shop/shopMerchantApply';
import type {
ShopMerchantApply,
ShopMerchantApplyParam
} from '@/api/shop/shopMerchantApply/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantApply[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantApply | 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 pageShopMerchantApply({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'applyId',
key: 'applyId',
align: 'center',
width: 90
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center'
},
{
title: '商户图标',
dataIndex: 'image',
key: 'image',
align: 'center'
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center'
},
{
title: '商户姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center'
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center'
},
{
title: '商户分类',
dataIndex: 'category',
key: 'category',
align: 'center'
},
{
title: '手续费',
dataIndex: 'commission',
key: 'commission',
align: 'center'
},
{
title: '关键字',
dataIndex: 'keywords',
key: 'keywords',
align: 'center'
},
{
title: '资质图片',
dataIndex: 'files',
key: 'files',
align: 'center'
},
{
title: '所有人',
dataIndex: 'userId',
key: 'userId',
align: 'center'
},
{
title: '是否自营',
dataIndex: 'ownStore',
key: 'ownStore',
align: 'center'
},
{
title: '是否推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center'
},
{
title: '是否需要审核',
dataIndex: 'goodsReview',
key: 'goodsReview',
align: 'center'
},
{
title: '工作负责人',
dataIndex: 'name2',
key: 'name2',
align: 'center'
},
{
title: '驳回原因',
dataIndex: 'reason',
key: 'reason',
align: 'center'
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center'
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center'
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center'
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopMerchantApplyParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantApply) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantApply) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantApply(row.shopMerchantApplyId)
.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);
removeBatchShopMerchantApply(
selection.value.map((d) => d.shopMerchantApplyId)
)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantApply) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantApply'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,196 @@
<!-- 编辑弹窗 -->
<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="name">
<a-input
allow-clear
placeholder="请输入店铺名称"
v-model:value="form.name"
/>
</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-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>
</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 { addShopMerchantCount, updateShopMerchantCount } from '@/api/shop/shopMerchantCount';
import { ShopMerchantCount } from '@/api/shop/shopMerchantCount/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?: ShopMerchantCount | 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<ShopMerchantCount>({
id: undefined,
name: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantCountId: undefined,
shopMerchantCountName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantCountName: [
{
required: true,
type: 'string',
message: '请填写门店销售统计表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopMerchantCount : addShopMerchantCount;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantCountId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantCountEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopMerchantCountEdit from './components/shopMerchantCountEdit.vue';
import { pageShopMerchantCount, removeShopMerchantCount, removeBatchShopMerchantCount } from '@/api/shop/shopMerchantCount';
import type { ShopMerchantCount, ShopMerchantCountParam } from '@/api/shop/shopMerchantCount/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantCount[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantCount | 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 pageShopMerchantCount({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '店铺名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '店铺说明',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopMerchantCountParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantCount) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantCount) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantCount(row.shopMerchantCountId)
.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);
removeBatchShopMerchantCount(selection.value.map((d) => d.shopMerchantCountId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantCount) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantCount'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,196 @@
<!-- 编辑弹窗 -->
<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="name">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.name"
/>
</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-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>
</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 { addShopMerchantType, updateShopMerchantType } from '@/api/shop/shopMerchantType';
import { ShopMerchantType } from '@/api/shop/shopMerchantType/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?: ShopMerchantType | 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<ShopMerchantType>({
id: undefined,
name: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantTypeId: undefined,
shopMerchantTypeName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantTypeName: [
{
required: true,
type: 'string',
message: '请填写商户类型名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopMerchantType : addShopMerchantType;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantTypeId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantTypeEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopMerchantTypeEdit from './components/shopMerchantTypeEdit.vue';
import { pageShopMerchantType, removeShopMerchantType, removeBatchShopMerchantType } from '@/api/shop/shopMerchantType';
import type { ShopMerchantType, ShopMerchantTypeParam } from '@/api/shop/shopMerchantType/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantType[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantType | 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 pageShopMerchantType({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '店铺类型',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '店铺入驻条件',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopMerchantTypeParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantType) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantType) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantType(row.shopMerchantTypeId)
.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);
removeBatchShopMerchantType(selection.value.map((d) => d.shopMerchantTypeId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantType) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantType'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,541 @@
<!-- 编辑弹窗 -->
<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="orderNo">
<a-input
allow-clear
placeholder="请输入订单编号"
v-model:value="form.orderNo"
/>
</a-form-item>
<a-form-item label="订单类型0商城订单 1预定订单 2会员卡" name="type">
<a-input
allow-clear
placeholder="请输入订单类型0商城订单 1预定订单 2会员卡"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="下单渠道0小程序预定 1俱乐部训练场 3活动订场" name="channel">
<a-input
allow-clear
placeholder="请输入下单渠道0小程序预定 1俱乐部训练场 3活动订场"
v-model:value="form.channel"
/>
</a-form-item>
<a-form-item label="微信支付订单号" name="transactionId">
<a-input
allow-clear
placeholder="请输入微信支付订单号"
v-model:value="form.transactionId"
/>
</a-form-item>
<a-form-item label="微信退款订单号" name="refundOrder">
<a-input
allow-clear
placeholder="请输入微信退款订单号"
v-model:value="form.refundOrder"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="商户编号" name="merchantCode">
<a-input
allow-clear
placeholder="请输入商户编号"
v-model:value="form.merchantCode"
/>
</a-form-item>
<a-form-item label="使用的优惠券id" name="couponId">
<a-input
allow-clear
placeholder="请输入使用的优惠券id"
v-model:value="form.couponId"
/>
</a-form-item>
<a-form-item label="使用的会员卡id" name="cardId">
<a-input
allow-clear
placeholder="请输入使用的会员卡id"
v-model:value="form.cardId"
/>
</a-form-item>
<a-form-item label="关联管理员id" name="adminId">
<a-input
allow-clear
placeholder="请输入关联管理员id"
v-model:value="form.adminId"
/>
</a-form-item>
<a-form-item label="核销管理员id" name="confirmId">
<a-input
allow-clear
placeholder="请输入核销管理员id"
v-model:value="form.confirmId"
/>
</a-form-item>
<a-form-item label="IC卡号" name="icCard">
<a-input
allow-clear
placeholder="请输入IC卡号"
v-model:value="form.icCard"
/>
</a-form-item>
<a-form-item label="真实姓名" name="realName">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="订单总额" name="totalPrice">
<a-input
allow-clear
placeholder="请输入订单总额"
v-model:value="form.totalPrice"
/>
</a-form-item>
<a-form-item label="减少的金额使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格" name="reducePrice">
<a-input
allow-clear
placeholder="请输入减少的金额使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
v-model:value="form.reducePrice"
/>
</a-form-item>
<a-form-item label="实际付款" name="payPrice">
<a-input
allow-clear
placeholder="请输入实际付款"
v-model:value="form.payPrice"
/>
</a-form-item>
<a-form-item label="用于统计" name="price">
<a-input
allow-clear
placeholder="请输入用于统计"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="价钱,用于积分赠送" name="money">
<a-input
allow-clear
placeholder="请输入价钱,用于积分赠送"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="退款金额" name="refundMoney">
<a-input
allow-clear
placeholder="请输入退款金额"
v-model:value="form.refundMoney"
/>
</a-form-item>
<a-form-item label="教练价格" name="coachPrice">
<a-input
allow-clear
placeholder="请输入教练价格"
v-model:value="form.coachPrice"
/>
</a-form-item>
<a-form-item label="购买数量" name="totalNum">
<a-input
allow-clear
placeholder="请输入购买数量"
v-model:value="form.totalNum"
/>
</a-form-item>
<a-form-item label="教练id" name="coachId">
<a-input
allow-clear
placeholder="请输入教练id"
v-model:value="form.coachId"
/>
</a-form-item>
<a-form-item label="0余额支付, 1微信支付102微信Native2会员卡支付3支付宝4现金5POS机6VIP月卡7VIP年卡8VIP次卡9IC月卡10IC年卡11IC次卡12免费13VIP充值卡14IC充值卡15积分支付16VIP季卡17IC季卡" name="payType">
<a-input
allow-clear
placeholder="请输入0余额支付, 1微信支付102微信Native2会员卡支付3支付宝4现金5POS机6VIP月卡7VIP年卡8VIP次卡9IC月卡10IC年卡11IC次卡12免费13VIP充值卡14IC充值卡15积分支付16VIP季卡17IC季卡"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="0未付款1已付款" name="payStatus">
<a-input
allow-clear
placeholder="请输入0未付款1已付款"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item label="0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款" name="orderStatus">
<a-input
allow-clear
placeholder="请输入0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item label="优惠类型0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡" name="couponType">
<a-input
allow-clear
placeholder="请输入优惠类型0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
v-model:value="form.couponType"
/>
</a-form-item>
<a-form-item label="优惠说明" name="couponDesc">
<a-input
allow-clear
placeholder="请输入优惠说明"
v-model:value="form.couponDesc"
/>
</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="vip月卡年卡、ic月卡年卡回退次数" name="returnNum">
<a-input
allow-clear
placeholder="请输入vip月卡年卡、ic月卡年卡回退次数"
v-model:value="form.returnNum"
/>
</a-form-item>
<a-form-item label="vip充值回退金额" name="returnMoney">
<a-input
allow-clear
placeholder="请输入vip充值回退金额"
v-model:value="form.returnMoney"
/>
</a-form-item>
<a-form-item label="预约详情开始时间数组" name="startTime">
<a-input
allow-clear
placeholder="请输入预约详情开始时间数组"
v-model:value="form.startTime"
/>
</a-form-item>
<a-form-item label="是否已开具发票0未开发票1已开发票2不能开具发票" name="isInvoice">
<a-input
allow-clear
placeholder="请输入是否已开具发票0未开发票1已开发票2不能开具发票"
v-model:value="form.isInvoice"
/>
</a-form-item>
<a-form-item label="发票流水号" name="invoiceNo">
<a-input
allow-clear
placeholder="请输入发票流水号"
v-model:value="form.invoiceNo"
/>
</a-form-item>
<a-form-item label="支付时间" name="payTime">
<a-input
allow-clear
placeholder="请输入支付时间"
v-model:value="form.payTime"
/>
</a-form-item>
<a-form-item label="退款时间" name="refundTime">
<a-input
allow-clear
placeholder="请输入退款时间"
v-model:value="form.refundTime"
/>
</a-form-item>
<a-form-item label="申请退款时间" name="refundApplyTime">
<a-input
allow-clear
placeholder="请输入申请退款时间"
v-model:value="form.refundApplyTime"
/>
</a-form-item>
<a-form-item label="过期时间" name="expirationTime">
<a-input
allow-clear
placeholder="请输入过期时间"
v-model:value="form.expirationTime"
/>
</a-form-item>
<a-form-item label="对账情况0=未对账1=已对账3=已对账金额对不上4=未查询到该订单" name="checkBill">
<a-input
allow-clear
placeholder="请输入对账情况0=未对账1=已对账3=已对账金额对不上4=未查询到该订单"
v-model:value="form.checkBill"
/>
</a-form-item>
<a-form-item label="订单是否已结算(0未结算 1已结算)" name="isSettled">
<a-input
allow-clear
placeholder="请输入订单是否已结算(0未结算 1已结算)"
v-model:value="form.isSettled"
/>
</a-form-item>
<a-form-item label="系统版本号 0当前版本 value=其他版本" name="version">
<a-input
allow-clear
placeholder="请输入系统版本号 0当前版本 value=其他版本"
v-model:value="form.version"
/>
</a-form-item>
<a-form-item label="用户id" name="userId">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.userId"
/>
</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="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopOrder, updateShopOrder } from '@/api/shop/shopOrder';
import { ShopOrder } from '@/api/shop/shopOrder/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?: ShopOrder | 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<ShopOrder>({
orderId: undefined,
orderNo: undefined,
type: undefined,
channel: undefined,
transactionId: undefined,
refundOrder: undefined,
merchantId: undefined,
merchantName: undefined,
merchantCode: undefined,
couponId: undefined,
cardId: undefined,
adminId: undefined,
confirmId: undefined,
icCard: undefined,
realName: undefined,
phone: undefined,
totalPrice: undefined,
reducePrice: undefined,
payPrice: undefined,
price: undefined,
money: undefined,
refundMoney: undefined,
coachPrice: undefined,
totalNum: undefined,
coachId: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
couponType: undefined,
couponDesc: undefined,
qrcode: undefined,
returnNum: undefined,
returnMoney: undefined,
startTime: undefined,
isInvoice: undefined,
invoiceNo: undefined,
payTime: undefined,
refundTime: undefined,
refundApplyTime: undefined,
expirationTime: undefined,
checkBill: undefined,
isSettled: undefined,
version: undefined,
userId: undefined,
comments: undefined,
sortNumber: undefined,
deleted: undefined,
tenantId: undefined,
updateTime: undefined,
createTime: undefined,
shopOrderId: undefined,
shopOrderName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopOrderName: [
{
required: true,
type: 'string',
message: '请填写订单名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopOrder : addShopOrder;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,497 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopOrderId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopOrderEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopOrderEdit from './components/shopOrderEdit.vue';
import { pageShopOrder, removeShopOrder, removeBatchShopOrder } from '@/api/shop/shopOrder';
import type { 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 pageShopOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '订单号',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
width: 90,
},
{
title: '订单编号',
dataIndex: 'orderNo',
key: 'orderNo',
align: 'center',
},
{
title: '订单类型0商城订单 1预定订单 2会员卡',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '下单渠道0小程序预定 1俱乐部训练场 3活动订场',
dataIndex: 'channel',
key: 'channel',
align: 'center',
},
{
title: '微信支付订单号',
dataIndex: 'transactionId',
key: 'transactionId',
align: 'center',
},
{
title: '微信退款订单号',
dataIndex: 'refundOrder',
key: 'refundOrder',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '商户编号',
dataIndex: 'merchantCode',
key: 'merchantCode',
align: 'center',
},
{
title: '使用的优惠券id',
dataIndex: 'couponId',
key: 'couponId',
align: 'center',
},
{
title: '使用的会员卡id',
dataIndex: 'cardId',
key: 'cardId',
align: 'center',
},
{
title: '关联管理员id',
dataIndex: 'adminId',
key: 'adminId',
align: 'center',
},
{
title: '核销管理员id',
dataIndex: 'confirmId',
key: 'confirmId',
align: 'center',
},
{
title: 'IC卡号',
dataIndex: 'icCard',
key: 'icCard',
align: 'center',
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '订单总额',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
},
{
title: '减少的金额使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格',
dataIndex: 'reducePrice',
key: 'reducePrice',
align: 'center',
},
{
title: '实际付款',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center',
},
{
title: '用于统计',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '价钱,用于积分赠送',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '退款金额',
dataIndex: 'refundMoney',
key: 'refundMoney',
align: 'center',
},
{
title: '教练价格',
dataIndex: 'coachPrice',
key: 'coachPrice',
align: 'center',
},
{
title: '购买数量',
dataIndex: 'totalNum',
key: 'totalNum',
align: 'center',
},
{
title: '教练id',
dataIndex: 'coachId',
key: 'coachId',
align: 'center',
},
{
title: '0余额支付, 1微信支付102微信Native2会员卡支付3支付宝4现金5POS机6VIP月卡7VIP年卡8VIP次卡9IC月卡10IC年卡11IC次卡12免费13VIP充值卡14IC充值卡15积分支付16VIP季卡17IC季卡',
dataIndex: 'payType',
key: 'payType',
align: 'center',
},
{
title: '0未付款1已付款',
dataIndex: 'payStatus',
key: 'payStatus',
align: 'center',
},
{
title: '0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center',
},
{
title: '优惠类型0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡',
dataIndex: 'couponType',
key: 'couponType',
align: 'center',
},
{
title: '优惠说明',
dataIndex: 'couponDesc',
key: 'couponDesc',
align: 'center',
},
{
title: '二维码地址,保存订单号,支付成功后才生成',
dataIndex: 'qrcode',
key: 'qrcode',
align: 'center',
},
{
title: 'vip月卡年卡、ic月卡年卡回退次数',
dataIndex: 'returnNum',
key: 'returnNum',
align: 'center',
},
{
title: 'vip充值回退金额',
dataIndex: 'returnMoney',
key: 'returnMoney',
align: 'center',
},
{
title: '预约详情开始时间数组',
dataIndex: 'startTime',
key: 'startTime',
align: 'center',
},
{
title: '是否已开具发票0未开发票1已开发票2不能开具发票',
dataIndex: 'isInvoice',
key: 'isInvoice',
align: 'center',
},
{
title: '发票流水号',
dataIndex: 'invoiceNo',
key: 'invoiceNo',
align: 'center',
},
{
title: '支付时间',
dataIndex: 'payTime',
key: 'payTime',
align: 'center',
},
{
title: '退款时间',
dataIndex: 'refundTime',
key: 'refundTime',
align: 'center',
},
{
title: '申请退款时间',
dataIndex: 'refundApplyTime',
key: 'refundApplyTime',
align: 'center',
},
{
title: '过期时间',
dataIndex: 'expirationTime',
key: 'expirationTime',
align: 'center',
},
{
title: '对账情况0=未对账1=已对账3=已对账金额对不上4=未查询到该订单',
dataIndex: 'checkBill',
key: 'checkBill',
align: 'center',
},
{
title: '订单是否已结算(0未结算 1已结算)',
dataIndex: 'isSettled',
key: 'isSettled',
align: 'center',
},
{
title: '系统版本号 0当前版本 value=其他版本',
dataIndex: 'version',
key: 'version',
align: 'center',
},
{
title: '用户id',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopOrder) => {
const hide = message.loading('请求中..', 0);
removeShopOrder(row.shopOrderId)
.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.shopOrderId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
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: 'ShopOrder'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,216 @@
<!-- 编辑弹窗 -->
<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="订单id" name="oid">
<a-input
allow-clear
placeholder="请输入订单id"
v-model:value="form.oid"
/>
</a-form-item>
<a-form-item label="订单号" name="orderId">
<a-input
allow-clear
placeholder="请输入订单号"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="购物车id" name="cartId">
<a-input
allow-clear
placeholder="请输入购物车id"
v-model:value="form.cartId"
/>
</a-form-item>
<a-form-item label="商品ID" name="productId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.productId"
/>
</a-form-item>
<a-form-item label="购买东西的详细信息" name="cartInfo">
<a-input
allow-clear
placeholder="请输入购买东西的详细信息"
v-model:value="form.cartInfo"
/>
</a-form-item>
<a-form-item label="唯一id" name="unique">
<a-input
allow-clear
placeholder="请输入唯一id"
v-model:value="form.unique"
/>
</a-form-item>
<a-form-item label="是否能售后0不能1能" name="isAfterSales">
<a-input
allow-clear
placeholder="请输入是否能售后0不能1能"
v-model:value="form.isAfterSales"
/>
</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 { addShopOrderCartInfo, updateShopOrderCartInfo } from '@/api/shop/shopOrderCartInfo';
import { ShopOrderCartInfo } from '@/api/shop/shopOrderCartInfo/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?: ShopOrderCartInfo | 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<ShopOrderCartInfo>({
id: undefined,
oid: undefined,
orderId: undefined,
cartId: undefined,
productId: undefined,
cartInfo: undefined,
unique: undefined,
isAfterSales: undefined,
shopOrderCartInfoId: undefined,
shopOrderCartInfoName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopOrderCartInfoName: [
{
required: true,
type: 'string',
message: '请填写订单购物详情表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopOrderCartInfo : addShopOrderCartInfo;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,248 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopOrderCartInfoId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopOrderCartInfoEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopOrderCartInfoEdit from './components/shopOrderCartInfoEdit.vue';
import { pageShopOrderCartInfo, removeShopOrderCartInfo, removeBatchShopOrderCartInfo } from '@/api/shop/shopOrderCartInfo';
import type { ShopOrderCartInfo, ShopOrderCartInfoParam } from '@/api/shop/shopOrderCartInfo/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopOrderCartInfo[]>([]);
// 当前编辑数据
const current = ref<ShopOrderCartInfo | 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 pageShopOrderCartInfo({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '订单id',
dataIndex: 'oid',
key: 'oid',
align: 'center',
},
{
title: '订单号',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '购物车id',
dataIndex: 'cartId',
key: 'cartId',
align: 'center',
},
{
title: '商品ID',
dataIndex: 'productId',
key: 'productId',
align: 'center',
},
{
title: '购买东西的详细信息',
dataIndex: 'cartInfo',
key: 'cartInfo',
align: 'center',
},
{
title: '唯一id',
dataIndex: 'unique',
key: 'unique',
align: 'center',
},
{
title: '是否能售后0不能1能',
dataIndex: 'isAfterSales',
key: 'isAfterSales',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopOrderCartInfoParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopOrderCartInfo) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopOrderCartInfo) => {
const hide = message.loading('请求中..', 0);
removeShopOrderCartInfo(row.shopOrderCartInfoId)
.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);
removeBatchShopOrderCartInfo(selection.value.map((d) => d.shopOrderCartInfoId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopOrderCartInfo) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopOrderCartInfo'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,343 @@
<!-- 编辑弹窗 -->
<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="关联订单表id" name="orderId">
<a-input
allow-clear
placeholder="请输入关联订单表id"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="订单标识" name="orderCode">
<a-input
allow-clear
placeholder="请输入订单标识"
v-model:value="form.orderCode"
/>
</a-form-item>
<a-form-item label="关联商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入关联商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item
label="商品封面图"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="关联商品id" name="goodsId">
<a-input
allow-clear
placeholder="请输入关联商品id"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="商品名称" name="goodsName">
<a-input
allow-clear
placeholder="请输入商品名称"
v-model:value="form.goodsName"
/>
</a-form-item>
<a-form-item label="单价" name="price">
<a-input
allow-clear
placeholder="请输入单价"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="购买数量" name="totalNum">
<a-input
allow-clear
placeholder="请输入购买数量"
v-model:value="form.totalNum"
/>
</a-form-item>
<a-form-item label="0 未付款 1已付款2无需付款或占用状态" name="payStatus">
<a-input
allow-clear
placeholder="请输入0 未付款 1已付款2无需付款或占用状态"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item label="0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款" name="orderStatus">
<a-input
allow-clear
placeholder="请输入0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item label="是否免费0收费、1免费" name="isFree">
<a-input
allow-clear
placeholder="请输入是否免费0收费、1免费"
v-model:value="form.isFree"
/>
</a-form-item>
<a-form-item label="系统版本 0当前版本 其他版本" name="version">
<a-input
allow-clear
placeholder="请输入系统版本 0当前版本 其他版本"
v-model:value="form.version"
/>
</a-form-item>
<a-form-item label="预约时间段" name="timePeriod">
<a-input
allow-clear
placeholder="请输入预约时间段"
v-model:value="form.timePeriod"
/>
</a-form-item>
<a-form-item label="预定日期" name="dateTime">
<a-input
allow-clear
placeholder="请输入预定日期"
v-model:value="form.dateTime"
/>
</a-form-item>
<a-form-item label="开场时间" name="startTime">
<a-input
allow-clear
placeholder="请输入开场时间"
v-model:value="form.startTime"
/>
</a-form-item>
<a-form-item label="结束时间" name="endTime">
<a-input
allow-clear
placeholder="请输入结束时间"
v-model:value="form.endTime"
/>
</a-form-item>
<a-form-item label="毫秒时间戳" name="timeFlag">
<a-input
allow-clear
placeholder="请输入毫秒时间戳"
v-model:value="form.timeFlag"
/>
</a-form-item>
<a-form-item label="过期时间" name="expirationTime">
<a-input
allow-clear
placeholder="请输入过期时间"
v-model:value="form.expirationTime"
/>
</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="用户id" name="userId">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="更新时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入更新时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopOrderGoods, updateShopOrderGoods } from '@/api/shop/shopOrderGoods';
import { ShopOrderGoods } from '@/api/shop/shopOrderGoods/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?: ShopOrderGoods | 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<ShopOrderGoods>({
id: undefined,
orderId: undefined,
orderCode: undefined,
merchantId: undefined,
merchantName: undefined,
image: undefined,
goodsId: undefined,
goodsName: undefined,
price: undefined,
totalNum: undefined,
payStatus: undefined,
orderStatus: undefined,
isFree: undefined,
version: undefined,
timePeriod: undefined,
dateTime: undefined,
startTime: undefined,
endTime: undefined,
timeFlag: undefined,
expirationTime: undefined,
comments: undefined,
userId: undefined,
tenantId: undefined,
updateTime: undefined,
createTime: undefined,
shopOrderGoodsId: undefined,
shopOrderGoodsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopOrderGoodsName: [
{
required: true,
type: 'string',
message: '请填写商品信息名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopOrderGoods : addShopOrderGoods;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,347 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopOrderGoodsId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopOrderGoodsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopOrderGoodsEdit from './components/shopOrderGoodsEdit.vue';
import { pageShopOrderGoods, removeShopOrderGoods, removeBatchShopOrderGoods } from '@/api/shop/shopOrderGoods';
import type { ShopOrderGoods, ShopOrderGoodsParam } from '@/api/shop/shopOrderGoods/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopOrderGoods[]>([]);
// 当前编辑数据
const current = ref<ShopOrderGoods | 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 pageShopOrderGoods({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '自增ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '关联订单表id',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '订单标识',
dataIndex: 'orderCode',
key: 'orderCode',
align: 'center',
},
{
title: '关联商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '商品封面图',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '关联商品id',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
},
{
title: '商品名称',
dataIndex: 'goodsName',
key: 'goodsName',
align: 'center',
},
{
title: '单价',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '购买数量',
dataIndex: 'totalNum',
key: 'totalNum',
align: 'center',
},
{
title: '0 未付款 1已付款2无需付款或占用状态',
dataIndex: 'payStatus',
key: 'payStatus',
align: 'center',
},
{
title: '0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center',
},
{
title: '是否免费0收费、1免费',
dataIndex: 'isFree',
key: 'isFree',
align: 'center',
},
{
title: '系统版本 0当前版本 其他版本',
dataIndex: 'version',
key: 'version',
align: 'center',
},
{
title: '预约时间段',
dataIndex: 'timePeriod',
key: 'timePeriod',
align: 'center',
},
{
title: '预定日期',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center',
},
{
title: '开场时间',
dataIndex: 'startTime',
key: 'startTime',
align: 'center',
},
{
title: '结束时间',
dataIndex: 'endTime',
key: 'endTime',
align: 'center',
},
{
title: '毫秒时间戳',
dataIndex: 'timeFlag',
key: 'timeFlag',
align: 'center',
},
{
title: '过期时间',
dataIndex: 'expirationTime',
key: 'expirationTime',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '用户id',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopOrderGoodsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopOrderGoods) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopOrderGoods) => {
const hide = message.loading('请求中..', 0);
removeShopOrderGoods(row.shopOrderGoodsId)
.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);
removeBatchShopOrderGoods(selection.value.map((d) => d.shopOrderGoodsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopOrderGoods) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopOrderGoods'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,379 @@
<!-- 编辑弹窗 -->
<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="关联订单表id" name="orderId">
<a-input
allow-clear
placeholder="请输入关联订单表id"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="组合数据:日期+时间段+场馆id+场地id" name="orderCode">
<a-input
allow-clear
placeholder="请输入组合数据:日期+时间段+场馆id+场地id"
v-model:value="form.orderCode"
/>
</a-form-item>
<a-form-item label="关联商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入关联商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="关联场地id" name="fieldId">
<a-input
allow-clear
placeholder="请输入关联场地id"
v-model:value="form.fieldId"
/>
</a-form-item>
<a-form-item label="场地名称" name="fieldName">
<a-input
allow-clear
placeholder="请输入场地名称"
v-model:value="form.fieldName"
/>
</a-form-item>
<a-form-item label="单价" name="price">
<a-input
allow-clear
placeholder="请输入单价"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="儿童价" name="childrenPrice">
<a-input
allow-clear
placeholder="请输入儿童价"
v-model:value="form.childrenPrice"
/>
</a-form-item>
<a-form-item label="成人人数" name="adultNum">
<a-input
allow-clear
placeholder="请输入成人人数"
v-model:value="form.adultNum"
/>
</a-form-item>
<a-form-item label="儿童人数" name="childrenNum">
<a-input
allow-clear
placeholder="请输入儿童人数"
v-model:value="form.childrenNum"
/>
</a-form-item>
<a-form-item label="已核销的成人票数" name="adultNumUse">
<a-input
allow-clear
placeholder="请输入已核销的成人票数"
v-model:value="form.adultNumUse"
/>
</a-form-item>
<a-form-item label="已核销的儿童票数" name="childrenNumUse">
<a-input
allow-clear
placeholder="请输入已核销的儿童票数"
v-model:value="form.childrenNumUse"
/>
</a-form-item>
<a-form-item label="0 未付款 1已付款2无需付款或占用状态" name="payStatus">
<a-input
allow-clear
placeholder="请输入0 未付款 1已付款2无需付款或占用状态"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item label="0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款" name="orderStatus">
<a-input
allow-clear
placeholder="请输入0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item label="是否免费0收费、1免费" name="isFree">
<a-input
allow-clear
placeholder="请输入是否免费0收费、1免费"
v-model:value="form.isFree"
/>
</a-form-item>
<a-form-item label="是否支持儿童票0不支持、1支持" name="isChildren">
<a-input
allow-clear
placeholder="请输入是否支持儿童票0不支持、1支持"
v-model:value="form.isChildren"
/>
</a-form-item>
<a-form-item label="系统版本 0当前版本 其他版本" name="version">
<a-input
allow-clear
placeholder="请输入系统版本 0当前版本 其他版本"
v-model:value="form.version"
/>
</a-form-item>
<a-form-item label="预订类型0全场1半场" name="isHalf">
<a-input
allow-clear
placeholder="请输入预订类型0全场1半场"
v-model:value="form.isHalf"
/>
</a-form-item>
<a-form-item label="预约时间段" name="timePeriod">
<a-input
allow-clear
placeholder="请输入预约时间段"
v-model:value="form.timePeriod"
/>
</a-form-item>
<a-form-item label="预定日期" name="dateTime">
<a-input
allow-clear
placeholder="请输入预定日期"
v-model:value="form.dateTime"
/>
</a-form-item>
<a-form-item label="开场时间" name="startTime">
<a-input
allow-clear
placeholder="请输入开场时间"
v-model:value="form.startTime"
/>
</a-form-item>
<a-form-item label="结束时间" name="endTime">
<a-input
allow-clear
placeholder="请输入结束时间"
v-model:value="form.endTime"
/>
</a-form-item>
<a-form-item label="毫秒时间戳" name="timeFlag">
<a-input
allow-clear
placeholder="请输入毫秒时间戳"
v-model:value="form.timeFlag"
/>
</a-form-item>
<a-form-item label="过期时间" name="expirationTime">
<a-input
allow-clear
placeholder="请输入过期时间"
v-model:value="form.expirationTime"
/>
</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="用户id" name="userId">
<a-input
allow-clear
placeholder="请输入用户id"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="更新时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入更新时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addShopOrderInfo, updateShopOrderInfo } from '@/api/shop/shopOrderInfo';
import { ShopOrderInfo } from '@/api/shop/shopOrderInfo/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?: ShopOrderInfo | 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<ShopOrderInfo>({
id: undefined,
orderId: undefined,
orderCode: undefined,
merchantId: undefined,
merchantName: undefined,
fieldId: undefined,
fieldName: undefined,
price: undefined,
childrenPrice: undefined,
adultNum: undefined,
childrenNum: undefined,
adultNumUse: undefined,
childrenNumUse: undefined,
payStatus: undefined,
orderStatus: undefined,
isFree: undefined,
isChildren: undefined,
version: undefined,
isHalf: undefined,
timePeriod: undefined,
dateTime: undefined,
startTime: undefined,
endTime: undefined,
timeFlag: undefined,
expirationTime: undefined,
comments: undefined,
userId: undefined,
tenantId: undefined,
updateTime: undefined,
createTime: undefined,
shopOrderInfoId: undefined,
shopOrderInfoName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopOrderInfoName: [
{
required: true,
type: 'string',
message: '请填写场地名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopOrderInfo : addShopOrderInfo;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,377 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopOrderInfoId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopOrderInfoEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopOrderInfoEdit from './components/shopOrderInfoEdit.vue';
import { pageShopOrderInfo, removeShopOrderInfo, removeBatchShopOrderInfo } from '@/api/shop/shopOrderInfo';
import type { ShopOrderInfo, ShopOrderInfoParam } from '@/api/shop/shopOrderInfo/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopOrderInfo[]>([]);
// 当前编辑数据
const current = ref<ShopOrderInfo | 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 pageShopOrderInfo({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '自增ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '关联订单表id',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '组合数据:日期+时间段+场馆id+场地id',
dataIndex: 'orderCode',
key: 'orderCode',
align: 'center',
},
{
title: '关联商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '关联场地id',
dataIndex: 'fieldId',
key: 'fieldId',
align: 'center',
},
{
title: '场地名称',
dataIndex: 'fieldName',
key: 'fieldName',
align: 'center',
},
{
title: '单价',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '儿童价',
dataIndex: 'childrenPrice',
key: 'childrenPrice',
align: 'center',
},
{
title: '成人人数',
dataIndex: 'adultNum',
key: 'adultNum',
align: 'center',
},
{
title: '儿童人数',
dataIndex: 'childrenNum',
key: 'childrenNum',
align: 'center',
},
{
title: '已核销的成人票数',
dataIndex: 'adultNumUse',
key: 'adultNumUse',
align: 'center',
},
{
title: '已核销的儿童票数',
dataIndex: 'childrenNumUse',
key: 'childrenNumUse',
align: 'center',
},
{
title: '0 未付款 1已付款2无需付款或占用状态',
dataIndex: 'payStatus',
key: 'payStatus',
align: 'center',
},
{
title: '0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center',
},
{
title: '是否免费0收费、1免费',
dataIndex: 'isFree',
key: 'isFree',
align: 'center',
},
{
title: '是否支持儿童票0不支持、1支持',
dataIndex: 'isChildren',
key: 'isChildren',
align: 'center',
},
{
title: '系统版本 0当前版本 其他版本',
dataIndex: 'version',
key: 'version',
align: 'center',
},
{
title: '预订类型0全场1半场',
dataIndex: 'isHalf',
key: 'isHalf',
align: 'center',
},
{
title: '预约时间段',
dataIndex: 'timePeriod',
key: 'timePeriod',
align: 'center',
},
{
title: '预定日期',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center',
},
{
title: '开场时间',
dataIndex: 'startTime',
key: 'startTime',
align: 'center',
},
{
title: '结束时间',
dataIndex: 'endTime',
key: 'endTime',
align: 'center',
},
{
title: '毫秒时间戳',
dataIndex: 'timeFlag',
key: 'timeFlag',
align: 'center',
},
{
title: '过期时间',
dataIndex: 'expirationTime',
key: 'expirationTime',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '用户id',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '更新时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopOrderInfoParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopOrderInfo) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopOrderInfo) => {
const hide = message.loading('请求中..', 0);
removeShopOrderInfo(row.shopOrderInfoId)
.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);
removeBatchShopOrderInfo(selection.value.map((d) => d.shopOrderInfoId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopOrderInfo) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopOrderInfo'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,194 @@
<!-- 编辑弹窗 -->
<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="关联订单表id" name="orderId">
<a-input
allow-clear
placeholder="请输入关联订单表id"
v-model:value="form.orderId"
/>
</a-form-item>
<a-form-item label="关联商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入关联商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="关联场地id" name="fieldId">
<a-input
allow-clear
placeholder="请输入关联场地id"
v-model:value="form.fieldId"
/>
</a-form-item>
<a-form-item label="核销数量" name="useNum">
<a-input
allow-clear
placeholder="请输入核销数量"
v-model:value="form.useNum"
/>
</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 { addShopOrderInfoLog, updateShopOrderInfoLog } from '@/api/shop/shopOrderInfoLog';
import { ShopOrderInfoLog } from '@/api/shop/shopOrderInfoLog/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?: ShopOrderInfoLog | 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<ShopOrderInfoLog>({
id: undefined,
orderId: undefined,
merchantId: undefined,
fieldId: undefined,
useNum: undefined,
tenantId: undefined,
createTime: undefined,
shopOrderInfoLogId: undefined,
shopOrderInfoLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopOrderInfoLogName: [
{
required: true,
type: 'string',
message: '请填写订单核销名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopOrderInfoLog : addShopOrderInfoLog;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopOrderInfoLogId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopOrderInfoLogEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopOrderInfoLogEdit from './components/shopOrderInfoLogEdit.vue';
import { pageShopOrderInfoLog, removeShopOrderInfoLog, removeBatchShopOrderInfoLog } from '@/api/shop/shopOrderInfoLog';
import type { ShopOrderInfoLog, ShopOrderInfoLogParam } from '@/api/shop/shopOrderInfoLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopOrderInfoLog[]>([]);
// 当前编辑数据
const current = ref<ShopOrderInfoLog | 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 pageShopOrderInfoLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '关联订单表id',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: '关联商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '关联场地id',
dataIndex: 'fieldId',
key: 'fieldId',
align: 'center',
},
{
title: '核销数量',
dataIndex: 'useNum',
key: 'useNum',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopOrderInfoLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopOrderInfoLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopOrderInfoLog) => {
const hide = message.loading('请求中..', 0);
removeShopOrderInfoLog(row.shopOrderInfoLogId)
.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);
removeBatchShopOrderInfoLog(selection.value.map((d) => d.shopOrderInfoLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopOrderInfoLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopOrderInfoLog'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,220 @@
<!-- 编辑弹窗 -->
<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="specName">
<a-input
allow-clear
placeholder="请输入规格名称"
v-model:value="form.specName"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
/>
</a-form-item>
<a-form-item label="创建用户" name="userId">
<a-input
allow-clear
placeholder="请输入创建用户"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="更新者" name="updater">
<a-input
allow-clear
placeholder="请输入更新者"
v-model:value="form.updater"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1待修,2异常已修3异常未修" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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 { addShopSpec, updateShopSpec } from '@/api/shop/shopSpec';
import { ShopSpec } from '@/api/shop/shopSpec/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?: ShopSpec | 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<ShopSpec>({
specId: undefined,
specName: undefined,
specValue: undefined,
userId: undefined,
updater: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopSpecId: undefined,
shopSpecName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopSpecName: [
{
required: true,
type: 'string',
message: '请填写规格名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopSpec : addShopSpec;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,257 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopSpecId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopSpecEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopSpecEdit from './components/shopSpecEdit.vue';
import { pageShopSpec, removeShopSpec, removeBatchShopSpec } from '@/api/shop/shopSpec';
import type { ShopSpec, ShopSpecParam } from '@/api/shop/shopSpec/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopSpec[]>([]);
// 当前编辑数据
const current = ref<ShopSpec | 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 pageShopSpec({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '规格ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
width: 90,
},
{
title: '规格名称',
dataIndex: 'specName',
key: 'specName',
align: 'center',
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
},
{
title: '创建用户',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '更新者',
dataIndex: 'updater',
key: 'updater',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0正常, 1待修,2异常已修3异常未修',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopSpecParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopSpec) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopSpec) => {
const hide = message.loading('请求中..', 0);
removeShopSpec(row.shopSpecId)
.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);
removeBatchShopSpec(selection.value.map((d) => d.shopSpecId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopSpec) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopSpec'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,197 @@
<!-- 编辑弹窗 -->
<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="规格组ID" name="specId">
<a-input
allow-clear
placeholder="请输入规格组ID"
v-model:value="form.specId"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
/>
</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="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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 { addShopSpecValue, updateShopSpecValue } from '@/api/shop/shopSpecValue';
import { ShopSpecValue } from '@/api/shop/shopSpecValue/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?: ShopSpecValue | 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<ShopSpecValue>({
specValueId: undefined,
specId: undefined,
specValue: undefined,
comments: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopSpecValueId: undefined,
shopSpecValueName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopSpecValueName: [
{
required: true,
type: 'string',
message: '请填写规格值名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopSpecValue : addShopSpecValue;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopSpecValueId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopSpecValueEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopSpecValueEdit from './components/shopSpecValueEdit.vue';
import { pageShopSpecValue, removeShopSpecValue, removeBatchShopSpecValue } from '@/api/shop/shopSpecValue';
import type { ShopSpecValue, ShopSpecValueParam } from '@/api/shop/shopSpecValue/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopSpecValue[]>([]);
// 当前编辑数据
const current = ref<ShopSpecValue | 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 pageShopSpecValue({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '规格值ID',
dataIndex: 'specValueId',
key: 'specValueId',
align: 'center',
width: 90,
},
{
title: '规格组ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopSpecValueParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopSpecValue) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopSpecValue) => {
const hide = message.loading('请求中..', 0);
removeShopSpecValue(row.shopSpecValueId)
.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);
removeBatchShopSpecValue(selection.value.map((d) => d.shopSpecValueId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopSpecValue) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopSpecValue'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,250 @@
<!-- 编辑弹窗 -->
<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="name">
<a-input
allow-clear
placeholder="请输入姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="所在国家" name="country">
<a-input
allow-clear
placeholder="请输入所在国家"
v-model:value="form.country"
/>
</a-form-item>
<a-form-item label="所在省份" name="province">
<a-input
allow-clear
placeholder="请输入所在省份"
v-model:value="form.province"
/>
</a-form-item>
<a-form-item label="所在城市" name="city">
<a-input
allow-clear
placeholder="请输入所在城市"
v-model:value="form.city"
/>
</a-form-item>
<a-form-item label="所在辖区" name="region">
<a-input
allow-clear
placeholder="请输入所在辖区"
v-model:value="form.region"
/>
</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="1先生 2女士" name="gender">
<a-input
allow-clear
placeholder="请输入1先生 2女士"
v-model:value="form.gender"
/>
</a-form-item>
<a-form-item label="家、公司、学校" name="type">
<a-input
allow-clear
placeholder="请输入家、公司、学校"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="默认收货地址" name="isDefault">
<a-input
allow-clear
placeholder="请输入默认收货地址"
v-model:value="form.isDefault"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</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 { addShopUserAddress, updateShopUserAddress } from '@/api/shop/shopUserAddress';
import { ShopUserAddress } from '@/api/shop/shopUserAddress/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?: ShopUserAddress | 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<ShopUserAddress>({
id: undefined,
name: undefined,
phone: undefined,
country: undefined,
province: undefined,
city: undefined,
region: undefined,
address: undefined,
gender: undefined,
type: undefined,
isDefault: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
shopUserAddressId: undefined,
shopUserAddressName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopUserAddressName: [
{
required: true,
type: 'string',
message: '请填写收货地址名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopUserAddress : addShopUserAddress;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -0,0 +1,281 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopUserAddressId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopUserAddressEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import ShopUserAddressEdit from './components/shopUserAddressEdit.vue';
import { pageShopUserAddress, removeShopUserAddress, removeBatchShopUserAddress } from '@/api/shop/shopUserAddress';
import type { ShopUserAddress, ShopUserAddressParam } from '@/api/shop/shopUserAddress/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopUserAddress[]>([]);
// 当前编辑数据
const current = ref<ShopUserAddress | 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 pageShopUserAddress({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '所在国家',
dataIndex: 'country',
key: 'country',
align: 'center',
},
{
title: '所在省份',
dataIndex: 'province',
key: 'province',
align: 'center',
},
{
title: '所在城市',
dataIndex: 'city',
key: 'city',
align: 'center',
},
{
title: '所在辖区',
dataIndex: 'region',
key: 'region',
align: 'center',
},
{
title: '收货地址',
dataIndex: 'address',
key: 'address',
align: 'center',
},
{
title: '1先生 2女士',
dataIndex: 'gender',
key: 'gender',
align: 'center',
},
{
title: '家、公司、学校',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '默认收货地址',
dataIndex: 'isDefault',
key: 'isDefault',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '注册时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ShopUserAddressParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopUserAddress) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopUserAddress) => {
const hide = message.loading('请求中..', 0);
removeShopUserAddress(row.shopUserAddressId)
.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);
removeBatchShopUserAddress(selection.value.map((d) => d.shopUserAddressId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopUserAddress) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopUserAddress'
};
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,178 @@
<!-- 编辑弹窗 -->
<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="租户ID" name="tid">
<a-input
allow-clear
placeholder="请输入租户ID"
v-model:value="form.tid"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</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 { addShopUserCollection, updateShopUserCollection } from '@/api/shop/shopUserCollection';
import { ShopUserCollection } from '@/api/shop/shopUserCollection/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?: ShopUserCollection | 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<ShopUserCollection>({
id: undefined,
tid: undefined,
userId: undefined,
tenantId: undefined,
createTime: undefined,
shopUserCollectionId: undefined,
shopUserCollectionName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopUserCollectionName: [
{
required: true,
type: 'string',
message: '请填写我的收藏名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateShopUserCollection : addShopUserCollection;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

Some files were not shown because too many files have changed in this diff Show More