优化网站导航模块

This commit is contained in:
2024-08-23 22:28:24 +08:00
parent 1d81fa9270
commit 13832d9de0
964 changed files with 90774 additions and 31362 deletions
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,184 @@
<!-- 编辑弹窗 -->
<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="version">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.version"
/>
</a-form-item>
<a-form-item label="" name="logContent">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.logContent"
/>
</a-form-item>
<a-form-item label="" name="addtime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.addtime"
/>
</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 { addSysLog, updateSysLog } from '@/api/think/sysLog';
import { SysLog } from '@/api/think/sysLog/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?: SysLog | 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<SysLog>({
id: undefined,
version: undefined,
logContent: undefined,
addtime: undefined,
sysLogId: undefined,
sysLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
sysLogName: [
{
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 ? updateSysLog : addSysLog;
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>
+224
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="sysLogId"
: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>
<!-- 编辑弹窗 -->
<SysLogEdit 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 SysLogEdit from './components/sysLogEdit.vue';
import { pageSysLog, removeSysLog, removeBatchSysLog } from '@/api/think/sysLog';
import type { SysLog, SysLogParam } from '@/api/think/sysLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<SysLog[]>([]);
// 当前编辑数据
const current = ref<SysLog | 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 pageSysLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '',
dataIndex: 'version',
key: 'version',
align: 'center',
},
{
title: '',
dataIndex: 'logContent',
key: 'logContent',
align: 'center',
},
{
title: '',
dataIndex: 'addtime',
key: 'addtime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: SysLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: SysLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: SysLog) => {
const hide = message.loading('请求中..', 0);
removeSysLog(row.sysLogId)
.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);
removeBatchSysLog(selection.value.map((d) => d.sysLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: SysLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'SysLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,271 @@
<!-- 编辑弹窗 -->
<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="username">
<a-input
allow-clear
placeholder="请输入用户名"
v-model:value="form.username"
/>
</a-form-item>
<a-form-item label="密码" name="password">
<a-input
allow-clear
placeholder="请输入密码"
v-model:value="form.password"
/>
</a-form-item>
<a-form-item label="头像" name="portrait">
<a-input
allow-clear
placeholder="请输入头像"
v-model:value="form.portrait"
/>
</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="loginnum">
<a-input
allow-clear
placeholder="请输入登陆次数"
v-model:value="form.loginnum"
/>
</a-form-item>
<a-form-item label="最后登录IP" name="lastLoginIp">
<a-input
allow-clear
placeholder="请输入最后登录IP"
v-model:value="form.lastLoginIp"
/>
</a-form-item>
<a-form-item label="最后登录时间" name="lastLoginTime">
<a-input
allow-clear
placeholder="请输入最后登录时间"
v-model:value="form.lastLoginTime"
/>
</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="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="sid">
<a-input
allow-clear
placeholder="请输入场馆id集合,用于区分管理可管理的场馆"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="用户角色id" name="groupid">
<a-input
allow-clear
placeholder="请输入用户角色id"
v-model:value="form.groupid"
/>
</a-form-item>
<a-form-item label="" name="token">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.token"
/>
</a-form-item>
<a-form-item label="过期时间" name="expireTime">
<a-input
allow-clear
placeholder="请输入过期时间"
v-model:value="form.expireTime"
/>
</a-form-item>
<a-form-item label="员工卡号" name="cardCode">
<a-input
allow-clear
placeholder="请输入员工卡号"
v-model:value="form.cardCode"
/>
</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 { addThinkAdmin, updateThinkAdmin } from '@/api/think/thinkAdmin';
import { ThinkAdmin } from '@/api/think/thinkAdmin/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?: ThinkAdmin | 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<ThinkAdmin>({
id: undefined,
username: undefined,
password: undefined,
portrait: undefined,
phone: undefined,
loginnum: undefined,
lastLoginIp: undefined,
lastLoginTime: undefined,
realName: undefined,
status: undefined,
sid: undefined,
groupid: undefined,
token: undefined,
expireTime: undefined,
cardCode: undefined,
thinkAdminId: undefined,
thinkAdminName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkAdminName: [
{
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 ? updateThinkAdmin : addThinkAdmin;
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>
+290
View File
@@ -0,0 +1,290 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkAdminId"
: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>
<!-- 编辑弹窗 -->
<ThinkAdminEdit 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 ThinkAdminEdit from './components/thinkAdminEdit.vue';
import { pageThinkAdmin, removeThinkAdmin, removeBatchThinkAdmin } from '@/api/think/thinkAdmin';
import type { ThinkAdmin, ThinkAdminParam } from '@/api/think/thinkAdmin/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkAdmin[]>([]);
// 当前编辑数据
const current = ref<ThinkAdmin | 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 pageThinkAdmin({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
align: 'center',
},
{
title: '密码',
dataIndex: 'password',
key: 'password',
align: 'center',
},
{
title: '头像',
dataIndex: 'portrait',
key: 'portrait',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '登陆次数',
dataIndex: 'loginnum',
key: 'loginnum',
align: 'center',
},
{
title: '最后登录IP',
dataIndex: 'lastLoginIp',
key: 'lastLoginIp',
align: 'center',
},
{
title: '最后登录时间',
dataIndex: 'lastLoginTime',
key: 'lastLoginTime',
align: 'center',
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '场馆id集合,用于区分管理可管理的场馆',
dataIndex: 'sid',
key: 'sid',
align: 'center',
},
{
title: '用户角色id',
dataIndex: 'groupid',
key: 'groupid',
align: 'center',
},
{
title: '',
dataIndex: 'token',
key: 'token',
align: 'center',
},
{
title: '过期时间',
dataIndex: 'expireTime',
key: 'expireTime',
align: 'center',
},
{
title: '员工卡号',
dataIndex: 'cardCode',
key: 'cardCode',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkAdminParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkAdmin) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkAdmin) => {
const hide = message.loading('请求中..', 0);
removeThinkAdmin(row.thinkAdminId)
.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);
removeBatchThinkAdmin(selection.value.map((d) => d.thinkAdminId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkAdmin) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkAdmin'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,200 @@
<!-- 编辑弹窗 -->
<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="username">
<a-input
allow-clear
placeholder="请输入用户名"
v-model:value="form.username"
/>
</a-form-item>
<a-form-item label="操作栏目" name="column">
<a-input
allow-clear
placeholder="请输入操作栏目"
v-model:value="form.column"
/>
</a-form-item>
<a-form-item label="变更说明" name="remate">
<a-input
allow-clear
placeholder="请输入变更说明"
v-model:value="form.remate"
/>
</a-form-item>
<a-form-item label="变更时间" name="addtime">
<a-input
allow-clear
placeholder="请输入变更时间"
v-model:value="form.addtime"
/>
</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 { addThinkAdminLog, updateThinkAdminLog } from '@/api/think/thinkAdminLog';
import { ThinkAdminLog } from '@/api/think/thinkAdminLog/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?: ThinkAdminLog | 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<ThinkAdminLog>({
id: undefined,
userid: undefined,
username: undefined,
column: undefined,
remate: undefined,
addtime: undefined,
thinkAdminLogId: undefined,
thinkAdminLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkAdminLogName: [
{
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 ? updateThinkAdminLog : addThinkAdminLog;
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>
+236
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="thinkAdminLogId"
: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>
<!-- 编辑弹窗 -->
<ThinkAdminLogEdit 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 ThinkAdminLogEdit from './components/thinkAdminLogEdit.vue';
import { pageThinkAdminLog, removeThinkAdminLog, removeBatchThinkAdminLog } from '@/api/think/thinkAdminLog';
import type { ThinkAdminLog, ThinkAdminLogParam } from '@/api/think/thinkAdminLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkAdminLog[]>([]);
// 当前编辑数据
const current = ref<ThinkAdminLog | 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 pageThinkAdminLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户ID',
dataIndex: 'userid',
key: 'userid',
align: 'center',
},
{
title: '用户名',
dataIndex: 'username',
key: 'username',
align: 'center',
},
{
title: '操作栏目',
dataIndex: 'column',
key: 'column',
align: 'center',
},
{
title: '变更说明',
dataIndex: 'remate',
key: 'remate',
align: 'center',
},
{
title: '变更时间',
dataIndex: 'addtime',
key: 'addtime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkAdminLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkAdminLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkAdminLog) => {
const hide = message.loading('请求中..', 0);
removeThinkAdminLog(row.thinkAdminLogId)
.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);
removeBatchThinkAdminLog(selection.value.map((d) => d.thinkAdminLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkAdminLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkAdminLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,192 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑' : '添加'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="" name="title">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="" name="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="rules">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.rules"
/>
</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 { addThinkAuthGroup, updateThinkAuthGroup } from '@/api/think/thinkAuthGroup';
import { ThinkAuthGroup } from '@/api/think/thinkAuthGroup/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?: ThinkAuthGroup | 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<ThinkAuthGroup>({
id: undefined,
title: undefined,
status: undefined,
rules: undefined,
createTime: undefined,
updateTime: undefined,
thinkAuthGroupId: undefined,
thinkAuthGroupName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkAuthGroupName: [
{
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 ? updateThinkAuthGroup : addThinkAuthGroup;
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>
+239
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="thinkAuthGroupId"
: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>
<!-- 编辑弹窗 -->
<ThinkAuthGroupEdit 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 ThinkAuthGroupEdit from './components/thinkAuthGroupEdit.vue';
import { pageThinkAuthGroup, removeThinkAuthGroup, removeBatchThinkAuthGroup } from '@/api/think/thinkAuthGroup';
import type { ThinkAuthGroup, ThinkAuthGroupParam } from '@/api/think/thinkAuthGroup/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkAuthGroup[]>([]);
// 当前编辑数据
const current = ref<ThinkAuthGroup | 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 pageThinkAuthGroup({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '',
dataIndex: 'rules',
key: 'rules',
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?: ThinkAuthGroupParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkAuthGroup) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkAuthGroup) => {
const hide = message.loading('请求中..', 0);
removeThinkAuthGroup(row.thinkAuthGroupId)
.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);
removeBatchThinkAuthGroup(selection.value.map((d) => d.thinkAuthGroupId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkAuthGroup) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkAuthGroup'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,168 @@
<!-- 编辑弹窗 -->
<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="groupId">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.groupId"
/>
</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 { addThinkAuthGroupAccess, updateThinkAuthGroupAccess } from '@/api/think/thinkAuthGroupAccess';
import { ThinkAuthGroupAccess } from '@/api/think/thinkAuthGroupAccess/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?: ThinkAuthGroupAccess | 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<ThinkAuthGroupAccess>({
uid: undefined,
groupId: undefined,
thinkAuthGroupAccessId: undefined,
thinkAuthGroupAccessName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkAuthGroupAccessName: [
{
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 ? updateThinkAuthGroupAccess : addThinkAuthGroupAccess;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,212 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkAuthGroupAccessId"
: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>
<!-- 编辑弹窗 -->
<ThinkAuthGroupAccessEdit 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 ThinkAuthGroupAccessEdit from './components/thinkAuthGroupAccessEdit.vue';
import { pageThinkAuthGroupAccess, removeThinkAuthGroupAccess, removeBatchThinkAuthGroupAccess } from '@/api/think/thinkAuthGroupAccess';
import type { ThinkAuthGroupAccess, ThinkAuthGroupAccessParam } from '@/api/think/thinkAuthGroupAccess/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkAuthGroupAccess[]>([]);
// 当前编辑数据
const current = ref<ThinkAuthGroupAccess | 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 pageThinkAuthGroupAccess({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'uid',
key: 'uid',
align: 'center',
width: 90,
},
{
title: '',
dataIndex: 'groupId',
key: 'groupId',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkAuthGroupAccessParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkAuthGroupAccess) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkAuthGroupAccess) => {
const hide = message.loading('请求中..', 0);
removeThinkAuthGroupAccess(row.thinkAuthGroupAccessId)
.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);
removeBatchThinkAuthGroupAccess(selection.value.map((d) => d.thinkAuthGroupAccessId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkAuthGroupAccess) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkAuthGroupAccess'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,232 @@
<!-- 编辑弹窗 -->
<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="title">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.title"
/>
</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="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="css">
<a-input
allow-clear
placeholder="请输入样式"
v-model:value="form.css"
/>
</a-form-item>
<a-form-item label="" name="condition">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.condition"
/>
</a-form-item>
<a-form-item label="父栏目ID" name="pid">
<a-input
allow-clear
placeholder="请输入父栏目ID"
v-model:value="form.pid"
/>
</a-form-item>
<a-form-item label="排序" name="sort">
<a-input
allow-clear
placeholder="请输入排序"
v-model:value="form.sort"
/>
</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 { addThinkAuthRule, updateThinkAuthRule } from '@/api/think/thinkAuthRule';
import { ThinkAuthRule } from '@/api/think/thinkAuthRule/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?: ThinkAuthRule | 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<ThinkAuthRule>({
id: undefined,
name: undefined,
title: undefined,
type: undefined,
status: undefined,
css: undefined,
condition: undefined,
pid: undefined,
sort: undefined,
createTime: undefined,
updateTime: undefined,
thinkAuthRuleId: undefined,
thinkAuthRuleName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkAuthRuleName: [
{
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 ? updateThinkAuthRule : addThinkAuthRule;
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>
+269
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="thinkAuthRuleId"
: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>
<!-- 编辑弹窗 -->
<ThinkAuthRuleEdit 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 ThinkAuthRuleEdit from './components/thinkAuthRuleEdit.vue';
import { pageThinkAuthRule, removeThinkAuthRule, removeBatchThinkAuthRule } from '@/api/think/thinkAuthRule';
import type { ThinkAuthRule, ThinkAuthRuleParam } from '@/api/think/thinkAuthRule/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkAuthRule[]>([]);
// 当前编辑数据
const current = ref<ThinkAuthRule | 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 pageThinkAuthRule({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '样式',
dataIndex: 'css',
key: 'css',
align: 'center',
},
{
title: '',
dataIndex: 'condition',
key: 'condition',
align: 'center',
},
{
title: '父栏目ID',
dataIndex: 'pid',
key: 'pid',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '添加时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkAuthRuleParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkAuthRule) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkAuthRule) => {
const hide = message.loading('请求中..', 0);
removeThinkAuthRule(row.thinkAuthRuleId)
.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);
removeBatchThinkAuthRule(selection.value.map((d) => d.thinkAuthRuleId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkAuthRule) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkAuthRule'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,200 @@
<!-- 编辑弹窗 -->
<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="银行卡号" name="cardId">
<a-input
allow-clear
placeholder="请输入银行卡号"
v-model:value="form.cardId"
/>
</a-form-item>
<a-form-item label="所属银行" name="cardName">
<a-input
allow-clear
placeholder="请输入所属银行"
v-model:value="form.cardName"
/>
</a-form-item>
<a-form-item label="用户姓名" name="name">
<a-input
allow-clear
placeholder="请输入用户姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="手机号" name="phone">
<a-input
allow-clear
placeholder="请输入手机号"
v-model:value="form.phone"
/>
</a-form-item>
</a-form>
</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 { addThinkBankCard, updateThinkBankCard } from '@/api/think/thinkBankCard';
import { ThinkBankCard } from '@/api/think/thinkBankCard/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?: ThinkBankCard | 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<ThinkBankCard>({
id: undefined,
uid: undefined,
cardId: undefined,
cardName: undefined,
name: undefined,
phone: undefined,
thinkBankCardId: undefined,
thinkBankCardName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkBankCardName: [
{
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 ? updateThinkBankCard : addThinkBankCard;
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>
+236
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="thinkBankCardId"
: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>
<!-- 编辑弹窗 -->
<ThinkBankCardEdit 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 ThinkBankCardEdit from './components/thinkBankCardEdit.vue';
import { pageThinkBankCard, removeThinkBankCard, removeBatchThinkBankCard } from '@/api/think/thinkBankCard';
import type { ThinkBankCard, ThinkBankCardParam } from '@/api/think/thinkBankCard/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkBankCard[]>([]);
// 当前编辑数据
const current = ref<ThinkBankCard | 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 pageThinkBankCard({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户ID',
dataIndex: 'uid',
key: 'uid',
align: 'center',
},
{
title: '银行卡号',
dataIndex: 'cardId',
key: 'cardId',
align: 'center',
},
{
title: '所属银行',
dataIndex: 'cardName',
key: 'cardName',
align: 'center',
},
{
title: '用户姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkBankCardParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkBankCard) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkBankCard) => {
const hide = message.loading('请求中..', 0);
removeThinkBankCard(row.thinkBankCardId)
.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);
removeBatchThinkBankCard(selection.value.map((d) => d.thinkBankCardId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkBankCard) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkBankCard'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,177 @@
<!-- 搜索表单 -->
<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-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入关键词"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import { watch, ref } from 'vue';
import useSearch from '@/utils/use-search';
import dayjs from 'dayjs';
import { toDateString } from 'ele-admin-pro';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
import {
ThinkCardLog,
ThinkCardLogParam
} from '@/api/think/thinkCardLog/model';
import { listThinkCardLog } from '@/api/think/thinkCardLog';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkCardLogParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<ThinkCardLog[] | any[]>();
const xlsFileName = ref<string>();
const payType = ref<string[]>([
'',
'微信支付',
'支付宝支付',
'现金支付',
'POS机支付'
]);
// 表单数据
const { where, resetFields } = useSearch<ThinkCardLogParam>({
code: undefined,
timeStart: undefined,
timeEnd: undefined,
keywords: undefined
});
// 新增
const add = () => {
emit('add');
};
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
emit('search', {
...where
});
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'卡号',
'姓名',
'手机号',
'会员卡名称',
'支付方式',
'充值金额',
'充值次数',
'操作员',
'第三方订单号',
'充值时间'
]
];
if (!where.timeStart) {
message.error('请选择导出的开始日期、结束日期,每次最多导出5000条记录');
return false;
}
await listThinkCardLog(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkCardLog) => {
array.push([
`${d.code}`,
`${d.username}`,
`${d.phone}`,
`${d.cardName}`,
`${payType.value[Number(d.payType)]}`,
`${d.money}`,
`${d.count}`,
`${d.adminName || d.aid}`,
`${d.wechatOrder}`,
`${toDateString(d.createTime)}`
]);
});
const sheetName = `充值记录导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {});
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,478 @@
<!-- 编辑弹窗 -->
<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="code">
<a-input
allow-clear
placeholder="卡号"
:disabled="true"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="姓名" name="username">
<a-input
allow-clear
placeholder="姓名"
:disabled="true"
v-model:value="form.username"
/>
</a-form-item>
<a-form-item label="手机号" name="phone">
<a-input
allow-clear
:disabled="true"
placeholder="手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="会员卡名称" name="name">
<a-input
allow-clear
placeholder="会员卡名称"
:disabled="true"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="IC卡数字" name="cardNum">
<a-input
allow-clear
placeholder="IC卡数字"
:disabled="true"
v-model:value="form.cardNum"
/>
</a-form-item>
<a-form-item label="紧急联系人" name="urgentName">
<a-input
allow-clear
placeholder="紧急联系人"
:disabled="true"
v-model:value="form.urgentName"
/>
</a-form-item>
<a-form-item label="紧急联系人号码" name="urgentPhone">
<a-input
allow-clear
placeholder="紧急联系人号码"
:disabled="true"
v-model:value="form.urgentPhone"
/>
</a-form-item>
<a-form-item label="可用场馆" name="sid">
<a-input
allow-clear
placeholder="可用场馆"
:disabled="true"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="购卡价格" name="price">
<a-input
allow-clear
placeholder="购卡价格"
:disabled="true"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="折扣率" name="discount">
<a-input
allow-clear
placeholder="折扣率"
:disabled="true"
v-model:value="form.discount"
/>
</a-form-item>
<a-form-item label="使用次数" name="count">
<a-input
allow-clear
placeholder="使用次数"
:disabled="true"
v-model:value="form.count"
/>
</a-form-item>
<a-form-item label="剩余次数" name="num">
<a-input
allow-clear
placeholder="剩余次数"
:disabled="true"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="每使用一次减少的金额" name="eachMoney">
<a-input
allow-clear
placeholder="每使用一次减少的金额"
:disabled="true"
v-model:value="form.eachMoney"
/>
</a-form-item>
<a-form-item label="剩余金额" name="remainingMoney">
<a-input
allow-clear
placeholder="剩余金额"
:disabled="true"
v-model:value="form.remainingMoney"
/>
</a-form-item>
<a-form-item label="月限" name="month">
<a-input
allow-clear
placeholder="月限"
:disabled="true"
v-model:value="form.month"
/>
</a-form-item>
<a-form-item label="年限" name="term">
<a-input
allow-clear
placeholder="年限"
:disabled="true"
v-model:value="form.term"
/>
</a-form-item>
<a-form-item label="IC卡类型" name="type">
<a-input
allow-clear
placeholder="IC卡类型"
:disabled="true"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="到期时间" name="expireTime">
<a-input
allow-clear
placeholder="到期时间"
:disabled="true"
v-model:value="form.expireTime"
/>
</a-form-item>
<a-form-item label="支付状态" name="status">
<a-input
allow-clear
placeholder="支付状态"
:disabled="true"
v-model:value="form.status"
/>
</a-form-item>
<a-form-item label="付款方式" name="payType">
<a-input
allow-clear
placeholder="付款方式"
:disabled="true"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="是否赠送积分" name="isIntegral">
<a-input
allow-clear
placeholder="是否赠送积分"
:disabled="true"
v-model:value="form.isIntegral"
/>
</a-form-item>
<a-form-item label="是否已开具发票" name="isInvoice">
<a-input
allow-clear
placeholder="是否已开具发票"
:disabled="true"
v-model:value="form.isInvoice"
/>
</a-form-item>
<a-form-item label="微信订单号" name="wechatOrder">
<a-input
allow-clear
:disabled="true"
placeholder="请输入微信订单号"
v-model:value="form.wechatOrder"
/>
</a-form-item>
<a-form-item label="购卡时间" name="createTime">
<a-input
allow-clear
placeholder="购卡时间"
:disabled="true"
v-model:value="form.createTime"
/>
</a-form-item>
<a-form-item label="会员卡介绍" name="desc">
{{ form.desc }}
</a-form-item>
<a-form-item label="会员卡说明" name="info">
<div v-html="form.info"></div>
</a-form-item>
<a-form-item label="续费累加次数" name="number">
<a-input
allow-clear
:disabled="true"
placeholder="请输入续费累加次数"
v-model:value="form.number"
/>
</a-form-item>
<a-form-item label="支付状态" name="status">
<a-radio-group v-model:value="form.status" :disabled="true">
<a-radio :value="1">已付款</a-radio>
<a-radio :value="2">未付款</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="IC卡类型" name="type">
<a-radio-group v-model:value="form.type" :disabled="true">
<a-radio :value="1">年卡</a-radio>
<a-radio :value="2">次卡</a-radio>
<a-radio :value="3">月卡</a-radio>
<a-radio :value="4">会员IC卡</a-radio>
<a-radio :value="5">充值卡</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="卡类型" name="cardType">
<a-radio-group v-model:value="form.cardType" :disabled="true">
<a-radio :value="1">成人卡</a-radio>
<a-radio :value="2">儿童卡</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="卡等级类型" name="vipType">
<a-radio-group v-model:value="form.vipType" :disabled="true">
<a-radio :value="1">特殊vip卡</a-radio>
<a-radio :value="2">普通vip卡</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="特殊卡开发凭证图" name="pic">
<a-avatar :src="`${IMG_URL}${form.pic}`" :size="120" />
</a-form-item>
<a-form-item label="价格组" name="prices">
<a-input
allow-clear
:disabled="true"
placeholder="请输入价格组"
v-model:value="form.prices"
/>
</a-form-item>
<a-form-item label="是否赠送积分" name="isIntegral">
<a-input
allow-clear
:disabled="true"
placeholder="请输入是否赠送积分:1赠送,2不赠送"
v-model:value="form.isIntegral"
/>
</a-form-item>
<a-form-item label="是否已开具发票" name="isInvoice">
<a-radio-group v-model:value="form.isInvoice" :disabled="true">
<a-radio :value="1">已开票</a-radio>
<a-radio :value="2">未开票</a-radio>
</a-radio-group>
</a-form-item>
<!-- <a-form-item label="密码" name="password">-->
<!-- <a-input-password-->
<!-- allow-clear-->
<!-- placeholder="请输入密码"-->
<!-- v-model:value="form.password"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="使用时间" name="useTime">
{{ toDateString(form.useTime, 'yyyy-MM-dd HH:mm:ss') }}
</a-form-item>
<a-form-item label="身份证号码" name="idcard">
<a-input
allow-clear
:disabled="true"
placeholder="请输入身份证号码"
v-model:value="form.idcard"
/>
</a-form-item>
<a-form-item label="备注" name="remark">
<a-input
allow-clear
placeholder="请输入备注"
v-model:value="form.remark"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkCard, updateThinkCard } from '@/api/think/thinkCard';
import { ThinkCard } from '@/api/think/thinkCard/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { toDateString } from 'ele-admin-pro';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
import { IMG_URL } from '@/config/setting';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkCard | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
// 用户信息
const form = reactive<ThinkCard>({
id: undefined,
sid: undefined,
uid: undefined,
vid: undefined,
aid: undefined,
wechatOrder: undefined,
code: undefined,
name: undefined,
username: undefined,
phone: undefined,
price: undefined,
desc: undefined,
info: undefined,
discount: undefined,
count: undefined,
eachMoney: undefined,
remainingMoney: undefined,
number: undefined,
num: undefined,
status: undefined,
term: undefined,
month: undefined,
type: undefined,
cardType: undefined,
vipType: undefined,
pic: undefined,
prices: undefined,
payType: undefined,
isIntegral: undefined,
isInvoice: undefined,
expireTime: undefined,
urgentName: undefined,
urgentPhone: undefined,
cardNum: undefined,
password: undefined,
useTime: undefined,
createTime: undefined,
updateTime: undefined,
remark: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardName: [
{
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 ? updateThinkCard : addThinkCard;
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>
+550
View File
@@ -0,0 +1,550 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 3800 }"
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 === 'username'">
<a-space>
<span>{{ record.username }}</span>
<a-divider type="vertical" />
<a-popconfirm
title="确定要解除绑定吗?"
@confirm="unBindCard(record)"
>
<a>解除绑定</a>
</a-popconfirm>
<a-divider type="vertical" />
<ThinkSelectUsers :id="record.id" @done="changeBindCard" />
<a-divider type="vertical" />
<a-popconfirm
title="确定要注销该卡吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">注销</a>
</a-popconfirm>
</a-space>
</template>
<template v-if="column.key === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'type'">
<a-tag>{{ types[record.type] }}</a-tag>
</template>
<template v-if="column.key === 'payType'">
<a-tag>{{ payTypes[record.payType] }}</a-tag>
</template>
<template v-if="column.key === 'isIntegral'">
<a-tag>{{ isIntegral[record.isIntegral] }}</a-tag>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 1" color="green">已付款</a-tag>
<a-tag v-if="record.status === 2" color="red">未付款</a-tag>
</template>
<template v-if="column.key === 'expireTime'">
{{ toDateString(record.expireTime) }}
</template>
<template v-if="column.key === 'isInvoice'">
<a-tag v-if="record.isInvoice === 1" color="green">已开票</a-tag>
<a-tag v-if="record.isInvoice === 2">未开票</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>
<!-- 编辑弹窗 -->
<ThinkCardEdit
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 ThinkCardEdit from './components/thinkCardEdit.vue';
import {
pageThinkCard,
removeThinkCard,
removeBatchThinkCard,
updateThinkCard
} from '@/api/think/thinkCard';
import type { ThinkCard, ThinkCardParam } from '@/api/think/thinkCard/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCard[]>([]);
// 当前编辑数据
const current = ref<ThinkCard | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
const types = ref<string[]>([
'',
'年卡',
'次卡',
'月卡',
'会员IC卡',
'充值卡'
]);
const payTypes = ref<string[]>([
'',
'微信支付',
'支付宝支付',
'现金',
'POS机刷卡',
'平安健康卡'
]);
const isIntegral = ref<string[]>(['', '赠送', '不赠送']);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkCard({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '姓名',
dataIndex: 'username',
key: 'username',
align: 'center',
fixed: 'left',
width: 280
},
{
title: '卡号',
dataIndex: 'code',
key: 'code',
align: 'center',
fixed: 'left',
width: 140
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
fixed: 'left',
width: 140
},
{
title: '会员卡名称',
dataIndex: 'name',
key: 'name',
align: 'center',
width: 140,
fixed: 'left'
},
{
title: 'IC卡数字',
dataIndex: 'cardNum',
key: 'cardNum',
width: 140,
align: 'center'
},
{
title: '紧急联系人',
dataIndex: 'urgentName',
key: 'urgentName',
width: 140,
align: 'center'
},
{
title: '紧急联系人号码',
dataIndex: 'urgentPhone',
key: 'urgentPhone',
width: 140,
align: 'center'
},
{
title: '可用场馆',
dataIndex: 'sid',
key: 'sid',
width: 140,
align: 'center'
},
{
title: 'vip购卡价格',
dataIndex: 'price',
key: 'price',
width: 140,
sorter: true,
align: 'center'
},
{
title: 'vip卡折扣率',
dataIndex: 'discount',
key: 'discount',
width: 140,
sorter: true,
align: 'center'
},
{
title: '使用次数',
dataIndex: 'count',
key: 'count',
width: 140,
sorter: true,
align: 'center'
},
{
title: '剩余次数',
dataIndex: 'num',
key: 'num',
width: 140,
sorter: true,
align: 'center'
},
{
title: '每使用一次减少的金额',
dataIndex: 'eachMoney',
key: 'eachMoney',
width: 140,
sorter: true,
align: 'center'
},
{
title: '剩余金额',
dataIndex: 'remainingMoney',
key: 'remainingMoney',
width: 140,
sorter: true,
align: 'center'
},
{
title: '月限',
dataIndex: 'month',
key: 'month',
width: 140,
align: 'center'
},
{
title: '年限',
dataIndex: 'term',
key: 'term',
width: 140,
align: 'center'
},
{
title: 'IC卡类型',
dataIndex: 'type',
key: 'type',
width: 140,
align: 'center'
},
{
title: '到期时间',
dataIndex: 'expireTime',
key: 'expireTime',
width: 140,
sorter: true,
align: 'center'
},
{
title: '支付状态',
dataIndex: 'status',
key: 'status',
width: 140,
sorter: true,
align: 'center'
},
{
title: '付款方式',
dataIndex: 'payType',
key: 'payType',
width: 140,
align: 'center'
},
{
title: '是否赠送积分',
dataIndex: 'isIntegral',
key: 'isIntegral',
width: 140,
sorter: true,
align: 'center'
},
{
title: '是否已开具发票',
dataIndex: 'isInvoice',
key: 'isInvoice',
width: 140,
sorter: true,
align: 'center'
},
{
title: '购卡时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
width: 180,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
}
// {
// title: '微信订单号',
// dataIndex: 'wechatOrder',
// key: 'wechatOrder',
// align: 'center'
// },
// {
// title: '手机号码',
// dataIndex: 'phone',
// key: 'phone',
// align: 'center',
// },
// {
// title: '会员卡介绍',
// dataIndex: 'desc',
// key: 'desc',
// align: 'center',
// },
// {
// title: '会员卡说明',
// dataIndex: 'info',
// key: 'info',
// align: 'center',
// },
// {
// title: '续费累加次数',
// dataIndex: 'number',
// key: 'number',
// align: 'center',
// },
// {
// title: '付款状态,1已付款,2未付款',
// dataIndex: 'status',
// key: 'status',
// align: 'center',
// },
// {
// title: '卡类型:1成人卡,2儿童卡',
// dataIndex: 'cardType',
// key: 'cardType',
// align: 'center',
// },
// {
// title: 'vip卡等级类型:1特殊vip卡,2普通vip卡',
// dataIndex: 'vipType',
// key: 'vipType',
// align: 'center',
// },
// {
// title: '特殊卡开发凭证图',
// dataIndex: 'pic',
// key: 'pic',
// align: 'center',
// },
// {
// title: '价格组',
// dataIndex: 'prices',
// key: 'prices',
// align: 'center',
// },
// {
// title: '卡号',
// dataIndex: 'cardNum',
// key: 'cardNum',
// align: 'center'
// }
// {
// title: '密码',
// dataIndex: 'password',
// key: 'password',
// align: 'center',
// },
// {
// title: '使用时间',
// dataIndex: 'useTime',
// key: 'useTime',
// align: 'center',
// },
// {
// title: '',
// dataIndex: 'updateTime',
// key: 'updateTime',
// align: 'center',
// },
// {
// title: '身份证号码',
// dataIndex: 'idcard',
// key: 'idcard',
// align: 'center',
// },
// {
// title: '备注',
// dataIndex: 'remark',
// key: 'remark',
// align: 'center',
// },
// {
// title: '操作',
// key: 'action',
// width: 180,
// fixed: 'right',
// align: 'center',
// hideInSetting: true
// }
]);
/* 搜索 */
const reload = (where?: ThinkCardParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCard) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
const unBindCard = (row: ThinkCard) => {
updateThinkCard({ id: row.id, uid: 0 }).then((res) => {
message.success('操作成功');
});
};
const changeBindCard = (row: any, id: number) => {
console.log(row, id);
updateThinkCard({ id, uid: row.id }).then((res) => {
message.success('操作成功');
});
};
/* 删除单个 */
const remove = (row: ThinkCard) => {
const hide = message.loading('请求中..', 0);
removeThinkCard(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkCard(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCard) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCard'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,177 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑IC卡绑定微信日志表' : '添加IC卡绑定微信日志表'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="参数" name="param">
<a-input
allow-clear
placeholder="请输入参数"
v-model:value="form.param"
/>
</a-form-item>
<a-form-item label="修改参数" name="editData">
<a-input
allow-clear
placeholder="请输入修改参数"
v-model:value="form.editData"
/>
</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 { addThinkCardBindLog, updateThinkCardBindLog } from '@/api/think/thinkCardBindLog';
import { ThinkCardBindLog } from '@/api/think/thinkCardBindLog/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?: ThinkCardBindLog | 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<ThinkCardBindLog>({
id: undefined,
param: undefined,
editData: undefined,
createTime: undefined,
thinkCardBindLogId: undefined,
thinkCardBindLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardBindLogName: [
{
required: true,
type: 'string',
message: '请填写IC卡绑定微信日志表名称',
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 ? updateThinkCardBindLog : addThinkCardBindLog;
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>
+227
View File
@@ -0,0 +1,227 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCardBindLogId"
: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>
<!-- 编辑弹窗 -->
<ThinkCardBindLogEdit 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 ThinkCardBindLogEdit from './components/thinkCardBindLogEdit.vue';
import { pageThinkCardBindLog, removeThinkCardBindLog, removeBatchThinkCardBindLog } from '@/api/think/thinkCardBindLog';
import type { ThinkCardBindLog, ThinkCardBindLogParam } from '@/api/think/thinkCardBindLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardBindLog[]>([]);
// 当前编辑数据
const current = ref<ThinkCardBindLog | 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 pageThinkCardBindLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '参数',
dataIndex: 'param',
key: 'param',
align: 'center',
},
{
title: '修改参数',
dataIndex: 'editData',
key: 'editData',
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?: ThinkCardBindLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardBindLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardBindLog) => {
const hide = message.loading('请求中..', 0);
removeThinkCardBindLog(row.thinkCardBindLogId)
.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);
removeBatchThinkCardBindLog(selection.value.map((d) => d.thinkCardBindLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardBindLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCardBindLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,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="userId">
<a-input
allow-clear
placeholder="请输入操作用户"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="类型:1VIP卡,2IC卡" name="type">
<a-input
allow-clear
placeholder="请输入类型:1VIP卡,2IC卡"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="原数据" name="oldJson">
<a-input
allow-clear
placeholder="请输入原数据"
v-model:value="form.oldJson"
/>
</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 { addThinkCardDelLog, updateThinkCardDelLog } from '@/api/think/thinkCardDelLog';
import { ThinkCardDelLog } from '@/api/think/thinkCardDelLog/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?: ThinkCardDelLog | 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<ThinkCardDelLog>({
id: undefined,
userId: undefined,
type: undefined,
oldJson: undefined,
createTime: undefined,
thinkCardDelLogId: undefined,
thinkCardDelLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardDelLogName: [
{
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 ? updateThinkCardDelLog : addThinkCardDelLog;
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>
+233
View File
@@ -0,0 +1,233 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCardDelLogId"
: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>
<!-- 编辑弹窗 -->
<ThinkCardDelLogEdit 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 ThinkCardDelLogEdit from './components/thinkCardDelLogEdit.vue';
import { pageThinkCardDelLog, removeThinkCardDelLog, removeBatchThinkCardDelLog } from '@/api/think/thinkCardDelLog';
import type { ThinkCardDelLog, ThinkCardDelLogParam } from '@/api/think/thinkCardDelLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardDelLog[]>([]);
// 当前编辑数据
const current = ref<ThinkCardDelLog | 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 pageThinkCardDelLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '操作用户',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '类型:1VIP卡,2IC卡',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '原数据',
dataIndex: 'oldJson',
key: 'oldJson',
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?: ThinkCardDelLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardDelLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardDelLog) => {
const hide = message.loading('请求中..', 0);
removeThinkCardDelLog(row.thinkCardDelLogId)
.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);
removeBatchThinkCardDelLog(selection.value.map((d) => d.thinkCardDelLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardDelLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCardDelLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,193 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑IC卡编辑日志' : '添加IC卡编辑日志'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="操作类型:price=更新价格;card_type=卡种;count=变更次数;expire=有效期;" name="type">
<a-input
allow-clear
placeholder="请输入操作类型:price=更新价格;card_type=卡种;count=变更次数;expire=有效期;"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="旧值" name="oldJson">
<a-input
allow-clear
placeholder="请输入旧值"
v-model:value="form.oldJson"
/>
</a-form-item>
<a-form-item label="新值" name="newJson">
<a-input
allow-clear
placeholder="请输入新值"
v-model:value="form.newJson"
/>
</a-form-item>
<a-form-item label="操作员id" name="aid">
<a-input
allow-clear
placeholder="请输入操作员id"
v-model:value="form.aid"
/>
</a-form-item>
</a-form>
</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 { addThinkCardEditLog, updateThinkCardEditLog } from '@/api/think/thinkCardEditLog';
import { ThinkCardEditLog } from '@/api/think/thinkCardEditLog/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?: ThinkCardEditLog | 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<ThinkCardEditLog>({
id: undefined,
type: undefined,
oldJson: undefined,
newJson: undefined,
createTime: undefined,
aid: undefined,
thinkCardEditLogId: undefined,
thinkCardEditLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardEditLogName: [
{
required: true,
type: 'string',
message: '请填写IC卡编辑日志名称',
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 ? updateThinkCardEditLog : addThinkCardEditLog;
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>
+239
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="thinkCardEditLogId"
: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>
<!-- 编辑弹窗 -->
<ThinkCardEditLogEdit 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 ThinkCardEditLogEdit from './components/thinkCardEditLogEdit.vue';
import { pageThinkCardEditLog, removeThinkCardEditLog, removeBatchThinkCardEditLog } from '@/api/think/thinkCardEditLog';
import type { ThinkCardEditLog, ThinkCardEditLogParam } from '@/api/think/thinkCardEditLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardEditLog[]>([]);
// 当前编辑数据
const current = ref<ThinkCardEditLog | 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 pageThinkCardEditLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '操作类型:price=更新价格;card_type=卡种;count=变更次数;expire=有效期;',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '旧值',
dataIndex: 'oldJson',
key: 'oldJson',
align: 'center',
},
{
title: '新值',
dataIndex: 'newJson',
key: 'newJson',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作员id',
dataIndex: 'aid',
key: 'aid',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCardEditLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardEditLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardEditLog) => {
const hide = message.loading('请求中..', 0);
removeThinkCardEditLog(row.thinkCardEditLogId)
.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);
removeBatchThinkCardEditLog(selection.value.map((d) => d.thinkCardEditLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardEditLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCardEditLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,183 @@
<!-- 搜索表单 -->
<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-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入关键词"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
style="width: 380px"
/>
<a-button @click="reset">重置</a-button>
<a-button class="ele-btn-icon" :disabled="loading" @click="handleExport">
<template #icon>
<download-outlined />
</template>
<span>导出充值记录</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import { watch, ref } from 'vue';
import useSearch from '@/utils/use-search';
import dayjs from 'dayjs';
import { toDateString } from 'ele-admin-pro';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
import {
ThinkCardLog,
ThinkCardLogParam
} from '@/api/think/thinkCardLog/model';
import { listThinkCardLog } from '@/api/think/thinkCardLog';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: ThinkCardLogParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<ThinkCardLog[] | any[]>();
const xlsFileName = ref<string>();
const payType = ref<string[]>([
'',
'微信支付',
'支付宝支付',
'现金支付',
'POS机支付'
]);
// 表单数据
const { where, resetFields } = useSearch<ThinkCardLogParam>({
code: undefined,
timeStart: undefined,
timeEnd: undefined,
keywords: undefined
});
// 新增
const add = () => {
emit('add');
};
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.timeStart = d1 ? dayjs(d1).valueOf() / 1000 : undefined;
where.timeEnd = d2 ? dayjs(d2).valueOf() / 1000 : undefined;
emit('search', {
...where
});
};
/* 重置 */
const reset = () => {
resetFields();
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'卡号',
'姓名',
'手机号',
'会员卡名称',
'支付方式',
'充值金额',
'充值次数',
'操作员',
'第三方订单号',
'充值时间'
]
];
if (!where.timeStart) {
message.error('请选择导出的开始日期、结束日期,每次最多导出5000条记录');
return false;
}
await listThinkCardLog(where)
.then((list) => {
orders.value = list;
orders.value?.forEach((d: ThinkCardLog) => {
array.push([
`${d.code}`,
`${d.username}`,
`${d.phone}`,
`${d.cardName}`,
`${payType.value[Number(d.payType)]}`,
`${d.money}`,
`${d.count}`,
`${d.adminName || d.aid}`,
`${d.wechatOrder}`,
`${toDateString(d.createTime)}`
]);
});
const sheetName = `充值记录导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 20 },
{ wch: 40 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {});
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,273 @@
<!-- 编辑弹窗 -->
<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="code">
<a-input
allow-clear
placeholder="请输入卡号"
:disabled="true"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="姓名" name="username">
<a-input
allow-clear
placeholder="请姓名"
:disabled="true"
v-model:value="form.username"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="phone"
:disabled="true"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="可使用场馆" name="sid">
<a-input
allow-clear
placeholder="siteName"
:disabled="true"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="支付方式" name="payType">
<a-tag v-if="form.payType === 1">微信支付</a-tag>
<a-tag v-if="form.payType === 2">支付宝支付</a-tag>
<a-tag v-if="form.payType === 3">现金支付</a-tag>
<a-tag v-if="form.payType === 4">POS机支付</a-tag>
</a-form-item>
<a-form-item label="总次数" name="count">
<a-input
allow-clear
placeholder="总次数"
:disabled="true"
v-model:value="form.count"
/>
</a-form-item>
<a-form-item label="剩余次数" name="num">
<a-input
allow-clear
placeholder="剩余次数"
:disabled="true"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="余额" name="remainingMoney">
<a-input
allow-clear
placeholder="余额"
:disabled="true"
v-model:value="form.remainingMoney"
/>
</a-form-item>
<a-form-item label="IC卡类型" name="type">
<a-radio-group
v-model:value="form.type"
button-style="solid"
:disabled="true"
>
<a-radio-button :value="1">年卡</a-radio-button>
<a-radio-button :value="2">次卡</a-radio-button>
<a-radio-button :value="3">月卡</a-radio-button>
<a-radio-button :value="4">会员IC卡</a-radio-button>
<a-radio-button :value="5">充值卡</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="到期时间" name="expireTime">
{{ toDateString(form.expireTime, 'yyyy-MM-dd HH:mm:ss') }}
<!-- <a-date-picker-->
<!-- v-model:value="form.expireTime"-->
<!-- show-time-->
<!-- placeholder="Select Time"-->
<!-- format=""-->
<!-- value-format="YYYY-MM-DD HH:mm:ss"-->
<!-- class="ele-fluid"-->
<!-- />-->
</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="count">
<a-input allow-clear placeholder="请输入" v-model:value="form.count" />
</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 {
addThinkCardLog,
updateThinkCardLog
} from '@/api/think/thinkCardLog';
import { isExternalLink, random, toDateString } from 'ele-admin-pro';
import { ThinkCardLog } from '@/api/think/thinkCardLog/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?: ThinkCardLog | 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<ThinkCardLog>({
id: undefined,
code: undefined,
payType: undefined,
sid: undefined,
money: undefined,
num: undefined,
phone: undefined,
aid: undefined,
type: undefined,
cardType: undefined,
remainingMoney: undefined,
wechatOrder: undefined,
expireTime: undefined,
createTime: undefined,
count: undefined,
username: ''
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardLogName: [
{
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
? updateThinkCardLog
: addThinkCardLog;
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>
+288
View File
@@ -0,0 +1,288 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
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 === 'payType'">
<a-tag v-if="record.payType === 1">微信支付</a-tag>
<a-tag v-if="record.payType === 2">支付宝支付</a-tag>
<a-tag v-if="record.payType === 3">现金支付</a-tag>
<a-tag v-if="record.payType === 4">POS支付</a-tag>
</template>
<template v-if="column.key === 'money'">
¥{{ formatNumber(record.money) }}
</template>
<template v-if="column.key === 'aid'">
<span v-if="record.adminName">{{ record.adminName }}</span>
<span v-else>{{ record.aid }}</span>
</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>
<!-- 编辑弹窗 -->
<ThinkCardLogEdit
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 { formatNumber } from 'ele-admin-pro/es';
import ThinkCardLogEdit from './components/thinkCardLogEdit.vue';
import {
pageThinkCardLog,
removeThinkCardLog,
removeBatchThinkCardLog
} from '@/api/think/thinkCardLog';
import type {
ThinkCardLog,
ThinkCardLogParam
} from '@/api/think/thinkCardLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardLog[]>([]);
// 当前编辑数据
const current = ref<ThinkCardLog | 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 pageThinkCardLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '卡号',
dataIndex: 'code',
key: 'code',
align: 'center'
},
{
title: '会员卡',
dataIndex: 'cardName',
key: 'cardName',
align: 'center'
},
{
title: '手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center'
},
{
title: '姓名',
dataIndex: 'username',
key: 'username',
align: 'center'
},
{
title: '支付方式',
dataIndex: 'payType',
key: 'payType',
align: 'center'
},
{
title: '充值金额',
dataIndex: 'money',
key: 'money',
sorter: true,
align: 'center'
},
{
title: '操作员/ID',
dataIndex: 'aid',
key: 'aid',
sorter: true,
align: 'center'
},
{
title: '第三方订单号',
dataIndex: 'wechatOrder',
key: 'wechatOrder',
align: 'center'
},
{
title: '充值次数',
dataIndex: 'count',
key: 'count',
align: 'center'
},
{
title: '充值时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCardLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardLog) => {
const hide = message.loading('请求中..', 0);
removeThinkCardLog(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkCardLog(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCardLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,209 @@
<!-- 编辑弹窗 -->
<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次卡,3月卡,4会员VIP,VIP充值卡" name="type">
<a-input
allow-clear
placeholder="请输入会员卡类型:1年卡,2次卡,3月卡,4会员VIP,VIP充值卡"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="卡类型:1成人卡,2儿童卡" name="cardType">
<a-input
allow-clear
placeholder="请输入卡类型:1成人卡,2儿童卡"
v-model:value="form.cardType"
/>
</a-form-item>
<a-form-item label="vip卡等级类型:1特殊vip卡,2普通vip卡" name="vipType">
<a-input
allow-clear
placeholder="请输入vip卡等级类型:1特殊vip卡,2普通vip卡"
v-model:value="form.vipType"
/>
</a-form-item>
<a-form-item label="统计金额(正是收入,负是冲抵(退卡后产生))" name="price">
<a-input
allow-clear
placeholder="请输入统计金额(正是收入,负是冲抵(退卡后产生))"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="虚拟卡ID" name="usersVipId">
<a-input
allow-clear
placeholder="请输入虚拟卡ID"
v-model:value="form.usersVipId"
/>
</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>
</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 { addThinkCardUserLog, updateThinkCardUserLog } from '@/api/think/thinkCardUserLog';
import { ThinkCardUserLog } from '@/api/think/thinkCardUserLog/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?: ThinkCardUserLog | 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<ThinkCardUserLog>({
id: undefined,
type: undefined,
cardType: undefined,
vipType: undefined,
price: undefined,
createTime: undefined,
usersVipId: undefined,
cardId: undefined,
thinkCardUserLogId: undefined,
thinkCardUserLogName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCardUserLogName: [
{
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 ? updateThinkCardUserLog : addThinkCardUserLog;
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>
+251
View File
@@ -0,0 +1,251 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCardUserLogId"
: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>
<!-- 编辑弹窗 -->
<ThinkCardUserLogEdit 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 ThinkCardUserLogEdit from './components/thinkCardUserLogEdit.vue';
import { pageThinkCardUserLog, removeThinkCardUserLog, removeBatchThinkCardUserLog } from '@/api/think/thinkCardUserLog';
import type { ThinkCardUserLog, ThinkCardUserLogParam } from '@/api/think/thinkCardUserLog/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCardUserLog[]>([]);
// 当前编辑数据
const current = ref<ThinkCardUserLog | 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 pageThinkCardUserLog({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '会员卡类型:1年卡,2次卡,3月卡,4会员VIP,VIP充值卡',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '卡类型:1成人卡,2儿童卡',
dataIndex: 'cardType',
key: 'cardType',
align: 'center',
},
{
title: 'vip卡等级类型:1特殊vip卡,2普通vip卡',
dataIndex: 'vipType',
key: 'vipType',
align: 'center',
},
{
title: '统计金额(正是收入,负是冲抵(退卡后产生))',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '虚拟卡ID',
dataIndex: 'usersVipId',
key: 'usersVipId',
align: 'center',
},
{
title: '实体卡id',
dataIndex: 'cardId',
key: 'cardId',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCardUserLogParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCardUserLog) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCardUserLog) => {
const hide = message.loading('请求中..', 0);
removeThinkCardUserLog(row.thinkCardUserLogId)
.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);
removeBatchThinkCardUserLog(selection.value.map((d) => d.thinkCardUserLogId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCardUserLog) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCardUserLog'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,224 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑' : '添加'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="轮播图标题" name="title">
<a-input
allow-clear
placeholder="请输入轮播图标题"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="轮播图" name="img">
<a-input
allow-clear
placeholder="请输入轮播图"
v-model:value="form.img"
/>
</a-form-item>
<a-form-item label="轮播图链接" name="link">
<a-input
allow-clear
placeholder="请输入轮播图链接"
v-model:value="form.link"
/>
</a-form-item>
<a-form-item label="小程序APPID" name="appid">
<a-input
allow-clear
placeholder="请输入小程序APPID"
v-model:value="form.appid"
/>
</a-form-item>
<a-form-item label="排序" name="sort">
<a-input
allow-clear
placeholder="请输入排序"
v-model:value="form.sort"
/>
</a-form-item>
<a-form-item label="1显示,2不显示" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="类型:1资讯,2商城,3小程序" name="type">
<a-input
allow-clear
placeholder="请输入类型:1资讯,2商城,3小程序"
v-model:value="form.type"
/>
</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 { addThinkCarousel, updateThinkCarousel } from '@/api/think/thinkCarousel';
import { ThinkCarousel } from '@/api/think/thinkCarousel/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?: ThinkCarousel | 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<ThinkCarousel>({
id: undefined,
title: undefined,
img: undefined,
link: undefined,
appid: undefined,
sort: undefined,
status: undefined,
type: undefined,
createTime: undefined,
updateTime: undefined,
thinkCarouselId: undefined,
thinkCarouselName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCarouselName: [
{
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 ? updateThinkCarousel : addThinkCarousel;
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>
+263
View File
@@ -0,0 +1,263 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCarouselId"
: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>
<!-- 编辑弹窗 -->
<ThinkCarouselEdit 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 ThinkCarouselEdit from './components/thinkCarouselEdit.vue';
import { pageThinkCarousel, removeThinkCarousel, removeBatchThinkCarousel } from '@/api/think/thinkCarousel';
import type { ThinkCarousel, ThinkCarouselParam } from '@/api/think/thinkCarousel/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCarousel[]>([]);
// 当前编辑数据
const current = ref<ThinkCarousel | 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 pageThinkCarousel({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '轮播图标题',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '轮播图',
dataIndex: 'img',
key: 'img',
align: 'center',
},
{
title: '轮播图链接',
dataIndex: 'link',
key: 'link',
align: 'center',
},
{
title: '小程序APPID',
dataIndex: 'appid',
key: 'appid',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '1显示,2不显示',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '类型:1资讯,2商城,3小程序',
dataIndex: 'type',
key: 'type',
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?: ThinkCarouselParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCarousel) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCarousel) => {
const hide = message.loading('请求中..', 0);
removeThinkCarousel(row.thinkCarouselId)
.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);
removeBatchThinkCarousel(selection.value.map((d) => d.thinkCarouselId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCarousel) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCarousel'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,241 @@
<!-- 编辑弹窗 -->
<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="教练姓名" name="name">
<a-input
allow-clear
placeholder="请输入教练姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="所在场馆" name="sid">
<a-input
allow-clear
placeholder="请输入所在场馆"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="教练简介" name="intro">
<a-input
allow-clear
placeholder="请输入教练简介"
v-model:value="form.intro"
/>
</a-form-item>
<a-form-item label="教练介绍" name="info">
<a-input
allow-clear
placeholder="请输入教练介绍"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="价格" name="price">
<a-input
allow-clear
placeholder="请输入价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="教练图片" name="cimage">
<a-input
allow-clear
placeholder="请输入教练图片"
v-model:value="form.cimage"
/>
</a-form-item>
<a-form-item label="等级" name="level">
<a-input
allow-clear
placeholder="请输入等级"
v-model:value="form.level"
/>
</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="coachMoney">
<a-input
allow-clear
placeholder="请输入教练余额"
v-model:value="form.coachMoney"
/>
</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 { addThinkCoach, updateThinkCoach } from '@/api/think/thinkCoach';
import { ThinkCoach } from '@/api/think/thinkCoach/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?: ThinkCoach | 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<ThinkCoach>({
id: undefined,
uid: undefined,
name: undefined,
sid: undefined,
intro: undefined,
info: undefined,
price: undefined,
cimage: undefined,
level: undefined,
createTime: undefined,
timePeriod: undefined,
coachMoney: undefined,
thinkCoachId: undefined,
thinkCoachName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachName: [
{
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 ? updateThinkCoach : addThinkCoach;
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>
+275
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="thinkCoachId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachEdit 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 ThinkCoachEdit from './components/thinkCoachEdit.vue';
import { pageThinkCoach, removeThinkCoach, removeBatchThinkCoach } from '@/api/think/thinkCoach';
import type { ThinkCoach, ThinkCoachParam } from '@/api/think/thinkCoach/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoach[]>([]);
// 当前编辑数据
const current = ref<ThinkCoach | 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 pageThinkCoach({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '用户表ID',
dataIndex: 'uid',
key: 'uid',
align: 'center',
},
{
title: '教练姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '所在场馆',
dataIndex: 'sid',
key: 'sid',
align: 'center',
},
{
title: '教练简介',
dataIndex: 'intro',
key: 'intro',
align: 'center',
},
{
title: '教练介绍',
dataIndex: 'info',
key: 'info',
align: 'center',
},
{
title: '价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '教练图片',
dataIndex: 'cimage',
key: 'cimage',
align: 'center',
},
{
title: '等级',
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: 'timePeriod',
key: 'timePeriod',
align: 'center',
},
{
title: '教练余额',
dataIndex: 'coachMoney',
key: 'coachMoney',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoach) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoach) => {
const hide = message.loading('请求中..', 0);
removeThinkCoach(row.thinkCoachId)
.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);
removeBatchThinkCoach(selection.value.map((d) => d.thinkCoachId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoach) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoach'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,223 @@
<!-- 编辑弹窗 -->
<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="cid">
<a-input
allow-clear
placeholder="请输入教练ID"
v-model:value="form.cid"
/>
</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="提现金额" name="price">
<a-input
allow-clear
placeholder="请输入提现金额"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="提现所剩金额" name="coachMoney">
<a-input
allow-clear
placeholder="请输入提现所剩金额"
v-model:value="form.coachMoney"
/>
</a-form-item>
<a-form-item label="当前金额" name="nowMoney">
<a-input
allow-clear
placeholder="请输入当前金额"
v-model:value="form.nowMoney"
/>
</a-form-item>
<a-form-item label="添加时间" name="addtime">
<a-input
allow-clear
placeholder="请输入添加时间"
v-model:value="form.addtime"
/>
</a-form-item>
<a-form-item label="状态(0待审核,1审核通过,2审核不通过)" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="审核时间" name="staTime">
<a-input
allow-clear
placeholder="请输入审核时间"
v-model:value="form.staTime"
/>
</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 { addThinkCoachCash, updateThinkCoachCash } from '@/api/think/thinkCoachCash';
import { ThinkCoachCash } from '@/api/think/thinkCoachCash/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?: ThinkCoachCash | 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<ThinkCoachCash>({
id: undefined,
cid: undefined,
cardId: undefined,
price: undefined,
coachMoney: undefined,
nowMoney: undefined,
addtime: undefined,
status: undefined,
staTime: undefined,
thinkCoachCashId: undefined,
thinkCoachCashName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachCashName: [
{
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 ? updateThinkCoachCash : addThinkCoachCash;
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>
+254
View File
@@ -0,0 +1,254 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCoachCashId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachCashEdit 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 ThinkCoachCashEdit from './components/thinkCoachCashEdit.vue';
import { pageThinkCoachCash, removeThinkCoachCash, removeBatchThinkCoachCash } from '@/api/think/thinkCoachCash';
import type { ThinkCoachCash, ThinkCoachCashParam } from '@/api/think/thinkCoachCash/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoachCash[]>([]);
// 当前编辑数据
const current = ref<ThinkCoachCash | 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 pageThinkCoachCash({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '教练ID',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '银行卡信息ID',
dataIndex: 'cardId',
key: 'cardId',
align: 'center',
},
{
title: '提现金额',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '提现所剩金额',
dataIndex: 'coachMoney',
key: 'coachMoney',
align: 'center',
},
{
title: '当前金额',
dataIndex: 'nowMoney',
key: 'nowMoney',
align: 'center',
},
{
title: '添加时间',
dataIndex: 'addtime',
key: 'addtime',
align: 'center',
},
{
title: '状态(0待审核,1审核通过,2审核不通过)',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '审核时间',
dataIndex: 'staTime',
key: 'staTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachCashParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoachCash) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoachCash) => {
const hide = message.loading('请求中..', 0);
removeThinkCoachCash(row.thinkCoachCashId)
.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);
removeBatchThinkCoachCash(selection.value.map((d) => d.thinkCoachCashId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoachCash) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoachCash'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,207 @@
<!-- 编辑弹窗 -->
<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="cid">
<a-input
allow-clear
placeholder="请输入教练ID"
v-model:value="form.cid"
/>
</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="remake">
<a-input
allow-clear
placeholder="请输入教学备注"
v-model:value="form.remake"
/>
</a-form-item>
<a-form-item label="教学内容" name="info">
<a-input
allow-clear
placeholder="请输入教学内容"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="价格" name="price">
<a-input
allow-clear
placeholder="请输入价格"
v-model:value="form.price"
/>
</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 { addThinkCoachCur, updateThinkCoachCur } from '@/api/think/thinkCoachCur';
import { ThinkCoachCur } from '@/api/think/thinkCoachCur/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?: ThinkCoachCur | 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<ThinkCoachCur>({
id: undefined,
cid: undefined,
name: undefined,
remake: undefined,
info: undefined,
price: undefined,
status: undefined,
thinkCoachCurId: undefined,
thinkCoachCurName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachCurName: [
{
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 ? updateThinkCoachCur : addThinkCoachCur;
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>
+242
View File
@@ -0,0 +1,242 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCoachCurId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachCurEdit 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 ThinkCoachCurEdit from './components/thinkCoachCurEdit.vue';
import { pageThinkCoachCur, removeThinkCoachCur, removeBatchThinkCoachCur } from '@/api/think/thinkCoachCur';
import type { ThinkCoachCur, ThinkCoachCurParam } from '@/api/think/thinkCoachCur/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoachCur[]>([]);
// 当前编辑数据
const current = ref<ThinkCoachCur | 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 pageThinkCoachCur({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '教练ID',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '课程名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '教学备注',
dataIndex: 'remake',
key: 'remake',
align: 'center',
},
{
title: '教学内容',
dataIndex: 'info',
key: 'info',
align: 'center',
},
{
title: '价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '类型(0课程,1小时)',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachCurParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoachCur) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoachCur) => {
const hide = message.loading('请求中..', 0);
removeThinkCoachCur(row.thinkCoachCurId)
.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);
removeBatchThinkCoachCur(selection.value.map((d) => d.thinkCoachCurId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoachCur) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoachCur'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,176 @@
<!-- 编辑弹窗 -->
<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="path">
<a-input
allow-clear
placeholder="请输入图片地址"
v-model:value="form.path"
/>
</a-form-item>
<a-form-item label="关联id" name="cid">
<a-input
allow-clear
placeholder="请输入关联id"
v-model:value="form.cid"
/>
</a-form-item>
</a-form>
</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 { addThinkCoachImgs, updateThinkCoachImgs } from '@/api/think/thinkCoachImgs';
import { ThinkCoachImgs } from '@/api/think/thinkCoachImgs/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?: ThinkCoachImgs | 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<ThinkCoachImgs>({
id: undefined,
path: undefined,
cid: undefined,
thinkCoachImgsId: undefined,
thinkCoachImgsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachImgsName: [
{
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 ? updateThinkCoachImgs : addThinkCoachImgs;
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>
+218
View File
@@ -0,0 +1,218 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCoachImgsId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachImgsEdit 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 ThinkCoachImgsEdit from './components/thinkCoachImgsEdit.vue';
import { pageThinkCoachImgs, removeThinkCoachImgs, removeBatchThinkCoachImgs } from '@/api/think/thinkCoachImgs';
import type { ThinkCoachImgs, ThinkCoachImgsParam } from '@/api/think/thinkCoachImgs/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoachImgs[]>([]);
// 当前编辑数据
const current = ref<ThinkCoachImgs | 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 pageThinkCoachImgs({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '图片地址',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '关联id',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachImgsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoachImgs) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoachImgs) => {
const hide = message.loading('请求中..', 0);
removeThinkCoachImgs(row.thinkCoachImgsId)
.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);
removeBatchThinkCoachImgs(selection.value.map((d) => d.thinkCoachImgsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoachImgs) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoachImgs'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,224 @@
<!-- 编辑弹窗 -->
<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="sid">
<a-input
allow-clear
placeholder="请输入场馆ID"
v-model:value="form.sid"
/>
</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="cid">
<a-input
allow-clear
placeholder="请输入教练ID"
v-model:value="form.cid"
/>
</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="orderTime">
<a-input
allow-clear
placeholder="请输入预约时间"
v-model:value="form.orderTime"
/>
</a-form-item>
<a-form-item label="预约人姓名" name="name">
<a-input
allow-clear
placeholder="请输入预约人姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="预约人手机号" name="phone">
<a-input
allow-clear
placeholder="请输入预约人手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="添加时间" name="addtime">
<a-input
allow-clear
placeholder="请输入添加时间"
v-model:value="form.addtime"
/>
</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 { addThinkCoachOrder, updateThinkCoachOrder } from '@/api/think/thinkCoachOrder';
import { ThinkCoachOrder } from '@/api/think/thinkCoachOrder/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?: ThinkCoachOrder | 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<ThinkCoachOrder>({
id: undefined,
sid: undefined,
oid: undefined,
cid: undefined,
price: undefined,
orderTime: undefined,
name: undefined,
phone: undefined,
addtime: undefined,
thinkCoachOrderId: undefined,
thinkCoachOrderName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachOrderName: [
{
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 ? updateThinkCoachOrder : addThinkCoachOrder;
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>
+254
View File
@@ -0,0 +1,254 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCoachOrderId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachOrderEdit 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 ThinkCoachOrderEdit from './components/thinkCoachOrderEdit.vue';
import { pageThinkCoachOrder, removeThinkCoachOrder, removeBatchThinkCoachOrder } from '@/api/think/thinkCoachOrder';
import type { ThinkCoachOrder, ThinkCoachOrderParam } from '@/api/think/thinkCoachOrder/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoachOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkCoachOrder | 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 pageThinkCoachOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '场馆ID',
dataIndex: 'sid',
key: 'sid',
align: 'center',
},
{
title: '订单详情ID',
dataIndex: 'oid',
key: 'oid',
align: 'center',
},
{
title: '教练ID',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '教练价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '预约时间',
dataIndex: 'orderTime',
key: 'orderTime',
align: 'center',
},
{
title: '预约人姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '预约人手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '添加时间',
dataIndex: 'addtime',
key: 'addtime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoachOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoachOrder) => {
const hide = message.loading('请求中..', 0);
removeThinkCoachOrder(row.thinkCoachOrderId)
.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);
removeBatchThinkCoachOrder(selection.value.map((d) => d.thinkCoachOrderId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoachOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoachOrder'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,176 @@
<!-- 编辑弹窗 -->
<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="cid">
<a-input
allow-clear
placeholder="请输入教练ID"
v-model:value="form.cid"
/>
</a-form-item>
<a-form-item label="预约时间JSON格式" name="json">
<a-input
allow-clear
placeholder="请输入预约时间JSON格式"
v-model:value="form.json"
/>
</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 { addThinkCoachTime, updateThinkCoachTime } from '@/api/think/thinkCoachTime';
import { ThinkCoachTime } from '@/api/think/thinkCoachTime/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?: ThinkCoachTime | 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<ThinkCoachTime>({
id: undefined,
cid: undefined,
json: undefined,
thinkCoachTimeId: undefined,
thinkCoachTimeName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCoachTimeName: [
{
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 ? updateThinkCoachTime : addThinkCoachTime;
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>
+218
View File
@@ -0,0 +1,218 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkCoachTimeId"
: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>
<!-- 编辑弹窗 -->
<ThinkCoachTimeEdit 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 ThinkCoachTimeEdit from './components/thinkCoachTimeEdit.vue';
import { pageThinkCoachTime, removeThinkCoachTime, removeBatchThinkCoachTime } from '@/api/think/thinkCoachTime';
import type { ThinkCoachTime, ThinkCoachTimeParam } from '@/api/think/thinkCoachTime/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoachTime[]>([]);
// 当前编辑数据
const current = ref<ThinkCoachTime | 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 pageThinkCoachTime({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '教练ID',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '预约时间JSON格式',
dataIndex: 'json',
key: 'json',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCoachTimeParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoachTime) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoachTime) => {
const hide = message.loading('请求中..', 0);
removeThinkCoachTime(row.thinkCoachTimeId)
.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);
removeBatchThinkCoachTime(selection.value.map((d) => d.thinkCoachTimeId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoachTime) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoachTime'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,176 @@
<!-- 编辑弹窗 -->
<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="value">
<a-input
allow-clear
placeholder="请输入配置值"
v-model:value="form.value"
/>
</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 { addThinkConfig, updateThinkConfig } from '@/api/think/thinkConfig';
import { ThinkConfig } from '@/api/think/thinkConfig/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?: ThinkConfig | 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<ThinkConfig>({
id: undefined,
name: undefined,
value: undefined,
thinkConfigId: undefined,
thinkConfigName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkConfigName: [
{
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 ? updateThinkConfig : addThinkConfig;
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>
+218
View File
@@ -0,0 +1,218 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkConfigId"
: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>
<!-- 编辑弹窗 -->
<ThinkConfigEdit 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 ThinkConfigEdit from './components/thinkConfigEdit.vue';
import { pageThinkConfig, removeThinkConfig, removeBatchThinkConfig } from '@/api/think/thinkConfig';
import type { ThinkConfig, ThinkConfigParam } from '@/api/think/thinkConfig/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkConfig[]>([]);
// 当前编辑数据
const current = ref<ThinkConfig | 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 pageThinkConfig({
...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: 'value',
key: 'value',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkConfigParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkConfig) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkConfig) => {
const hide = message.loading('请求中..', 0);
removeThinkConfig(row.thinkConfigId)
.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);
removeBatchThinkConfig(selection.value.map((d) => d.thinkConfigId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkConfig) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkConfig'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,288 @@
<!-- 编辑弹窗 -->
<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="discount">
<a-input
allow-clear
placeholder="请输入折扣率"
v-model:value="form.discount"
/>
</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="price">
<a-input
allow-clear
placeholder="请输入购买价格"
v-model:value="form.price"
/>
</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="number">
<a-input
allow-clear
placeholder="请输入优惠券剩余数量"
v-model:value="form.number"
/>
</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="sid场馆id集合,适用的场馆" name="sid">
<a-input
allow-clear
placeholder="请输入sid场馆id集合,适用的场馆"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="排序" name="sort">
<a-input
allow-clear
placeholder="请输入排序"
v-model:value="form.sort"
/>
</a-form-item>
<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="券类型:1成人,2儿童" name="couponType">
<a-input
allow-clear
placeholder="请输入券类型:1成人,2儿童"
v-model:value="form.couponType"
/>
</a-form-item>
<a-form-item label="是否免费领取:1免费,2收费" name="isFree">
<a-input
allow-clear
placeholder="请输入是否免费领取:1免费,2收费"
v-model:value="form.isFree"
/>
</a-form-item>
<a-form-item label="状态,1可领取、2不可领取" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="0 是通用,1是仅线下" name="isOffline">
<a-input
allow-clear
placeholder="请输入0 是通用,1是仅线下"
v-model:value="form.isOffline"
/>
</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 { addThinkCoupon, updateThinkCoupon } from '@/api/think/thinkCoupon';
import { ThinkCoupon } from '@/api/think/thinkCoupon/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?: ThinkCoupon | 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<ThinkCoupon>({
id: undefined,
name: undefined,
discount: undefined,
money: undefined,
price: undefined,
count: undefined,
number: undefined,
startTime: undefined,
endTime: undefined,
sid: undefined,
sort: undefined,
type: undefined,
couponType: undefined,
isFree: undefined,
status: undefined,
createTime: undefined,
updateTime: undefined,
isOffline: undefined,
thinkCouponId: undefined,
thinkCouponName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkCouponName: [
{
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 ? updateThinkCoupon : addThinkCoupon;
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>
+311
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="thinkCouponId"
: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>
<!-- 编辑弹窗 -->
<ThinkCouponEdit 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 ThinkCouponEdit from './components/thinkCouponEdit.vue';
import { pageThinkCoupon, removeThinkCoupon, removeBatchThinkCoupon } from '@/api/think/thinkCoupon';
import type { ThinkCoupon, ThinkCouponParam } from '@/api/think/thinkCoupon/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkCoupon[]>([]);
// 当前编辑数据
const current = ref<ThinkCoupon | 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 pageThinkCoupon({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '优惠券名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '折扣率',
dataIndex: 'discount',
key: 'discount',
align: 'center',
},
{
title: '抵扣金额',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '购买价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '可使用次数',
dataIndex: 'count',
key: 'count',
align: 'center',
},
{
title: '优惠券剩余数量',
dataIndex: 'number',
key: 'number',
align: 'center',
},
{
title: '开始时间',
dataIndex: 'startTime',
key: 'startTime',
align: 'center',
},
{
title: '结束时间',
dataIndex: 'endTime',
key: 'endTime',
align: 'center',
},
{
title: 'sid场馆id集合,适用的场馆',
dataIndex: 'sid',
key: 'sid',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '优惠券类型:1折扣式,2抵扣式',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '券类型:1成人,2儿童',
dataIndex: 'couponType',
key: 'couponType',
align: 'center',
},
{
title: '是否免费领取:1免费,2收费',
dataIndex: 'isFree',
key: 'isFree',
align: 'center',
},
{
title: '状态,1可领取、2不可领取',
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: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '0 是通用,1是仅线下',
dataIndex: 'isOffline',
key: 'isOffline',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkCouponParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkCoupon) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkCoupon) => {
const hide = message.loading('请求中..', 0);
removeThinkCoupon(row.thinkCouponId)
.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);
removeBatchThinkCoupon(selection.value.map((d) => d.thinkCouponId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkCoupon) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkCoupon'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,240 @@
<!-- 编辑弹窗 -->
<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="1微信支付,2支付宝支付,3现金支付,4POS机支付" name="moneyType">
<a-input
allow-clear
placeholder="请输入1微信支付,2支付宝支付,3现金支付,4POS机支付"
v-model:value="form.moneyType"
/>
</a-form-item>
<a-form-item label="场馆名称" name="siteName">
<a-input
allow-clear
placeholder="请输入场馆名称"
v-model:value="form.siteName"
/>
</a-form-item>
<a-form-item label="姓名" name="name">
<a-input
allow-clear
placeholder="请输入姓名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="手机号码" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="押金" name="money">
<a-input
allow-clear
placeholder="请输入押金"
v-model:value="form.money"
/>
</a-form-item>
<a-form-item label="1已付,2已退" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="" name="info">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="管理员id" name="aid">
<a-input
allow-clear
placeholder="请输入管理员id"
v-model:value="form.aid"
/>
</a-form-item>
<a-form-item label="" 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 { addThinkDeposit, updateThinkDeposit } from '@/api/think/thinkDeposit';
import { ThinkDeposit } from '@/api/think/thinkDeposit/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?: ThinkDeposit | 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<ThinkDeposit>({
id: undefined,
type: undefined,
moneyType: undefined,
siteName: undefined,
name: undefined,
phone: undefined,
money: undefined,
status: undefined,
info: undefined,
aid: undefined,
createTime: undefined,
updateTime: undefined,
thinkDepositId: undefined,
thinkDepositName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkDepositName: [
{
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 ? updateThinkDeposit : addThinkDeposit;
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>
+275
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="thinkDepositId"
: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>
<!-- 编辑弹窗 -->
<ThinkDepositEdit 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 ThinkDepositEdit from './components/thinkDepositEdit.vue';
import { pageThinkDeposit, removeThinkDeposit, removeBatchThinkDeposit } from '@/api/think/thinkDeposit';
import type { ThinkDeposit, ThinkDepositParam } from '@/api/think/thinkDeposit/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkDeposit[]>([]);
// 当前编辑数据
const current = ref<ThinkDeposit | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageThinkDeposit({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '1收押金、2退押金',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '1微信支付,2支付宝支付,3现金支付,4POS机支付',
dataIndex: 'moneyType',
key: 'moneyType',
align: 'center',
},
{
title: '场馆名称',
dataIndex: 'siteName',
key: 'siteName',
align: 'center',
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '押金',
dataIndex: 'money',
key: 'money',
align: 'center',
},
{
title: '1已付,2已退',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '',
dataIndex: 'info',
key: 'info',
align: 'center',
},
{
title: '管理员id',
dataIndex: 'aid',
key: 'aid',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkDepositParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkDeposit) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkDeposit) => {
const hide = message.loading('请求中..', 0);
removeThinkDeposit(row.thinkDepositId)
.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);
removeBatchThinkDeposit(selection.value.map((d) => d.thinkDepositId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkDeposit) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkDeposit'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,246 @@
<!-- 编辑弹窗 -->
<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="是否有卫生间,1有,2没有" name="isToilet">
<a-input
allow-clear
placeholder="请输入是否有卫生间,1有,2没有"
v-model:value="form.isToilet"
/>
</a-form-item>
<a-form-item label="是否关闭,1开启,2关闭" name="isStatus">
<a-input
allow-clear
placeholder="请输入是否关闭,1开启,2关闭"
v-model:value="form.isStatus"
/>
</a-form-item>
<a-form-item label="是否重复预订,1可以,2不可以" name="isRepeat">
<a-input
allow-clear
placeholder="请输入是否重复预订,1可以,2不可以"
v-model:value="form.isRepeat"
/>
</a-form-item>
<a-form-item label="是否可预定半场,1可以,2不可以" name="isHalf">
<a-input
allow-clear
placeholder="请输入是否可预定半场,1可以,2不可以"
v-model:value="form.isHalf"
/>
</a-form-item>
<a-form-item label="是否支持儿童价:1支持,2不支持" name="isChildren">
<a-input
allow-clear
placeholder="请输入是否支持儿童价:1支持,2不支持"
v-model:value="form.isChildren"
/>
</a-form-item>
<a-form-item label="可重复预订次数" name="num">
<a-input
allow-clear
placeholder="请输入可重复预订次数"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="排序" name="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="sid">
<a-input
allow-clear
placeholder="请输入关联id"
v-model:value="form.sid"
/>
</a-form-item>
<a-form-item label="显示在第几行" name="row">
<a-input
allow-clear
placeholder="请输入显示在第几行"
v-model:value="form.row"
/>
</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 { addThinkField, updateThinkField } from '@/api/think/thinkField';
import { ThinkField } from '@/api/think/thinkField/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?: ThinkField | 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<ThinkField>({
id: undefined,
name: undefined,
isToilet: undefined,
isStatus: undefined,
isRepeat: undefined,
isHalf: undefined,
isChildren: undefined,
num: undefined,
sort: undefined,
sid: undefined,
row: undefined,
createTime: undefined,
updateTime: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkField : addThinkField;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if (props.data.image) {
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
});
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,289 @@
<!-- 分类编辑弹窗 -->
<template>
<ele-modal
:width="620"
:visible="visible"
:confirm-loading="loading"
:title="isUpdate ? '修改分类' : '添加分类'"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 7, sm: 4, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 18, sm: 20, xs: 24 } : { flex: '1' }
"
>
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
>
<a-form-item label="上级分类" name="parentId">
<a-tree-select
allow-clear
:tree-data="categoryList"
tree-default-expand-all
placeholder="请选择上级分类"
:value="form.parentId || undefined"
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
@update:value="(value?: number) => (form.parentId = value)"
/>
</a-form-item>
<a-form-item label="分类名称" name="title">
<a-input
allow-clear
placeholder="请输入分类名称"
v-model:value="form.title"
@pressEnter="save"
/>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="99999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="是否展示" name="status">
<a-switch
checked-children="是"
un-checked-children="否"
:checked="form.status === 0"
@update:checked="updateHideValue"
/>
</a-form-item>
</a-col>
</a-row>
<div style="margin-bottom: 22px">
<a-divider />
</div>
<a-form-item
label="备注"
name="comments"
:label-col="
styleResponsive ? { md: 3, sm: 4, xs: 24 } : { flex: '90px' }
"
:wrapper-col="
styleResponsive ? { md: 21, sm: 20, xs: 24 } : { flex: '1' }
"
>
<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 } from 'ele-admin-pro';
import {
addArticleCategory,
updateArticleCategory
} from '@/api/cms/category';
import type { ArticleCategory } from '@/api/cms/category/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { Design } from '@/api/cms/design/model';
import type { Rule } from 'ant-design-vue/es/form';
const useForm = Form.useForm;
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ArticleCategory | null;
// 分类id
categoryId?: number;
// 全部分类
categoryList: ArticleCategory[];
}>();
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 表单数据
const form = reactive<ArticleCategory>({
categoryId: undefined,
type: 0,
title: '',
parentId: undefined,
image: '',
path: '/article/:id',
component: '/article/index',
pageId: undefined,
pageName: '',
status: 0,
showIndex: 0,
recommend: 0,
sortNumber: 100
});
// 表单验证规则
const rules = reactive({
type: [
{
required: true,
message: '请选择分类类型',
type: 'number',
trigger: 'blur'
}
],
title: [
{
required: true,
message: '请输入分类名称',
type: 'string',
trigger: 'blur'
}
],
sortNumber: [
{
required: true,
message: '请输入排序号',
type: 'number',
trigger: 'blur'
}
],
status: [
{
required: true,
message: '请设置是否展示',
type: 'number',
trigger: 'blur'
}
],
meta: [
{
type: 'string',
validator: async (_rule: Rule, value: string) => {
if (value) {
const msg = '请输入正确的JSON格式';
try {
const obj = JSON.parse(value);
if (typeof obj !== 'object' || obj === null) {
return Promise.reject(msg);
}
} catch (_e) {
return Promise.reject(msg);
}
}
return Promise.resolve();
},
trigger: 'blur'
}
]
});
const { resetFields, validate } = useForm(form, rules);
const onType = (index: number) => {
if (index == 0) {
form.path = '/article/:id';
form.component = '/article/index';
}
if (index == 1) {
form.path = '/page/:id';
form.component = '/about/index';
}
if (index == 2) {
form.path = undefined;
form.component = '';
}
};
const choosePageId = (data: Design) => {
form.pageName = data.name;
form.pageId = data.pageId;
form.title = data.name;
};
const updateHideValue = (value: boolean) => {
form.status = value ? 0 : 1;
};
const updateIndexValue = (value: boolean) => {
form.showIndex = value ? 1 : 0;
};
const updateRecommendValue = (value: boolean) => {
form.recommend = value ? 1 : 0;
};
/* 保存编辑 */
const save = () => {
validate()
.then(() => {
loading.value = true;
const categoryData = {
...form,
parentId: form.parentId || 0
};
const saveOrUpdate = isUpdate.value
? updateArticleCategory
: addArticleCategory;
saveOrUpdate(categoryData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignObject(form, props.data);
isUpdate.value = true;
} else {
form.parentId = props.categoryId;
isUpdate.value = false;
}
} else {
resetFields();
}
}
);
</script>
@@ -0,0 +1,39 @@
<!-- 目录选择下拉框 -->
<template>
<a-tree-select
allow-clear
tree-default-expand-all
:placeholder="placeholder"
:value="value || undefined"
:tree-data="data"
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
@update:value="updateValue"
/>
</template>
<script lang="ts" setup>
import type { Article } from '@/api/cms/article/model';
const emit = defineEmits<{
(e: 'update:value', value?: number): void;
}>();
withDefaults(
defineProps<{
// 选中的数据(v-modal)
value?: number;
// 提示信息
placeholder?: any;
// 文章分类
data: Article[];
}>(),
{
placeholder: '请选择上级分类'
}
);
/* 更新选中数据 */
const updateValue = (value?: number) => {
emit('update:value', value);
};
</script>
@@ -0,0 +1,85 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<plus-outlined />
</template>
<span>添加</span>
</a-button>
<a-button
danger
type="primary"
class="ele-btn-icon"
@click="removeBatch"
:disabled="props.selection?.length === 0"
>
<template #icon>
<delete-outlined />
</template>
<span>批量删除</span>
</a-button>
<a-input-search
allow-clear
v-model:value="where.keywords"
placeholder="请输入关键词"
@search="search"
@pressEnter="search"
/>
<a-button
type="primary"
style="background-color: var(--orange-6); border-color: var(--orange-5)"
@click="openPeriod"
>查看场馆时段</a-button
>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import useSearch from '@/utils/use-search';
import type { ThinkFieldParam } from '@/api/think/thinkField/model';
import { watch } from 'vue';
const emit = defineEmits<{
(e: 'search', where?: ThinkFieldParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'period'): void;
}>();
const props = defineProps<{
// 勾选的项目
selection?: [];
}>();
// 表单数据
const { where } = useSearch<ThinkFieldParam>({
keywords: ''
});
/* 搜索 */
const search = () => {
emit('search', where);
};
/* 添加 */
const add = () => {
emit('add');
};
const openPeriod = () => {
emit('period');
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
// 监听变化
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,217 @@
<!-- 编辑弹窗 -->
<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="isHalf">
<a-radio-group v-model:value="form.isHalf">
<a-radio :value="1">可以</a-radio>
<a-radio :value="2">不可以</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否可重复预定" name="isRepeat">
<a-radio-group v-model:value="form.isRepeat">
<a-radio :value="1">可以</a-radio>
<a-radio :value="2">不可以</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="可重复预订数" name="num" v-if="form.isRepeat == 1">
<a-input-number
allow-clear
style="width: 120px"
placeholder="可重复预订数"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="是否是卫生间" name="isToilet">
<a-radio-group v-model:value="form.isToilet">
<a-radio :value="1">是</a-radio>
<a-radio :value="2">否</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否支持儿童价" name="isChildren">
<a-radio-group v-model:value="form.isChildren">
<a-radio :value="1">支持</a-radio>
<a-radio :value="2">不支持</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="显示在第几行" name="row">
<a-input
allow-clear
placeholder="请输入显示在第几行"
v-model:value="form.row"
/>
</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="isStatus">
<a-radio-group v-model:value="form.isStatus">
<a-radio :value="1">开启</a-radio>
<a-radio :value="2">关闭</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 } from 'ele-admin-pro';
import { addThinkField, updateThinkField } from '@/api/think/thinkField';
import { ThinkField } from '@/api/think/thinkField/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 商户ID
categoryId?: number;
// 修改回显的数据
data?: ThinkField | 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<ThinkField>({
id: undefined,
name: undefined,
isToilet: undefined,
isStatus: undefined,
isRepeat: undefined,
isHalf: undefined,
isChildren: undefined,
num: undefined,
sort: undefined,
sid: undefined,
row: undefined,
createTime: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请填写场馆场地名称',
trigger: 'blur'
}
]
});
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
form.sid = props.categoryId;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkField : addThinkField;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,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>
+205
View File
@@ -0,0 +1,205 @@
<template>
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-split-layout
:width="!getMerchantName() ? '266px' : ''"
:allow-collapse="!getMerchantName()"
:right-style="{ overflow: 'hidden' }"
:style="{ minHeight: 'calc(100vh - 252px)' }"
>
<div v-if="!getMerchantName()">
<ele-toolbar theme="default">
<span class="ele-text-heading">场馆列表</span>
</ele-toolbar>
<div class="ele-border-split sys-category-list">
<a-tree
:tree-data="data"
v-model:expanded-keys="expandedRowKeys"
v-model:selected-keys="selectedRowKeys"
:show-line="true"
:show-icon="false"
@select="onTreeSelect"
>
<template #title="{ type, key: treeKey, title }">
<a-dropdown :trigger="['contextmenu']">
<span>{{ title }}</span>
<template #overlay v-if="type == 0">
<a-menu
@click="
({ key: menuKey }) =>
onContextMenuClick(treeKey, menuKey)
"
>
<a-menu-item key="1">修改</a-menu-item>
<a-menu-item key="2">删除</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</template>
</a-tree>
</div>
</div>
<template #content>
<list
v-if="current"
:category-list="data"
:data="current"
:category-id="current.id"
/>
</template>
</ele-split-layout>
</a-card>
<!-- 编辑弹窗 -->
<category-edit
v-model:visible="showEdit"
:data="editData"
:category-list="data"
:category-id="current?.categoryId"
@done="query"
/>
</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 { eachTreeData } from 'ele-admin-pro';
import List from './list.vue';
import CategoryEdit from './components/category-edit.vue';
import { getMerchantName } from '@/utils/merchant';
import { listThinkSite, removeThinkSite } from '@/api/think/thinkSite';
import { ThinkSite } from '@/api/think/thinkSite/model';
// 加载状态
const loading = ref(true);
// 树形数据
const data = ref<ThinkSite[]>([]);
// 树展开的key
const expandedRowKeys = ref<number[]>([]);
// 树选中的key
const selectedRowKeys = ref<number[]>([]);
// 选中数据
const current = ref<ThinkSite | any>(null);
// 是否显示表单弹窗
const showEdit = ref(false);
// 编辑回显数据
const editData = ref<ThinkSite | null>(null);
/* 查询 */
const query = () => {
loading.value = true;
listThinkSite()
.then((list) => {
loading.value = false;
const eks: number[] = [];
list.forEach((d) => {
d.key = d.id;
d.value = d.id;
if (typeof d.id === 'number') {
eks.push(d.id);
}
});
expandedRowKeys.value = eks;
data.value = list.map((d) => {
d.key = d.id;
d.value = d.id;
d.title = d.name;
return d;
});
// data.value = toTreeData({
// data: list,
// idField: 'categoryId',
// parentIdField: 'parentId'
// });
if (list.length) {
if (typeof list[0].id === 'number') {
selectedRowKeys.value = [list[0].id];
}
current.value = list[0];
} else {
selectedRowKeys.value = [];
current.value = null;
}
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
};
/* 选择数据 */
const onTreeSelect = () => {
current.value = {};
eachTreeData(data.value, (d) => {
if (typeof d.id === 'number' && selectedRowKeys.value.includes(d.id)) {
current.value = d;
return false;
}
});
};
const onContextMenuClick = (treeKey: number, menuKey: number) => {
// 修改
if (menuKey == 1) {
openEdit(current.value);
}
// 删除
if (menuKey == 2) {
remove();
}
};
/* 打开编辑弹窗 */
const openEdit = (item?: ThinkSite | null) => {
editData.value = item ?? null;
showEdit.value = true;
};
/* 删除 */
const remove = () => {
Modal.confirm({
title: '提示',
content: '确定要删除选中的分类吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeThinkSite(current.value?.id)
.then((msg) => {
hide();
message.success(msg);
query();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkField'
};
</script>
<style lang="less" scoped>
.sys-category-list {
padding: 12px 6px;
height: calc(100vh - 242px);
border-width: 1px;
border-style: solid;
overflow: auto;
}
</style>
+315
View File
@@ -0,0 +1,315 @@
<template>
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
v-model:selection="selection"
:customRow="customRow"
height="calc(100vh - 390px)"
tool-class="ele-toolbar-form"
:scroll="{ x: 800 }"
>
<template #toolbar>
<field-search
:selection="selection"
@search="reload"
@add="openEdit()"
@period="openPeriod()"
@remove="removeBatch"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'fieldName'">
{{ record.name }}
</template>
<template v-if="column.key === 'isToilet'">
<a-tag v-if="record.isToilet == 1" color="green">是</a-tag>
<a-tag v-else>否</a-tag>
</template>
<template v-if="column.key === 'isHalf'">
<a-tag v-if="record.isHalf == 2">不可以</a-tag>
<a-tag v-if="record.isHalf == 1" color="green">可以</a-tag>
</template>
<template v-if="column.key === 'isChildren'">
<a-tag v-if="record.isChildren == 2">不支持</a-tag>
<a-tag v-if="record.isChildren == 1" color="green">支持</a-tag>
</template>
<template v-if="column.key === 'isRepeat'">
<a-tag v-if="record.isRepeat == 2">不可以</a-tag>
<a-tag v-if="record.isRepeat == 1" color="green">可以</a-tag>
</template>
<template v-if="column.key === 'isStatus'">
<a-tag v-if="record.isStatus == 2">关闭</a-tag>
<a-tag v-if="record.isStatus == 1" color="green">开启</a-tag>
</template>
<template v-else-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>
<!-- 编辑弹窗 -->
<field-edit
:data="current"
v-model:visible="showEdit"
:category-list="categoryList"
:category-id="categoryId"
@done="reload"
/>
<!-- 时段弹窗 -->
<PeriodEdit
v-model:visible="showPeriodEidt"
:category-id="categoryId"
:data="data"
@done="reload"
/>
</template>
<script lang="ts" setup>
import { createVNode, ref, watch } from 'vue';
import { message, Modal } from 'ant-design-vue';
import type { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import { toDateString } from 'ele-admin-pro';
import FieldSearch from './components/field-search.vue';
import FieldEdit from './components/fieldEdit.vue';
import {
pageThinkField,
removeThinkField,
removeBatchThinkField
} from '@/api/think/thinkField';
import type {
ThinkField,
ThinkFieldParam
} from '@/api/think/thinkField/model';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import PeriodEdit from './period/index.vue';
import { ThinkSite } from '@/api/think/thinkSite/model';
const props = defineProps<{
// 场馆场地 id
categoryId?: number;
// 全部分类
categoryList: ThinkSite[];
// 当期选中
data: ThinkSite;
}>();
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<any[]>([]);
// 表格列配置
const columns = ref<ColumnItem[]>([
// {
// key: 'index',
// width: 48,
// align: 'center',
// fixed: 'left',
// hideInSetting: true,
// customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
// },
{
title: 'ID',
width: 80,
dataIndex: 'id'
},
{
title: '场地名称',
dataIndex: 'name',
key: 'name'
},
{
title: '显示在第几行',
dataIndex: 'row',
key: 'row'
},
{
title: '可重复预订次数',
dataIndex: 'num',
key: 'num'
},
{
title: '是否是卫生间',
dataIndex: 'isToilet',
key: 'isToilet',
align: 'center',
customRender: ({ text }) => (text == true ? '否' : '是')
},
{
title: '是否可预订半场',
dataIndex: 'isHalf',
key: 'isHalf',
align: 'center'
},
{
title: '是否支持儿童价',
dataIndex: 'isChildren',
key: 'isChildren',
align: 'center',
customRender: ({ text }) => (text == true ? '不支持' : '支持')
},
{
title: '是否可重复预订',
dataIndex: 'isRepeat',
key: 'isRepeat',
align: 'center',
customRender: ({ text }) => (text == true ? '不可以' : '可以')
},
{
title: '场地状态',
dataIndex: 'isStatus',
key: 'isStatus',
align: 'center',
customRender: ({ text }) => (text == 1 ? '开启' : '关闭')
},
{
title: '排序',
dataIndex: 'sort',
width: 100,
align: 'center'
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 120,
align: 'center',
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 100,
align: 'center'
}
]);
// 当前编辑数据
const current = ref<ThinkField | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示时段弹窗
const showPeriodEidt = ref(false);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (props.categoryId) {
where.sid = props.categoryId;
}
// 按条件排序
if (filters) {
where.virtualViews = filters.virtualViews;
where.actualViews = filters.actualViews;
where.status = filters.status;
}
// where.merchantId = getMerchantId();
return pageThinkField({
...where,
...orders,
page,
limit
});
};
/* 搜索 */
const reload = (where?: ThinkFieldParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkField) => {
current.value = row ?? null;
showEdit.value = true;
};
const openPeriod = () => {
showPeriodEidt.value = true;
};
/* 删除单个 */
const remove = (row: ThinkField) => {
const hide = message.loading('请求中..', 0);
removeThinkField(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkField(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 自定义行属性 */
const customRow = (record: ThinkField) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
// 监听场馆场地 id 变化
watch(
() => props.categoryId,
() => {
reload();
}
);
</script>
@@ -0,0 +1,286 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:title="isUpdate ? '编辑时段' : '添加时段'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-spin :spinning="loading">
<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="timePeriod">
<a-time-picker
v-model:value="form.timePeriod1"
format="HH:mm"
valueFormat="HH:mm"
/>
-
<a-time-picker
v-model:value="form.timePeriod2"
format="HH:mm"
valueFormat="HH:mm"
/>
</a-form-item>
<a-form-item label="价格" name="price">
<a-input-number
allow-clear
placeholder="请输入价格"
style="width: 200px"
v-model:value="form.price"
/>
</a-form-item>
<!-- <a-form-item label="每日不同价格" name="prices">-->
<!-- <a-input-number-->
<!-- allow-clear-->
<!-- style="width: 200px"-->
<!-- placeholder="请输入每日不同价格"-->
<!-- v-model:value="form.prices"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="半场价格" name="halfPrice">
<a-input-number
allow-clear
style="width: 200px"
placeholder="请输入半场价格"
v-model:value="form.halfPrice"
/>
</a-form-item>
<!-- <a-form-item label="每日不同半场价格" name="halfPrices">-->
<!-- <a-input-number-->
<!-- allow-clear-->
<!-- style="width: 200px"-->
<!-- placeholder="请输入每日不同半场价格"-->
<!-- v-model:value="form.halfPrices"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="儿童价" name="childrenPrice">
<a-input-number
allow-clear
style="width: 200px"
placeholder="请输入儿童价"
v-model:value="form.childrenPrice"
/>
</a-form-item>
<a-form-item label="星期选择" name="week">
<a-select
v-model:value="form.week"
:options="weekOptions"
mode="tags"
placeholder="星期选择"
style="width: 200px"
/>
</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="isStatus">
<a-radio-group v-model:value="form.isStatus">
<a-radio :value="1">开启</a-radio>
<a-radio :value="2">关闭</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否免费" name="isFree">
<a-radio-group v-model:value="form.isFree">
<a-radio :value="1">免费</a-radio>
<a-radio :value="2">收费</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>
</a-spin>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import {
addThinkSiteTime,
updateThinkSiteTime
} from '@/api/think/thinkSiteTime';
import { ThinkSiteTime } from '@/api/think/thinkSiteTime/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { FormInstance, RuleObject } from 'ant-design-vue/es/form';
import { ThinkSite } from '@/api/think/thinkSite/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 场馆ID
sid?: number;
// 场馆信息
site?: ThinkSite | null;
// 修改回显的数据
data?: ThinkSiteTime | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const weekOptions = ref([
{ label: '星期一', value: '1' },
{ label: '星期二', value: '2' },
{ label: '星期三', value: '3' },
{ label: '星期四', value: '4' },
{ label: '星期五', value: '5' },
{ label: '星期六', value: '6' },
{ label: '星期日', value: '7' }
]);
// 用户信息
const form = reactive<ThinkSiteTime>({
id: undefined,
timePeriod: '',
timePeriod1: undefined,
timePeriod2: undefined,
price: '0',
prices: '',
halfPrice: '0',
halfPrices: '',
childrenPrice: '0',
week: undefined,
sort: 0,
sid: 0,
isStatus: '1',
isFree: '2',
startTime: ''
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
period: [
{
required: true,
type: 'string',
message: '请填写时段,如红色、L码、远峰蓝、原色钛金属等',
trigger: 'blur'
}
],
timePeriod: [
{
required: true,
type: 'string',
message: '请选择时段',
trigger: 'blur',
validator: async (_rule: RuleObject, value: string) => {
if (form.timePeriod1 == undefined || form.timePeriod2 == undefined) {
return Promise.reject('请选择时段' + value);
}
return Promise.resolve();
}
}
]
});
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
form.sid = props.sid;
if (!form.sid || form.sid == 0) {
return;
}
form.week = JSON.stringify(form.week);
form.prices = JSON.stringify(form.prices);
form.halfPrices = JSON.stringify(form.halfPrices);
form.timePeriod = `${form.timePeriod1} - ${form.timePeriod2}`;
form.startTime = `${form.timePeriod1?.replace(':', '')}`;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value
? updateThinkSiteTime
: addThinkSiteTime;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignObject(form, props.data);
if (props.data.timePeriod) {
const strings = props.data.timePeriod.split('-');
form.timePeriod1 = strings[0].replace(' ', '');
form.timePeriod2 = strings[1].replace(' ', '');
}
if (props.data.week) {
form.week = JSON.parse(props.data.week);
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -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>
+300
View File
@@ -0,0 +1,300 @@
<template>
<a-drawer
width="70%"
:visible="visible"
:title="`${data?.name}时段列表`"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
:confirm-loading="loading"
:footer="null"
>
<ele-pro-table
ref="tableRef"
row-key="id"
: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 === 'isStatus'">
<a-tag v-if="record.isStatus === 1" color="green">开启</a-tag>
<a-tag v-if="record.isStatus === 2" color="red">关闭</a-tag>
</template>
<template v-if="column.key === 'isFree'">
<a-tag v-if="record.isFree === 1" color="green">免费</a-tag>
<a-tag v-if="record.isFree === 2" color="orange">收费</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="moveUp(record)">上移<ArrowUpOutlined /></a>
<a-divider type="vertical" />
<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>
<!-- 编辑弹窗 -->
<PeriodEdit
v-model:visible="showEdit"
:merchant="data"
:merchantId="categoryId"
:data="current"
@done="reload"
/>
</a-drawer>
</template>
<script lang="ts" setup>
import { createVNode, ref, watch } from 'vue';
import { message, Modal } from 'ant-design-vue';
import {
ArrowUpOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import PeriodEdit from './components/periodEdit.vue';
import {
pageThinkSiteTime,
removeThinkSiteTime,
removeBatchThinkSiteTime,
updateThinkSiteTime
} from '@/api/think/thinkSiteTime';
import type {
ThinkSiteTime,
ThinkSiteTimeParam
} from '@/api/think/thinkSiteTime/model';
import { ThinkSite } from '@/api/think/thinkSite/model';
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
categoryId?: number | null;
// 商户信息
data?: ThinkSite;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkSiteTime[]>([]);
// 当前编辑数据
const current = ref<ThinkSiteTime | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
where.sid = props.categoryId;
return pageThinkSiteTime({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '时段',
dataIndex: 'timePeriod',
key: 'timePeriod',
align: 'center'
},
{
title: '价格',
dataIndex: 'price',
key: 'price',
align: 'center'
},
{
title: '半场价格',
dataIndex: 'halfPrice',
key: 'halfPrice',
align: 'center'
},
{
title: '儿童价',
dataIndex: 'childrenPrice',
key: 'childrenPrice',
align: 'center'
},
{
title: '时间段状态',
dataIndex: 'isStatus',
key: 'isStatus',
align: 'center'
},
{
title: '是否免费',
dataIndex: 'isFree',
key: 'isFree',
align: 'center'
},
{
title: '排序',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center'
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkSiteTimeParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkSiteTime) => {
current.value = row ?? null;
// if (props.data?.specId) {
// specId.value = props.data?.specId;
// }
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkSiteTime) => {
const hide = message.loading('请求中..', 0);
removeThinkSiteTime(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchThinkSiteTime(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// 上移
const moveUp = (row?: ThinkSiteTime) => {
updateThinkSiteTime({
id: row?.id,
sort: Number(row?.sort) - 1
}).then((msg) => {
message.success(msg);
reload();
});
};
/* 自定义行属性 */
const customRow = (record: ThinkSiteTime) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
watch(
() => props.categoryId,
(categoryId) => {
if (categoryId) {
reload();
}
}
);
</script>
<script lang="ts">
export default {
name: 'ThinkSiteTime'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,264 @@
<!-- 编辑弹窗 -->
<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="gateName">
<a-input
allow-clear
placeholder="请输入闸机名称"
v-model:value="form.gateName"
/>
</a-form-item>
<a-form-item label="闸机被使用的展馆" name="siteId">
<a-input
allow-clear
placeholder="请输入闸机被使用的展馆"
v-model:value="form.siteId"
/>
</a-form-item>
<a-form-item label="闸机编码" name="gateCode">
<a-input
allow-clear
placeholder="请输入闸机编码"
v-model:value="form.gateCode"
/>
</a-form-item>
<a-form-item label="闸机序列码" name="gateMac">
<a-input
allow-clear
placeholder="请输入闸机序列码"
v-model:value="form.gateMac"
/>
</a-form-item>
<a-form-item label="闸机 IP" name="gateIp">
<a-input
allow-clear
placeholder="请输入闸机 IP"
v-model:value="form.gateIp"
/>
</a-form-item>
<a-form-item label="闸机状态(1=正常 2=模块异常)" name="gateState">
<a-input
allow-clear
placeholder="请输入闸机状态(1=正常 2=模块异常)"
v-model:value="form.gateState"
/>
</a-form-item>
<a-form-item label="闸机通心跳次数" name="liveNumber">
<a-input
allow-clear
placeholder="请输入闸机通心跳次数"
v-model:value="form.liveNumber"
/>
</a-form-item>
<a-form-item label="创建时间" name="crateTime">
<a-input
allow-clear
placeholder="请输入创建时间"
v-model:value="form.crateTime"
/>
</a-form-item>
<a-form-item label="创建人id" name="createUser">
<a-input
allow-clear
placeholder="请输入创建人id"
v-model:value="form.createUser"
/>
</a-form-item>
<a-form-item label="更新次数" name="updateNumber">
<a-input
allow-clear
placeholder="请输入更新次数"
v-model:value="form.updateNumber"
/>
</a-form-item>
<a-form-item label="最近更新时间,作为系统设计预留字段" name="updateTime">
<a-input
allow-clear
placeholder="请输入最近更新时间,作为系统设计预留字段"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="最近更新数据id 系统设计使用" name="updateUser">
<a-input
allow-clear
placeholder="请输入最近更新数据id 系统设计使用"
v-model:value="form.updateUser"
/>
</a-form-item>
<a-form-item label="数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段" name="deleteStatus">
<a-input
allow-clear
placeholder="请输入数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段"
v-model:value="form.deleteStatus"
/>
</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 { addThinkGate, updateThinkGate } from '@/api/think/thinkGate';
import { ThinkGate } from '@/api/think/thinkGate/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?: ThinkGate | 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<ThinkGate>({
id: undefined,
gateName: undefined,
siteId: undefined,
gateCode: undefined,
gateMac: undefined,
gateIp: undefined,
gateState: undefined,
liveNumber: undefined,
crateTime: undefined,
createUser: undefined,
updateNumber: undefined,
updateTime: undefined,
updateUser: undefined,
deleteStatus: undefined,
thinkGateId: undefined,
thinkGateName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGateName: [
{
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 ? updateThinkGate : addThinkGate;
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>
+284
View File
@@ -0,0 +1,284 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkGateId"
: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>
<!-- 编辑弹窗 -->
<ThinkGateEdit 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 ThinkGateEdit from './components/thinkGateEdit.vue';
import { pageThinkGate, removeThinkGate, removeBatchThinkGate } from '@/api/think/thinkGate';
import type { ThinkGate, ThinkGateParam } from '@/api/think/thinkGate/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGate[]>([]);
// 当前编辑数据
const current = ref<ThinkGate | 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 pageThinkGate({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '闸机名称',
dataIndex: 'gateName',
key: 'gateName',
align: 'center',
},
{
title: '闸机被使用的展馆',
dataIndex: 'siteId',
key: 'siteId',
align: 'center',
},
{
title: '闸机编码',
dataIndex: 'gateCode',
key: 'gateCode',
align: 'center',
},
{
title: '闸机序列码',
dataIndex: 'gateMac',
key: 'gateMac',
align: 'center',
},
{
title: '闸机 IP',
dataIndex: 'gateIp',
key: 'gateIp',
align: 'center',
},
{
title: '闸机状态(1=正常 2=模块异常)',
dataIndex: 'gateState',
key: 'gateState',
align: 'center',
},
{
title: '闸机通心跳次数',
dataIndex: 'liveNumber',
key: 'liveNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'crateTime',
key: 'crateTime',
align: 'center',
},
{
title: '创建人id',
dataIndex: 'createUser',
key: 'createUser',
align: 'center',
},
{
title: '更新次数',
dataIndex: 'updateNumber',
key: 'updateNumber',
align: 'center',
},
{
title: '最近更新时间,作为系统设计预留字段',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '最近更新数据id 系统设计使用',
dataIndex: 'updateUser',
key: 'updateUser',
align: 'center',
},
{
title: '数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段',
dataIndex: 'deleteStatus',
key: 'deleteStatus',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGateParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGate) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGate) => {
const hide = message.loading('请求中..', 0);
removeThinkGate(row.thinkGateId)
.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);
removeBatchThinkGate(selection.value.map((d) => d.thinkGateId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGate) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGate'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,272 @@
<!-- 编辑弹窗 -->
<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="gateId">
<a-input
allow-clear
placeholder="请输入闸机id"
v-model:value="form.gateId"
/>
</a-form-item>
<a-form-item label="扫码值 可能是二维码id" name="gateQrcode">
<a-input
allow-clear
placeholder="请输入扫码值 可能是二维码id"
v-model:value="form.gateQrcode"
/>
</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="通过闸 机状态 waitting:等待处理,finish:完成,fail:失败,overtime:超时" name="recordStaus">
<a-input
allow-clear
placeholder="请输入通过闸 机状态 waitting:等待处理,finish:完成,fail:失败,overtime:超时"
v-model:value="form.recordStaus"
/>
</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="vip卡id如果存在卡的话" name="vipCardId">
<a-input
allow-clear
placeholder="请输入vip卡id如果存在卡的话"
v-model:value="form.vipCardId"
/>
</a-form-item>
<a-form-item label="创建时间" name="crateTime">
<a-input
allow-clear
placeholder="请输入创建时间"
v-model:value="form.crateTime"
/>
</a-form-item>
<a-form-item label="创建人id" name="createUser">
<a-input
allow-clear
placeholder="请输入创建人id"
v-model:value="form.createUser"
/>
</a-form-item>
<a-form-item label="更新次数" name="updateNumber">
<a-input
allow-clear
placeholder="请输入更新次数"
v-model:value="form.updateNumber"
/>
</a-form-item>
<a-form-item label="最近更新时间,作为系统设计预留字段" name="updateTime">
<a-input
allow-clear
placeholder="请输入最近更新时间,作为系统设计预留字段"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="最近更新数据id 系统设计使用" name="updateUser">
<a-input
allow-clear
placeholder="请输入最近更新数据id 系统设计使用"
v-model:value="form.updateUser"
/>
</a-form-item>
<a-form-item label="数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段" name="deleteStatus">
<a-input
allow-clear
placeholder="请输入数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段"
v-model:value="form.deleteStatus"
/>
</a-form-item>
<a-form-item label="" name="siteId">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.siteId"
/>
</a-form-item>
<a-form-item label="本次消费金额 " name="consumeMoney">
<a-input
allow-clear
placeholder="请输入本次消费金额 "
v-model:value="form.consumeMoney"
/>
</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 { addThinkGatePassreord, updateThinkGatePassreord } from '@/api/think/thinkGatePassreord';
import { ThinkGatePassreord } from '@/api/think/thinkGatePassreord/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?: ThinkGatePassreord | 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<ThinkGatePassreord>({
id: undefined,
gateId: undefined,
gateQrcode: undefined,
userId: undefined,
recordStaus: undefined,
orderId: undefined,
vipCardId: undefined,
crateTime: undefined,
createUser: undefined,
updateNumber: undefined,
updateTime: undefined,
updateUser: undefined,
deleteStatus: undefined,
siteId: undefined,
consumeMoney: undefined,
thinkGatePassreordId: undefined,
thinkGatePassreordName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGatePassreordName: [
{
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 ? updateThinkGatePassreord : addThinkGatePassreord;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,290 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkGatePassreordId"
: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>
<!-- 编辑弹窗 -->
<ThinkGatePassreordEdit 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 ThinkGatePassreordEdit from './components/thinkGatePassreordEdit.vue';
import { pageThinkGatePassreord, removeThinkGatePassreord, removeBatchThinkGatePassreord } from '@/api/think/thinkGatePassreord';
import type { ThinkGatePassreord, ThinkGatePassreordParam } from '@/api/think/thinkGatePassreord/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGatePassreord[]>([]);
// 当前编辑数据
const current = ref<ThinkGatePassreord | 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 pageThinkGatePassreord({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '闸机id',
dataIndex: 'gateId',
key: 'gateId',
align: 'center',
},
{
title: '扫码值 可能是二维码id',
dataIndex: 'gateQrcode',
key: 'gateQrcode',
align: 'center',
},
{
title: '对应的通过的游客或者用户',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '通过闸 机状态 waitting:等待处理,finish:完成,fail:失败,overtime:超时',
dataIndex: 'recordStaus',
key: 'recordStaus',
align: 'center',
},
{
title: '如果存在订单的话,加入订单的id',
dataIndex: 'orderId',
key: 'orderId',
align: 'center',
},
{
title: 'vip卡id如果存在卡的话',
dataIndex: 'vipCardId',
key: 'vipCardId',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'crateTime',
key: 'crateTime',
align: 'center',
},
{
title: '创建人id',
dataIndex: 'createUser',
key: 'createUser',
align: 'center',
},
{
title: '更新次数',
dataIndex: 'updateNumber',
key: 'updateNumber',
align: 'center',
},
{
title: '最近更新时间,作为系统设计预留字段',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '最近更新数据id 系统设计使用',
dataIndex: 'updateUser',
key: 'updateUser',
align: 'center',
},
{
title: '数据逻辑删除状态 0:未删除 1 :已删除; 物理删除不用考虑该字段 作为系统设计预留字段',
dataIndex: 'deleteStatus',
key: 'deleteStatus',
align: 'center',
},
{
title: '',
dataIndex: 'siteId',
key: 'siteId',
align: 'center',
},
{
title: '本次消费金额 ',
dataIndex: 'consumeMoney',
key: 'consumeMoney',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGatePassreordParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGatePassreord) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGatePassreord) => {
const hide = message.loading('请求中..', 0);
removeThinkGatePassreord(row.thinkGatePassreordId)
.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);
removeBatchThinkGatePassreord(selection.value.map((d) => d.thinkGatePassreordId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGatePassreord) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGatePassreord'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,316 @@
<!-- 编辑弹窗 -->
<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="cid">
<a-input
allow-clear
placeholder="请输入关联商品分类id"
v-model:value="form.cid"
/>
</a-form-item>
<a-form-item label="商品标题" name="title">
<a-input
allow-clear
placeholder="请输入商品标题"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="划线价" name="linePrice">
<a-input
allow-clear
placeholder="请输入划线价"
v-model:value="form.linePrice"
/>
</a-form-item>
<a-form-item label="最低价格" name="minPrice">
<a-input
allow-clear
placeholder="请输入最低价格"
v-model:value="form.minPrice"
/>
</a-form-item>
<a-form-item label="最高价格" name="maxPrice">
<a-input
allow-clear
placeholder="请输入最高价格"
v-model:value="form.maxPrice"
/>
</a-form-item>
<a-form-item label="最低积分" name="minIntegral">
<a-input
allow-clear
placeholder="请输入最低积分"
v-model:value="form.minIntegral"
/>
</a-form-item>
<a-form-item label="最高积分" name="maxIntegral">
<a-input
allow-clear
placeholder="请输入最高积分"
v-model:value="form.maxIntegral"
/>
</a-form-item>
<a-form-item label="总库存" name="stockNum">
<a-input
allow-clear
placeholder="请输入总库存"
v-model:value="form.stockNum"
/>
</a-form-item>
<a-form-item label="总销量" name="goodsSales">
<a-input
allow-clear
placeholder="请输入总销量"
v-model:value="form.goodsSales"
/>
</a-form-item>
<a-form-item
label="封面图"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商品规格(1单规格 2多规格)" name="specType">
<a-input
allow-clear
placeholder="请输入商品规格(1单规格 2多规格)"
v-model:value="form.specType"
/>
</a-form-item>
<a-form-item label="状态:1上架,2下架" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="商品简介" name="desc">
<a-input
allow-clear
placeholder="请输入商品简介"
v-model:value="form.desc"
/>
</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="sort">
<a-input
allow-clear
placeholder="请输入排序"
v-model:value="form.sort"
/>
</a-form-item>
<a-form-item label="是否需要发货:1是;0否" name="isFh">
<a-input
allow-clear
placeholder="请输入是否需要发货:1是;0否"
v-model:value="form.isFh"
/>
</a-form-item>
<a-form-item label="积分/金额:1仅积分;2仅金额;3积分/金额" name="isIntegral">
<a-input
allow-clear
placeholder="请输入积分/金额:1仅积分;2仅金额;3积分/金额"
v-model:value="form.isIntegral"
/>
</a-form-item>
<a-form-item label="收货方式:1自提;2快递;3自提/快递" name="shType">
<a-input
allow-clear
placeholder="请输入收货方式:1自提;2快递;3自提/快递"
v-model:value="form.shType"
/>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addThinkGoods, updateThinkGoods } from '@/api/think/thinkGoods';
import { ThinkGoods } from '@/api/think/thinkGoods/model';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ThinkGoods | 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<ThinkGoods>({
goodsId: undefined,
cid: undefined,
title: undefined,
linePrice: undefined,
minPrice: undefined,
maxPrice: undefined,
minIntegral: undefined,
maxIntegral: undefined,
stockNum: undefined,
goodsSales: undefined,
image: undefined,
specType: undefined,
status: undefined,
desc: undefined,
content: undefined,
sort: undefined,
isFh: undefined,
isIntegral: undefined,
shType: undefined,
createTime: undefined,
updateTime: undefined,
thinkGoodsId: undefined,
thinkGoodsName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsName: [
{
required: true,
type: 'string',
message: '请填写名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateThinkGoods : addThinkGoods;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+329
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="thinkGoodsId"
: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>
<!-- 编辑弹窗 -->
<ThinkGoodsEdit 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 ThinkGoodsEdit from './components/thinkGoodsEdit.vue';
import { pageThinkGoods, removeThinkGoods, removeBatchThinkGoods } from '@/api/think/thinkGoods';
import type { ThinkGoods, ThinkGoodsParam } from '@/api/think/thinkGoods/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGoods[]>([]);
// 当前编辑数据
const current = ref<ThinkGoods | 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 pageThinkGoods({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
width: 90,
},
{
title: '关联商品分类id',
dataIndex: 'cid',
key: 'cid',
align: 'center',
},
{
title: '商品标题',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '划线价',
dataIndex: 'linePrice',
key: 'linePrice',
align: 'center',
},
{
title: '最低价格',
dataIndex: 'minPrice',
key: 'minPrice',
align: 'center',
},
{
title: '最高价格',
dataIndex: 'maxPrice',
key: 'maxPrice',
align: 'center',
},
{
title: '最低积分',
dataIndex: 'minIntegral',
key: 'minIntegral',
align: 'center',
},
{
title: '最高积分',
dataIndex: 'maxIntegral',
key: 'maxIntegral',
align: 'center',
},
{
title: '总库存',
dataIndex: 'stockNum',
key: 'stockNum',
align: 'center',
},
{
title: '总销量',
dataIndex: 'goodsSales',
key: 'goodsSales',
align: 'center',
},
{
title: '封面图',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商品规格(1单规格 2多规格)',
dataIndex: 'specType',
key: 'specType',
align: 'center',
},
{
title: '状态:1上架,2下架',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '商品简介',
dataIndex: 'desc',
key: 'desc',
align: 'center',
},
{
title: '商品详细介绍',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '是否需要发货:1是;0否',
dataIndex: 'isFh',
key: 'isFh',
align: 'center',
},
{
title: '积分/金额:1仅积分;2仅金额;3积分/金额',
dataIndex: 'isIntegral',
key: 'isIntegral',
align: 'center',
},
{
title: '收货方式:1自提;2快递;3自提/快递',
dataIndex: 'shType',
key: 'shType',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGoodsParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoods) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoods) => {
const hide = message.loading('请求中..', 0);
removeThinkGoods(row.thinkGoodsId)
.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);
removeBatchThinkGoods(selection.value.map((d) => d.thinkGoodsId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGoods) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGoods'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,205 @@
<!-- 编辑弹窗 -->
<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="pid">
<a-input
allow-clear
placeholder="请输入上级id"
v-model:value="form.pid"
/>
</a-form-item>
<a-form-item label="分类名称" name="catname">
<a-input
allow-clear
placeholder="请输入分类名称"
v-model:value="form.catname"
/>
</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="sort">
<a-input
allow-clear
placeholder="请输入排序"
v-model:value="form.sort"
/>
</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 { addThinkGoodsCategory, updateThinkGoodsCategory } from '@/api/think/thinkGoodsCategory';
import { ThinkGoodsCategory } from '@/api/think/thinkGoodsCategory/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?: ThinkGoodsCategory | 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<ThinkGoodsCategory>({
id: undefined,
pid: undefined,
catname: undefined,
image: undefined,
sort: undefined,
createTime: undefined,
updateTime: undefined,
thinkGoodsCategoryId: undefined,
thinkGoodsCategoryName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsCategoryName: [
{
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 ? updateThinkGoodsCategory : addThinkGoodsCategory;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkGoodsCategoryId"
: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>
<!-- 编辑弹窗 -->
<ThinkGoodsCategoryEdit 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 ThinkGoodsCategoryEdit from './components/thinkGoodsCategoryEdit.vue';
import { pageThinkGoodsCategory, removeThinkGoodsCategory, removeBatchThinkGoodsCategory } from '@/api/think/thinkGoodsCategory';
import type { ThinkGoodsCategory, ThinkGoodsCategoryParam } from '@/api/think/thinkGoodsCategory/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGoodsCategory[]>([]);
// 当前编辑数据
const current = ref<ThinkGoodsCategory | 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 pageThinkGoodsCategory({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '上级id',
dataIndex: 'pid',
key: 'pid',
align: 'center',
},
{
title: '分类名称',
dataIndex: 'catname',
key: 'catname',
align: 'center',
},
{
title: '分类图片',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '排序',
dataIndex: 'sort',
key: 'sort',
align: 'center',
},
{
title: '',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGoodsCategoryParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoodsCategory) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoodsCategory) => {
const hide = message.loading('请求中..', 0);
removeThinkGoodsCategory(row.thinkGoodsCategoryId)
.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);
removeBatchThinkGoodsCategory(selection.value.map((d) => d.thinkGoodsCategoryId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGoodsCategory) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGoodsCategory'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,176 @@
<!-- 编辑弹窗 -->
<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="path">
<a-input
allow-clear
placeholder="请输入图片地址"
v-model:value="form.path"
/>
</a-form-item>
<a-form-item label="关联id" name="gid">
<a-input
allow-clear
placeholder="请输入关联id"
v-model:value="form.gid"
/>
</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 { addThinkGoodsImage, updateThinkGoodsImage } from '@/api/think/thinkGoodsImage';
import { ThinkGoodsImage } from '@/api/think/thinkGoodsImage/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?: ThinkGoodsImage | 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<ThinkGoodsImage>({
id: undefined,
path: undefined,
gid: undefined,
thinkGoodsImageId: undefined,
thinkGoodsImageName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsImageName: [
{
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 ? updateThinkGoodsImage : addThinkGoodsImage;
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>
+218
View File
@@ -0,0 +1,218 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="thinkGoodsImageId"
: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>
<!-- 编辑弹窗 -->
<ThinkGoodsImageEdit 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 ThinkGoodsImageEdit from './components/thinkGoodsImageEdit.vue';
import { pageThinkGoodsImage, removeThinkGoodsImage, removeBatchThinkGoodsImage } from '@/api/think/thinkGoodsImage';
import type { ThinkGoodsImage, ThinkGoodsImageParam } from '@/api/think/thinkGoodsImage/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGoodsImage[]>([]);
// 当前编辑数据
const current = ref<ThinkGoodsImage | 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 pageThinkGoodsImage({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '图片地址',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '关联id',
dataIndex: 'gid',
key: 'gid',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGoodsImageParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoodsImage) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoodsImage) => {
const hide = message.loading('请求中..', 0);
removeThinkGoodsImage(row.thinkGoodsImageId)
.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);
removeBatchThinkGoodsImage(selection.value.map((d) => d.thinkGoodsImageId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGoodsImage) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGoodsImage'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,289 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑' : '添加'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="订单号" name="orderNum">
<a-input
allow-clear
placeholder="请输入订单号"
v-model:value="form.orderNum"
/>
</a-form-item>
<a-form-item label="微信订单号" name="wechatOrder">
<a-input
allow-clear
placeholder="请输入微信订单号"
v-model:value="form.wechatOrder"
/>
</a-form-item>
<a-form-item label="姓名" name="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="address">
<a-input
allow-clear
placeholder="请输入详细地址"
v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="购买数量" name="num">
<a-input
allow-clear
placeholder="请输入购买数量"
v-model:value="form.num"
/>
</a-form-item>
<a-form-item label="订单总价" name="totalPrice">
<a-input
allow-clear
placeholder="请输入订单总价"
v-model:value="form.totalPrice"
/>
</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="付款方式:1微信支付,2积分支付" name="payType">
<a-input
allow-clear
placeholder="请输入付款方式:1微信支付,2积分支付"
v-model:value="form.payType"
/>
</a-form-item>
<a-form-item label="付款状态:1已付款,2未付款" name="payStatus">
<a-input
allow-clear
placeholder="请输入付款状态:1已付款,2未付款"
v-model:value="form.payStatus"
/>
</a-form-item>
<a-form-item label="1未完成,2待发货,3待收货,4已完成,5申请退款,6退款被拒绝,7退款成功,8已取消" name="orderStatus">
<a-input
allow-clear
placeholder="请输入1未完成,2待发货,3待收货,4已完成,5申请退款,6退款被拒绝,7退款成功,8已取消"
v-model:value="form.orderStatus"
/>
</a-form-item>
<a-form-item label="关联users表id" name="uid">
<a-input
allow-clear
placeholder="请输入关联users表id"
v-model:value="form.uid"
/>
</a-form-item>
<a-form-item label="备注信息" name="info">
<a-input
allow-clear
placeholder="请输入备注信息"
v-model:value="form.info"
/>
</a-form-item>
<a-form-item label="发货时间" name="deliveryTime">
<a-input
allow-clear
placeholder="请输入发货时间"
v-model:value="form.deliveryTime"
/>
</a-form-item>
<a-form-item label="" name="updateTime">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.updateTime"
/>
</a-form-item>
<a-form-item label="支付时间" name="payTime">
<a-input
allow-clear
placeholder="请输入支付时间"
v-model:value="form.payTime"
/>
</a-form-item>
</a-form>
</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 { addThinkGoodsOrder, updateThinkGoodsOrder } from '@/api/think/thinkGoodsOrder';
import { ThinkGoodsOrder } from '@/api/think/thinkGoodsOrder/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?: ThinkGoodsOrder | 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<ThinkGoodsOrder>({
id: undefined,
orderNum: undefined,
wechatOrder: undefined,
name: undefined,
phone: undefined,
address: undefined,
num: undefined,
totalPrice: undefined,
payPrice: undefined,
payType: undefined,
payStatus: undefined,
orderStatus: undefined,
uid: undefined,
info: undefined,
deliveryTime: undefined,
createTime: undefined,
updateTime: undefined,
payTime: undefined,
thinkGoodsOrderId: undefined,
thinkGoodsOrderName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsOrderName: [
{
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 ? updateThinkGoodsOrder : addThinkGoodsOrder;
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>
+311
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="thinkGoodsOrderId"
: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>
<!-- 编辑弹窗 -->
<ThinkGoodsOrderEdit 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 ThinkGoodsOrderEdit from './components/thinkGoodsOrderEdit.vue';
import { pageThinkGoodsOrder, removeThinkGoodsOrder, removeBatchThinkGoodsOrder } from '@/api/think/thinkGoodsOrder';
import type { ThinkGoodsOrder, ThinkGoodsOrderParam } from '@/api/think/thinkGoodsOrder/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ThinkGoodsOrder[]>([]);
// 当前编辑数据
const current = ref<ThinkGoodsOrder | 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 pageThinkGoodsOrder({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '订单号',
dataIndex: 'orderNum',
key: 'orderNum',
align: 'center',
},
{
title: '微信订单号',
dataIndex: 'wechatOrder',
key: 'wechatOrder',
align: 'center',
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '详细地址',
dataIndex: 'address',
key: 'address',
align: 'center',
},
{
title: '购买数量',
dataIndex: 'num',
key: 'num',
align: 'center',
},
{
title: '订单总价',
dataIndex: 'totalPrice',
key: 'totalPrice',
align: 'center',
},
{
title: '实际付款金额',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center',
},
{
title: '付款方式:1微信支付,2积分支付',
dataIndex: 'payType',
key: 'payType',
align: 'center',
},
{
title: '付款状态:1已付款,2未付款',
dataIndex: 'payStatus',
key: 'payStatus',
align: 'center',
},
{
title: '1未完成,2待发货,3待收货,4已完成,5申请退款,6退款被拒绝,7退款成功,8已取消',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center',
},
{
title: '关联users表id',
dataIndex: 'uid',
key: 'uid',
align: 'center',
},
{
title: '备注信息',
dataIndex: 'info',
key: 'info',
align: 'center',
},
{
title: '发货时间',
dataIndex: 'deliveryTime',
key: 'deliveryTime',
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: '支付时间',
dataIndex: 'payTime',
key: 'payTime',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: ThinkGoodsOrderParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ThinkGoodsOrder) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ThinkGoodsOrder) => {
const hide = message.loading('请求中..', 0);
removeThinkGoodsOrder(row.thinkGoodsOrderId)
.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);
removeBatchThinkGoodsOrder(selection.value.map((d) => d.thinkGoodsOrderId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ThinkGoodsOrder) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ThinkGoodsOrder'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,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="商品id" name="goodsId">
<a-input
allow-clear
placeholder="请输入商品id"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="关联goods_order表id" name="oid">
<a-input
allow-clear
placeholder="请输入关联goods_order表id"
v-model:value="form.oid"
/>
</a-form-item>
<a-form-item label="商品标题" name="title">
<a-input
allow-clear
placeholder="请输入商品标题"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item
label="商品价格"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="价格" name="goodsPrice">
<a-input
allow-clear
placeholder="请输入价格"
v-model:value="form.goodsPrice"
/>
</a-form-item>
<a-form-item label="划线价格" name="linePrice">
<a-input
allow-clear
placeholder="请输入划线价格"
v-model:value="form.linePrice"
/>
</a-form-item>
<a-form-item label="积分" name="integral">
<a-input
allow-clear
placeholder="请输入积分"
v-model:value="form.integral"
/>
</a-form-item>
<a-form-item label="商品sku记录索引 (由规格id组成)" name="goodsSkuId">
<a-input
allow-clear
placeholder="请输入商品sku记录索引 (由规格id组成)"
v-model:value="form.goodsSkuId"
/>
</a-form-item>
<a-form-item label="" name="goodsAttr">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.goodsAttr"
/>
</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 { addThinkGoodsOrderInfo, updateThinkGoodsOrderInfo } from '@/api/think/thinkGoodsOrderInfo';
import { ThinkGoodsOrderInfo } from '@/api/think/thinkGoodsOrderInfo/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?: ThinkGoodsOrderInfo | 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<ThinkGoodsOrderInfo>({
id: undefined,
goodsId: undefined,
oid: undefined,
title: undefined,
image: undefined,
goodsPrice: undefined,
linePrice: undefined,
integral: undefined,
goodsSkuId: undefined,
goodsAttr: undefined,
thinkGoodsOrderInfoId: undefined,
thinkGoodsOrderInfoName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
thinkGoodsOrderInfoName: [
{
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 ? updateThinkGoodsOrderInfo : addThinkGoodsOrderInfo;
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