chore(config): 添加项目配置文件和隐私协议
- 添加 .editorconfig 文件统一代码风格 - 添加 .env.development 和 .env.example 环境配置文件 - 添加 .eslintignore 和 .eslintrc.js 代码检查配置 - 添加 .gitignore 版本控制忽略文件配置 - 添加 .prettierignore 格式化忽略配置 - 添加隐私协议HTML文件 - 添加API密钥管理组件基础结构
This commit is contained in:
199
src/views/bsyx/bsyxClass/components/bszxClassEdit.vue
Normal file
199
src/views/bsyx/bsyxClass/components/bszxClassEdit.vue
Normal file
@@ -0,0 +1,199 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="gradeId">
|
||||
<a-select
|
||||
v-model:value="form.gradeName"
|
||||
show-search
|
||||
placeholder="选择年级"
|
||||
style="width: 200px"
|
||||
:options="options"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.name"
|
||||
@pressEnter="save"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 { addBszxClass, updateBszxClass } from '@/api/bszx/bszxClass';
|
||||
import { BszxClass } from '@/api/bszx/bszxClass/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 { BszxGrade } from '@/api/bszx/bszxGrade/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxClass | 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 options = ref<BszxGrade[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxClass>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
gradeId: undefined,
|
||||
gradeName: undefined,
|
||||
branch: 2,
|
||||
sortNumber: 100,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxClassName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-班级名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const handleChange = (value: string, item: any) => {
|
||||
form.gradeName = value;
|
||||
form.gradeId = item.id;
|
||||
};
|
||||
|
||||
const handleBranch = () => {
|
||||
getBszxGradeList();
|
||||
};
|
||||
|
||||
const getBszxGradeList = () => {
|
||||
listBszxGrade({ branch: form.branch }).then((list) => {
|
||||
options.value = list.map((d) => {
|
||||
d.value = d.name;
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
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 ? updateBszxClass : addBszxClass;
|
||||
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) {
|
||||
getBszxGradeList();
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
// resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
96
src/views/bsyx/bsyxClass/components/search.vue
Normal file
96
src/views/bsyx/bsyxClass/components/search.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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-select
|
||||
show-search
|
||||
v-model:value="where.gradeId"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 240px"
|
||||
v-model:value="where.keywords"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<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 { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxClassParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<BszxClassParam>({
|
||||
gradeId: undefined,
|
||||
eraId: undefined,
|
||||
branch: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const onGrade = (gradeId: number) => {
|
||||
where.gradeId = gradeId;
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
listBszxGrade({}).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
reload();
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
231
src/views/bsyx/bsyxClass/index.vue
Normal file
231
src/views/bsyx/bsyxClass/index.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<a-button type="text" @click="openUrl('/bsyx/grade')">年级设置 </a-button>
|
||||
<a-button type="text" @click="openUrl('/bsyx/class')">班级设置 </a-button>
|
||||
</template>
|
||||
<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 === 'era'">
|
||||
<span>{{ record.era }}级</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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxClassEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxClassEdit from './components/bszxClassEdit.vue';
|
||||
import {
|
||||
pageBszxClass,
|
||||
removeBszxClass,
|
||||
removeBatchBszxClass
|
||||
} from '@/api/bszx/bszxClass';
|
||||
import type { BszxClass, BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { getPageTitle, openUrl } from '@/utils/common';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxClass[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxClass | 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 pageBszxClass({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
// {
|
||||
// title: 'ID',
|
||||
// dataIndex: 'id',
|
||||
// key: 'id',
|
||||
// width: 120,
|
||||
// },
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName',
|
||||
width: 120
|
||||
},
|
||||
// {
|
||||
// title: '年级',
|
||||
// dataIndex: 'gradeId',
|
||||
// key: 'gradeId',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxClassParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxClass) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxClass) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxClass(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);
|
||||
removeBatchBszxClass(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: BszxClass) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxClass'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
165
src/views/bsyx/bsyxGrade/components/bszxGradeEdit.vue
Normal file
165
src/views/bsyx/bsyxGrade/components/bszxGradeEdit.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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"
|
||||
@pressEnter="save"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 { addBszxGrade, updateBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { BszxGrade } from '@/api/bszx/bszxGrade/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;
|
||||
// 修改回显的数据
|
||||
data?: BszxGrade | 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<BszxGrade>({
|
||||
id: undefined,
|
||||
branch: 2,
|
||||
name: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxGradeName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-年级名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxGrade : addBszxGrade;
|
||||
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>
|
||||
52
src/views/bsyx/bsyxGrade/components/search.vue
Normal file
52
src/views/bsyx/bsyxGrade/components/search.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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 useSearch from '@/utils/use-search';
|
||||
import { watch } from 'vue';
|
||||
import { BszxGradeParam } from '@/api/bszx/bszxGrade/model';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxGradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxGradeParam>({
|
||||
branch: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
224
src/views/bsyx/bsyxGrade/index.vue
Normal file
224
src/views/bsyx/bsyxGrade/index.vue
Normal file
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<a-button type="text" @click="openUrl('/bsyx/grade')">年级设置 </a-button>
|
||||
<a-button type="text" @click="openUrl('/bsyx/class')">班级设置 </a-button>
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="appBszxGradeId"
|
||||
: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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxGradeEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxGradeEdit from './components/bszxGradeEdit.vue';
|
||||
import {
|
||||
pageBszxGrade,
|
||||
removeBszxGrade,
|
||||
removeBatchBszxGrade
|
||||
} from '@/api/bszx/bszxGrade';
|
||||
import type { BszxGrade, BszxGradeParam } from '@/api/bszx/bszxGrade/model';
|
||||
import { getPageTitle, openUrl } from '@/utils/common';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxGrade[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxGrade | 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 pageBszxGrade({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
// {
|
||||
// title: 'ID',
|
||||
// dataIndex: 'id',
|
||||
// key: 'id',
|
||||
// align: 'center',
|
||||
// width: 90,
|
||||
// },
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxGradeParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxGrade) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxGrade) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxGrade(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);
|
||||
removeBatchBszxGrade(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: BszxGrade) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxGrade'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
249
src/views/bsyx/bsyxOrder/components/bszxPayEdit.vue
Normal file
249
src/views/bsyx/bsyxOrder/components/bszxPayEdit.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑捐款记录' : '添加捐款记录'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="年龄" name="age">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="sex">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.sex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="捐赠证书" name="certificate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入捐赠证书"
|
||||
v-model:value="form.certificate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxPay | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const images = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxPayName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-捐款记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxPay : addBszxPay;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
566
src/views/bsyx/bsyxOrder/components/orderInfo.vue
Normal file
566
src/views/bsyx/bsyxOrder/components/orderInfo.vue
Normal file
@@ -0,0 +1,566 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="`80%`"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:maxable="maxAble"
|
||||
:title="isUpdate ? '编辑订单' : '订单详情'"
|
||||
:body-style="{ paddingBottom: '8px', background: '#f3f3f3' }"
|
||||
@update:visible="updateVisible"
|
||||
:maskClosable="false"
|
||||
:footer="null"
|
||||
@ok="save"
|
||||
>
|
||||
<a-card style="margin-bottom: 20px" :bordered="false">
|
||||
<a-descriptions :column="3">
|
||||
<!-- 第一排-->
|
||||
<a-descriptions-item
|
||||
label="订单编号"
|
||||
span="3"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<span @click="copyText(form.orderNo)">{{ form.orderNo }}</span>
|
||||
</a-descriptions-item>
|
||||
<!-- 第二排-->
|
||||
<a-descriptions-item
|
||||
label="买家信息"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-space class="flex items-center">
|
||||
<a-avatar :src="form.avatar" size="small" />
|
||||
{{ form.realName }}
|
||||
</a-space>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="订单金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.totalPrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="订单状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.orderStatus === 0">未完成</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 1" color="green">已完成</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 2" color="red">已取消</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 3" color="red">取消中</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 4" color="red">退款申请中</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 5" color="red">退款被拒绝</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 6" color="orange">退款成功</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 7" color="pink"
|
||||
>客户端申请退款</a-tag
|
||||
>
|
||||
</a-descriptions-item>
|
||||
<!-- 第三排-->
|
||||
<a-descriptions-item
|
||||
label="手机号码"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.phone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="实付金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.payPrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="支付状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.payStatus == 1" color="green">已付款</a-tag>
|
||||
<a-tag v-if="form.payStatus == 0">未付款</a-tag>
|
||||
<a-tag v-if="form.payStatus == 3">未付款,占场中</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第四排-->
|
||||
<a-descriptions-item
|
||||
label="收货地址"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.address }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="减少的金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.reducePrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="核销状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.deliveryStatus == 10">未核销</a-tag>
|
||||
<a-tag v-if="form.deliveryStatus == 20" color="green">已核销</a-tag>
|
||||
<a-tag v-if="form.deliveryStatus == 30" color="bule">部分核销</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第五排-->
|
||||
<a-descriptions-item
|
||||
label="备注信息"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.comments }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="支付方式"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tooltip :title="`支付时间:${form.payTime || ''}`">
|
||||
<template v-if="form.payStatus == 1">
|
||||
<a-tag v-if="form.payType == 0">余额支付</a-tag>
|
||||
<a-tag v-if="form.payType == 1">
|
||||
<WechatOutlined class="tag-icon" />
|
||||
微信支付
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 2">积分</a-tag>
|
||||
<a-tag v-if="form.payType == 3">
|
||||
<AlipayCircleOutlined class="tag-icon" />
|
||||
支付宝
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 4">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
现金
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 5">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
POS机
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 6">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP月卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 7">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP年卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 8">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP次卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 9">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC月卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 10">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC年卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 11">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC次卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 12">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
免费
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 13">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP充值卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 14">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC充值卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 15">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
积分支付
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 16">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP季卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 17">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC季卡
|
||||
</a-tag>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="开票状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.isInvoice == 0">未开具</a-tag>
|
||||
<a-tag v-if="form.isInvoice == 1" color="green">已开具</a-tag>
|
||||
<a-tag v-if="form.isInvoice == 2" color="blue">不能开具</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第六排-->
|
||||
<a-descriptions-item
|
||||
label="下单时间"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ toDateString(form.createTime, 'yyyy-MM-dd HH:mm') }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="交易流水号"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tooltip :title="form.payTime">{{ form.transactionId }}</a-tooltip>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="结算状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.isSettled == 0">未结算</a-tag>
|
||||
<a-tag v-if="form.isSettled == 1" color="green">已结算</a-tag>
|
||||
</a-descriptions-item>
|
||||
|
||||
<!-- <a-descriptions-item span="3">-->
|
||||
<!-- <a-divider/>-->
|
||||
<!-- </a-descriptions-item>-->
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
<a-card class="order-card" :bordered="false">
|
||||
<a-spin :spinning="loading">
|
||||
<a-table
|
||||
:data-source="orderInfo"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
/>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import { ColumnItem } from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import {
|
||||
CheckOutlined,
|
||||
CloseOutlined,
|
||||
CoffeeOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { ShopOrder } from '@/api/shop/shopOrder/model';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { pageBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { toDateString } from 'ele-admin-pro';
|
||||
import { copyText } from '@/utils/common';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: ShopOrder | null;
|
||||
}>();
|
||||
|
||||
export interface step {
|
||||
title?: String | undefined;
|
||||
subTitle?: String | undefined;
|
||||
description?: String | undefined;
|
||||
}
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxAble = ref(true);
|
||||
// 订单信息
|
||||
const orderInfo = ref<BszxPay[]>([]);
|
||||
|
||||
// 步骤条
|
||||
const steps = ref<step[]>([
|
||||
{
|
||||
title: '报餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '付款',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '发餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '取餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '完成',
|
||||
description: undefined
|
||||
}
|
||||
]);
|
||||
const active = ref(2);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 订单信息
|
||||
const form = reactive<ShopOrder>({
|
||||
// 订单号
|
||||
orderId: undefined,
|
||||
// 订单编号
|
||||
orderNo: undefined,
|
||||
// 订单类型,0商城订单 1预定订单/外卖 2会员卡
|
||||
type: undefined,
|
||||
// 快递/自提
|
||||
deliveryType: undefined,
|
||||
// 下单渠道,0小程序预定 1俱乐部训练场 3活动订场
|
||||
channel: undefined,
|
||||
// 微信支付订单号
|
||||
transactionId: undefined,
|
||||
// 微信退款订单号
|
||||
refundOrder: undefined,
|
||||
// 商户ID
|
||||
merchantId: undefined,
|
||||
// 商户名称
|
||||
merchantName: undefined,
|
||||
// 商户编号
|
||||
merchantCode: undefined,
|
||||
// 使用的优惠券id
|
||||
couponId: undefined,
|
||||
// 使用的会员卡id
|
||||
cardId: undefined,
|
||||
// 关联管理员id
|
||||
adminId: undefined,
|
||||
// 核销管理员id
|
||||
confirmId: undefined,
|
||||
// IC卡号
|
||||
icCard: undefined,
|
||||
// 头像
|
||||
avatar: undefined,
|
||||
// 真实姓名
|
||||
realName: undefined,
|
||||
// 手机号码
|
||||
phone: undefined,
|
||||
// 收货地址
|
||||
address: undefined,
|
||||
//
|
||||
addressLat: undefined,
|
||||
//
|
||||
addressLng: undefined,
|
||||
// 自提店铺id
|
||||
selfTakeMerchantId: undefined,
|
||||
// 自提店铺
|
||||
selfTakeMerchantName: undefined,
|
||||
// 配送开始时间
|
||||
sendStartTime: undefined,
|
||||
// 配送结束时间
|
||||
sendEndTime: undefined,
|
||||
// 发货店铺id
|
||||
expressMerchantId: undefined,
|
||||
// 发货店铺
|
||||
expressMerchantName: undefined,
|
||||
// 订单总额
|
||||
totalPrice: undefined,
|
||||
// 减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格
|
||||
reducePrice: undefined,
|
||||
// 实际付款
|
||||
payPrice: undefined,
|
||||
// 用于统计
|
||||
price: undefined,
|
||||
// 价钱,用于积分赠送
|
||||
money: undefined,
|
||||
// 退款金额
|
||||
refundMoney: undefined,
|
||||
// 教练价格
|
||||
coachPrice: undefined,
|
||||
// 购买数量
|
||||
totalNum: undefined,
|
||||
// 教练id
|
||||
coachId: undefined,
|
||||
// 支付的用户id
|
||||
payUserId: undefined,
|
||||
// 0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
payType: undefined,
|
||||
// 代付支付方式,0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
friendPayType: undefined,
|
||||
// 0未付款,1已付款
|
||||
payStatus: undefined,
|
||||
// 0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款
|
||||
orderStatus: undefined,
|
||||
// 发货状态(10未发货 20已发货 30部分发货)
|
||||
deliveryStatus: undefined,
|
||||
// 发货时间
|
||||
deliveryTime: undefined,
|
||||
// 优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡
|
||||
couponType: undefined,
|
||||
// 优惠说明
|
||||
couponDesc: undefined,
|
||||
// 二维码地址,保存订单号,支付成功后才生成
|
||||
qrcode: undefined,
|
||||
// vip月卡年卡、ic月卡年卡回退次数
|
||||
returnNum: undefined,
|
||||
// vip充值回退金额
|
||||
returnMoney: undefined,
|
||||
// 预约详情开始时间数组
|
||||
startTime: undefined,
|
||||
// 是否已开具发票:0未开发票,1已开发票,2不能开具发票
|
||||
isInvoice: undefined,
|
||||
// 发票流水号
|
||||
invoiceNo: undefined,
|
||||
// 支付时间
|
||||
payTime: undefined,
|
||||
// 退款时间
|
||||
refundTime: undefined,
|
||||
// 申请退款时间
|
||||
refundApplyTime: undefined,
|
||||
// 过期时间
|
||||
expirationTime: undefined,
|
||||
// 对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单
|
||||
checkBill: undefined,
|
||||
// 订单是否已结算(0未结算 1已结算)
|
||||
isSettled: undefined,
|
||||
// 系统版本号 0当前版本 value=其他版本
|
||||
version: undefined,
|
||||
// 用户id
|
||||
userId: undefined,
|
||||
// 备注
|
||||
comments: undefined,
|
||||
// 排序号
|
||||
sortNumber: undefined,
|
||||
// 是否删除, 0否, 1是
|
||||
deleted: undefined,
|
||||
// 租户id
|
||||
tenantId: undefined,
|
||||
// 修改时间
|
||||
updateTime: undefined,
|
||||
// 创建时间
|
||||
createTime: undefined,
|
||||
// 自提码
|
||||
selfTakeCode: undefined,
|
||||
// 是否已收到赠品
|
||||
hasTakeGift: undefined
|
||||
});
|
||||
|
||||
// 请求状态
|
||||
const loading = ref(true);
|
||||
|
||||
const { resetFields } = useForm(form);
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '商品名称',
|
||||
dataIndex: 'formName',
|
||||
key: 'formName',
|
||||
align: 'center',
|
||||
width: 280
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
dataIndex: 'price',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'isFree',
|
||||
align: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
/* 制作步骤条 */
|
||||
const loadSteps = (order) => {
|
||||
steps.value = [];
|
||||
steps.value.push({
|
||||
title: '下单'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '付款'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '发货'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '收货'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '完成'
|
||||
});
|
||||
|
||||
// 下单
|
||||
if (order.payStatus == 10) {
|
||||
active.value = 0;
|
||||
steps.value[0].description = order.createTime;
|
||||
}
|
||||
// 付款
|
||||
if (order.payStatus == 20) {
|
||||
active.value = 1;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
}
|
||||
// 发货
|
||||
if (order.payStatus == 20 && order.deliveryStatus == 20) {
|
||||
active.value = 2;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
}
|
||||
// 收货
|
||||
if (order.payStatus == 20 && order.receiptStatus == 20) {
|
||||
active.value = 3;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
steps.value[3].description = order.receiptTime;
|
||||
}
|
||||
// 完成
|
||||
if (order.payStatus == 20 && order.orderStatus == 30) {
|
||||
active.value = 4;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
steps.value[3].description = order.receiptTime;
|
||||
}
|
||||
// 已取消
|
||||
if (order.orderStatus == 20) {
|
||||
active.value = 4;
|
||||
}
|
||||
};
|
||||
|
||||
// const getOrderInfo = () => {
|
||||
// const orderId = props.data?.orderId;
|
||||
// listOrderInfo({ orderId }).then((data) => {
|
||||
// orderInfo.value = data.filter((d) => d.totalNum > 0);
|
||||
// });
|
||||
// };
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
if (props.data) {
|
||||
loading.value = true;
|
||||
assignObject(form, props.data);
|
||||
pageBszxPay({ orderNo: form.orderNo }).then((res) => {
|
||||
if (res?.list) {
|
||||
orderInfo.value = res?.list;
|
||||
}
|
||||
loading.value = false;
|
||||
});
|
||||
loadSteps(props.data);
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import * as MenuIcons from '@/layout/menu-icons';
|
||||
|
||||
export default {
|
||||
name: 'BszxOrderInfo',
|
||||
components: MenuIcons
|
||||
};
|
||||
</script>
|
||||
203
src/views/bsyx/bsyxOrder/components/search.vue
Normal file
203
src/views/bsyx/bsyxOrder/components/search.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-select
|
||||
v-model:value="where.payStatus"
|
||||
style="width: 150px"
|
||||
placeholder="付款状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">已付款</a-select-option>
|
||||
<a-select-option :value="0">未付款</a-select-option>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model:value="where.orderStatus"
|
||||
style="width: 150px"
|
||||
placeholder="订单状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">已完成</a-select-option>
|
||||
<a-select-option :value="0">未完成</a-select-option>
|
||||
<a-select-option :value="2">未使用</a-select-option>
|
||||
<a-select-option :value="3">已取消</a-select-option>
|
||||
<a-select-option :value="4">退款中</a-select-option>
|
||||
<a-select-option :value="5">退款被拒</a-select-option>
|
||||
<a-select-option :value="6">退款成功</a-select-option>
|
||||
</a-select>
|
||||
<a-select
|
||||
:options="getPayType()"
|
||||
v-model:value="where.payType"
|
||||
style="width: 150px"
|
||||
placeholder="付款方式"
|
||||
@change="search"
|
||||
/>
|
||||
<a-select
|
||||
v-model:value="where.isInvoice"
|
||||
style="width: 150px"
|
||||
placeholder="开票状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option :value="1">已开票</a-select-option>
|
||||
<a-select-option :value="0">未开票</a-select-option>
|
||||
<a-select-option :value="2">不能开票</a-select-option>
|
||||
</a-select>
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 280px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
<a-button @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import { message } from 'ant-design-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { ShopOrder, ShopOrderParam } from '@/api/shop/shopOrder/model';
|
||||
import { listShopOrder } from '@/api/shop/shopOrder';
|
||||
import { getPayType } from '@/utils/shop';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: ShopOrderParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<ShopOrderParam>({
|
||||
keywords: '',
|
||||
orderId: undefined,
|
||||
orderNo: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
userId: undefined,
|
||||
phone: undefined,
|
||||
payStatus: undefined,
|
||||
orderStatus: undefined,
|
||||
payType: undefined,
|
||||
isInvoice: undefined
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
xlsFileName.value = `${d1}至${d2}`;
|
||||
where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
|
||||
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : undefined;
|
||||
emit('search', {
|
||||
...where
|
||||
});
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
search();
|
||||
};
|
||||
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const orders = ref<ShopOrder[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'订单编号',
|
||||
'订单标题',
|
||||
'买家姓名',
|
||||
'手机号码',
|
||||
'实付金额(元)',
|
||||
'支付方式',
|
||||
'付款时间',
|
||||
'下单时间'
|
||||
]
|
||||
];
|
||||
|
||||
await listShopOrder(where)
|
||||
.then((list) => {
|
||||
orders.value = list;
|
||||
list?.forEach((d: ShopOrder) => {
|
||||
array.push([
|
||||
`${d.orderNo}`,
|
||||
`${d.comments}`,
|
||||
`${d.realName}`,
|
||||
`${d.phone}`,
|
||||
`${d.payPrice}`,
|
||||
`${getPayType(d.payType)}`,
|
||||
`${d.payTime || ''}`,
|
||||
`${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: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
334
src/views/bsyx/bsyxOrder/index.vue
Normal file
334
src/views/bsyx/bsyxOrder/index.vue
Normal file
@@ -0,0 +1,334 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="orderId"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
@add="openEdit"
|
||||
@batchMove="openMove"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<div @click="onSearch(record)" class="cursor-pointer">{{
|
||||
record.name || '匿名'
|
||||
}}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'phone'">
|
||||
<div v-if="record.mobile" class="text-gray-400">{{
|
||||
record.mobile
|
||||
}}</div>
|
||||
<div v-else class="text-gray-600">{{ record.phone }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'payType'">
|
||||
<template v-for="item in getPayType()">
|
||||
<template v-if="record.payStatus == 1">
|
||||
<span v-if="item.value == record.payType">{{
|
||||
item.label
|
||||
}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span></span>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="column.key === 'payStatus'">
|
||||
<a-tag
|
||||
v-if="record.payStatus == 1"
|
||||
color="green"
|
||||
@click="updatePayStatus(record)"
|
||||
>已付款</a-tag
|
||||
>
|
||||
<a-tag v-if="record.payStatus == 0" @click="updatePayStatus(record)"
|
||||
>未付款</a-tag
|
||||
>
|
||||
<a-tag v-if="record.payStatus == 3">未付款,占场中</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'image'">
|
||||
<a-image :src="record.image" :width="50" />
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag v-if="record.sex === 2">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'deliveryStatus'">
|
||||
<a-tag v-if="record.deliveryStatus == 10">未核销</a-tag>
|
||||
<a-tag v-if="record.deliveryStatus == 20" color="green"
|
||||
>已核销</a-tag
|
||||
>
|
||||
<a-tag v-if="record.deliveryStatus == 30" color="bule"
|
||||
>部分核销</a-tag
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.key === 'orderStatus'">
|
||||
<a-tag v-if="record.orderStatus === 0">未完成</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 1" color="green">已完成</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 2" color="red">已取消</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 3" color="red">取消中</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 4" color="red"
|
||||
>退款申请中</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 5" color="red"
|
||||
>退款被拒绝</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 6" color="orange"
|
||||
>退款成功</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 7" color="pink"
|
||||
>客户端申请退款</a-tag
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.key === 'isInvoice'">
|
||||
<a-tag v-if="record.isInvoice == 0">未开具</a-tag>
|
||||
<a-tag v-if="record.isInvoice == 1" color="green">已开具</a-tag>
|
||||
<a-tag v-if="record.isInvoice == 2" color="blue">不能开具</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
import { pageBszxOrder } from '@/api/bszx/bszxOrder';
|
||||
import OrderInfo from './components/orderInfo.vue';
|
||||
import { ShopOrder, ShopOrderParam } from '@/api/shop/shopOrder/model';
|
||||
import { updateShopOrder } from '@/api/shop/shopOrder';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { updateUser } from '@/api/system/user';
|
||||
import { getPayType } from '@/utils/shop';
|
||||
import { repairOrder } from '@/api/bszx/bszxPay';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ShopOrder[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ShopOrder | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
return pageBszxOrder({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '订单号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '实付金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
align: 'center',
|
||||
customRender: ({ text }) => '¥' + text
|
||||
},
|
||||
{
|
||||
title: '支付方式',
|
||||
dataIndex: 'payType',
|
||||
key: 'payType',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '支付状态',
|
||||
dataIndex: 'payStatus',
|
||||
key: 'payStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '核销状态',
|
||||
dataIndex: 'deliveryStatus',
|
||||
key: 'deliveryStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '开票状态',
|
||||
dataIndex: 'isInvoice',
|
||||
key: 'isInvoice',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '订单状态',
|
||||
// dataIndex: 'orderStatus',
|
||||
// key: 'orderStatus',
|
||||
// align: 'center',
|
||||
// },
|
||||
// {
|
||||
// title: '支付时间',
|
||||
// dataIndex: 'payTime',
|
||||
// key: 'payTime',
|
||||
// align: 'center',
|
||||
// width: 180,
|
||||
// sorter: true,
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '下单时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
sorter: true,
|
||||
ellipsis: true
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: ShopOrderParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
const onSearch = (item: ShopOrder) => {
|
||||
reload({ userId: item.userId });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ShopOrder) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 修复订单支付状态
|
||||
*/
|
||||
const updatePayStatus = (record: ShopOrder) => {
|
||||
// 修复订单
|
||||
repairOrder(record)
|
||||
.then(() => {
|
||||
message.success('修复成功');
|
||||
})
|
||||
.then(() => {
|
||||
if (record.realName == '' || record.realName == undefined) {
|
||||
// 更新用户真实姓名
|
||||
updateUser({
|
||||
userId: record.userId,
|
||||
realName: record.realName
|
||||
});
|
||||
}
|
||||
reload();
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: ShopOrder) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import * as MenuIcons from '@/layout/menu-icons';
|
||||
|
||||
export default {
|
||||
name: 'BszxOrder',
|
||||
components: MenuIcons
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
249
src/views/bsyx/bsyxPay/components/bszxPayEdit.vue
Normal file
249
src/views/bsyx/bsyxPay/components/bszxPayEdit.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑捐款记录' : '添加捐款记录'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="年龄" name="age">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="sex">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.sex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="捐赠证书" name="certificate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入捐赠证书"
|
||||
v-model:value="form.certificate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxPay | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const images = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxPayName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-捐款记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxPay : addBszxPay;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
226
src/views/bsyx/bsyxPay/components/search.vue
Normal file
226
src/views/bsyx/bsyxPay/components/search.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-select
|
||||
show-search
|
||||
v-model:value="where.gradeName"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-select
|
||||
v-if="where.gradeName"
|
||||
show-search
|
||||
v-model:value="where.className"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="classList"
|
||||
@change="onClass"
|
||||
/>
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 220px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-button @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
import { BszxBm } from '@/api/bszx/bszxBm/model';
|
||||
import { listBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { listBszxClass } from '@/api/bszx/bszxClass';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxPayParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxPayParam>({
|
||||
id: undefined,
|
||||
keywords: '',
|
||||
gradeName: undefined,
|
||||
className: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
|
||||
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : undefined;
|
||||
emit('search', {
|
||||
...where
|
||||
});
|
||||
};
|
||||
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const bmList = ref<BszxBm[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
const branchId = ref<number>();
|
||||
const gradeId = ref<number>();
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
const classList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const getGradeList = () => {
|
||||
listBszxGrade({ branch: branchId.value }).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getClassList = () => {
|
||||
listBszxClass({ gradeId: gradeId.value }).then((res) => {
|
||||
classList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onGrade = (gradeName: number, item: any) => {
|
||||
where.gradeName = item.name;
|
||||
if (gradeName) {
|
||||
console.log(item);
|
||||
gradeId.value = item.id;
|
||||
getClassList();
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const onBranchId = () => {
|
||||
getGradeList();
|
||||
};
|
||||
|
||||
const onClass = (classId, item) => {
|
||||
console.log(classId);
|
||||
where.className = item.name;
|
||||
reload();
|
||||
};
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'订单编号',
|
||||
'姓名',
|
||||
'手机号码',
|
||||
'捐款金额',
|
||||
'性别',
|
||||
'年级',
|
||||
'班级',
|
||||
'居住地址',
|
||||
'工作单位',
|
||||
'职务',
|
||||
'捐款时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 按搜索结果导出
|
||||
where.sceneType = 'Content';
|
||||
await listBszxPay(where)
|
||||
.then((list) => {
|
||||
bmList.value = list;
|
||||
list?.forEach((d: BszxBm) => {
|
||||
array.push([
|
||||
`${d.orderNo}`,
|
||||
`${d.name}`,
|
||||
`${d.mobile}`,
|
||||
`${d.price}`,
|
||||
`${d.sex == 1 ? '男' : ''}${d.sex == 2 ? '女' : '-'}`,
|
||||
`${d.gradeName ? d.gradeName : '-'}`,
|
||||
`${d.className ? d.className : '-'}`,
|
||||
`${d.address ? d.address : '-'}`,
|
||||
`${d.workUnit ? d.workUnit : '-'}`,
|
||||
`${d.position ? d.position : '-'}`,
|
||||
`${d.createTime}`
|
||||
]);
|
||||
});
|
||||
const sheetName = `导出捐款记录${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 },
|
||||
{ wch: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
getGradeList();
|
||||
|
||||
watch(
|
||||
() => props.totalPriceAmount,
|
||||
(totalPriceAmount) => {
|
||||
console.log(totalPriceAmount, 'totalPriceAmount');
|
||||
}
|
||||
);
|
||||
</script>
|
||||
346
src/views/bsyx/bsyxPay/index.vue
Normal file
346
src/views/bsyx/bsyxPay/index.vue
Normal file
@@ -0,0 +1,346 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
:parse-data="parseData"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
@add="openEdit"
|
||||
@remove="removeBatch"
|
||||
@batchMove="openMove"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<div @click="onSearch(record)" class="cursor-pointer">{{
|
||||
record.name || '匿名'
|
||||
}}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'phone'">
|
||||
<div v-if="record.mobile" class="text-gray-400">{{
|
||||
record.mobile
|
||||
}}</div>
|
||||
<div v-else class="text-gray-600">{{ record.phone }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'image'">
|
||||
<a-image :src="record.image" :width="50" />
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag v-if="record.sex === 2">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'present'">
|
||||
<a-tag v-if="record.present">能</a-tag>
|
||||
<a-tag v-else>不能</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span v-if="totalPriceAmount" class="text-red-500 font-bold"
|
||||
>小计:¥{{ totalPriceAmount.toFixed(2) }}</span
|
||||
>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxPayEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxPayEdit from './components/bszxPayEdit.vue';
|
||||
import {
|
||||
pageBszxPay,
|
||||
removeBszxPay,
|
||||
removeBatchBszxPay
|
||||
} from '@/api/bszx/bszxPay';
|
||||
import type { BszxPay, BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bsyx/extra.vue';
|
||||
import { PageResult } from '@/api';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxPay[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxPay | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
const totalPriceAmount = ref<number>(0);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
return pageBszxPay({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 整理数据
|
||||
const parseData = (data: PageResult<BszxPay>) => {
|
||||
totalPriceAmount.value = 0;
|
||||
data.list?.map((item) => {
|
||||
if (item.price) {
|
||||
totalPriceAmount.value += Number(item.price);
|
||||
}
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '捐款金额',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
customRender: ({ text }) => '¥' + text
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
align: 'center',
|
||||
customRender: ({ text }) => ['', '男', '女'][text]
|
||||
},
|
||||
{
|
||||
title: '分部',
|
||||
dataIndex: 'branchName',
|
||||
key: 'branchName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'className',
|
||||
key: 'className',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '居住地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '工作单位',
|
||||
dataIndex: 'workUnit',
|
||||
key: 'workUnit',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '职务',
|
||||
dataIndex: 'position',
|
||||
key: 'position',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '捐赠证书',
|
||||
// dataIndex: 'certificate',
|
||||
// key: 'certificate',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '心愿',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '状态',
|
||||
// dataIndex: 'status',
|
||||
// key: 'status',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '捐款时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
sorter: true,
|
||||
ellipsis: true
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxPayParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
const onSearch = (item: BszxPay) => {
|
||||
reload({ userId: item.userId });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxPay) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxPay) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxPay(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);
|
||||
removeBatchBszxPay(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: BszxPay) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
// openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPay'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
219
src/views/bsyx/bsyxPayRanking/components/bszxPayRankingEdit.vue
Normal file
219
src/views/bsyx/bsyxPayRanking/components/bszxPayRankingEdit.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑百色中学-捐款排行' : '添加百色中学-捐款排行'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="来源表ID(项目名称)" name="formId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入来源表ID(项目名称)"
|
||||
v-model:value="form.formId"
|
||||
/>
|
||||
</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="totalPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入获得捐款总金额"
|
||||
v-model:value="form.totalPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态, 0正常, 1冻结" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否删除, 0否, 1是" name="deleted">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否删除, 0否, 1是"
|
||||
v-model:value="form.deleted"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 {
|
||||
addBszxPayRanking,
|
||||
updateBszxPayRanking
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import { BszxPayRanking } from '@/api/bszx/bszxPayRanking/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?: BszxPayRanking | 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<BszxPayRanking>({
|
||||
id: undefined,
|
||||
formId: undefined,
|
||||
number: undefined,
|
||||
totalPrice: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
status: 0,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
bszxPayRankingName: [
|
||||
{
|
||||
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
|
||||
? updateBszxPayRanking
|
||||
: addBszxPayRanking;
|
||||
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>
|
||||
90
src/views/bsyx/bsyxPayRanking/components/search.vue
Normal file
90
src/views/bsyx/bsyxPayRanking/components/search.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-tooltip title="实际订单总金额(来自订单表)" class="flex px-4">
|
||||
<span class="text-gray-400">实际订单总金额:</span>
|
||||
<span class="text-gray-700 font-bold"
|
||||
>¥{{ formatNumber(bszxTotalPrice) }}</span
|
||||
>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip title="排行榜统计金额(来自排行榜表)" class="flex px-4 ml-4">
|
||||
<span class="text-gray-400">排行榜统计金额:</span>
|
||||
<span class="text-gray-700 font-bold"
|
||||
>¥{{ formatNumber(rankingTotalPrice) }}</span
|
||||
>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import { formatNumber } from 'ele-admin-pro/es';
|
||||
import { BszxPayRankingParam } from '@/api/bszx/bszxPayRanking/model';
|
||||
import { useBszxStatisticsStore } from '@/store/modules/bszx-statistics';
|
||||
|
||||
// 使用百色中学统计数据 store
|
||||
const bszxStatisticsStore = useBszxStatisticsStore();
|
||||
|
||||
// 从 store 中获取总金额
|
||||
const bszxTotalPrice = computed(() => bszxStatisticsStore.bszxTotalPrice);
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
// 保留这个属性以保持向后兼容,但不再使用
|
||||
totalPriceAmount?: number;
|
||||
// 排行榜统计金额
|
||||
rankingTotalPrice?: number;
|
||||
}>(),
|
||||
{
|
||||
rankingTotalPrice: 0
|
||||
}
|
||||
);
|
||||
|
||||
// 日期范围选择
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxPayRankingParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<BszxPayRankingParam>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
emit('search', {
|
||||
...where,
|
||||
createTimeStart: d1 ? d1 + ' 00:00:00' : '',
|
||||
createTimeEnd: d2 ? d2 + ' 23:59:59' : ''
|
||||
});
|
||||
};
|
||||
|
||||
const onSearch = (text: string) => {
|
||||
where.sceneType = text;
|
||||
search();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
255
src/views/bsyx/bsyxPayRanking/index.vue
Normal file
255
src/views/bsyx/bsyxPayRanking/index.vue
Normal file
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
:rankingTotalPrice="rankingTotalPrice"
|
||||
@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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxPayRankingEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, onMounted } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxPayRankingEdit from './components/bszxPayRankingEdit.vue';
|
||||
import {
|
||||
removeBszxPayRanking,
|
||||
removeBatchBszxPayRanking,
|
||||
ranking
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import type {
|
||||
BszxPayRanking,
|
||||
BszxPayRankingParam
|
||||
} from '@/api/bszx/bszxPayRanking/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bsyx/extra.vue';
|
||||
import { useBszxStatisticsStore } from '@/store/modules/bszx-statistics';
|
||||
|
||||
// 使用百色中学统计数据 store
|
||||
const bszxStatisticsStore = useBszxStatisticsStore();
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxPayRanking[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxPayRanking | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
// 排行榜总金额(本地计算)
|
||||
const rankingTotalPrice = ref<number>(0);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({ where }) => {
|
||||
return ranking({ ...where }).then((data) => {
|
||||
// 计算排行榜总金额(用于对比显示)
|
||||
let total = 0;
|
||||
data.forEach((item) => {
|
||||
if (item.totalPrice) {
|
||||
total += item.totalPrice;
|
||||
}
|
||||
});
|
||||
rankingTotalPrice.value = total;
|
||||
|
||||
// 不再在这里更新 store 数据,因为这里的数据是排行榜数据,不是真实的订单统计
|
||||
// store 中的数据应该来自 bszxOrderTotal API,代表真实的订单金额
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 48,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'formName',
|
||||
key: 'formName'
|
||||
},
|
||||
{
|
||||
title: '捐款人数',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '获得捐款总金额',
|
||||
dataIndex: 'totalPrice',
|
||||
key: 'totalPrice',
|
||||
align: 'center'
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxPayRankingParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
// 初始化数据
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 初始化百色中学统计数据
|
||||
await bszxStatisticsStore.fetchBszxStatistics();
|
||||
} catch (error) {
|
||||
console.error('初始化百色中学统计数据失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxPayRanking) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxPayRanking) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxPayRanking(row.bszxPayRankingId)
|
||||
.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);
|
||||
removeBatchBszxPayRanking(
|
||||
selection.value.map((d) => d.bszxPayRankingId)
|
||||
)
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: BszxPayRanking) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPayRanking'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
60
src/views/bsyx/extra.vue
Normal file
60
src/views/bsyx/extra.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space
|
||||
style="flex-wrap: wrap"
|
||||
v-if="hasRole('superAdmin') || hasRole('admin') || hasRole('foundation')"
|
||||
>
|
||||
<a-button type="text" @click="openUrl('/bsyx/ranking')"
|
||||
>捐款排行榜
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, nextTick } from 'vue';
|
||||
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||
import { openUrl } from '@/utils/common';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||
import { hasRole } from '@/utils/permission';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
website?: CmsWebsite;
|
||||
count?: 0;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'add'): void;
|
||||
}>();
|
||||
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 清除缓存
|
||||
const clearSiteInfoCache = () => {
|
||||
removeSiteInfoCache(
|
||||
'SiteInfo:' + localStorage.getItem('TenantId') + '*'
|
||||
).then((msg) => {
|
||||
if (msg) {
|
||||
message.success(msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
nextTick(() => {
|
||||
if (localStorage.getItem('NotActive')) {
|
||||
// IsActive.value = false
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
282
src/views/bszx/bszxBm/components/bszxBmEdit.vue
Normal file
282
src/views/bszx/bszxBm/components/bszxBmEdit.vue
Normal file
@@ -0,0 +1,282 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="type">
|
||||
<a-radio-group v-model:value="form.type">
|
||||
<a-radio :value="0">校友</a-radio>
|
||||
<a-radio :value="1">单位</a-radio>
|
||||
<a-radio :value="2">爱心人士</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别" name="sex">
|
||||
<DictSelect
|
||||
dict-code="sex"
|
||||
:placeholder="`请选择性别`"
|
||||
v-model:value="form.sexName"
|
||||
@done="chooseSex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别" name="sex">
|
||||
{{ form }}
|
||||
{{ form.sex == 1 ? '男' : '' }}
|
||||
{{ form.sex == 2 ? '女' : '' }}
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="mobile">
|
||||
<a-input
|
||||
allow-clear
|
||||
:disabled="form.mobile"
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.mobile"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
disabled
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
disabled
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否能到场" name="present">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否能到场"
|
||||
v-model:value="form.present"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="邀请函" name="certificate">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入邀请函"-->
|
||||
<!-- v-model:value="form.certificate"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="排序" name="sortNumber">-->
|
||||
<!-- <a-input-number-->
|
||||
<!-- :min="0"-->
|
||||
<!-- :max="9999"-->
|
||||
<!-- class="ele-fluid"-->
|
||||
<!-- placeholder="请输入排序号"-->
|
||||
<!-- v-model:value="form.sortNumber"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="状态" name="status">-->
|
||||
<!-- <a-radio-group v-model:value="form.status">-->
|
||||
<!-- <a-radio :value="0">显示</a-radio>-->
|
||||
<!-- <a-radio :value="1">隐藏</a-radio>-->
|
||||
<!-- </a-radio-group>-->
|
||||
<!-- </a-form-item>-->
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxBm, updateBszxBm } from '@/api/bszx/bszxBm';
|
||||
import { BszxBm } from '@/api/bszx/bszxBm/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;
|
||||
// 修改回显的数据
|
||||
data?: BszxBm | 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<BszxBm>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
sexName: undefined,
|
||||
phone: undefined,
|
||||
mobile: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
present: undefined,
|
||||
age: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
certificate: undefined,
|
||||
dateTime: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxBmName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-报名记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const chooseSex = (data: any) => {
|
||||
form.sex = data.key;
|
||||
form.sexName = data.label;
|
||||
};
|
||||
|
||||
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 ? updateBszxBm : addBszxBm;
|
||||
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.sex) {
|
||||
form.sexName = props.data.sexName;
|
||||
}
|
||||
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>
|
||||
220
src/views/bszx/bszxBm/components/search.vue
Normal file
220
src/views/bszx/bszxBm/components/search.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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-radio-group v-model:value="where.branchId" @change="reload">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
<a-radio-button :value="8">教职员工</a-radio-button>
|
||||
<a-radio-button :value="9">其他</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
show-search
|
||||
v-model:value="where.gradeName"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-select
|
||||
v-if="where.gradeName"
|
||||
show-search
|
||||
v-model:value="where.classId"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="classList"
|
||||
@change="onClass"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 280px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-button type="text" @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { BszxBm, BszxBmParam } from '@/api/bszx/bszxBm/model';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { listBszxBm } from '@/api/bszx/bszxBm';
|
||||
import { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { listBszxClass } from '@/api/bszx/bszxClass';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxBmParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxBmParam>({
|
||||
id: undefined,
|
||||
keywords: '',
|
||||
className: undefined,
|
||||
classId: undefined,
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const bmList = ref<BszxBm[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
const gradeId = ref<number>();
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
const classList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
const getGradeList = () => {
|
||||
listBszxGrade({ branch: where.branchId }).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getClassList = () => {
|
||||
listBszxClass({ gradeId: gradeId.value }).then((res) => {
|
||||
classList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onGrade = (gradeName: number, item: any) => {
|
||||
where.gradeName = item.name;
|
||||
if (gradeName) {
|
||||
console.log(item);
|
||||
gradeId.value = item.id;
|
||||
getClassList();
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const onClass = (classId, item) => {
|
||||
console.log(classId);
|
||||
where.className = item.name;
|
||||
reload();
|
||||
};
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'用户ID',
|
||||
'姓名',
|
||||
'性别',
|
||||
'手机号码',
|
||||
'班级',
|
||||
'年级',
|
||||
'居住地址',
|
||||
'工作单位',
|
||||
'职务',
|
||||
'是否能到场',
|
||||
'邀请函',
|
||||
'报名时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 按搜索结果导出
|
||||
where.sceneType = 'Content';
|
||||
await listBszxBm(where)
|
||||
.then((list) => {
|
||||
bmList.value = list;
|
||||
list?.forEach((d: BszxBm) => {
|
||||
array.push([
|
||||
`${d.userId}`,
|
||||
`${d.name}`,
|
||||
`${d.sex}`,
|
||||
`${d.phone}`,
|
||||
`${d.className}`,
|
||||
`${d.gradeName}`,
|
||||
`${d.address}`,
|
||||
`${d.workUnit}`,
|
||||
`${d.position}`,
|
||||
`${d.present}`,
|
||||
`${d.certificate}`,
|
||||
`${d.createTime}`
|
||||
]);
|
||||
});
|
||||
const sheetName = `导出报名列表${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 },
|
||||
{ wch: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
getGradeList();
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
310
src/views/bszx/bszxBm/index.vue
Normal file
310
src/views/bszx/bszxBm/index.vue
Normal file
@@ -0,0 +1,310 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<!-- <Extra/>-->
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="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 === 'name'">
|
||||
<a-space>
|
||||
<a-avatar :src="record.avatar" />
|
||||
<span>{{ record.name }}</span>
|
||||
</a-space>
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag v-if="record.sex === 2">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'present'">
|
||||
<a-tag v-if="record.present">能</a-tag>
|
||||
<a-tag v-else>不能</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<!-- <a @click="openEdit(record)">修改</a>-->
|
||||
<!-- <a-divider type="vertical" />-->
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<bszxBmEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxBmEdit from './components/bszxBmEdit.vue';
|
||||
import {
|
||||
pageBszxBm,
|
||||
removeBszxBm,
|
||||
removeBatchBszxBm
|
||||
} from '@/api/bszx/bszxBm';
|
||||
import type { BszxBm, BszxBmParam } from '@/api/bszx/bszxBm/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxBm[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxBm | 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 pageBszxBm({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 90,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
customRender: ({ text }) => ['校友', '单位', '爱心人士'][text]
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'mobile',
|
||||
key: 'mobile',
|
||||
width: 130,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
width: 90,
|
||||
align: 'center',
|
||||
customRender: ({ text }) => ['', '男', '女'][text]
|
||||
},
|
||||
{
|
||||
title: '分部',
|
||||
dataIndex: 'branchName',
|
||||
key: 'branchName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'className',
|
||||
key: 'className',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '居住地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '工作单位',
|
||||
dataIndex: 'workUnit',
|
||||
key: 'workUnit',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '职务',
|
||||
dataIndex: 'position',
|
||||
key: 'position',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '是否能到场',
|
||||
dataIndex: 'present',
|
||||
key: 'present',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '状态',
|
||||
// dataIndex: 'status',
|
||||
// key: 'status',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '报名时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxBmParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxBm) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxBm) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxBm(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);
|
||||
removeBatchBszxBm(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: BszxBm) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxBm'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
179
src/views/bszx/bszxBranch/components/bszxBranchEdit.vue
Normal file
179
src/views/bszx/bszxBranch/components/bszxBranchEdit.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxBranch, updateBszxBranch } from '@/api/bszx/bszxBranch';
|
||||
import { BszxBranch } from '@/api/bszx/bszxBranch/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?: BszxBranch | 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<BszxBranch>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
sortNumber: undefined,
|
||||
tenantId: undefined,
|
||||
bszxBranchId: undefined,
|
||||
bszxBranchName: '',
|
||||
status: 0,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
bszxBranchName: [
|
||||
{
|
||||
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 ? updateBszxBranch : addBszxBranch;
|
||||
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>
|
||||
42
src/views/bszx/bszxBranch/components/search.vue
Normal file
42
src/views/bszx/bszxBranch/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
229
src/views/bszx/bszxBranch/index.vue
Normal file
229
src/views/bszx/bszxBranch/index.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="ele-body">
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="bszxBranchId"
|
||||
: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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxBranchEdit
|
||||
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 BszxBranchEdit from './components/bszxBranchEdit.vue';
|
||||
import {
|
||||
pageBszxBranch,
|
||||
removeBszxBranch,
|
||||
removeBatchBszxBranch
|
||||
} from '@/api/bszx/bszxBranch';
|
||||
import type {
|
||||
BszxBranch,
|
||||
BszxBranchParam
|
||||
} from '@/api/bszx/bszxBranch/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxBranch[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxBranch | 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 pageBszxBranch({
|
||||
...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: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxBranchParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxBranch) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxBranch) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxBranch(row.bszxBranchId)
|
||||
.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);
|
||||
removeBatchBszxBranch(selection.value.map((d) => d.bszxBranchId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: BszxBranch) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxBranch'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
205
src/views/bszx/bszxClass/components/bszxClassEdit.vue
Normal file
205
src/views/bszx/bszxClass/components/bszxClassEdit.vue
Normal file
@@ -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="初高中部" name="branch">
|
||||
<a-radio-group v-model:value="form.branch" @change="handleBranch">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="选择年级" name="gradeId">
|
||||
<a-select
|
||||
v-model:value="form.gradeName"
|
||||
show-search
|
||||
placeholder="选择年级"
|
||||
style="width: 200px"
|
||||
:options="options"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.name"
|
||||
@pressEnter="save"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 { addBszxClass, updateBszxClass } from '@/api/bszx/bszxClass';
|
||||
import { BszxClass } from '@/api/bszx/bszxClass/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 { BszxGrade } from '@/api/bszx/bszxGrade/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxClass | 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 options = ref<BszxGrade[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxClass>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
gradeId: undefined,
|
||||
gradeName: undefined,
|
||||
branch: 2,
|
||||
sortNumber: 100,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxClassName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-班级名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const handleChange = (value: string, item: any) => {
|
||||
form.gradeName = value;
|
||||
form.gradeId = item.id;
|
||||
};
|
||||
|
||||
const handleBranch = () => {
|
||||
getBszxGradeList();
|
||||
};
|
||||
|
||||
const getBszxGradeList = () => {
|
||||
listBszxGrade({ branch: form.branch }).then((list) => {
|
||||
options.value = list.map((d) => {
|
||||
d.value = d.name;
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
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 ? updateBszxClass : addBszxClass;
|
||||
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) {
|
||||
getBszxGradeList();
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
// resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
100
src/views/bszx/bszxClass/components/search.vue
Normal file
100
src/views/bszx/bszxClass/components/search.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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-radio-group v-model:value="where.branch" @change="handleSearch">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
show-search
|
||||
v-model:value="where.gradeId"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 240px"
|
||||
v-model:value="where.keywords"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<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 { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxClassParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<BszxClassParam>({
|
||||
gradeId: undefined,
|
||||
eraId: undefined,
|
||||
branch: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const onGrade = (gradeId: number) => {
|
||||
where.gradeId = gradeId;
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
listBszxGrade({}).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
reload();
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
238
src/views/bszx/bszxClass/index.vue
Normal file
238
src/views/bszx/bszxClass/index.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<a-button type="text" @click="openUrl('/bszx/grade')">年级设置 </a-button>
|
||||
<a-button type="text" @click="openUrl('/bszx/class')">班级设置 </a-button>
|
||||
</template>
|
||||
<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 === 'era'">
|
||||
<span>{{ record.era }}级</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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxClassEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxClassEdit from './components/bszxClassEdit.vue';
|
||||
import {
|
||||
pageBszxClass,
|
||||
removeBszxClass,
|
||||
removeBatchBszxClass
|
||||
} from '@/api/bszx/bszxClass';
|
||||
import type { BszxClass, BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { getPageTitle, openUrl } from '@/utils/common';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxClass[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxClass | 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 pageBszxClass({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '初高中',
|
||||
dataIndex: 'branch',
|
||||
key: 'branch',
|
||||
width: 120,
|
||||
customRender: ({ text }) => ['', '初中', '高中'][text]
|
||||
},
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName',
|
||||
width: 120
|
||||
},
|
||||
// {
|
||||
// title: '年级',
|
||||
// dataIndex: 'gradeId',
|
||||
// key: 'gradeId',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxClassParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxClass) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxClass) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxClass(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);
|
||||
removeBatchBszxClass(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: BszxClass) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxClass'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
170
src/views/bszx/bszxGrade/components/bszxGradeEdit.vue
Normal file
170
src/views/bszx/bszxGrade/components/bszxGradeEdit.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="branch">
|
||||
<a-radio-group v-model:value="form.branch">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
</a-radio-group>
|
||||
</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="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 { addBszxGrade, updateBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { BszxGrade } from '@/api/bszx/bszxGrade/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;
|
||||
// 修改回显的数据
|
||||
data?: BszxGrade | 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<BszxGrade>({
|
||||
id: undefined,
|
||||
branch: 2,
|
||||
name: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxGradeName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-年级名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxGrade : addBszxGrade;
|
||||
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>
|
||||
56
src/views/bszx/bszxGrade/components/search.vue
Normal file
56
src/views/bszx/bszxGrade/components/search.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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-radio-group v-model:value="where.branch" @change="handleSearch">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { watch } from 'vue';
|
||||
import { BszxGradeParam } from '@/api/bszx/bszxGrade/model';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxGradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxGradeParam>({
|
||||
branch: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
231
src/views/bszx/bszxGrade/index.vue
Normal file
231
src/views/bszx/bszxGrade/index.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<a-button type="text" @click="openUrl('/bszx/grade')">年级设置 </a-button>
|
||||
<a-button type="text" @click="openUrl('/bszx/class')">班级设置 </a-button>
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="appBszxGradeId"
|
||||
: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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxGradeEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxGradeEdit from './components/bszxGradeEdit.vue';
|
||||
import {
|
||||
pageBszxGrade,
|
||||
removeBszxGrade,
|
||||
removeBatchBszxGrade
|
||||
} from '@/api/bszx/bszxGrade';
|
||||
import type { BszxGrade, BszxGradeParam } from '@/api/bszx/bszxGrade/model';
|
||||
import { getPageTitle, openUrl } from '@/utils/common';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxGrade[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxGrade | 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 pageBszxGrade({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
// {
|
||||
// title: 'ID',
|
||||
// dataIndex: 'id',
|
||||
// key: 'id',
|
||||
// align: 'center',
|
||||
// width: 90,
|
||||
// },
|
||||
{
|
||||
title: '初高中',
|
||||
dataIndex: 'branch',
|
||||
key: 'branch',
|
||||
width: 120,
|
||||
customRender: ({ text }) => ['', '初中', '高中'][text]
|
||||
},
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxGradeParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxGrade) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxGrade) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxGrade(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);
|
||||
removeBatchBszxGrade(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: BszxGrade) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxGrade'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
249
src/views/bszx/bszxOrder/components/bszxPayEdit.vue
Normal file
249
src/views/bszx/bszxOrder/components/bszxPayEdit.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑捐款记录' : '添加捐款记录'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="年龄" name="age">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="sex">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.sex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="捐赠证书" name="certificate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入捐赠证书"
|
||||
v-model:value="form.certificate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxPay | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const images = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxPayName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-捐款记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxPay : addBszxPay;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
566
src/views/bszx/bszxOrder/components/orderInfo.vue
Normal file
566
src/views/bszx/bszxOrder/components/orderInfo.vue
Normal file
@@ -0,0 +1,566 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="`80%`"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:maxable="maxAble"
|
||||
:title="isUpdate ? '编辑订单' : '订单详情'"
|
||||
:body-style="{ paddingBottom: '8px', background: '#f3f3f3' }"
|
||||
@update:visible="updateVisible"
|
||||
:maskClosable="false"
|
||||
:footer="null"
|
||||
@ok="save"
|
||||
>
|
||||
<a-card style="margin-bottom: 20px" :bordered="false">
|
||||
<a-descriptions :column="3">
|
||||
<!-- 第一排-->
|
||||
<a-descriptions-item
|
||||
label="订单编号"
|
||||
span="3"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<span @click="copyText(form.orderNo)">{{ form.orderNo }}</span>
|
||||
</a-descriptions-item>
|
||||
<!-- 第二排-->
|
||||
<a-descriptions-item
|
||||
label="买家信息"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-space class="flex items-center">
|
||||
<a-avatar :src="form.avatar" size="small" />
|
||||
{{ form.realName }}
|
||||
</a-space>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="订单金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.totalPrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="订单状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.orderStatus === 0">未完成</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 1" color="green">已完成</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 2" color="red">已取消</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 3" color="red">取消中</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 4" color="red">退款申请中</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 5" color="red">退款被拒绝</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 6" color="orange">退款成功</a-tag>
|
||||
<a-tag v-if="form.orderStatus === 7" color="pink"
|
||||
>客户端申请退款</a-tag
|
||||
>
|
||||
</a-descriptions-item>
|
||||
<!-- 第三排-->
|
||||
<a-descriptions-item
|
||||
label="手机号码"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.phone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="实付金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.payPrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="支付状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.payStatus == 1" color="green">已付款</a-tag>
|
||||
<a-tag v-if="form.payStatus == 0">未付款</a-tag>
|
||||
<a-tag v-if="form.payStatus == 3">未付款,占场中</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第四排-->
|
||||
<a-descriptions-item
|
||||
label="收货地址"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.address }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="减少的金额"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
¥{{ form.reducePrice }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="核销状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.deliveryStatus == 10">未核销</a-tag>
|
||||
<a-tag v-if="form.deliveryStatus == 20" color="green">已核销</a-tag>
|
||||
<a-tag v-if="form.deliveryStatus == 30" color="bule">部分核销</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第五排-->
|
||||
<a-descriptions-item
|
||||
label="备注信息"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ form.comments }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="支付方式"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tooltip :title="`支付时间:${form.payTime || ''}`">
|
||||
<template v-if="form.payStatus == 1">
|
||||
<a-tag v-if="form.payType == 0">余额支付</a-tag>
|
||||
<a-tag v-if="form.payType == 1">
|
||||
<WechatOutlined class="tag-icon" />
|
||||
微信支付
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 2">积分</a-tag>
|
||||
<a-tag v-if="form.payType == 3">
|
||||
<AlipayCircleOutlined class="tag-icon" />
|
||||
支付宝
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 4">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
现金
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 5">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
POS机
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 6">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP月卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 7">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP年卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 8">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP次卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 9">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC月卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 10">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC年卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 11">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC次卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 12">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
免费
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 13">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP充值卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 14">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC充值卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 15">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
积分支付
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 16">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
VIP季卡
|
||||
</a-tag>
|
||||
<a-tag v-if="form.payType == 17">
|
||||
<IdcardOutlined class="tag-icon" />
|
||||
IC季卡
|
||||
</a-tag>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="开票状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.isInvoice == 0">未开具</a-tag>
|
||||
<a-tag v-if="form.isInvoice == 1" color="green">已开具</a-tag>
|
||||
<a-tag v-if="form.isInvoice == 2" color="blue">不能开具</a-tag>
|
||||
</a-descriptions-item>
|
||||
<!-- 第六排-->
|
||||
<a-descriptions-item
|
||||
label="下单时间"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
{{ toDateString(form.createTime, 'yyyy-MM-dd HH:mm') }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="交易流水号"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tooltip :title="form.payTime">{{ form.transactionId }}</a-tooltip>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="结算状态"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<a-tag v-if="form.isSettled == 0">未结算</a-tag>
|
||||
<a-tag v-if="form.isSettled == 1" color="green">已结算</a-tag>
|
||||
</a-descriptions-item>
|
||||
|
||||
<!-- <a-descriptions-item span="3">-->
|
||||
<!-- <a-divider/>-->
|
||||
<!-- </a-descriptions-item>-->
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
<a-card class="order-card" :bordered="false">
|
||||
<a-spin :spinning="loading">
|
||||
<a-table
|
||||
:data-source="orderInfo"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
/>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import { ColumnItem } from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import {
|
||||
CheckOutlined,
|
||||
CloseOutlined,
|
||||
CoffeeOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { ShopOrder } from '@/api/shop/shopOrder/model';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { pageBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { toDateString } from 'ele-admin-pro';
|
||||
import { copyText } from '@/utils/common';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: ShopOrder | null;
|
||||
}>();
|
||||
|
||||
export interface step {
|
||||
title?: String | undefined;
|
||||
subTitle?: String | undefined;
|
||||
description?: String | undefined;
|
||||
}
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxAble = ref(true);
|
||||
// 订单信息
|
||||
const orderInfo = ref<BszxPay[]>([]);
|
||||
|
||||
// 步骤条
|
||||
const steps = ref<step[]>([
|
||||
{
|
||||
title: '报餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '付款',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '发餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '取餐',
|
||||
description: undefined
|
||||
},
|
||||
{
|
||||
title: '完成',
|
||||
description: undefined
|
||||
}
|
||||
]);
|
||||
const active = ref(2);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 订单信息
|
||||
const form = reactive<ShopOrder>({
|
||||
// 订单号
|
||||
orderId: undefined,
|
||||
// 订单编号
|
||||
orderNo: undefined,
|
||||
// 订单类型,0商城订单 1预定订单/外卖 2会员卡
|
||||
type: undefined,
|
||||
// 快递/自提
|
||||
deliveryType: undefined,
|
||||
// 下单渠道,0小程序预定 1俱乐部训练场 3活动订场
|
||||
channel: undefined,
|
||||
// 微信支付订单号
|
||||
transactionId: undefined,
|
||||
// 微信退款订单号
|
||||
refundOrder: undefined,
|
||||
// 商户ID
|
||||
merchantId: undefined,
|
||||
// 商户名称
|
||||
merchantName: undefined,
|
||||
// 商户编号
|
||||
merchantCode: undefined,
|
||||
// 使用的优惠券id
|
||||
couponId: undefined,
|
||||
// 使用的会员卡id
|
||||
cardId: undefined,
|
||||
// 关联管理员id
|
||||
adminId: undefined,
|
||||
// 核销管理员id
|
||||
confirmId: undefined,
|
||||
// IC卡号
|
||||
icCard: undefined,
|
||||
// 头像
|
||||
avatar: undefined,
|
||||
// 真实姓名
|
||||
realName: undefined,
|
||||
// 手机号码
|
||||
phone: undefined,
|
||||
// 收货地址
|
||||
address: undefined,
|
||||
//
|
||||
addressLat: undefined,
|
||||
//
|
||||
addressLng: undefined,
|
||||
// 自提店铺id
|
||||
selfTakeMerchantId: undefined,
|
||||
// 自提店铺
|
||||
selfTakeMerchantName: undefined,
|
||||
// 配送开始时间
|
||||
sendStartTime: undefined,
|
||||
// 配送结束时间
|
||||
sendEndTime: undefined,
|
||||
// 发货店铺id
|
||||
expressMerchantId: undefined,
|
||||
// 发货店铺
|
||||
expressMerchantName: undefined,
|
||||
// 订单总额
|
||||
totalPrice: undefined,
|
||||
// 减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格
|
||||
reducePrice: undefined,
|
||||
// 实际付款
|
||||
payPrice: undefined,
|
||||
// 用于统计
|
||||
price: undefined,
|
||||
// 价钱,用于积分赠送
|
||||
money: undefined,
|
||||
// 退款金额
|
||||
refundMoney: undefined,
|
||||
// 教练价格
|
||||
coachPrice: undefined,
|
||||
// 购买数量
|
||||
totalNum: undefined,
|
||||
// 教练id
|
||||
coachId: undefined,
|
||||
// 支付的用户id
|
||||
payUserId: undefined,
|
||||
// 0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
payType: undefined,
|
||||
// 代付支付方式,0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
||||
friendPayType: undefined,
|
||||
// 0未付款,1已付款
|
||||
payStatus: undefined,
|
||||
// 0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款
|
||||
orderStatus: undefined,
|
||||
// 发货状态(10未发货 20已发货 30部分发货)
|
||||
deliveryStatus: undefined,
|
||||
// 发货时间
|
||||
deliveryTime: undefined,
|
||||
// 优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡
|
||||
couponType: undefined,
|
||||
// 优惠说明
|
||||
couponDesc: undefined,
|
||||
// 二维码地址,保存订单号,支付成功后才生成
|
||||
qrcode: undefined,
|
||||
// vip月卡年卡、ic月卡年卡回退次数
|
||||
returnNum: undefined,
|
||||
// vip充值回退金额
|
||||
returnMoney: undefined,
|
||||
// 预约详情开始时间数组
|
||||
startTime: undefined,
|
||||
// 是否已开具发票:0未开发票,1已开发票,2不能开具发票
|
||||
isInvoice: undefined,
|
||||
// 发票流水号
|
||||
invoiceNo: undefined,
|
||||
// 支付时间
|
||||
payTime: undefined,
|
||||
// 退款时间
|
||||
refundTime: undefined,
|
||||
// 申请退款时间
|
||||
refundApplyTime: undefined,
|
||||
// 过期时间
|
||||
expirationTime: undefined,
|
||||
// 对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单
|
||||
checkBill: undefined,
|
||||
// 订单是否已结算(0未结算 1已结算)
|
||||
isSettled: undefined,
|
||||
// 系统版本号 0当前版本 value=其他版本
|
||||
version: undefined,
|
||||
// 用户id
|
||||
userId: undefined,
|
||||
// 备注
|
||||
comments: undefined,
|
||||
// 排序号
|
||||
sortNumber: undefined,
|
||||
// 是否删除, 0否, 1是
|
||||
deleted: undefined,
|
||||
// 租户id
|
||||
tenantId: undefined,
|
||||
// 修改时间
|
||||
updateTime: undefined,
|
||||
// 创建时间
|
||||
createTime: undefined,
|
||||
// 自提码
|
||||
selfTakeCode: undefined,
|
||||
// 是否已收到赠品
|
||||
hasTakeGift: undefined
|
||||
});
|
||||
|
||||
// 请求状态
|
||||
const loading = ref(true);
|
||||
|
||||
const { resetFields } = useForm(form);
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '商品名称',
|
||||
dataIndex: 'formName',
|
||||
key: 'formName',
|
||||
align: 'center',
|
||||
width: 280
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
dataIndex: 'price',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'isFree',
|
||||
align: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
/* 制作步骤条 */
|
||||
const loadSteps = (order) => {
|
||||
steps.value = [];
|
||||
steps.value.push({
|
||||
title: '下单'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '付款'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '发货'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '收货'
|
||||
});
|
||||
steps.value.push({
|
||||
title: '完成'
|
||||
});
|
||||
|
||||
// 下单
|
||||
if (order.payStatus == 10) {
|
||||
active.value = 0;
|
||||
steps.value[0].description = order.createTime;
|
||||
}
|
||||
// 付款
|
||||
if (order.payStatus == 20) {
|
||||
active.value = 1;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
}
|
||||
// 发货
|
||||
if (order.payStatus == 20 && order.deliveryStatus == 20) {
|
||||
active.value = 2;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
}
|
||||
// 收货
|
||||
if (order.payStatus == 20 && order.receiptStatus == 20) {
|
||||
active.value = 3;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
steps.value[3].description = order.receiptTime;
|
||||
}
|
||||
// 完成
|
||||
if (order.payStatus == 20 && order.orderStatus == 30) {
|
||||
active.value = 4;
|
||||
steps.value[0].description = order.createTime;
|
||||
steps.value[1].description = order.payTime;
|
||||
steps.value[2].description = order.deliveryTime;
|
||||
steps.value[3].description = order.receiptTime;
|
||||
}
|
||||
// 已取消
|
||||
if (order.orderStatus == 20) {
|
||||
active.value = 4;
|
||||
}
|
||||
};
|
||||
|
||||
// const getOrderInfo = () => {
|
||||
// const orderId = props.data?.orderId;
|
||||
// listOrderInfo({ orderId }).then((data) => {
|
||||
// orderInfo.value = data.filter((d) => d.totalNum > 0);
|
||||
// });
|
||||
// };
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
if (props.data) {
|
||||
loading.value = true;
|
||||
assignObject(form, props.data);
|
||||
pageBszxPay({ orderNo: form.orderNo }).then((res) => {
|
||||
if (res?.list) {
|
||||
orderInfo.value = res?.list;
|
||||
}
|
||||
loading.value = false;
|
||||
});
|
||||
loadSteps(props.data);
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import * as MenuIcons from '@/layout/menu-icons';
|
||||
|
||||
export default {
|
||||
name: 'BszxOrderInfo',
|
||||
components: MenuIcons
|
||||
};
|
||||
</script>
|
||||
203
src/views/bszx/bszxOrder/components/search.vue
Normal file
203
src/views/bszx/bszxOrder/components/search.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-select
|
||||
v-model:value="where.payStatus"
|
||||
style="width: 150px"
|
||||
placeholder="付款状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">已付款</a-select-option>
|
||||
<a-select-option :value="0">未付款</a-select-option>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model:value="where.orderStatus"
|
||||
style="width: 150px"
|
||||
placeholder="订单状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">已完成</a-select-option>
|
||||
<a-select-option :value="0">未完成</a-select-option>
|
||||
<a-select-option :value="2">未使用</a-select-option>
|
||||
<a-select-option :value="3">已取消</a-select-option>
|
||||
<a-select-option :value="4">退款中</a-select-option>
|
||||
<a-select-option :value="5">退款被拒</a-select-option>
|
||||
<a-select-option :value="6">退款成功</a-select-option>
|
||||
</a-select>
|
||||
<a-select
|
||||
:options="getPayType()"
|
||||
v-model:value="where.payType"
|
||||
style="width: 150px"
|
||||
placeholder="付款方式"
|
||||
@change="search"
|
||||
/>
|
||||
<a-select
|
||||
v-model:value="where.isInvoice"
|
||||
style="width: 150px"
|
||||
placeholder="开票状态"
|
||||
@change="search"
|
||||
>
|
||||
<a-select-option :value="1">已开票</a-select-option>
|
||||
<a-select-option :value="0">未开票</a-select-option>
|
||||
<a-select-option :value="2">不能开票</a-select-option>
|
||||
</a-select>
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 280px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
<a-button @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import { message } from 'ant-design-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { ShopOrder, ShopOrderParam } from '@/api/shop/shopOrder/model';
|
||||
import { listShopOrder } from '@/api/shop/shopOrder';
|
||||
import { getPayType } from '@/utils/shop';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: ShopOrderParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<ShopOrderParam>({
|
||||
keywords: '',
|
||||
orderId: undefined,
|
||||
orderNo: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
userId: undefined,
|
||||
phone: undefined,
|
||||
payStatus: undefined,
|
||||
orderStatus: undefined,
|
||||
payType: undefined,
|
||||
isInvoice: undefined
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
xlsFileName.value = `${d1}至${d2}`;
|
||||
where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
|
||||
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : undefined;
|
||||
emit('search', {
|
||||
...where
|
||||
});
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
search();
|
||||
};
|
||||
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const orders = ref<ShopOrder[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'订单编号',
|
||||
'订单标题',
|
||||
'买家姓名',
|
||||
'手机号码',
|
||||
'实付金额(元)',
|
||||
'支付方式',
|
||||
'付款时间',
|
||||
'下单时间'
|
||||
]
|
||||
];
|
||||
|
||||
await listShopOrder(where)
|
||||
.then((list) => {
|
||||
orders.value = list;
|
||||
list?.forEach((d: ShopOrder) => {
|
||||
array.push([
|
||||
`${d.orderNo}`,
|
||||
`${d.comments}`,
|
||||
`${d.realName}`,
|
||||
`${d.phone}`,
|
||||
`${d.payPrice}`,
|
||||
`${getPayType(d.payType)}`,
|
||||
`${d.payTime || ''}`,
|
||||
`${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: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
334
src/views/bszx/bszxOrder/index.vue
Normal file
334
src/views/bszx/bszxOrder/index.vue
Normal file
@@ -0,0 +1,334 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="orderId"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
@add="openEdit"
|
||||
@batchMove="openMove"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<div @click="onSearch(record)" class="cursor-pointer">{{
|
||||
record.name || '匿名'
|
||||
}}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'phone'">
|
||||
<div v-if="record.mobile" class="text-gray-400">{{
|
||||
record.mobile
|
||||
}}</div>
|
||||
<div v-else class="text-gray-600">{{ record.phone }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'payType'">
|
||||
<template v-for="item in getPayType()">
|
||||
<template v-if="record.payStatus == 1">
|
||||
<span v-if="item.value == record.payType">{{
|
||||
item.label
|
||||
}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span></span>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="column.key === 'payStatus'">
|
||||
<a-tag
|
||||
v-if="record.payStatus == 1"
|
||||
color="green"
|
||||
@click="updatePayStatus(record)"
|
||||
>已付款</a-tag
|
||||
>
|
||||
<a-tag v-if="record.payStatus == 0" @click="updatePayStatus(record)"
|
||||
>未付款</a-tag
|
||||
>
|
||||
<a-tag v-if="record.payStatus == 3">未付款,占场中</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'image'">
|
||||
<a-image :src="record.image" :width="50" />
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag v-if="record.sex === 2">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'deliveryStatus'">
|
||||
<a-tag v-if="record.deliveryStatus == 10">未核销</a-tag>
|
||||
<a-tag v-if="record.deliveryStatus == 20" color="green"
|
||||
>已核销</a-tag
|
||||
>
|
||||
<a-tag v-if="record.deliveryStatus == 30" color="bule"
|
||||
>部分核销</a-tag
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.key === 'orderStatus'">
|
||||
<a-tag v-if="record.orderStatus === 0">未完成</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 1" color="green">已完成</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 2" color="red">已取消</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 3" color="red">取消中</a-tag>
|
||||
<a-tag v-if="record.orderStatus === 4" color="red"
|
||||
>退款申请中</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 5" color="red"
|
||||
>退款被拒绝</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 6" color="orange"
|
||||
>退款成功</a-tag
|
||||
>
|
||||
<a-tag v-if="record.orderStatus === 7" color="pink"
|
||||
>客户端申请退款</a-tag
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.key === 'isInvoice'">
|
||||
<a-tag v-if="record.isInvoice == 0">未开具</a-tag>
|
||||
<a-tag v-if="record.isInvoice == 1" color="green">已开具</a-tag>
|
||||
<a-tag v-if="record.isInvoice == 2" color="blue">不能开具</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<OrderInfo v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
import { pageBszxOrder } from '@/api/bszx/bszxOrder';
|
||||
import OrderInfo from './components/orderInfo.vue';
|
||||
import { ShopOrder, ShopOrderParam } from '@/api/shop/shopOrder/model';
|
||||
import { updateShopOrder } from '@/api/shop/shopOrder';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { updateUser } from '@/api/system/user';
|
||||
import { getPayType } from '@/utils/shop';
|
||||
import { repairOrder } from '@/api/bszx/bszxPay';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ShopOrder[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ShopOrder | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
return pageBszxOrder({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '订单号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '实付金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
align: 'center',
|
||||
customRender: ({ text }) => '¥' + text
|
||||
},
|
||||
{
|
||||
title: '支付方式',
|
||||
dataIndex: 'payType',
|
||||
key: 'payType',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '支付状态',
|
||||
dataIndex: 'payStatus',
|
||||
key: 'payStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '核销状态',
|
||||
dataIndex: 'deliveryStatus',
|
||||
key: 'deliveryStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '开票状态',
|
||||
dataIndex: 'isInvoice',
|
||||
key: 'isInvoice',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '订单状态',
|
||||
dataIndex: 'orderStatus',
|
||||
key: 'orderStatus',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '支付时间',
|
||||
// dataIndex: 'payTime',
|
||||
// key: 'payTime',
|
||||
// align: 'center',
|
||||
// width: 180,
|
||||
// sorter: true,
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '下单时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
sorter: true,
|
||||
ellipsis: true
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: ShopOrderParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
const onSearch = (item: ShopOrder) => {
|
||||
reload({ userId: item.userId });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ShopOrder) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 修复订单支付状态
|
||||
*/
|
||||
const updatePayStatus = (record: ShopOrder) => {
|
||||
// 修复订单
|
||||
repairOrder(record)
|
||||
.then(() => {
|
||||
message.success('修复成功');
|
||||
})
|
||||
.then(() => {
|
||||
if (record.realName == '' || record.realName == undefined) {
|
||||
// 更新用户真实姓名
|
||||
updateUser({
|
||||
userId: record.userId,
|
||||
realName: record.realName
|
||||
});
|
||||
}
|
||||
reload();
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: ShopOrder) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import * as MenuIcons from '@/layout/menu-icons';
|
||||
|
||||
export default {
|
||||
name: 'BszxOrder',
|
||||
components: MenuIcons
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
249
src/views/bszx/bszxPay/components/bszxPayEdit.vue
Normal file
249
src/views/bszx/bszxPay/components/bszxPayEdit.vue
Normal file
@@ -0,0 +1,249 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑捐款记录' : '添加捐款记录'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="年龄" name="age">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="sex">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.sex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="捐赠证书" name="certificate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入捐赠证书"
|
||||
v-model:value="form.certificate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxPay | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const images = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxPayName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-捐款记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateBszxPay : addBszxPay;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
231
src/views/bszx/bszxPay/components/search.vue
Normal file
231
src/views/bszx/bszxPay/components/search.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-radio-group v-model:value="branchId" @change="onBranchId">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
v-if="branchId"
|
||||
show-search
|
||||
v-model:value="where.gradeName"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-select
|
||||
v-if="where.gradeName"
|
||||
show-search
|
||||
v-model:value="where.className"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="classList"
|
||||
@change="onClass"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 220px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-button @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
import { BszxBm } from '@/api/bszx/bszxBm/model';
|
||||
import { listBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { listBszxClass } from '@/api/bszx/bszxClass';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxPayParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxPayParam>({
|
||||
id: undefined,
|
||||
keywords: '',
|
||||
gradeName: undefined,
|
||||
className: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
where.createTimeStart = d1 ? d1 + ' 00:00:00' : undefined;
|
||||
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : undefined;
|
||||
emit('search', {
|
||||
...where
|
||||
});
|
||||
};
|
||||
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const bmList = ref<BszxBm[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
const branchId = ref<number>();
|
||||
const gradeId = ref<number>();
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
const classList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const getGradeList = () => {
|
||||
listBszxGrade({ branch: branchId.value }).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getClassList = () => {
|
||||
listBszxClass({ gradeId: gradeId.value }).then((res) => {
|
||||
classList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onGrade = (gradeName: number, item: any) => {
|
||||
where.gradeName = item.name;
|
||||
if (gradeName) {
|
||||
console.log(item);
|
||||
gradeId.value = item.id;
|
||||
getClassList();
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const onBranchId = () => {
|
||||
getGradeList();
|
||||
};
|
||||
|
||||
const onClass = (classId, item) => {
|
||||
console.log(classId);
|
||||
where.className = item.name;
|
||||
reload();
|
||||
};
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'订单编号',
|
||||
'姓名',
|
||||
'手机号码',
|
||||
'捐款金额',
|
||||
'性别',
|
||||
'年级',
|
||||
'班级',
|
||||
'居住地址',
|
||||
'工作单位',
|
||||
'职务',
|
||||
'捐款时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 按搜索结果导出
|
||||
where.sceneType = 'Content';
|
||||
await listBszxPay(where)
|
||||
.then((list) => {
|
||||
bmList.value = list;
|
||||
list?.forEach((d: BszxBm) => {
|
||||
array.push([
|
||||
`${d.orderNo}`,
|
||||
`${d.name}`,
|
||||
`${d.mobile}`,
|
||||
`${d.price}`,
|
||||
`${d.sex == 1 ? '男' : ''}${d.sex == 2 ? '女' : '-'}`,
|
||||
`${d.gradeName ? d.gradeName : '-'}`,
|
||||
`${d.className ? d.className : '-'}`,
|
||||
`${d.address ? d.address : '-'}`,
|
||||
`${d.workUnit ? d.workUnit : '-'}`,
|
||||
`${d.position ? d.position : '-'}`,
|
||||
`${d.createTime}`
|
||||
]);
|
||||
});
|
||||
const sheetName = `导出捐款记录${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 },
|
||||
{ wch: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
getGradeList();
|
||||
|
||||
watch(
|
||||
() => props.totalPriceAmount,
|
||||
(totalPriceAmount) => {
|
||||
console.log(totalPriceAmount, 'totalPriceAmount');
|
||||
}
|
||||
);
|
||||
</script>
|
||||
346
src/views/bszx/bszxPay/index.vue
Normal file
346
src/views/bszx/bszxPay/index.vue
Normal file
@@ -0,0 +1,346 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
:parse-data="parseData"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
@add="openEdit"
|
||||
@remove="removeBatch"
|
||||
@batchMove="openMove"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<div @click="onSearch(record)" class="cursor-pointer">{{
|
||||
record.name || '匿名'
|
||||
}}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'phone'">
|
||||
<div v-if="record.mobile" class="text-gray-400">{{
|
||||
record.mobile
|
||||
}}</div>
|
||||
<div v-else class="text-gray-600">{{ record.phone }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'image'">
|
||||
<a-image :src="record.image" :width="50" />
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag v-if="record.sex === 2">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'present'">
|
||||
<a-tag v-if="record.present">能</a-tag>
|
||||
<a-tag v-else>不能</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span v-if="totalPriceAmount" class="text-red-500 font-bold"
|
||||
>小计:¥{{ totalPriceAmount.toFixed(2) }}</span
|
||||
>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxPayEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxPayEdit from './components/bszxPayEdit.vue';
|
||||
import {
|
||||
pageBszxPay,
|
||||
removeBszxPay,
|
||||
removeBatchBszxPay
|
||||
} from '@/api/bszx/bszxPay';
|
||||
import type { BszxPay, BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
import { PageResult } from '@/api';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxPay[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxPay | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
const totalPriceAmount = ref<number>(0);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
return pageBszxPay({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 整理数据
|
||||
const parseData = (data: PageResult<BszxPay>) => {
|
||||
totalPriceAmount.value = 0;
|
||||
data.list?.map((item) => {
|
||||
if (item.price) {
|
||||
totalPriceAmount.value += Number(item.price);
|
||||
}
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '捐款金额',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
customRender: ({ text }) => '¥' + text
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
align: 'center',
|
||||
customRender: ({ text }) => ['', '男', '女'][text]
|
||||
},
|
||||
{
|
||||
title: '分部',
|
||||
dataIndex: 'branchName',
|
||||
key: 'branchName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'className',
|
||||
key: 'className',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '居住地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '工作单位',
|
||||
dataIndex: 'workUnit',
|
||||
key: 'workUnit',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '职务',
|
||||
dataIndex: 'position',
|
||||
key: 'position',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '捐赠证书',
|
||||
// dataIndex: 'certificate',
|
||||
// key: 'certificate',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '心愿',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '状态',
|
||||
// dataIndex: 'status',
|
||||
// key: 'status',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '捐款时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
sorter: true,
|
||||
ellipsis: true
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxPayParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
const onSearch = (item: BszxPay) => {
|
||||
reload({ userId: item.userId });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxPay) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxPay) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxPay(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);
|
||||
removeBatchBszxPay(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: BszxPay) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
// openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPay'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
272
src/views/bszx/bszxPayCert/components/appBszxPayEdit.vue
Normal file
272
src/views/bszx/bszxPayCert/components/appBszxPayEdit.vue
Normal file
@@ -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="年龄" name="age">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="sex">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.sex"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="班级" name="className">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入班级"
|
||||
v-model:value="form.className"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年级" name="gradeName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入年级"
|
||||
v-model:value="form.gradeName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="居住地址" name="address">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入居住地址"
|
||||
v-model:value="form.address"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="捐赠证书" name="certificate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入捐赠证书"
|
||||
v-model:value="form.certificate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addBszxPay, updateBszxPay } from '@/api/bszx/bszxPay';
|
||||
import { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: BszxPay | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const images = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
appBszxPayName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写应用-百色中学-捐款记录名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const 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 ? updateBszxPay : addBszxPay;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
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>
|
||||
140
src/views/bszx/bszxPayCert/components/search.vue
Normal file
140
src/views/bszx/bszxPayCert/components/search.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 280px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
<a-button type="text" @click="handleExport">导出</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
import { BszxBm } from '@/api/bszx/bszxBm/model';
|
||||
import { listBszxPay } from '@/api/bszx/bszxPay';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxPayParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxPayParam>({
|
||||
id: undefined,
|
||||
keywords: '',
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const bmList = ref<BszxBm[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'用户ID',
|
||||
'姓名',
|
||||
'性别',
|
||||
'手机号码',
|
||||
'班级',
|
||||
'年级',
|
||||
'居住地址',
|
||||
'工作单位',
|
||||
'职务',
|
||||
'是否能到场',
|
||||
'邀请函',
|
||||
'捐款时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 按搜索结果导出
|
||||
where.sceneType = 'Content';
|
||||
await listBszxPay(where)
|
||||
.then((list) => {
|
||||
bmList.value = list;
|
||||
list?.forEach((d: BszxBm) => {
|
||||
array.push([
|
||||
`${d.userId}`,
|
||||
`${d.name}`,
|
||||
`${d.sex}`,
|
||||
`${d.phone}`,
|
||||
`${d.className}`,
|
||||
`${d.gradeName}`,
|
||||
`${d.address}`,
|
||||
`${d.workUnit}`,
|
||||
`${d.position}`,
|
||||
`${d.present}`,
|
||||
`${d.certificate}`,
|
||||
`${d.createTime}`
|
||||
]);
|
||||
});
|
||||
const sheetName = `导出捐款记录${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 },
|
||||
{ wch: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
119
src/views/bszx/bszxPayCert/index.vue
Normal file
119
src/views/bszx/bszxPayCert/index.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="cert-box h-screen">
|
||||
<div class="cert-content" v-html="article.content"></div>
|
||||
<div class="create-time text-right">
|
||||
<span>广西百色中学</span>
|
||||
<p>{{ toDateString(form.createTime, 'YYYY-MM-dd') }}</p>
|
||||
</div>
|
||||
<!-- 二维码 -->
|
||||
<div class="qrcode mt-10 text-center">
|
||||
<ele-qr-code-svg :value="`${qrcode}`" :size="200" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
import { onMounted, ref, unref, reactive } from 'vue';
|
||||
import { assignObject, toDateString } from 'ele-admin-pro';
|
||||
import { getBszxPay } from '@/api/bszx/bszxPay';
|
||||
import type { BszxPay } from '@/api/bszx/bszxPay/model';
|
||||
import { getCmsArticle } from '@/api/cms/cmsArticle';
|
||||
import { CmsArticle } from '@/api/cms/cmsArticle/model';
|
||||
|
||||
// 二维码内容
|
||||
const qrcode = ref('123');
|
||||
// 当前编辑数据
|
||||
// 是否显示编辑弹窗
|
||||
// 是否显示批量移动弹窗
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
// 捐款记录
|
||||
const form = reactive<BszxPay>({
|
||||
id: undefined,
|
||||
age: undefined,
|
||||
name: undefined,
|
||||
sex: undefined,
|
||||
phone: undefined,
|
||||
className: undefined,
|
||||
gradeName: undefined,
|
||||
address: undefined,
|
||||
workUnit: undefined,
|
||||
position: undefined,
|
||||
number: undefined,
|
||||
price: undefined,
|
||||
extra: undefined,
|
||||
dateTime: undefined,
|
||||
certificate: undefined,
|
||||
formData: undefined,
|
||||
formId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
// 文章
|
||||
const article = reactive<CmsArticle>({
|
||||
articleId: undefined,
|
||||
content: undefined,
|
||||
createTime: undefined
|
||||
});
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
const { currentRoute } = useRouter();
|
||||
const { params } = unref(currentRoute);
|
||||
console.log(params.id, 'query');
|
||||
getBszxPay(Number(params?.id)).then((data) => {
|
||||
assignObject(form, data);
|
||||
if (data.formId && data.formId > 0) {
|
||||
getCmsArticle(data.formId).then((result) => {
|
||||
if (result.content) {
|
||||
result.content = result?.content.replace(
|
||||
'校友',
|
||||
data?.name + '___校友'
|
||||
);
|
||||
result.content = result?.content.replace(
|
||||
'人民币',
|
||||
'人民币 ' + data?.price
|
||||
);
|
||||
qrcode.value =
|
||||
'https://website.websoft.top/bszx/pay-cert/' + data?.id;
|
||||
}
|
||||
assignObject(article, result);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
query();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPay'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.cert-box {
|
||||
width: 500px;
|
||||
margin: 10px auto;
|
||||
padding: 58px;
|
||||
border-bottom: blue 1px solid;
|
||||
background: url('https://oss.wsdns.cn/20250127/cb1088c3b1354a118477a0b1a3cdac41.png')
|
||||
no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
.cert-content {
|
||||
margin-top: 250px;
|
||||
}
|
||||
</style>
|
||||
220
src/views/bszx/bszxPayRanking/components/bszxPayRankingEdit.vue
Normal file
220
src/views/bszx/bszxPayRanking/components/bszxPayRankingEdit.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑百色中学-捐款排行' : '添加百色中学-捐款排行'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="来源表ID(项目名称)" name="formId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入来源表ID(项目名称)"
|
||||
v-model:value="form.formId"
|
||||
/>
|
||||
</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="totalPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入获得捐款总金额"
|
||||
v-model:value="form.totalPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态, 0正常, 1冻结" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否删除, 0否, 1是" name="deleted">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否删除, 0否, 1是"
|
||||
v-model:value="form.deleted"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 {
|
||||
addBszxPayRanking,
|
||||
updateBszxPayRanking
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import { BszxPayRanking } from '@/api/bszx/bszxPayRanking/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?: BszxPayRanking | 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<BszxPayRanking>({
|
||||
id: undefined,
|
||||
formId: undefined,
|
||||
number: undefined,
|
||||
totalPrice: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
status: 0,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
bszxPayRankingName: [
|
||||
{
|
||||
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
|
||||
? updateBszxPayRanking
|
||||
: addBszxPayRanking;
|
||||
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>
|
||||
90
src/views/bszx/bszxPayRanking/components/search.vue
Normal file
90
src/views/bszx/bszxPayRanking/components/search.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
@change="search"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<a-tooltip title="实际订单总金额(来自订单表)" class="flex px-4">
|
||||
<span class="text-gray-400">实际订单总金额:</span>
|
||||
<span class="text-gray-700 font-bold"
|
||||
>¥{{ formatNumber(bszxTotalPrice) }}</span
|
||||
>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip title="排行榜统计金额(来自排行榜表)" class="flex px-4 ml-4">
|
||||
<span class="text-gray-400">排行榜统计金额:</span>
|
||||
<span class="text-gray-700 font-bold"
|
||||
>¥{{ formatNumber(rankingTotalPrice) }}</span
|
||||
>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { watch, ref, computed } from 'vue';
|
||||
import { formatNumber } from 'ele-admin-pro/es';
|
||||
import { BszxPayRankingParam } from '@/api/bszx/bszxPayRanking/model';
|
||||
import { useBszxStatisticsStore } from '@/store/modules/bszx-statistics';
|
||||
|
||||
// 使用百色中学统计数据 store
|
||||
const bszxStatisticsStore = useBszxStatisticsStore();
|
||||
|
||||
// 从 store 中获取总金额
|
||||
const bszxTotalPrice = computed(() => bszxStatisticsStore.bszxTotalPrice);
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
// 保留这个属性以保持向后兼容,但不再使用
|
||||
totalPriceAmount?: number;
|
||||
// 排行榜统计金额
|
||||
rankingTotalPrice?: number;
|
||||
}>(),
|
||||
{
|
||||
rankingTotalPrice: 0
|
||||
}
|
||||
);
|
||||
|
||||
// 日期范围选择
|
||||
const dateRange = ref<[string, string]>(['', '']);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxPayRankingParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<BszxPayRankingParam>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
createTimeStart: undefined,
|
||||
createTimeEnd: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
const [d1, d2] = dateRange.value ?? [];
|
||||
emit('search', {
|
||||
...where,
|
||||
createTimeStart: d1 ? d1 + ' 00:00:00' : '',
|
||||
createTimeEnd: d2 ? d2 + ' 23:59:59' : ''
|
||||
});
|
||||
};
|
||||
|
||||
const onSearch = (text: string) => {
|
||||
where.sceneType = text;
|
||||
search();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
255
src/views/bszx/bszxPayRanking/index.vue
Normal file
255
src/views/bszx/bszxPayRanking/index.vue
Normal file
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
:rankingTotalPrice="rankingTotalPrice"
|
||||
@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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxPayRankingEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, onMounted } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxPayRankingEdit from './components/bszxPayRankingEdit.vue';
|
||||
import {
|
||||
removeBszxPayRanking,
|
||||
removeBatchBszxPayRanking,
|
||||
ranking
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import type {
|
||||
BszxPayRanking,
|
||||
BszxPayRankingParam
|
||||
} from '@/api/bszx/bszxPayRanking/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
import { useBszxStatisticsStore } from '@/store/modules/bszx-statistics';
|
||||
|
||||
// 使用百色中学统计数据 store
|
||||
const bszxStatisticsStore = useBszxStatisticsStore();
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxPayRanking[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxPayRanking | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
// 排行榜总金额(本地计算)
|
||||
const rankingTotalPrice = ref<number>(0);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({ where }) => {
|
||||
return ranking({ ...where }).then((data) => {
|
||||
// 计算排行榜总金额(用于对比显示)
|
||||
let total = 0;
|
||||
data.forEach((item) => {
|
||||
if (item.totalPrice) {
|
||||
total += item.totalPrice;
|
||||
}
|
||||
});
|
||||
rankingTotalPrice.value = total;
|
||||
|
||||
// 不再在这里更新 store 数据,因为这里的数据是排行榜数据,不是真实的订单统计
|
||||
// store 中的数据应该来自 bszxOrderTotal API,代表真实的订单金额
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 48,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'formName',
|
||||
key: 'formName'
|
||||
},
|
||||
{
|
||||
title: '捐款人数',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '获得捐款总金额',
|
||||
dataIndex: 'totalPrice',
|
||||
key: 'totalPrice',
|
||||
align: 'center'
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxPayRankingParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
// 初始化数据
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 初始化百色中学统计数据
|
||||
await bszxStatisticsStore.fetchBszxStatistics();
|
||||
} catch (error) {
|
||||
console.error('初始化百色中学统计数据失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxPayRanking) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxPayRanking) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxPayRanking(row.bszxPayRankingId)
|
||||
.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);
|
||||
removeBatchBszxPayRanking(
|
||||
selection.value.map((d) => d.bszxPayRankingId)
|
||||
)
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: BszxPayRanking) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPayRanking'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
218
src/views/bszx/bszxPayRanking2/components/bszxPayRankingEdit.vue
Normal file
218
src/views/bszx/bszxPayRanking2/components/bszxPayRankingEdit.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑百色中学-捐款排行' : '添加百色中学-捐款排行'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="来源表ID(项目名称)" name="formId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入来源表ID(项目名称)"
|
||||
v-model:value="form.formId"
|
||||
/>
|
||||
</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="totalPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入获得捐款总金额"
|
||||
v-model:value="form.totalPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态, 0正常, 1冻结" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否删除, 0否, 1是" name="deleted">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否删除, 0否, 1是"
|
||||
v-model:value="form.deleted"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</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 {
|
||||
addBszxPayRanking,
|
||||
updateBszxPayRanking
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import { BszxPayRanking } from '@/api/bszx/bszxPayRanking/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?: BszxPayRanking | 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<BszxPayRanking>({
|
||||
id: undefined,
|
||||
formId: undefined,
|
||||
number: undefined,
|
||||
totalPrice: undefined,
|
||||
createTime: undefined,
|
||||
status: 0,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
bszxPayRankingName: [
|
||||
{
|
||||
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
|
||||
? updateBszxPayRanking
|
||||
: addBszxPayRanking;
|
||||
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>
|
||||
213
src/views/bszx/bszxPayRanking2/components/search.vue
Normal file
213
src/views/bszx/bszxPayRanking2/components/search.vue
Normal file
@@ -0,0 +1,213 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-radio-group v-model:value="where.branch" @change="onBranch">
|
||||
<a-radio-button :value="1">初中部</a-radio-button>
|
||||
<a-radio-button :value="2">高中部</a-radio-button>
|
||||
<!-- <a-radio-button :value="8">教职员工</a-radio-button>-->
|
||||
<!-- <a-radio-button :value="9">其他</a-radio-button>-->
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
show-search
|
||||
v-model:value="where.gradeId"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="gradeList"
|
||||
@change="onGrade"
|
||||
/>
|
||||
<a-select
|
||||
v-if="where.gradeId"
|
||||
show-search
|
||||
v-model:value="where.name"
|
||||
style="width: 240px"
|
||||
placeholder="选择年级"
|
||||
:options="classList"
|
||||
@change="onClass"
|
||||
/>
|
||||
<!-- <a-input-search-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入关键词"-->
|
||||
<!-- style="width: 280px"-->
|
||||
<!-- v-model:value="where.keywords"-->
|
||||
<!-- @search="reload"-->
|
||||
<!-- />-->
|
||||
<!-- <a-button type="text" @click="handleExport">导出</a-button>-->
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { BszxBm } from '@/api/bszx/bszxBm/model';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { listBszxBm } from '@/api/bszx/bszxBm';
|
||||
import { BszxClassParam } from '@/api/bszx/bszxClass/model';
|
||||
import { listBszxGrade } from '@/api/bszx/bszxGrade';
|
||||
import { listBszxClass } from '@/api/bszx/bszxClass';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: BszxClassParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<BszxClassParam>({
|
||||
id: undefined,
|
||||
keywords: '',
|
||||
name: undefined,
|
||||
branch: undefined,
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
// 变量
|
||||
const loading = ref(false);
|
||||
const bmList = ref<BszxBm[]>([]);
|
||||
const xlsFileName = ref<string>();
|
||||
const gradeId = ref<number>();
|
||||
const gradeList = ref<BszxClassParam[]>([]);
|
||||
const classList = ref<BszxClassParam[]>([]);
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const getGradeList = () => {
|
||||
listBszxGrade({ branch: where.branch }).then((res) => {
|
||||
gradeList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getClassList = () => {
|
||||
listBszxClass({ gradeId: gradeId.value }).then((res) => {
|
||||
classList.value = res.map((d) => {
|
||||
d.value = Number(d.id);
|
||||
d.label = d.name;
|
||||
return d;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onBranch = () => {
|
||||
getGradeList();
|
||||
reload();
|
||||
};
|
||||
|
||||
const onGrade = (gradeName: number, item: any) => {
|
||||
where.gradeId = item.id;
|
||||
if (gradeName) {
|
||||
console.log(item);
|
||||
gradeId.value = item.id;
|
||||
getClassList();
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const onClass = (classId, item) => {
|
||||
console.log(classId);
|
||||
where.name = item.name;
|
||||
reload();
|
||||
};
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
loading.value = true;
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'用户ID',
|
||||
'姓名',
|
||||
'性别',
|
||||
'手机号码',
|
||||
'班级',
|
||||
'年级',
|
||||
'居住地址',
|
||||
'工作单位',
|
||||
'职务',
|
||||
'是否能到场',
|
||||
'邀请函',
|
||||
'报名时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 按搜索结果导出
|
||||
where.sceneType = 'Content';
|
||||
await listBszxBm(where)
|
||||
.then((list) => {
|
||||
bmList.value = list;
|
||||
list?.forEach((d: BszxBm) => {
|
||||
array.push([
|
||||
`${d.userId}`,
|
||||
`${d.name}`,
|
||||
`${d.sex}`,
|
||||
`${d.phone}`,
|
||||
`${d.className}`,
|
||||
`${d.gradeName}`,
|
||||
`${d.address}`,
|
||||
`${d.workUnit}`,
|
||||
`${d.position}`,
|
||||
`${d.present}`,
|
||||
`${d.certificate}`,
|
||||
`${d.createTime}`
|
||||
]);
|
||||
});
|
||||
const sheetName = `导出报名列表${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 },
|
||||
{ wch: 40 },
|
||||
{ wch: 20 },
|
||||
{ wch: 20 },
|
||||
{ wch: 60 },
|
||||
{ wch: 15 },
|
||||
{ wch: 10 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 },
|
||||
{ wch: 10 },
|
||||
{ wch: 20 }
|
||||
];
|
||||
message.loading('正在导出...');
|
||||
setTimeout(() => {
|
||||
writeFile(
|
||||
workbook,
|
||||
`${
|
||||
where.createTimeEnd ? xlsFileName.value + '_' : ''
|
||||
}${sheetName}.xlsx`
|
||||
);
|
||||
loading.value = false;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((msg) => {
|
||||
message.error(msg);
|
||||
loading.value = false;
|
||||
})
|
||||
.finally(() => {});
|
||||
};
|
||||
|
||||
getGradeList();
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
234
src/views/bszx/bszxPayRanking2/index.vue
Normal file
234
src/views/bszx/bszxPayRanking2/index.vue
Normal file
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<Extra />
|
||||
</template>
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
:totalPriceAmount="totalPriceAmount.toFixed(2)"
|
||||
@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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<BszxPayRankingEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import BszxPayRankingEdit from './components/bszxPayRankingEdit.vue';
|
||||
import {
|
||||
removeBszxPayRanking,
|
||||
removeBatchBszxPayRanking,
|
||||
ranking2
|
||||
} from '@/api/bszx/bszxPayRanking';
|
||||
import type { BszxPayRanking } from '@/api/bszx/bszxPayRanking/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import Extra from '@/views/bszx/extra.vue';
|
||||
import { BszxPayParam } from '@/api/bszx/bszxPay/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<BszxPayRanking[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<BszxPayRanking | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
// 合计总金额
|
||||
const totalPriceAmount = ref<number>(0);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({ where }) => {
|
||||
return ranking2({ ...where }).then((data) => {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 48,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id'
|
||||
},
|
||||
{
|
||||
title: '分部',
|
||||
dataIndex: 'branchName',
|
||||
key: 'branchName'
|
||||
},
|
||||
{
|
||||
title: '所在年级',
|
||||
dataIndex: 'gradeName',
|
||||
key: 'gradeName'
|
||||
},
|
||||
{
|
||||
title: '班级',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '累计捐款金额',
|
||||
dataIndex: 'totalMoney',
|
||||
key: 'totalMoney',
|
||||
align: 'center'
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 180,
|
||||
// fixed: 'right',
|
||||
// align: 'center',
|
||||
// hideInSetting: true
|
||||
// }
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: BszxPayParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: BszxPayRanking) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: BszxPayRanking) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBszxPayRanking(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);
|
||||
removeBatchBszxPayRanking(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: BszxPayRanking) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
// openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'BszxPayRanking'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
71
src/views/bszx/dashboard/components/search.vue
Normal file
71
src/views/bszx/dashboard/components/search.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space style="flex-wrap: wrap">
|
||||
<a-button type="text" @click="openUrl(`/website/field`)"
|
||||
>字段扩展
|
||||
</a-button>
|
||||
<a-button type="text" @click="openUrl('/website/dict')">字典管理 </a-button>
|
||||
<a-button type="text" @click="openUrl('/website/domain')"
|
||||
>域名管理
|
||||
</a-button>
|
||||
<a-button type="text" @click="openUrl('/website/model')"
|
||||
>模型管理
|
||||
</a-button>
|
||||
<a-button type="text" @click="openUrl('/website/form')">表单管理 </a-button>
|
||||
<a-button type="text" @click="openUrl('/website/lang')">国际化 </a-button>
|
||||
<a-button type="text" @click="openUrl('/website/setting')"
|
||||
>网站设置
|
||||
</a-button>
|
||||
<a-button type="text" class="ele-btn-icon" @click="clearSiteInfoCache">
|
||||
清除缓存
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, nextTick } from 'vue';
|
||||
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||
import { openUrl } from '@/utils/common';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
website?: CmsWebsite;
|
||||
count?: 0;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'add'): void;
|
||||
}>();
|
||||
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 清除缓存
|
||||
const clearSiteInfoCache = () => {
|
||||
removeSiteInfoCache(
|
||||
'SiteInfo:' + localStorage.getItem('TenantId') + '*'
|
||||
).then((msg) => {
|
||||
if (msg) {
|
||||
message.success(msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
nextTick(() => {
|
||||
if (localStorage.getItem('NotActive')) {
|
||||
// IsActive.value = false
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
408
src/views/bszx/dashboard/components/websiteEdit.vue
Normal file
408
src/views/bszx/dashboard/components/websiteEdit.vue
Normal file
@@ -0,0 +1,408 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑小程序' : '创建小程序'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
:confirm-loading="loading"
|
||||
@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="Logo" name="avatar">
|
||||
<SelectFile
|
||||
:placeholder="`请选择图片`"
|
||||
:limit="1"
|
||||
:data="images"
|
||||
@done="chooseImage"
|
||||
@del="onDeleteItem"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="账号类型" name="type">
|
||||
{{ form.type }}
|
||||
</a-form-item>
|
||||
<a-form-item label="小程序名称" name="websiteName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入小程序名称"
|
||||
v-model:value="form.websiteName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="网站域名" name="domain" v-if="form.type == 10">
|
||||
<a-input v-model:value="form.domain" placeholder="huawei.com">
|
||||
<template #addonBefore>
|
||||
<a-select v-model:value="form.prefix" style="width: 90px">
|
||||
<a-select-option value="http://">http://</a-select-option>
|
||||
<a-select-option value="https://">https://</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="AppId" name="websiteCode" v-if="form.type == 20">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入AppId"
|
||||
v-model:value="form.websiteCode"
|
||||
/>
|
||||
</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="SEO关键词" name="keywords">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入SEO关键词"
|
||||
v-model:value="form.keywords"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="全局样式" name="style">-->
|
||||
<!-- <a-textarea-->
|
||||
<!-- :rows="4"-->
|
||||
<!-- :maxlength="200"-->
|
||||
<!-- placeholder="全局样式"-->
|
||||
<!-- v-model:value="form.style"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="小程序类型" name="websiteType">-->
|
||||
<!-- <a-select-->
|
||||
<!-- :options="websiteType"-->
|
||||
<!-- :value="form.websiteType"-->
|
||||
<!-- placeholder="请选择主体类型"-->
|
||||
<!-- @change="onCmsWebsiteType"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="当前版本" name="version">-->
|
||||
<!-- <a-tag color="red" v-if="form.version === 10">标准版</a-tag>-->
|
||||
<!-- <a-tag color="green" v-if="form.version === 20">专业版</a-tag>-->
|
||||
<!-- <a-tag color="cyan" v-if="form.version === 30">永久授权</a-tag>-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="状态" name="running">
|
||||
<a-radio-group
|
||||
v-model:value="form.running"
|
||||
:disabled="form.running == 4 || form.running == 5"
|
||||
>
|
||||
<a-radio :value="1">运行中</a-radio>
|
||||
<a-radio :value="2">维护中</a-radio>
|
||||
<a-radio :value="3">已关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="form.running == 2" label="维护说明" name="statusText">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="状态说明"
|
||||
v-model:value="form.statusText"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-divider style="margin-bottom: 24px" />-->
|
||||
</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 { addCmsWebsite, updateCmsWebsite } from '@/api/cms/cmsWebsite';
|
||||
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance, type Rule } from 'ant-design-vue/es/form';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
import { checkExistence } from '@/api/cms/cmsDomain';
|
||||
import { updateCmsDomain } from '@/api/cms/cmsDomain';
|
||||
import { updateTenant } from '@/api/system/tenant';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: CmsWebsite | 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 websiteQrcode = ref<ItemType[]>([]);
|
||||
const oldDomain = ref();
|
||||
const files = ref<ItemType[]>([]);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<CmsWebsite>({
|
||||
websiteId: undefined,
|
||||
websiteLogo: undefined,
|
||||
websiteName: undefined,
|
||||
websiteCode: undefined,
|
||||
type: 20,
|
||||
files: undefined,
|
||||
keywords: '',
|
||||
prefix: '',
|
||||
domain: '',
|
||||
adminUrl: '',
|
||||
style: '',
|
||||
icpNo: undefined,
|
||||
email: undefined,
|
||||
version: undefined,
|
||||
websiteType: '',
|
||||
running: 1,
|
||||
expirationTime: undefined,
|
||||
sortNumber: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
statusText: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
// comments: [
|
||||
// {
|
||||
// required: true,
|
||||
// type: 'string',
|
||||
// message: '请填写小程序描述',
|
||||
// trigger: 'blur'
|
||||
// }
|
||||
// ],
|
||||
keywords: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写SEO关键词',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
running: [
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请选择小程序状态',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
domain: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写小程序域名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
websiteCode: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写小程序码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
// websiteCode: [
|
||||
// {
|
||||
// required: true,
|
||||
// type: 'string',
|
||||
// message: '该域名已被使用',
|
||||
// validator: (_rule: Rule, value: string) => {
|
||||
// return new Promise<void>((resolve, reject) => {
|
||||
// if (!value) {
|
||||
// return reject('请输入二级域名');
|
||||
// }
|
||||
// checkExistence('domain', `${value}.wsdns.cn`)
|
||||
// .then(() => {
|
||||
// if (value === oldDomain.value) {
|
||||
// return resolve();
|
||||
// }
|
||||
// reject('已存在');
|
||||
// })
|
||||
// .catch(() => {
|
||||
// resolve();
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
// trigger: 'blur'
|
||||
// }
|
||||
// ],
|
||||
adminUrl: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写小程序后台管理地址',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
icpNo: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写ICP备案号',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
appSecret: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写小程序秘钥',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
websiteName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写小程序信息名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const chooseImage = (data: FileRecord) => {
|
||||
images.value.push({
|
||||
uid: data.id,
|
||||
url: data.path,
|
||||
status: 'done'
|
||||
});
|
||||
form.websiteLogo = data.downloadUrl;
|
||||
};
|
||||
|
||||
const onDeleteItem = (index: number) => {
|
||||
images.value.splice(index, 1);
|
||||
form.websiteLogo = '';
|
||||
};
|
||||
|
||||
const chooseFile = (data: FileRecord) => {
|
||||
form.websiteCode = data.url;
|
||||
files.value.push({
|
||||
uid: data.id,
|
||||
url: data.url,
|
||||
status: 'done'
|
||||
});
|
||||
};
|
||||
|
||||
const onDeleteFile = (index: number) => {
|
||||
files.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// const onWebsiteType = (text: string) => {
|
||||
// form.websiteType = text;
|
||||
// };
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const saveOrUpdate = isUpdate.value ? updateCmsWebsite : addCmsWebsite;
|
||||
if (!isUpdate.value) {
|
||||
updateVisible(false);
|
||||
message.loading('创建过程中请勿刷新页面!', 0);
|
||||
}
|
||||
const formData = {
|
||||
...form,
|
||||
type: 20,
|
||||
adminUrl: `mp.websoft.top`,
|
||||
files: JSON.stringify(files.value)
|
||||
};
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
updateVisible(false);
|
||||
updateCmsDomain({
|
||||
websiteId: form.websiteId,
|
||||
domain: `${localStorage.getItem('TenantId')}.shoplnk.cn`
|
||||
});
|
||||
updateTenant({
|
||||
tenantName: `${form.websiteName}`
|
||||
}).then(() => {});
|
||||
localStorage.setItem('Domain', `${form.websiteCode}.shoplnk.cn`);
|
||||
localStorage.setItem('WebsiteId', `${form.websiteId}`);
|
||||
localStorage.setItem('WebsiteName', `${form.websiteName}`);
|
||||
message.destroy();
|
||||
message.success(msg);
|
||||
// window.location.reload();
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.destroy();
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
files.value = [];
|
||||
websiteQrcode.value = [];
|
||||
if (props.data?.websiteId) {
|
||||
assignObject(form, props.data);
|
||||
if (props.data.websiteLogo) {
|
||||
images.value.push({
|
||||
uid: uuid(),
|
||||
url: props.data.websiteLogo,
|
||||
status: 'done'
|
||||
});
|
||||
}
|
||||
if (props.data.files) {
|
||||
files.value = JSON.parse(props.data.files);
|
||||
}
|
||||
if (props.data.websiteCode) {
|
||||
oldDomain.value = props.data.websiteCode;
|
||||
}
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
280
src/views/bszx/dashboard/index.vue
Normal file
280
src/views/bszx/dashboard/index.vue
Normal file
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<a-page-header :show-back="false">
|
||||
<a-row :gutter="16">
|
||||
<!-- 应用基本信息卡片 -->
|
||||
<a-col :span="24" style="margin-bottom: 16px">
|
||||
<a-card title="概况" :bordered="false">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="6">
|
||||
<a-image
|
||||
:width="80"
|
||||
:height="80"
|
||||
:preview="false"
|
||||
style="border-radius: 8px"
|
||||
:src="siteStore.logo"
|
||||
fallback="/logo.png"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="14">
|
||||
<div class="system-info">
|
||||
<h2 class="ele-text-heading">{{ siteStore.appName }}</h2>
|
||||
<p class="ele-text-secondary">{{ siteStore.description }}</p>
|
||||
<a-space>
|
||||
<a-tag color="blue">{{ siteStore.version }}</a-tag>
|
||||
<a-tag color="green">{{ siteStore.statusText }}</a-tag>
|
||||
<a-popover title="小程序码">
|
||||
<template #content>
|
||||
<p
|
||||
><img
|
||||
:src="siteStore.mpQrCode"
|
||||
alt="小程序码"
|
||||
width="300"
|
||||
height="300"
|
||||
/></p>
|
||||
</template>
|
||||
<a-tag>
|
||||
<QrcodeOutlined />
|
||||
</a-tag>
|
||||
</a-popover>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="3">
|
||||
<div class="flex justify-center items-center h-full w-full">
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<!-- 统计数据卡片 -->
|
||||
<a-col :span="6">
|
||||
<a-card :bordered="false" class="stat-card">
|
||||
<a-statistic
|
||||
title="用户总数"
|
||||
:value="userCount"
|
||||
:value-style="{ color: '#3f8600' }"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #prefix>
|
||||
<UserOutlined />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="6">
|
||||
<a-card :bordered="false" class="stat-card">
|
||||
<a-statistic
|
||||
title="订单总数"
|
||||
:value="orderCount"
|
||||
:value-style="{ color: '#1890ff' }"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #prefix>
|
||||
<AccountBookOutlined />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="6">
|
||||
<a-card :bordered="false" class="stat-card">
|
||||
<a-statistic
|
||||
title="总营业额"
|
||||
:value="totalBszxPrice"
|
||||
:value-style="{ color: '#cf1322' }"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #prefix>
|
||||
<MoneyCollectOutlined />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="6">
|
||||
<a-card :bordered="false" class="stat-card">
|
||||
<a-statistic
|
||||
title="系统运行天数"
|
||||
:value="runDays"
|
||||
suffix="天"
|
||||
:value-style="{ color: '#722ed1' }"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #prefix>
|
||||
<ClockCircleOutlined />
|
||||
</template>
|
||||
</a-statistic>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<!-- 系统基本信息 -->
|
||||
<a-col :span="12">
|
||||
<a-card title="基本信息" :bordered="false">
|
||||
<a-descriptions :column="1" size="small">
|
||||
<a-descriptions-item label="系统名称">
|
||||
{{ systemInfo.name }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="版本号">
|
||||
{{ systemInfo.version }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="部署环境">
|
||||
{{ systemInfo.environment }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="数据库">
|
||||
{{ systemInfo.database }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器">
|
||||
{{ systemInfo.server }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ siteInfo?.createTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="到期时间">
|
||||
{{ siteInfo?.expirationTime }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="技术支持">
|
||||
<span
|
||||
class="cursor-pointer"
|
||||
@click="openNew(`https://websoft.top/order/3429.html`)"
|
||||
>网宿软件</span
|
||||
>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<!-- 快捷操作 -->
|
||||
<a-col :span="12">
|
||||
<a-card title="快捷操作" :bordered="false">
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-button
|
||||
type="primary"
|
||||
block
|
||||
@click="$router.push('/website/index')"
|
||||
>
|
||||
<ShopOutlined />
|
||||
站点管理
|
||||
</a-button>
|
||||
<a-button block @click="$router.push('/website/order')">
|
||||
<CalendarOutlined />
|
||||
订单管理
|
||||
</a-button>
|
||||
<a-button block @click="$router.push('/system/user')">
|
||||
<UserOutlined />
|
||||
用户管理
|
||||
</a-button>
|
||||
<a-button block @click="$router.push('/system/login-record')">
|
||||
<FileTextOutlined />
|
||||
系统日志
|
||||
</a-button>
|
||||
<a-button block @click="$router.push('/system/setting')">
|
||||
<SettingOutlined />
|
||||
系统设置
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import {
|
||||
UserOutlined,
|
||||
CalendarOutlined,
|
||||
QrcodeOutlined,
|
||||
ShopOutlined,
|
||||
ClockCircleOutlined,
|
||||
SettingOutlined,
|
||||
AccountBookOutlined,
|
||||
FileTextOutlined,
|
||||
MoneyCollectOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { openNew } from '@/utils/common';
|
||||
import { useSiteStore } from '@/store/modules/site';
|
||||
import { useStatisticsStore } from '@/store/modules/statistics';
|
||||
import { useBszxStatisticsStore } from '@/store/modules/bszx-statistics';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
// 使用状态管理
|
||||
const siteStore = useSiteStore();
|
||||
const statisticsStore = useStatisticsStore();
|
||||
const bszxStatisticsStore = useBszxStatisticsStore();
|
||||
|
||||
// 从 store 中获取响应式数据
|
||||
const { siteInfo, loading: siteLoading } = storeToRefs(siteStore);
|
||||
const { loading: statisticsLoading } = storeToRefs(statisticsStore);
|
||||
const { loading: bszxLoading } = storeToRefs(bszxStatisticsStore);
|
||||
|
||||
// 系统信息
|
||||
const systemInfo = ref({
|
||||
name: '小程序开发',
|
||||
description:
|
||||
'基于Spring、SpringBoot、SpringMVC等技术栈构建的前后端分离开发平台',
|
||||
version: '2.0.0',
|
||||
status: '运行中',
|
||||
logo: '/logo.png',
|
||||
environment: '生产环境',
|
||||
database: 'MySQL 8.0',
|
||||
server: 'Linux CentOS 7.9',
|
||||
expirationTime: '2024-01-01 09:00:00'
|
||||
});
|
||||
|
||||
// 计算属性
|
||||
const runDays = computed(() => siteStore.runDays);
|
||||
const userCount = computed(() => statisticsStore.userCount);
|
||||
const orderCount = computed(() => statisticsStore.orderCount);
|
||||
const totalBszxPrice = computed(() => bszxStatisticsStore.bszxTotalPrice);
|
||||
|
||||
// 加载状态
|
||||
const loading = computed(
|
||||
() => siteLoading.value || statisticsLoading.value || bszxLoading.value
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
// 加载网站信息和统计数据
|
||||
try {
|
||||
await Promise.all([
|
||||
siteStore.fetchSiteInfo(),
|
||||
statisticsStore.fetchStatistics(),
|
||||
bszxStatisticsStore.fetchBszxStatistics() // 加载百色中学统计数据
|
||||
]);
|
||||
|
||||
// 开始自动刷新统计数据(每5分钟)
|
||||
statisticsStore.startAutoRefresh();
|
||||
bszxStatisticsStore.startAutoRefresh();
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 组件卸载时停止自动刷新
|
||||
statisticsStore.stopAutoRefresh();
|
||||
bszxStatisticsStore.stopAutoRefresh();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.system-info h2 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.stat-card :deep(.ant-statistic-title) {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.stat-card :deep(.ant-statistic-content) {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
63
src/views/bszx/extra.vue
Normal file
63
src/views/bszx/extra.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space
|
||||
style="flex-wrap: wrap"
|
||||
v-if="hasRole('superAdmin') || hasRole('admin') || hasRole('foundation')"
|
||||
>
|
||||
<a-button type="text" @click="openUrl('/bszx/ranking')"
|
||||
>捐款排行榜
|
||||
</a-button>
|
||||
<a-button type="text" @click="openUrl('/bszx/ranking2')"
|
||||
>千班万元
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, nextTick } from 'vue';
|
||||
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||
import { openUrl } from '@/utils/common';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||
import { hasRole } from '@/utils/permission';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
website?: CmsWebsite;
|
||||
count?: 0;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'add'): void;
|
||||
}>();
|
||||
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 清除缓存
|
||||
const clearSiteInfoCache = () => {
|
||||
removeSiteInfoCache(
|
||||
'SiteInfo:' + localStorage.getItem('TenantId') + '*'
|
||||
).then((msg) => {
|
||||
if (msg) {
|
||||
message.success(msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
nextTick(() => {
|
||||
if (localStorage.getItem('NotActive')) {
|
||||
// IsActive.value = false
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
@@ -0,0 +1,239 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="type">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入类型"-->
|
||||
<!-- v-model:value="form.type"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="就诊原因" name="reason">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
disabled
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.reason"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="挂号时间" name="evaluateTime">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入挂号时间"-->
|
||||
<!-- v-model:value="form.evaluateTime"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="医生" name="doctorId">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入医生"-->
|
||||
<!-- v-model:value="form.doctorId"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="患者" name="userId">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入患者"-->
|
||||
<!-- v-model:value="form.userId"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序号" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="是否删除" name="isDelete">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入是否删除"-->
|
||||
<!-- v-model:value="form.isDelete"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="修改时间" name="updateTime">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入修改时间"-->
|
||||
<!-- v-model:value="form.updateTime"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import {
|
||||
addClinicAppointment,
|
||||
updateClinicAppointment
|
||||
} from '@/api/clinic/clinicAppointment';
|
||||
import { ClinicAppointment } from '@/api/clinic/clinicAppointment/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?: ClinicAppointment | 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<ClinicAppointment>({
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
reason: undefined,
|
||||
evaluateTime: undefined,
|
||||
doctorId: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
isDelete: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicAppointmentName: [
|
||||
{
|
||||
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
|
||||
? updateClinicAppointment
|
||||
: addClinicAppointment;
|
||||
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>
|
||||
42
src/views/clinic/clinicAppointment/components/search.vue
Normal file
42
src/views/clinic/clinicAppointment/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
273
src/views/clinic/clinicAppointment/index.vue
Normal file
273
src/views/clinic/clinicAppointment/index.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === 'userId'">
|
||||
<div>{{ record.nickname }}</div>
|
||||
<div class="text-gray-400">{{ record.phone }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'doctorId'">
|
||||
<div>{{ record.doctorName }}</div>
|
||||
<div class="text-gray-400">{{ record.doctorPosition }}</div>
|
||||
</template>
|
||||
<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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicAppointmentEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicAppointmentEdit from './components/clinicAppointmentEdit.vue';
|
||||
import {
|
||||
pageClinicAppointment,
|
||||
removeClinicAppointment,
|
||||
removeBatchClinicAppointment
|
||||
} from '@/api/clinic/clinicAppointment';
|
||||
import type {
|
||||
ClinicAppointment,
|
||||
ClinicAppointmentParam
|
||||
} from '@/api/clinic/clinicAppointment/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicAppointment[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicAppointment | 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 pageClinicAppointment({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '患者',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId'
|
||||
},
|
||||
{
|
||||
title: '挂号医生',
|
||||
dataIndex: 'doctorId',
|
||||
key: 'doctorId'
|
||||
},
|
||||
// {
|
||||
// title: '类型',
|
||||
// dataIndex: 'type',
|
||||
// key: 'type',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '就诊原因',
|
||||
dataIndex: 'reason',
|
||||
key: 'reason',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '排序号',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
width: 120
|
||||
},
|
||||
// {
|
||||
// title: '挂号时间',
|
||||
// dataIndex: 'evaluateTime',
|
||||
// key: 'evaluateTime',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '挂号时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicAppointmentParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicAppointment) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicAppointment) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicAppointment(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);
|
||||
removeBatchClinicAppointment(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: ClinicAppointment) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicAppointment'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,389 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑医生入驻申请' : '添加医生入驻申请'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="类型 0医生" name="type">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入类型 0医生"
|
||||
v-model:value="form.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="用户ID" name="userId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用户ID"
|
||||
v-model:value="form.userId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="realName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.realName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别 1男 2女" name="gender">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入性别 1男 2女"
|
||||
v-model:value="form.gender"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号" name="mobile">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号"
|
||||
v-model:value="form.mobile"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="客户名称" name="dealerName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入客户名称"
|
||||
v-model:value="form.dealerName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="证件号码" name="idCard">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入证件号码"
|
||||
v-model:value="form.idCard"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="生日" name="birthDate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入生日"
|
||||
v-model:value="form.birthDate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="区分职称等级(如主治医师、副主任医师)"
|
||||
name="professionalTitle"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入区分职称等级(如主治医师、副主任医师)"
|
||||
v-model:value="form.professionalTitle"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作单位" name="workUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作单位"
|
||||
v-model:value="form.workUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="执业资格核心凭证" name="practiceLicense">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入执业资格核心凭证"
|
||||
v-model:value="form.practiceLicense"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="限定可执业科室或疾病类型" name="practiceScope">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入限定可执业科室或疾病类型"
|
||||
v-model:value="form.practiceScope"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开始工作时间" name="startWorkDate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入开始工作时间"
|
||||
v-model:value="form.startWorkDate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="简历" name="resume">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入简历"
|
||||
v-model:value="form.resume"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="使用 JSON 存储多个证件文件路径(如执业证、学历证)"
|
||||
name="certificationFiles"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入使用 JSON 存储多个证件文件路径(如执业证、学历证)"
|
||||
v-model:value="form.certificationFiles"
|
||||
/>
|
||||
</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="money">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入签约价格"
|
||||
v-model:value="form.money"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="推荐人用户ID" name="refereeId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入推荐人用户ID"
|
||||
v-model:value="form.refereeId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请方式(10需后台审核 20无需审核)" name="applyType">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入申请方式(10需后台审核 20无需审核)"
|
||||
v-model:value="form.applyType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="审核状态 (10待审核 20审核通过 30驳回)"
|
||||
name="applyStatus"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入审核状态 (10待审核 20审核通过 30驳回)"
|
||||
v-model:value="form.applyStatus"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请时间" name="applyTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入申请时间"
|
||||
v-model:value="form.applyTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="审核时间" name="auditTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入审核时间"
|
||||
v-model:value="form.auditTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="合同时间" name="contractTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入合同时间"
|
||||
v-model:value="form.contractTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="过期时间" name="expirationTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入过期时间"
|
||||
v-model:value="form.expirationTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="驳回原因" name="rejectReason">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入驳回原因"
|
||||
v-model:value="form.rejectReason"
|
||||
/>
|
||||
</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="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 {
|
||||
addClinicDoctorApply,
|
||||
updateClinicDoctorApply
|
||||
} from '@/api/clinic/clinicDoctorApply';
|
||||
import { ClinicDoctorApply } from '@/api/clinic/clinicDoctorApply/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?: ClinicDoctorApply | 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<ClinicDoctorApply>({
|
||||
applyId: undefined,
|
||||
type: undefined,
|
||||
userId: undefined,
|
||||
realName: undefined,
|
||||
gender: undefined,
|
||||
mobile: undefined,
|
||||
dealerName: undefined,
|
||||
idCard: undefined,
|
||||
birthDate: undefined,
|
||||
professionalTitle: undefined,
|
||||
workUnit: undefined,
|
||||
practiceLicense: undefined,
|
||||
practiceScope: undefined,
|
||||
startWorkDate: undefined,
|
||||
resume: undefined,
|
||||
certificationFiles: undefined,
|
||||
address: undefined,
|
||||
money: undefined,
|
||||
refereeId: undefined,
|
||||
applyType: undefined,
|
||||
applyStatus: undefined,
|
||||
applyTime: undefined,
|
||||
auditTime: undefined,
|
||||
contractTime: undefined,
|
||||
expirationTime: undefined,
|
||||
rejectReason: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicDoctorApplyName: [
|
||||
{
|
||||
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
|
||||
? updateClinicDoctorApply
|
||||
: addClinicDoctorApply;
|
||||
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>
|
||||
42
src/views/clinic/clinicDoctorApply/components/search.vue
Normal file
42
src/views/clinic/clinicDoctorApply/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
391
src/views/clinic/clinicDoctorApply/index.vue
Normal file
391
src/views/clinic/clinicDoctorApply/index.vue
Normal file
@@ -0,0 +1,391 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicDoctorApplyEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicDoctorApplyEdit from './components/clinicDoctorApplyEdit.vue';
|
||||
import {
|
||||
pageClinicDoctorApply,
|
||||
removeClinicDoctorApply,
|
||||
removeBatchClinicDoctorApply
|
||||
} from '@/api/clinic/clinicDoctorApply';
|
||||
import type {
|
||||
ClinicDoctorApply,
|
||||
ClinicDoctorApplyParam
|
||||
} from '@/api/clinic/clinicDoctorApply/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicDoctorApply[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicDoctorApply | 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 pageClinicDoctorApply({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'applyId',
|
||||
key: 'applyId',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '类型 0医生',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '性别 1男 2女',
|
||||
dataIndex: 'gender',
|
||||
key: 'gender',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'mobile',
|
||||
key: 'mobile',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '客户名称',
|
||||
dataIndex: 'dealerName',
|
||||
key: 'dealerName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '证件号码',
|
||||
dataIndex: 'idCard',
|
||||
key: 'idCard',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '生日',
|
||||
dataIndex: 'birthDate',
|
||||
key: 'birthDate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '区分职称等级(如主治医师、副主任医师)',
|
||||
dataIndex: 'professionalTitle',
|
||||
key: 'professionalTitle',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '工作单位',
|
||||
dataIndex: 'workUnit',
|
||||
key: 'workUnit',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '执业资格核心凭证',
|
||||
dataIndex: 'practiceLicense',
|
||||
key: 'practiceLicense',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '限定可执业科室或疾病类型',
|
||||
dataIndex: 'practiceScope',
|
||||
key: 'practiceScope',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '开始工作时间',
|
||||
dataIndex: 'startWorkDate',
|
||||
key: 'startWorkDate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '简历',
|
||||
dataIndex: 'resume',
|
||||
key: 'resume',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '使用 JSON 存储多个证件文件路径(如执业证、学历证)',
|
||||
dataIndex: 'certificationFiles',
|
||||
key: 'certificationFiles',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '详细地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '签约价格',
|
||||
dataIndex: 'money',
|
||||
key: 'money',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '推荐人用户ID',
|
||||
dataIndex: 'refereeId',
|
||||
key: 'refereeId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '申请方式(10需后台审核 20无需审核)',
|
||||
dataIndex: 'applyType',
|
||||
key: 'applyType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '审核状态 (10待审核 20审核通过 30驳回)',
|
||||
dataIndex: 'applyStatus',
|
||||
key: 'applyStatus',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '申请时间',
|
||||
dataIndex: 'applyTime',
|
||||
key: 'applyTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '审核时间',
|
||||
dataIndex: 'auditTime',
|
||||
key: 'auditTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '合同时间',
|
||||
dataIndex: 'contractTime',
|
||||
key: 'contractTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '过期时间',
|
||||
dataIndex: 'expirationTime',
|
||||
key: 'expirationTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '驳回原因',
|
||||
dataIndex: 'rejectReason',
|
||||
key: 'rejectReason',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicDoctorApplyParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicDoctorApply) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicDoctorApply) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicDoctorApply(row.applyId)
|
||||
.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);
|
||||
removeBatchClinicDoctorApply(selection.value.map((d) => d.applyId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: ClinicDoctorApply) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicDoctorApply'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,323 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(一级)" name="firstUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(一级)"
|
||||
v-model:value="form.firstUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(二级)" name="secondUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(二级)"
|
||||
v-model:value="form.secondUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(三级)"
|
||||
v-model:value="form.thirdUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(一级)" name="firstMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(一级)"
|
||||
v-model:value="form.firstMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(二级)" name="secondMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(二级)"
|
||||
v-model:value="form.secondMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(三级)" name="thirdMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(三级)"
|
||||
v-model:value="form.thirdMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算金额" name="settledPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算金额"
|
||||
v-model:value="form.settledPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="换算成度" name="degreePrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入换算成度"
|
||||
v-model:value="form.degreePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实发金额" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实发金额"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="税率" name="rate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入税率"
|
||||
v-model:value="form.rate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算月份" name="month">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算月份"
|
||||
v-model:value="form.month"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入佣金结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</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 {
|
||||
addClinicDoctorMedicalRecord,
|
||||
updateClinicDoctorMedicalRecord
|
||||
} from '@/api/clinic/clinicDoctorMedicalRecord';
|
||||
import { ClinicDoctorMedicalRecord } from '@/api/clinic/clinicDoctorMedicalRecord/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?: ClinicDoctorMedicalRecord | 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<ClinicDoctorMedicalRecord>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
orderNo: undefined,
|
||||
firstUserId: undefined,
|
||||
secondUserId: undefined,
|
||||
thirdUserId: undefined,
|
||||
firstMoney: undefined,
|
||||
secondMoney: undefined,
|
||||
thirdMoney: undefined,
|
||||
price: undefined,
|
||||
orderPrice: undefined,
|
||||
settledPrice: undefined,
|
||||
degreePrice: undefined,
|
||||
payPrice: undefined,
|
||||
rate: undefined,
|
||||
month: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
comments: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicDoctorMedicalRecordName: [
|
||||
{
|
||||
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
|
||||
? updateClinicDoctorMedicalRecord
|
||||
: addClinicDoctorMedicalRecord;
|
||||
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,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>
|
||||
243
src/views/clinic/clinicDoctorMedicalRecord/index.vue
Normal file
243
src/views/clinic/clinicDoctorMedicalRecord/index.vue
Normal file
@@ -0,0 +1,243 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicDoctorMedicalRecordEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicDoctorMedicalRecordEdit from './components/clinicDoctorMedicalRecordEdit.vue';
|
||||
import {
|
||||
pageClinicDoctorMedicalRecord,
|
||||
removeClinicDoctorMedicalRecord,
|
||||
removeBatchClinicDoctorMedicalRecord
|
||||
} from '@/api/clinic/clinicDoctorMedicalRecord';
|
||||
import type {
|
||||
ClinicDoctorMedicalRecord,
|
||||
ClinicDoctorMedicalRecordParam
|
||||
} from '@/api/clinic/clinicDoctorMedicalRecord/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicDoctorMedicalRecord[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicDoctorMedicalRecord | 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 pageClinicDoctorMedicalRecord({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicDoctorMedicalRecordParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicDoctorMedicalRecord) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicDoctorMedicalRecord) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicDoctorMedicalRecord(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);
|
||||
removeBatchClinicDoctorMedicalRecord(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: ClinicDoctorMedicalRecord) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicDoctorMedicalRecord'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,279 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑医生' : '添加医生'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<!-- <a-form-item label="类型 0经销商 1企业 2集团" name="type">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入类型 0经销商 1企业 2集团"-->
|
||||
<!-- v-model:value="form.type"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="自增ID" name="userId">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入自增ID"-->
|
||||
<!-- v-model:value="form.userId"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="姓名" name="realName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.realName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="部门" name="departmentId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入部门"
|
||||
v-model:value="form.departmentId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="专业领域" name="specialty">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入专业领域"
|
||||
v-model:value="form.specialty"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="职务级别" name="position">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入职务级别"
|
||||
v-model:value="form.position"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="执业资格" name="qualification">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入执业资格"
|
||||
v-model:value="form.qualification"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="医生简介" name="introduction">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入医生简介"
|
||||
v-model:value="form.introduction"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="挂号费" name="consultationFee">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入挂号费"
|
||||
v-model:value="form.consultationFee"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="工作年限" name="workYears">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入工作年限"
|
||||
v-model:value="form.workYears"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="问诊人数" name="consultationCount">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入问诊人数"
|
||||
v-model:value="form.consultationCount"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="专属二维码" name="qrcode">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入专属二维码"
|
||||
v-model:value="form.qrcode"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序号" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import {
|
||||
addClinicDoctorUser,
|
||||
updateClinicDoctorUser
|
||||
} from '@/api/clinic/clinicDoctorUser';
|
||||
import { ClinicDoctorUser } from '@/api/clinic/clinicDoctorUser/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?: ClinicDoctorUser | 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<ClinicDoctorUser>({
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
userId: undefined,
|
||||
realName: undefined,
|
||||
departmentId: undefined,
|
||||
specialty: undefined,
|
||||
position: undefined,
|
||||
qualification: undefined,
|
||||
introduction: undefined,
|
||||
consultationFee: undefined,
|
||||
workYears: undefined,
|
||||
consultationCount: undefined,
|
||||
qrcode: undefined,
|
||||
comments: undefined,
|
||||
isDelete: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicDoctorUserName: [
|
||||
{
|
||||
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
|
||||
? updateClinicDoctorUser
|
||||
: addClinicDoctorUser;
|
||||
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>
|
||||
42
src/views/clinic/clinicDoctorUser/components/search.vue
Normal file
42
src/views/clinic/clinicDoctorUser/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
291
src/views/clinic/clinicDoctorUser/index.vue
Normal file
291
src/views/clinic/clinicDoctorUser/index.vue
Normal file
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicDoctorUserEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicDoctorUserEdit from './components/clinicDoctorUserEdit.vue';
|
||||
import {
|
||||
pageClinicDoctorUser,
|
||||
removeClinicDoctorUser,
|
||||
removeBatchClinicDoctorUser
|
||||
} from '@/api/clinic/clinicDoctorUser';
|
||||
import type {
|
||||
ClinicDoctorUser,
|
||||
ClinicDoctorUserParam
|
||||
} from '@/api/clinic/clinicDoctorUser/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicDoctorUser[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicDoctorUser | 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 pageClinicDoctorUser({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
ellipsis: true
|
||||
},
|
||||
// {
|
||||
// title: '部门',
|
||||
// dataIndex: 'departmentId',
|
||||
// key: 'departmentId',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '专业领域',
|
||||
dataIndex: 'specialty',
|
||||
key: 'specialty',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '职务级别',
|
||||
dataIndex: 'position',
|
||||
key: 'position',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '执业资格',
|
||||
dataIndex: 'qualification',
|
||||
key: 'qualification',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '挂号费',
|
||||
dataIndex: 'consultationFee',
|
||||
key: 'consultationFee',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '工作年限',
|
||||
dataIndex: 'workYears',
|
||||
key: 'workYears',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '问诊人数',
|
||||
dataIndex: 'consultationCount',
|
||||
key: 'consultationCount',
|
||||
width: 120
|
||||
},
|
||||
// {
|
||||
// title: '专属二维码',
|
||||
// dataIndex: 'qrcode',
|
||||
// key: 'qrcode',
|
||||
// ellipsis: true
|
||||
// },
|
||||
// {
|
||||
// title: '备注',
|
||||
// dataIndex: 'comments',
|
||||
// key: 'comments',
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '排序号',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicDoctorUserParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicDoctorUser) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicDoctorUser) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicDoctorUser(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);
|
||||
removeBatchClinicDoctorUser(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: ClinicDoctorUser) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicDoctorUser'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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-radio-group v-model:value="where.type">-->
|
||||
<!-- <a-radio-button :value="0" @click="push(`/user-verify`)">个人</a-radio-button>-->
|
||||
<!-- <a-radio-button :value="1" @click="push(`/user-verify2`)">企业</a-radio-button>-->
|
||||
<!-- </a-radio-group>-->
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 240px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { watch } from 'vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import { UserVerifyParam } from '@/api/system/userVerify/model';
|
||||
import { push } from '@/utils/common';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: UserVerifyParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<UserVerifyParam>({
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
keywords: '',
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
// 新增
|
||||
// const add = () => {
|
||||
// emit('add');
|
||||
// };
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
@@ -0,0 +1,352 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="type">
|
||||
<a-tag v-if="form.type === 0">{{ ['个人', '企业'][form.type] }}</a-tag>
|
||||
<a-tag color="pink" v-if="form.type === 1">{{
|
||||
['个人', '企业'][form.type]
|
||||
}}</a-tag>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属站点" name="organizationName">
|
||||
<a-input
|
||||
allow-clear
|
||||
disabled
|
||||
placeholder="请选择属站点"
|
||||
v-model:value="form.organizationName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="真实姓名" name="realName">
|
||||
<a-input
|
||||
allow-clear
|
||||
disabled
|
||||
placeholder="请输入真实姓名"
|
||||
v-model:value="form.realName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号码" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
disabled
|
||||
placeholder="请输入手机号码"
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="证件号码" name="idCard">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- :disabled="form.status == 1"-->
|
||||
<!-- placeholder="请输入证件号码"-->
|
||||
<!-- v-model:value="form.idCard"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="身份证(正面)" name="sfz1">-->
|
||||
<!-- <SelectFile-->
|
||||
<!-- :placeholder="`请选择图片`"-->
|
||||
<!-- :limit="1"-->
|
||||
<!-- :data="sfz1"-->
|
||||
<!-- @done="chooseSfz1"-->
|
||||
<!-- @del="onDeleteSfz1"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="身份证(反面)" name="sfz2">-->
|
||||
<!-- <SelectFile-->
|
||||
<!-- :placeholder="`请选择图片`"-->
|
||||
<!-- :limit="1"-->
|
||||
<!-- :data="sfz2"-->
|
||||
<!-- @done="chooseSfz2"-->
|
||||
<!-- @del="onDeleteSfz2"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="1">审核通过</a-radio>
|
||||
<a-radio :value="2">驳回</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="驳回原因" name="comments" v-if="form.status == 2">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请填写驳回原因"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addUserVerify, updateUserVerify } from '@/api/system/userVerify';
|
||||
import { UserVerify } from '@/api/system/userVerify/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';
|
||||
import { listUserRole, updateUserRole } from '@/api/system/userRole';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: UserVerify | 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 sfz1 = ref<ItemType[]>([]);
|
||||
const sfz2 = ref<ItemType[]>([]);
|
||||
const userRoleId = ref<number>(0);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<UserVerify>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
type: undefined,
|
||||
name: undefined,
|
||||
realName: undefined,
|
||||
phone: undefined,
|
||||
idCard: undefined,
|
||||
birthday: undefined,
|
||||
sfz1: undefined,
|
||||
sfz2: undefined,
|
||||
organizationName: undefined,
|
||||
status: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
comments: ''
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请选择类型',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
realName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写真实姓名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
idCard: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写证件号码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写手机号码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
sfz1: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请上传身份证正面',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
sfz2: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请上传身份证反面',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
status: [
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请选择审核状态',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
comments: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写驳回原因',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const chooseSfz1 = (data: FileRecord) => {
|
||||
sfz1.value.push({
|
||||
uid: data.id,
|
||||
url: data.path,
|
||||
status: 'done'
|
||||
});
|
||||
form.sfz1 = data.path;
|
||||
};
|
||||
|
||||
const onDeleteSfz1 = (index: number) => {
|
||||
sfz1.value.splice(index, 1);
|
||||
form.sfz1 = '';
|
||||
};
|
||||
|
||||
const chooseSfz2 = (data: FileRecord) => {
|
||||
sfz2.value.push({
|
||||
uid: data.id,
|
||||
url: data.path,
|
||||
status: 'done'
|
||||
});
|
||||
form.sfz2 = data.path;
|
||||
};
|
||||
|
||||
const onDeleteSfz2 = (index: number) => {
|
||||
sfz2.value.splice(index, 1);
|
||||
form.sfz2 = '';
|
||||
};
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = async () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
if (form.status == 0) {
|
||||
message.error('请选择审核状态');
|
||||
return;
|
||||
}
|
||||
// 审核通过
|
||||
if (form.status == 1) {
|
||||
const res = await listUserRole({ userId: form.userId, roleId: 1701 });
|
||||
const role = res[0];
|
||||
if (role) {
|
||||
role.roleId = 1738;
|
||||
userRoleId.value = Number(role.id);
|
||||
updateUserRole(role).then(() => {});
|
||||
}
|
||||
}
|
||||
// 驳回
|
||||
if (form.status == 2) {
|
||||
const res = await listUserRole({ userId: form.userId, roleId: 1738 });
|
||||
const role = res[0];
|
||||
if (role) {
|
||||
role.roleId = 1701;
|
||||
userRoleId.value = Number(role.id);
|
||||
updateUserRole(role).then(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form,
|
||||
userRoleId: userRoleId.value
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateUserVerify : addUserVerify;
|
||||
saveOrUpdate(formData)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
if (formData.status == 1) {
|
||||
}
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
images.value = [];
|
||||
sfz1.value = [];
|
||||
sfz2.value = [];
|
||||
if (props.data) {
|
||||
assignObject(form, props.data);
|
||||
if (props.data.sfz1) {
|
||||
sfz1.value.push({
|
||||
uid: uuid(),
|
||||
url: props.data.sfz1,
|
||||
status: 'done'
|
||||
});
|
||||
}
|
||||
if (props.data.sfz2) {
|
||||
sfz2.value.push({
|
||||
uid: uuid(),
|
||||
url: props.data.sfz2,
|
||||
status: 'done'
|
||||
});
|
||||
}
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
287
src/views/clinic/clinicDoctorUser/userVerify/index.vue
Normal file
287
src/views/clinic/clinicDoctorUser/userVerify/index.vue
Normal file
@@ -0,0 +1,287 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="orange">待审核</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="green">审核通过</a-tag>
|
||||
<a-tag v-if="record.status === 2" color="red">已驳回</a-tag>
|
||||
<div class="text-orange-500 py-1" v-if="record.status == 2"
|
||||
>原因:{{ record.comments }}</div
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<div v-if="hasPermission('sys:userVerify:update')">
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<UserVerifyEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import UserVerifyEdit from './components/userVerifyEdit.vue';
|
||||
import {
|
||||
pageUserVerify,
|
||||
removeUserVerify,
|
||||
removeBatchUserVerify
|
||||
} from '@/api/system/userVerify';
|
||||
import type {
|
||||
UserVerify,
|
||||
UserVerifyParam
|
||||
} from '@/api/system/userVerify/model';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import { hasPermission } from '@/utils/permission';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<UserVerify[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<UserVerify | 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.type = 0;
|
||||
return pageUserVerify({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
align: 'center',
|
||||
width: 90
|
||||
},
|
||||
// {
|
||||
// title: '所属站点',
|
||||
// dataIndex: 'organizationName',
|
||||
// key: 'organizationName',
|
||||
// align: 'center'
|
||||
// },
|
||||
// {
|
||||
// title: '类型',
|
||||
// dataIndex: 'type',
|
||||
// key: 'type',
|
||||
// align: 'center',
|
||||
// customRender: ({text}) => ['个人', '企业'][text]
|
||||
// },
|
||||
{
|
||||
title: '真实姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '证件号码',
|
||||
// dataIndex: 'idCard',
|
||||
// key: 'idCard',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '身份证',
|
||||
// dataIndex: 'sfz1',
|
||||
// key: 'sfz1',
|
||||
// align: 'center',
|
||||
// },
|
||||
// {
|
||||
// title: '营业执照',
|
||||
// dataIndex: 'yyzz',
|
||||
// key: 'yyzz',
|
||||
// align: 'center',
|
||||
// },
|
||||
// {
|
||||
// title: '其他',
|
||||
// dataIndex: 'files',
|
||||
// key: 'files',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
align: 'center'
|
||||
},
|
||||
// {
|
||||
// title: '驳回',
|
||||
// dataIndex: 'comments',
|
||||
// key: 'comments',
|
||||
// align: 'center',
|
||||
// },
|
||||
{
|
||||
title: '添加时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 130,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: UserVerifyParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: UserVerify) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: UserVerify) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeUserVerify(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);
|
||||
removeBatchUserVerify(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: UserVerify) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
if (hasPermission('sys:userVerify:update')) {
|
||||
openEdit(record);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'UserVerify'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,324 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(一级)" name="firstUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(一级)"
|
||||
v-model:value="form.firstUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(二级)" name="secondUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(二级)"
|
||||
v-model:value="form.secondUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(三级)"
|
||||
v-model:value="form.thirdUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(一级)" name="firstMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(一级)"
|
||||
v-model:value="form.firstMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(二级)" name="secondMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(二级)"
|
||||
v-model:value="form.secondMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(三级)" name="thirdMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(三级)"
|
||||
v-model:value="form.thirdMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算金额" name="settledPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算金额"
|
||||
v-model:value="form.settledPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="换算成度" name="degreePrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入换算成度"
|
||||
v-model:value="form.degreePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实发金额" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实发金额"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="税率" name="rate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入税率"
|
||||
v-model:value="form.rate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算月份" name="month">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算月份"
|
||||
v-model:value="form.month"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入佣金结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</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 {
|
||||
addClinicMedicalHistory,
|
||||
updateClinicMedicalHistory
|
||||
} from '@/api/clinic/clinicMedicalHistory';
|
||||
import { ClinicMedicalHistory } from '@/api/clinic/clinicMedicalHistory/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?: ClinicMedicalHistory | 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<ClinicMedicalHistory>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
orderNo: undefined,
|
||||
firstUserId: undefined,
|
||||
secondUserId: undefined,
|
||||
thirdUserId: undefined,
|
||||
firstMoney: undefined,
|
||||
secondMoney: undefined,
|
||||
thirdMoney: undefined,
|
||||
price: undefined,
|
||||
orderPrice: undefined,
|
||||
settledPrice: undefined,
|
||||
degreePrice: undefined,
|
||||
payPrice: undefined,
|
||||
rate: undefined,
|
||||
month: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
comments: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicMedicalHistoryName: [
|
||||
{
|
||||
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
|
||||
? updateClinicMedicalHistory
|
||||
: addClinicMedicalHistory;
|
||||
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>
|
||||
42
src/views/clinic/clinicMedicalHistory/components/search.vue
Normal file
42
src/views/clinic/clinicMedicalHistory/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
349
src/views/clinic/clinicMedicalHistory/index.vue
Normal file
349
src/views/clinic/clinicMedicalHistory/index.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicMedicalHistoryEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicMedicalHistoryEdit from './components/clinicMedicalHistoryEdit.vue';
|
||||
import {
|
||||
pageClinicMedicalHistory,
|
||||
removeClinicMedicalHistory,
|
||||
removeBatchClinicMedicalHistory
|
||||
} from '@/api/clinic/clinicMedicalHistory';
|
||||
import type {
|
||||
ClinicMedicalHistory,
|
||||
ClinicMedicalHistoryParam
|
||||
} from '@/api/clinic/clinicMedicalHistory/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicMedicalHistory[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicMedicalHistory | 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 pageClinicMedicalHistory({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(一级)',
|
||||
dataIndex: 'firstUserId',
|
||||
key: 'firstUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(二级)',
|
||||
dataIndex: 'secondUserId',
|
||||
key: 'secondUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(三级)',
|
||||
dataIndex: 'thirdUserId',
|
||||
key: 'thirdUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(一级)',
|
||||
dataIndex: 'firstMoney',
|
||||
key: 'firstMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(二级)',
|
||||
dataIndex: 'secondMoney',
|
||||
key: 'secondMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(三级)',
|
||||
dataIndex: 'thirdMoney',
|
||||
key: 'thirdMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单总金额',
|
||||
dataIndex: 'orderPrice',
|
||||
key: 'orderPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算金额',
|
||||
dataIndex: 'settledPrice',
|
||||
key: 'settledPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '换算成度',
|
||||
dataIndex: 'degreePrice',
|
||||
key: 'degreePrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实发金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '税率',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算月份',
|
||||
dataIndex: 'month',
|
||||
key: 'month',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单是否失效(0未失效 1已失效)',
|
||||
dataIndex: 'isInvalid',
|
||||
key: 'isInvalid',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '佣金结算(0未结算 1已结算)',
|
||||
dataIndex: 'isSettled',
|
||||
key: 'isSettled',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算时间',
|
||||
dataIndex: 'settleTime',
|
||||
key: 'settleTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicMedicalHistoryParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicMedicalHistory) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicMedicalHistory) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicMedicalHistory(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);
|
||||
removeBatchClinicMedicalHistory(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: ClinicMedicalHistory) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicMedicalHistory'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,216 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑药品库' : '添加药品库'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="药名" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入药名"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="拼音" name="pinyin">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入拼音"
|
||||
v-model:value="form.pinyin"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类" name="category">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分类"
|
||||
v-model:value="form.category"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="规格" name="specification">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入规格"
|
||||
v-model:value="form.specification"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单位" name="unit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单位(如“克”、“袋”)"
|
||||
v-model:value="form.unit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="描述" name="content">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.content"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="pricePerUnit">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.pricePerUnit"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否活跃" name="isActive">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否活跃"
|
||||
v-model:value="form.isActive"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import {
|
||||
addClinicMedicine,
|
||||
updateClinicMedicine
|
||||
} from '@/api/clinic/clinicMedicine';
|
||||
import { ClinicMedicine } from '@/api/clinic/clinicMedicine/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;
|
||||
// 修改回显的数据
|
||||
data?: ClinicMedicine | 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<ClinicMedicine>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
pinyin: undefined,
|
||||
category: undefined,
|
||||
specification: undefined,
|
||||
unit: undefined,
|
||||
content: undefined,
|
||||
pricePerUnit: undefined,
|
||||
isActive: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicMedicineName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写药品库名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value
|
||||
? updateClinicMedicine
|
||||
: addClinicMedicine;
|
||||
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>
|
||||
42
src/views/clinic/clinicMedicine/components/search.vue
Normal file
42
src/views/clinic/clinicMedicine/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
279
src/views/clinic/clinicMedicine/index.vue
Normal file
279
src/views/clinic/clinicMedicine/index.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicMedicineEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicMedicineEdit from './components/clinicMedicineEdit.vue';
|
||||
import {
|
||||
pageClinicMedicine,
|
||||
removeClinicMedicine,
|
||||
removeBatchClinicMedicine
|
||||
} from '@/api/clinic/clinicMedicine';
|
||||
import type {
|
||||
ClinicMedicine,
|
||||
ClinicMedicineParam
|
||||
} from '@/api/clinic/clinicMedicine/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicMedicine[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicMedicine | 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 pageClinicMedicine({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '药名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '拼音',
|
||||
dataIndex: 'pinyin',
|
||||
key: 'pinyin',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '规格',
|
||||
dataIndex: 'specification',
|
||||
key: 'specification',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'unit',
|
||||
key: 'unit',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'content',
|
||||
key: 'content',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'pricePerUnit',
|
||||
key: 'pricePerUnit',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '是否活跃',
|
||||
dataIndex: 'isActive',
|
||||
key: 'isActive',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicMedicineParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicMedicine) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicMedicine) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicMedicine(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);
|
||||
removeBatchClinicMedicine(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: ClinicMedicine) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicMedicine'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,323 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(一级)" name="firstUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(一级)"
|
||||
v-model:value="form.firstUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(二级)" name="secondUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(二级)"
|
||||
v-model:value="form.secondUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(三级)"
|
||||
v-model:value="form.thirdUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(一级)" name="firstMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(一级)"
|
||||
v-model:value="form.firstMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(二级)" name="secondMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(二级)"
|
||||
v-model:value="form.secondMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(三级)" name="thirdMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(三级)"
|
||||
v-model:value="form.thirdMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算金额" name="settledPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算金额"
|
||||
v-model:value="form.settledPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="换算成度" name="degreePrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入换算成度"
|
||||
v-model:value="form.degreePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实发金额" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实发金额"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="税率" name="rate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入税率"
|
||||
v-model:value="form.rate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算月份" name="month">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算月份"
|
||||
v-model:value="form.month"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入佣金结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</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 {
|
||||
addClinicMedicineInout,
|
||||
updateClinicMedicineInout
|
||||
} from '@/api/clinic/clinicMedicineInout';
|
||||
import { ClinicMedicineInout } from '@/api/clinic/clinicMedicineInout/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?: ClinicMedicineInout | 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<ClinicMedicineInout>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
orderNo: undefined,
|
||||
firstUserId: undefined,
|
||||
secondUserId: undefined,
|
||||
thirdUserId: undefined,
|
||||
firstMoney: undefined,
|
||||
secondMoney: undefined,
|
||||
thirdMoney: undefined,
|
||||
price: undefined,
|
||||
orderPrice: undefined,
|
||||
settledPrice: undefined,
|
||||
degreePrice: undefined,
|
||||
payPrice: undefined,
|
||||
rate: undefined,
|
||||
month: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
comments: ''
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicMedicineInoutName: [
|
||||
{
|
||||
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
|
||||
? updateClinicMedicineInout
|
||||
: addClinicMedicineInout;
|
||||
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>
|
||||
42
src/views/clinic/clinicMedicineInout/components/search.vue
Normal file
42
src/views/clinic/clinicMedicineInout/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
349
src/views/clinic/clinicMedicineInout/index.vue
Normal file
349
src/views/clinic/clinicMedicineInout/index.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicMedicineInoutEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicMedicineInoutEdit from './components/clinicMedicineInoutEdit.vue';
|
||||
import {
|
||||
pageClinicMedicineInout,
|
||||
removeClinicMedicineInout,
|
||||
removeBatchClinicMedicineInout
|
||||
} from '@/api/clinic/clinicMedicineInout';
|
||||
import type {
|
||||
ClinicMedicineInout,
|
||||
ClinicMedicineInoutParam
|
||||
} from '@/api/clinic/clinicMedicineInout/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicMedicineInout[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicMedicineInout | 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 pageClinicMedicineInout({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(一级)',
|
||||
dataIndex: 'firstUserId',
|
||||
key: 'firstUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(二级)',
|
||||
dataIndex: 'secondUserId',
|
||||
key: 'secondUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(三级)',
|
||||
dataIndex: 'thirdUserId',
|
||||
key: 'thirdUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(一级)',
|
||||
dataIndex: 'firstMoney',
|
||||
key: 'firstMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(二级)',
|
||||
dataIndex: 'secondMoney',
|
||||
key: 'secondMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(三级)',
|
||||
dataIndex: 'thirdMoney',
|
||||
key: 'thirdMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单总金额',
|
||||
dataIndex: 'orderPrice',
|
||||
key: 'orderPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算金额',
|
||||
dataIndex: 'settledPrice',
|
||||
key: 'settledPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '换算成度',
|
||||
dataIndex: 'degreePrice',
|
||||
key: 'degreePrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实发金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '税率',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算月份',
|
||||
dataIndex: 'month',
|
||||
key: 'month',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单是否失效(0未失效 1已失效)',
|
||||
dataIndex: 'isInvalid',
|
||||
key: 'isInvalid',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '佣金结算(0未结算 1已结算)',
|
||||
dataIndex: 'isSettled',
|
||||
key: 'isSettled',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算时间',
|
||||
dataIndex: 'settleTime',
|
||||
key: 'settleTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicMedicineInoutParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicMedicineInout) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicMedicineInout) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicMedicineInout(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);
|
||||
removeBatchClinicMedicineInout(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: ClinicMedicineInout) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicMedicineInout'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,219 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑药品库存' : '添加药品库存'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="药品" name="medicineId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入药品"
|
||||
v-model:value="form.medicineId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="库存数量" name="stockQuantity">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入库存数量"
|
||||
v-model:value="form.stockQuantity"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="最小库存预警" name="minStockLevel">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入最小库存预警"
|
||||
v-model:value="form.minStockLevel"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="上次更新时间" name="lastUpdated">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入上次更新时间"
|
||||
v-model:value="form.lastUpdated"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="买家用户ID" name="userId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入买家用户ID"
|
||||
v-model:value="form.userId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="修改时间" name="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 {
|
||||
addClinicMedicineStock,
|
||||
updateClinicMedicineStock
|
||||
} from '@/api/clinic/clinicMedicineStock';
|
||||
import { ClinicMedicineStock } from '@/api/clinic/clinicMedicineStock/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?: ClinicMedicineStock | 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<ClinicMedicineStock>({
|
||||
id: undefined,
|
||||
medicineId: undefined,
|
||||
stockQuantity: undefined,
|
||||
minStockLevel: undefined,
|
||||
lastUpdated: undefined,
|
||||
userId: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
comments: ''
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicMedicineStockName: [
|
||||
{
|
||||
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
|
||||
? updateClinicMedicineStock
|
||||
: addClinicMedicineStock;
|
||||
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>
|
||||
42
src/views/clinic/clinicMedicineStock/components/search.vue
Normal file
42
src/views/clinic/clinicMedicineStock/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
271
src/views/clinic/clinicMedicineStock/index.vue
Normal file
271
src/views/clinic/clinicMedicineStock/index.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicMedicineStockEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicMedicineStockEdit from './components/clinicMedicineStockEdit.vue';
|
||||
import {
|
||||
pageClinicMedicineStock,
|
||||
removeClinicMedicineStock,
|
||||
removeBatchClinicMedicineStock
|
||||
} from '@/api/clinic/clinicMedicineStock';
|
||||
import type {
|
||||
ClinicMedicineStock,
|
||||
ClinicMedicineStockParam
|
||||
} from '@/api/clinic/clinicMedicineStock/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicMedicineStock[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicMedicineStock | 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 pageClinicMedicineStock({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '药品',
|
||||
dataIndex: 'medicineId',
|
||||
key: 'medicineId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '库存数量',
|
||||
dataIndex: 'stockQuantity',
|
||||
key: 'stockQuantity',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '最小库存预警',
|
||||
dataIndex: 'minStockLevel',
|
||||
key: 'minStockLevel',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '上次更新时间',
|
||||
dataIndex: 'lastUpdated',
|
||||
key: 'lastUpdated',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicMedicineStockParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicMedicineStock) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicMedicineStock) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicMedicineStock(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);
|
||||
removeBatchClinicMedicineStock(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: ClinicMedicineStock) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicMedicineStock'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
782
src/views/clinic/clinicOrder/components/clinicOrderEdit.vue
Normal file
782
src/views/clinic/clinicOrder/components/clinicOrderEdit.vue
Normal file
@@ -0,0 +1,782 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑处方订单' : '添加处方订单'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="订单编号" name="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="订单类型,0商城订单 1预定订单/外卖 2会员卡"
|
||||
name="type"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单类型,0商城订单 1预定订单/外卖 2会员卡"
|
||||
v-model:value="form.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单标题" name="title">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单标题"
|
||||
v-model:value="form.title"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="快递/自提" name="deliveryType">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入快递/自提"
|
||||
v-model:value="form.deliveryType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="下单渠道,0小程序预定 1俱乐部训练场 3活动订场"
|
||||
name="channel"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入下单渠道,0小程序预定 1俱乐部训练场 3活动订场"
|
||||
v-model:value="form.channel"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信支付交易号号" name="transactionId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入微信支付交易号号"
|
||||
v-model:value="form.transactionId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信退款订单号" name="refundOrder">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入微信退款订单号"
|
||||
v-model:value="form.refundOrder"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户ID" name="merchantId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入商户ID"
|
||||
v-model:value="form.merchantId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户名称" name="merchantName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入商户名称"
|
||||
v-model:value="form.merchantName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户编号" name="merchantCode">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入商户编号"
|
||||
v-model:value="form.merchantCode"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="使用的优惠券id" name="couponId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入使用的优惠券id"
|
||||
v-model:value="form.couponId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="使用的会员卡id" name="cardId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入使用的会员卡id"
|
||||
v-model:value="form.cardId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="关联管理员id" name="adminId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入关联管理员id"
|
||||
v-model:value="form.adminId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="核销管理员id" name="confirmId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入核销管理员id"
|
||||
v-model:value="form.confirmId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="IC卡号" name="icCard">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入IC卡号"
|
||||
v-model:value="form.icCard"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="真实姓名" name="realName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入真实姓名"
|
||||
v-model:value="form.realName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="关联收货地址" name="addressId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入关联收货地址"
|
||||
v-model:value="form.addressId"
|
||||
/>
|
||||
</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="addressLat">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入"
|
||||
v-model:value="form.addressLat"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="" name="addressLng">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入"
|
||||
v-model:value="form.addressLng"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="买家留言" name="buyerRemarks">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入买家留言"
|
||||
v-model:value="form.buyerRemarks"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="自提店铺id" name="selfTakeMerchantId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入自提店铺id"
|
||||
v-model:value="form.selfTakeMerchantId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="自提店铺" name="selfTakeMerchantName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入自提店铺"
|
||||
v-model:value="form.selfTakeMerchantName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="配送开始时间" name="sendStartTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入配送开始时间"
|
||||
v-model:value="form.sendStartTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="配送结束时间" name="sendEndTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入配送结束时间"
|
||||
v-model:value="form.sendEndTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="发货店铺id" name="expressMerchantId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入发货店铺id"
|
||||
v-model:value="form.expressMerchantId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="发货店铺" name="expressMerchantName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入发货店铺"
|
||||
v-model:value="form.expressMerchantName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总额" name="totalPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总额"
|
||||
v-model:value="form.totalPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
|
||||
name="reducePrice"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格"
|
||||
v-model:value="form.reducePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实际付款" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实际付款"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="用于统计" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用于统计"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="价钱,用于积分赠送" name="money">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入价钱,用于积分赠送"
|
||||
v-model:value="form.money"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="取消时间" name="cancelTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入取消时间"
|
||||
v-model:value="form.cancelTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="取消原因" name="cancelReason">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入取消原因"
|
||||
v-model:value="form.cancelReason"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="退款金额" name="refundMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入退款金额"
|
||||
v-model:value="form.refundMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="教练价格" name="coachPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入教练价格"
|
||||
v-model:value="form.coachPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="购买数量" name="totalNum">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入购买数量"
|
||||
v-model:value="form.totalNum"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="教练id" name="coachId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入教练id"
|
||||
v-model:value="form.coachId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商品ID" name="formId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入商品ID"
|
||||
v-model:value="form.formId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="支付的用户id" name="payUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入支付的用户id"
|
||||
v-model:value="form.payUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付"
|
||||
name="payType"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付"
|
||||
v-model:value="form.payType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="微信支付子类型:JSAPI小程序支付,NATIVE扫码支付"
|
||||
name="wechatPayType"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入微信支付子类型:JSAPI小程序支付,NATIVE扫码支付"
|
||||
v-model:value="form.wechatPayType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付"
|
||||
name="friendPayType"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付"
|
||||
v-model:value="form.friendPayType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="0未付款,1已付款" name="payStatus">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入0未付款,1已付款"
|
||||
v-model:value="form.payStatus"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
|
||||
name="orderStatus"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款"
|
||||
v-model:value="form.orderStatus"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="发货状态(10未发货 20已发货 30部分发货)"
|
||||
name="deliveryStatus"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入发货状态(10未发货 20已发货 30部分发货)"
|
||||
v-model:value="form.deliveryStatus"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="无需发货备注" name="deliveryNote">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入无需发货备注"
|
||||
v-model:value="form.deliveryNote"
|
||||
/>
|
||||
</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="评价状态(0未评价 1已评价)" name="evaluateStatus">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入评价状态(0未评价 1已评价)"
|
||||
v-model:value="form.evaluateStatus"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="评价时间" name="evaluateTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入评价时间"
|
||||
v-model:value="form.evaluateTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
|
||||
name="couponType"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡"
|
||||
v-model:value="form.couponType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="优惠说明" name="couponDesc">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入优惠说明"
|
||||
v-model:value="form.couponDesc"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="二维码地址,保存订单号,支付成功后才生成"
|
||||
name="qrcode"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入二维码地址,保存订单号,支付成功后才生成"
|
||||
v-model:value="form.qrcode"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="vip月卡年卡、ic月卡年卡回退次数" name="returnNum">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入vip月卡年卡、ic月卡年卡回退次数"
|
||||
v-model:value="form.returnNum"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="vip充值回退金额" name="returnMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入vip充值回退金额"
|
||||
v-model:value="form.returnMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="预约详情开始时间数组" name="startTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入预约详情开始时间数组"
|
||||
v-model:value="form.startTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="是否已开具发票:0未开发票,1已开发票,2不能开具发票"
|
||||
name="isInvoice"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否已开具发票:0未开发票,1已开发票,2不能开具发票"
|
||||
v-model:value="form.isInvoice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="发票流水号" name="invoiceNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入发票流水号"
|
||||
v-model:value="form.invoiceNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商家留言" name="merchantRemarks">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入商家留言"
|
||||
v-model:value="form.merchantRemarks"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="支付时间" name="payTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入支付时间"
|
||||
v-model:value="form.payTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="退款时间" name="refundTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入退款时间"
|
||||
v-model:value="form.refundTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请退款时间" name="refundApplyTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入申请退款时间"
|
||||
v-model:value="form.refundApplyTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="过期时间" name="expirationTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入过期时间"
|
||||
v-model:value="form.expirationTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="自提码" name="selfTakeCode">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入自提码"
|
||||
v-model:value="form.selfTakeCode"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否已收到赠品" name="hasTakeGift">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否已收到赠品"
|
||||
v-model:value="form.hasTakeGift"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单"
|
||||
name="checkBill"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单"
|
||||
v-model:value="form.checkBill"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否已结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否已结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="系统版本号 0当前版本 value=其他版本" name="version">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入系统版本号 0当前版本 value=其他版本"
|
||||
v-model:value="form.version"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="用户id" name="userId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用户id"
|
||||
v-model:value="form.userId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序号" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="是否删除, 0否, 1是" name="deleted">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入是否删除, 0否, 1是"
|
||||
v-model:value="form.deleted"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="修改时间" name="updateTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入修改时间"
|
||||
v-model:value="form.updateTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, uuid } from 'ele-admin-pro';
|
||||
import { addClinicOrder, updateClinicOrder } from '@/api/clinic/clinicOrder';
|
||||
import { ClinicOrder } from '@/api/clinic/clinicOrder/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?: ClinicOrder | 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<ClinicOrder>({
|
||||
orderId: undefined,
|
||||
orderNo: undefined,
|
||||
type: undefined,
|
||||
title: undefined,
|
||||
deliveryType: undefined,
|
||||
channel: undefined,
|
||||
transactionId: undefined,
|
||||
refundOrder: undefined,
|
||||
merchantId: undefined,
|
||||
merchantName: undefined,
|
||||
merchantCode: undefined,
|
||||
couponId: undefined,
|
||||
cardId: undefined,
|
||||
adminId: undefined,
|
||||
confirmId: undefined,
|
||||
icCard: undefined,
|
||||
realName: undefined,
|
||||
addressId: undefined,
|
||||
address: undefined,
|
||||
addressLat: undefined,
|
||||
addressLng: undefined,
|
||||
buyerRemarks: undefined,
|
||||
selfTakeMerchantId: undefined,
|
||||
selfTakeMerchantName: undefined,
|
||||
sendStartTime: undefined,
|
||||
sendEndTime: undefined,
|
||||
expressMerchantId: undefined,
|
||||
expressMerchantName: undefined,
|
||||
totalPrice: undefined,
|
||||
reducePrice: undefined,
|
||||
payPrice: undefined,
|
||||
price: undefined,
|
||||
money: undefined,
|
||||
cancelTime: undefined,
|
||||
cancelReason: undefined,
|
||||
refundMoney: undefined,
|
||||
coachPrice: undefined,
|
||||
totalNum: undefined,
|
||||
coachId: undefined,
|
||||
formId: undefined,
|
||||
payUserId: undefined,
|
||||
payType: undefined,
|
||||
wechatPayType: undefined,
|
||||
friendPayType: undefined,
|
||||
payStatus: undefined,
|
||||
orderStatus: undefined,
|
||||
deliveryStatus: undefined,
|
||||
deliveryNote: undefined,
|
||||
deliveryTime: undefined,
|
||||
evaluateStatus: undefined,
|
||||
evaluateTime: undefined,
|
||||
couponType: undefined,
|
||||
couponDesc: undefined,
|
||||
qrcode: undefined,
|
||||
returnNum: undefined,
|
||||
returnMoney: undefined,
|
||||
startTime: undefined,
|
||||
isInvoice: undefined,
|
||||
invoiceNo: undefined,
|
||||
merchantRemarks: undefined,
|
||||
payTime: undefined,
|
||||
refundTime: undefined,
|
||||
refundApplyTime: undefined,
|
||||
expirationTime: undefined,
|
||||
selfTakeCode: undefined,
|
||||
hasTakeGift: undefined,
|
||||
checkBill: undefined,
|
||||
isSettled: undefined,
|
||||
version: undefined,
|
||||
userId: undefined,
|
||||
comments: undefined,
|
||||
deleted: undefined,
|
||||
tenantId: undefined,
|
||||
updateTime: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicOrderName: [
|
||||
{
|
||||
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
|
||||
? updateClinicOrder
|
||||
: addClinicOrder;
|
||||
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>
|
||||
42
src/views/clinic/clinicOrder/components/search.vue
Normal file
42
src/views/clinic/clinicOrder/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
672
src/views/clinic/clinicOrder/index.vue
Normal file
672
src/views/clinic/clinicOrder/index.vue
Normal file
@@ -0,0 +1,672 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicOrderEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicOrderEdit from './components/clinicOrderEdit.vue';
|
||||
import {
|
||||
pageClinicOrder,
|
||||
removeClinicOrder,
|
||||
removeBatchClinicOrder
|
||||
} from '@/api/clinic/clinicOrder';
|
||||
import type {
|
||||
ClinicOrder,
|
||||
ClinicOrderParam
|
||||
} from '@/api/clinic/clinicOrder/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicOrder[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicOrder | 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 pageClinicOrder({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '订单号',
|
||||
dataIndex: 'orderId',
|
||||
key: 'orderId',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单类型,0商城订单 1预定订单/外卖 2会员卡',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单标题',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '快递/自提',
|
||||
dataIndex: 'deliveryType',
|
||||
key: 'deliveryType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '下单渠道,0小程序预定 1俱乐部训练场 3活动订场',
|
||||
dataIndex: 'channel',
|
||||
key: 'channel',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '微信支付交易号号',
|
||||
dataIndex: 'transactionId',
|
||||
key: 'transactionId',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '微信退款订单号',
|
||||
dataIndex: 'refundOrder',
|
||||
key: 'refundOrder',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '商户ID',
|
||||
dataIndex: 'merchantId',
|
||||
key: 'merchantId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '商户名称',
|
||||
dataIndex: 'merchantName',
|
||||
key: 'merchantName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '商户编号',
|
||||
dataIndex: 'merchantCode',
|
||||
key: 'merchantCode',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '使用的优惠券id',
|
||||
dataIndex: 'couponId',
|
||||
key: 'couponId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '使用的会员卡id',
|
||||
dataIndex: 'cardId',
|
||||
key: 'cardId',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '关联管理员id',
|
||||
dataIndex: 'adminId',
|
||||
key: 'adminId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '核销管理员id',
|
||||
dataIndex: 'confirmId',
|
||||
key: 'confirmId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: 'IC卡号',
|
||||
dataIndex: 'icCard',
|
||||
key: 'icCard',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '真实姓名',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '关联收货地址',
|
||||
dataIndex: 'addressId',
|
||||
key: 'addressId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '收货地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'addressLat',
|
||||
key: 'addressLat',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'addressLng',
|
||||
key: 'addressLng',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '买家留言',
|
||||
dataIndex: 'buyerRemarks',
|
||||
key: 'buyerRemarks',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '自提店铺id',
|
||||
dataIndex: 'selfTakeMerchantId',
|
||||
key: 'selfTakeMerchantId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '自提店铺',
|
||||
dataIndex: 'selfTakeMerchantName',
|
||||
key: 'selfTakeMerchantName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '配送开始时间',
|
||||
dataIndex: 'sendStartTime',
|
||||
key: 'sendStartTime',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '配送结束时间',
|
||||
dataIndex: 'sendEndTime',
|
||||
key: 'sendEndTime',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '发货店铺id',
|
||||
dataIndex: 'expressMerchantId',
|
||||
key: 'expressMerchantId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '发货店铺',
|
||||
dataIndex: 'expressMerchantName',
|
||||
key: 'expressMerchantName',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单总额',
|
||||
dataIndex: 'totalPrice',
|
||||
key: 'totalPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '减少的金额,使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格',
|
||||
dataIndex: 'reducePrice',
|
||||
key: 'reducePrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实际付款',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '用于统计',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '价钱,用于积分赠送',
|
||||
dataIndex: 'money',
|
||||
key: 'money',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '取消时间',
|
||||
dataIndex: 'cancelTime',
|
||||
key: 'cancelTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '取消原因',
|
||||
dataIndex: 'cancelReason',
|
||||
key: 'cancelReason',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '退款金额',
|
||||
dataIndex: 'refundMoney',
|
||||
key: 'refundMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '教练价格',
|
||||
dataIndex: 'coachPrice',
|
||||
key: 'coachPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '购买数量',
|
||||
dataIndex: 'totalNum',
|
||||
key: 'totalNum',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '教练id',
|
||||
dataIndex: 'coachId',
|
||||
key: 'coachId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '商品ID',
|
||||
dataIndex: 'formId',
|
||||
key: 'formId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '支付的用户id',
|
||||
dataIndex: 'payUserId',
|
||||
key: 'payUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title:
|
||||
'0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付',
|
||||
dataIndex: 'payType',
|
||||
key: 'payType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '微信支付子类型:JSAPI小程序支付,NATIVE扫码支付',
|
||||
dataIndex: 'wechatPayType',
|
||||
key: 'wechatPayType',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title:
|
||||
'0余额支付,1微信支付,2支付宝支付,3银联支付,4现金支付,5POS机支付,6免费,7积分支付',
|
||||
dataIndex: 'friendPayType',
|
||||
key: 'friendPayType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '0未付款,1已付款',
|
||||
dataIndex: 'payStatus',
|
||||
key: 'payStatus',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title:
|
||||
'0未使用,1已完成,2已取消,3取消中,4退款申请中,5退款被拒绝,6退款成功,7客户端申请退款',
|
||||
dataIndex: 'orderStatus',
|
||||
key: 'orderStatus',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '发货状态(10未发货 20已发货 30部分发货)',
|
||||
dataIndex: 'deliveryStatus',
|
||||
key: 'deliveryStatus',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '无需发货备注',
|
||||
dataIndex: 'deliveryNote',
|
||||
key: 'deliveryNote',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '发货时间',
|
||||
dataIndex: 'deliveryTime',
|
||||
key: 'deliveryTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '评价状态(0未评价 1已评价)',
|
||||
dataIndex: 'evaluateStatus',
|
||||
key: 'evaluateStatus',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '评价时间',
|
||||
dataIndex: 'evaluateTime',
|
||||
key: 'evaluateTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title:
|
||||
'优惠类型:0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡,5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡',
|
||||
dataIndex: 'couponType',
|
||||
key: 'couponType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '优惠说明',
|
||||
dataIndex: 'couponDesc',
|
||||
key: 'couponDesc',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '二维码地址,保存订单号,支付成功后才生成',
|
||||
dataIndex: 'qrcode',
|
||||
key: 'qrcode',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: 'vip月卡年卡、ic月卡年卡回退次数',
|
||||
dataIndex: 'returnNum',
|
||||
key: 'returnNum',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: 'vip充值回退金额',
|
||||
dataIndex: 'returnMoney',
|
||||
key: 'returnMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '预约详情开始时间数组',
|
||||
dataIndex: 'startTime',
|
||||
key: 'startTime',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '是否已开具发票:0未开发票,1已开发票,2不能开具发票',
|
||||
dataIndex: 'isInvoice',
|
||||
key: 'isInvoice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '发票流水号',
|
||||
dataIndex: 'invoiceNo',
|
||||
key: 'invoiceNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '商家留言',
|
||||
dataIndex: 'merchantRemarks',
|
||||
key: 'merchantRemarks',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '支付时间',
|
||||
dataIndex: 'payTime',
|
||||
key: 'payTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '退款时间',
|
||||
dataIndex: 'refundTime',
|
||||
key: 'refundTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '申请退款时间',
|
||||
dataIndex: 'refundApplyTime',
|
||||
key: 'refundApplyTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '过期时间',
|
||||
dataIndex: 'expirationTime',
|
||||
key: 'expirationTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '自提码',
|
||||
dataIndex: 'selfTakeCode',
|
||||
key: 'selfTakeCode',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '是否已收到赠品',
|
||||
dataIndex: 'hasTakeGift',
|
||||
key: 'hasTakeGift',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title:
|
||||
'对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单',
|
||||
dataIndex: 'checkBill',
|
||||
key: 'checkBill',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单是否已结算(0未结算 1已结算)',
|
||||
dataIndex: 'isSettled',
|
||||
key: 'isSettled',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '系统版本号 0当前版本 value=其他版本',
|
||||
dataIndex: 'version',
|
||||
key: 'version',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '用户id',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '排序号',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '是否删除, 0否, 1是',
|
||||
dataIndex: 'deleted',
|
||||
key: 'deleted',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicOrderParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicOrder) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicOrder) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicOrder(row.orderId)
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
/* 批量删除 */
|
||||
const removeBatch = () => {
|
||||
if (!selection.value.length) {
|
||||
message.error('请至少选择一条数据');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定要删除选中的记录吗?',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
maskClosable: true,
|
||||
onOk: () => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBatchClinicOrder(selection.value.map((d) => d.orderId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: ClinicOrder) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicOrder'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,228 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:maxable="maxable"
|
||||
:title="isUpdate ? '编辑患者' : '添加患者'"
|
||||
:body-style="{ paddingBottom: '28px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<!-- <a-form-item label="类型 0经销商 1企业 2集团" name="type">-->
|
||||
<!-- <a-input-->
|
||||
<!-- allow-clear-->
|
||||
<!-- placeholder="请输入类型 0经销商 1企业 2集团"-->
|
||||
<!-- v-model:value="form.type"-->
|
||||
<!-- />-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item v-if="isUpdate" label="用户ID" name="userId">
|
||||
{{ form.userId }}
|
||||
</a-form-item>
|
||||
<a-form-item label="姓名" name="realName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入姓名"
|
||||
v-model:value="form.realName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号" name="phone">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入手机号"
|
||||
disabled
|
||||
v-model:value="form.phone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="年龄" name="age">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入年龄"
|
||||
v-model:value="form.age"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="身高" name="height">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入身高"
|
||||
v-model:value="form.height"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="体重" name="weight">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入体重"
|
||||
v-model:value="form.weight"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="过敏史" name="allergyHistory">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入过敏史"
|
||||
v-model:value="form.allergyHistory"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序号" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import {
|
||||
addClinicPatientUser,
|
||||
updateClinicPatientUser
|
||||
} from '@/api/clinic/clinicPatientUser';
|
||||
import { ClinicPatientUser } from '@/api/clinic/clinicPatientUser/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;
|
||||
// 修改回显的数据
|
||||
data?: ClinicPatientUser | 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<ClinicPatientUser>({
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
userId: undefined,
|
||||
realName: undefined,
|
||||
phone: undefined,
|
||||
age: undefined,
|
||||
height: undefined,
|
||||
weight: undefined,
|
||||
allergyHistory: undefined,
|
||||
qrcode: undefined,
|
||||
comments: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicPatientUserName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写患者名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value
|
||||
? updateClinicPatientUser
|
||||
: addClinicPatientUser;
|
||||
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>
|
||||
42
src/views/clinic/clinicPatientUser/components/search.vue
Normal file
42
src/views/clinic/clinicPatientUser/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
298
src/views/clinic/clinicPatientUser/index.vue
Normal file
298
src/views/clinic/clinicPatientUser/index.vue
Normal file
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === 'realName'">
|
||||
<a-space>
|
||||
<a-avatar :src="record.avatar" />
|
||||
<div class="flex flex-col">
|
||||
<div>{{ record.realName }}</div>
|
||||
<div class="text-gray-400">{{ record.phone }}</div>
|
||||
</div>
|
||||
</a-space>
|
||||
</template>
|
||||
<template v-if="column.key === 'sex'">
|
||||
<a-tag v-if="record.sex == '1'" color="blue">男</a-tag>
|
||||
<a-tag v-if="record.sex == '2'" color="pink">女</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicPatientUserEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicPatientUserEdit from './components/clinicPatientUserEdit.vue';
|
||||
import {
|
||||
pageClinicPatientUser,
|
||||
removeClinicPatientUser,
|
||||
removeBatchClinicPatientUser
|
||||
} from '@/api/clinic/clinicPatientUser';
|
||||
import type {
|
||||
ClinicPatientUser,
|
||||
ClinicPatientUserParam
|
||||
} from '@/api/clinic/clinicPatientUser/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicPatientUser[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicPatientUser | 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 pageClinicPatientUser({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '患者ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '患者信息',
|
||||
dataIndex: 'realName',
|
||||
key: 'realName',
|
||||
width: 180
|
||||
},
|
||||
// {
|
||||
// title: '手机号',
|
||||
// dataIndex: 'phone',
|
||||
// key: 'phone',
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
align: 'center',
|
||||
dataIndex: 'age',
|
||||
key: 'age'
|
||||
},
|
||||
{
|
||||
title: '身高',
|
||||
align: 'center',
|
||||
dataIndex: 'height',
|
||||
key: 'height'
|
||||
},
|
||||
{
|
||||
title: '体重',
|
||||
align: 'center',
|
||||
dataIndex: 'weight',
|
||||
key: 'weight'
|
||||
},
|
||||
// {
|
||||
// title: '专属二维码',
|
||||
// dataIndex: 'qrcode',
|
||||
// key: 'qrcode',
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '过敏史',
|
||||
dataIndex: 'allergyHistory',
|
||||
key: 'allergyHistory'
|
||||
},
|
||||
{
|
||||
title: '患者描述',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '排序号',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
align: 'center',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicPatientUserParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicPatientUser) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicPatientUser) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicPatientUser(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);
|
||||
removeBatchClinicPatientUser(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: ClinicPatientUser) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicPatientUser'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,277 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="医生" name="doctorId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入医生"
|
||||
v-model:value="form.doctorId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单编号" name="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="关联就诊表" name="visitRecordId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入关联就诊表"
|
||||
v-model:value="form.visitRecordId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="处方类型 0中药 1西药" name="prescriptionType">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入处方类型 0中药 1西药"
|
||||
v-model:value="form.prescriptionType"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="诊断结果" name="diagnosis">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入诊断结果"
|
||||
v-model:value="form.diagnosis"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="治疗方案" name="treatmentPlan">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入治疗方案"
|
||||
v-model:value="form.treatmentPlan"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="煎药说明" name="decoctionInstructions">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入煎药说明"
|
||||
v-model:value="form.decoctionInstructions"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</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="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态, 0正常, 1已完成,2已支付,3已取消" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">显示</a-radio>
|
||||
<a-radio :value="1">隐藏</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="修改时间" name="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 {
|
||||
addClinicPrescription,
|
||||
updateClinicPrescription
|
||||
} from '@/api/clinic/clinicPrescription';
|
||||
import { ClinicPrescription } from '@/api/clinic/clinicPrescription/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?: ClinicPrescription | 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<ClinicPrescription>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
doctorId: undefined,
|
||||
orderNo: undefined,
|
||||
visitRecordId: undefined,
|
||||
prescriptionType: undefined,
|
||||
diagnosis: undefined,
|
||||
treatmentPlan: undefined,
|
||||
decoctionInstructions: undefined,
|
||||
orderPrice: undefined,
|
||||
price: undefined,
|
||||
payPrice: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
status: 0,
|
||||
comments: ''
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicPrescriptionName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写处方主表名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value
|
||||
? updateClinicPrescription
|
||||
: addClinicPrescription;
|
||||
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>
|
||||
42
src/views/clinic/clinicPrescription/components/search.vue
Normal file
42
src/views/clinic/clinicPrescription/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
331
src/views/clinic/clinicPrescription/index.vue
Normal file
331
src/views/clinic/clinicPrescription/index.vue
Normal file
@@ -0,0 +1,331 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicPrescriptionEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicPrescriptionEdit from './components/clinicPrescriptionEdit.vue';
|
||||
import {
|
||||
pageClinicPrescription,
|
||||
removeClinicPrescription,
|
||||
removeBatchClinicPrescription
|
||||
} from '@/api/clinic/clinicPrescription';
|
||||
import type {
|
||||
ClinicPrescription,
|
||||
ClinicPrescriptionParam
|
||||
} from '@/api/clinic/clinicPrescription/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicPrescription[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicPrescription | 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 pageClinicPrescription({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '患者',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '医生',
|
||||
dataIndex: 'doctorId',
|
||||
key: 'doctorId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '关联就诊表',
|
||||
dataIndex: 'visitRecordId',
|
||||
key: 'visitRecordId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '处方类型',
|
||||
dataIndex: 'prescriptionType',
|
||||
key: 'prescriptionType',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '诊断结果',
|
||||
dataIndex: 'diagnosis',
|
||||
key: 'diagnosis',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '治疗方案',
|
||||
dataIndex: 'treatmentPlan',
|
||||
key: 'treatmentPlan',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '煎药说明',
|
||||
dataIndex: 'decoctionInstructions',
|
||||
key: 'decoctionInstructions',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单总金额',
|
||||
dataIndex: 'orderPrice',
|
||||
key: 'orderPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实付金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
// {
|
||||
// title: '是否失效',
|
||||
// dataIndex: 'isInvalid',
|
||||
// key: 'isInvalid',
|
||||
// width: 120
|
||||
// },
|
||||
// {
|
||||
// title: '结算(0未结算 1已结算)',
|
||||
// dataIndex: 'isSettled',
|
||||
// key: 'isSettled',
|
||||
// width: 120
|
||||
// },
|
||||
// {
|
||||
// title: '结算时间',
|
||||
// dataIndex: 'settleTime',
|
||||
// key: 'settleTime',
|
||||
// width: 120
|
||||
// },
|
||||
// {
|
||||
// title: '状态, 0正常, 1已完成,2已支付,3已取消',
|
||||
// dataIndex: 'status',
|
||||
// key: 'status',
|
||||
// width: 120
|
||||
// },
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicPrescriptionParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicPrescription) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicPrescription) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicPrescription(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);
|
||||
removeBatchClinicPrescription(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: ClinicPrescription) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicPrescription'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,247 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="prescriptionId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入关联处方"
|
||||
v-model:value="form.prescriptionId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单编号" name="prescriptionNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.prescriptionNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="关联药品" name="medicineId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入关联药品"
|
||||
v-model:value="form.medicineId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="剂量(如“10g”)" name="dosage">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入剂量(如“10g”)"
|
||||
v-model:value="form.dosage"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="用法频率(如“每日三次”)" name="usageFrequency">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用法频率(如“每日三次”)"
|
||||
v-model:value="form.usageFrequency"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="服用天数" name="days">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入服用天数"
|
||||
v-model:value="form.days"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="购买数量" name="amount">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入购买数量"
|
||||
v-model:value="form.amount"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="unitPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.unitPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="数量" name="quantity">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入数量"
|
||||
v-model:value="form.quantity"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序号" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="用户id" name="userId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用户id"
|
||||
v-model:value="form.userId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="更新时间" name="updateTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入更新时间"
|
||||
v-model:value="form.updateTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import {
|
||||
addClinicPrescriptionItem,
|
||||
updateClinicPrescriptionItem
|
||||
} from '@/api/clinic/clinicPrescriptionItem';
|
||||
import { ClinicPrescriptionItem } from '@/api/clinic/clinicPrescriptionItem/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;
|
||||
// 修改回显的数据
|
||||
data?: ClinicPrescriptionItem | 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<ClinicPrescriptionItem>({
|
||||
id: undefined,
|
||||
prescriptionId: undefined,
|
||||
prescriptionNo: undefined,
|
||||
medicineId: undefined,
|
||||
dosage: undefined,
|
||||
usageFrequency: undefined,
|
||||
days: undefined,
|
||||
amount: undefined,
|
||||
unitPrice: undefined,
|
||||
quantity: undefined,
|
||||
userId: undefined,
|
||||
tenantId: undefined,
|
||||
updateTime: undefined,
|
||||
createTime: undefined,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicPrescriptionItemName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写处方明细表名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value
|
||||
? updateClinicPrescriptionItem
|
||||
: addClinicPrescriptionItem;
|
||||
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>
|
||||
307
src/views/clinic/clinicPrescriptionItem/index.vue
Normal file
307
src/views/clinic/clinicPrescriptionItem/index.vue
Normal file
@@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicPrescriptionItemEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref, computed } 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicPrescriptionItemEdit from './components/clinicPrescriptionItemEdit.vue';
|
||||
import {
|
||||
pageClinicPrescriptionItem,
|
||||
removeClinicPrescriptionItem,
|
||||
removeBatchClinicPrescriptionItem
|
||||
} from '@/api/clinic/clinicPrescriptionItem';
|
||||
import type {
|
||||
ClinicPrescriptionItem,
|
||||
ClinicPrescriptionItemParam
|
||||
} from '@/api/clinic/clinicPrescriptionItem/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicPrescriptionItem[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicPrescriptionItem | 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 pageClinicPrescriptionItem({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '自增ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '关联处方',
|
||||
dataIndex: 'prescriptionId',
|
||||
key: 'prescriptionId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'prescriptionNo',
|
||||
key: 'prescriptionNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '关联药品',
|
||||
dataIndex: 'medicineId',
|
||||
key: 'medicineId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '剂量(如“10g”)',
|
||||
dataIndex: 'dosage',
|
||||
key: 'dosage',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '用法频率(如“每日三次”)',
|
||||
dataIndex: 'usageFrequency',
|
||||
key: 'usageFrequency',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '服用天数',
|
||||
dataIndex: 'days',
|
||||
key: 'days',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '购买数量',
|
||||
dataIndex: 'amount',
|
||||
key: 'amount',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'unitPrice',
|
||||
key: 'unitPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
dataIndex: 'quantity',
|
||||
key: 'quantity',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '排序号',
|
||||
dataIndex: 'sortNumber',
|
||||
key: 'sortNumber',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '用户id',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicPrescriptionItemParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicPrescriptionItem) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicPrescriptionItem) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicPrescriptionItem(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);
|
||||
removeBatchClinicPrescriptionItem(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: ClinicPrescriptionItem) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicPrescriptionItem'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
323
src/views/clinic/clinicReport/components/clinicReportEdit.vue
Normal file
323
src/views/clinic/clinicReport/components/clinicReportEdit.vue
Normal file
@@ -0,0 +1,323 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(一级)" name="firstUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(一级)"
|
||||
v-model:value="form.firstUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(二级)" name="secondUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(二级)"
|
||||
v-model:value="form.secondUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(三级)"
|
||||
v-model:value="form.thirdUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(一级)" name="firstMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(一级)"
|
||||
v-model:value="form.firstMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(二级)" name="secondMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(二级)"
|
||||
v-model:value="form.secondMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(三级)" name="thirdMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(三级)"
|
||||
v-model:value="form.thirdMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算金额" name="settledPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算金额"
|
||||
v-model:value="form.settledPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="换算成度" name="degreePrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入换算成度"
|
||||
v-model:value="form.degreePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实发金额" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实发金额"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="税率" name="rate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入税率"
|
||||
v-model:value="form.rate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算月份" name="month">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算月份"
|
||||
v-model:value="form.month"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入佣金结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</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 {
|
||||
addClinicReport,
|
||||
updateClinicReport
|
||||
} from '@/api/clinic/clinicReport';
|
||||
import { ClinicReport } from '@/api/clinic/clinicReport/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?: ClinicReport | 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<ClinicReport>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
orderNo: undefined,
|
||||
firstUserId: undefined,
|
||||
secondUserId: undefined,
|
||||
thirdUserId: undefined,
|
||||
firstMoney: undefined,
|
||||
secondMoney: undefined,
|
||||
thirdMoney: undefined,
|
||||
price: undefined,
|
||||
orderPrice: undefined,
|
||||
settledPrice: undefined,
|
||||
degreePrice: undefined,
|
||||
payPrice: undefined,
|
||||
rate: undefined,
|
||||
month: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
comments: ''
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicReportName: [
|
||||
{
|
||||
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
|
||||
? updateClinicReport
|
||||
: addClinicReport;
|
||||
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>
|
||||
42
src/views/clinic/clinicReport/components/search.vue
Normal file
42
src/views/clinic/clinicReport/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
349
src/views/clinic/clinicReport/index.vue
Normal file
349
src/views/clinic/clinicReport/index.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicReportEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicReportEdit from './components/clinicReportEdit.vue';
|
||||
import {
|
||||
pageClinicReport,
|
||||
removeClinicReport,
|
||||
removeBatchClinicReport
|
||||
} from '@/api/clinic/clinicReport';
|
||||
import type {
|
||||
ClinicReport,
|
||||
ClinicReportParam
|
||||
} from '@/api/clinic/clinicReport/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicReport[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicReport | 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 pageClinicReport({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(一级)',
|
||||
dataIndex: 'firstUserId',
|
||||
key: 'firstUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(二级)',
|
||||
dataIndex: 'secondUserId',
|
||||
key: 'secondUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(三级)',
|
||||
dataIndex: 'thirdUserId',
|
||||
key: 'thirdUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(一级)',
|
||||
dataIndex: 'firstMoney',
|
||||
key: 'firstMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(二级)',
|
||||
dataIndex: 'secondMoney',
|
||||
key: 'secondMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(三级)',
|
||||
dataIndex: 'thirdMoney',
|
||||
key: 'thirdMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单总金额',
|
||||
dataIndex: 'orderPrice',
|
||||
key: 'orderPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算金额',
|
||||
dataIndex: 'settledPrice',
|
||||
key: 'settledPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '换算成度',
|
||||
dataIndex: 'degreePrice',
|
||||
key: 'degreePrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实发金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '税率',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算月份',
|
||||
dataIndex: 'month',
|
||||
key: 'month',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单是否失效(0未失效 1已失效)',
|
||||
dataIndex: 'isInvalid',
|
||||
key: 'isInvalid',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '佣金结算(0未结算 1已结算)',
|
||||
dataIndex: 'isSettled',
|
||||
key: 'isSettled',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算时间',
|
||||
dataIndex: 'settleTime',
|
||||
key: 'settleTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicReportParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicReport) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicReport) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicReport(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);
|
||||
removeBatchClinicReport(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: ClinicReport) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicReport'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -0,0 +1,302 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<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="orderNo">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单编号"
|
||||
v-model:value="form.orderNo"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(一级)" name="firstUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(一级)"
|
||||
v-model:value="form.firstUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(二级)" name="secondUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(二级)"
|
||||
v-model:value="form.secondUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销商用户id(三级)" name="thirdUserId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销商用户id(三级)"
|
||||
v-model:value="form.thirdUserId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(一级)" name="firstMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(一级)"
|
||||
v-model:value="form.firstMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(二级)" name="secondMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(二级)"
|
||||
v-model:value="form.secondMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分销佣金(三级)" name="thirdMoney">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入分销佣金(三级)"
|
||||
v-model:value="form.thirdMoney"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入单价"
|
||||
v-model:value="form.price"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单总金额" name="orderPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单总金额"
|
||||
v-model:value="form.orderPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算金额" name="settledPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算金额"
|
||||
v-model:value="form.settledPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="换算成度" name="degreePrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入换算成度"
|
||||
v-model:value="form.degreePrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="实发金额" name="payPrice">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入实发金额"
|
||||
v-model:value="form.payPrice"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="税率" name="rate">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入税率"
|
||||
v-model:value="form.rate"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算月份" name="month">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算月份"
|
||||
v-model:value="form.month"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入订单是否失效(0未失效 1已失效)"
|
||||
v-model:value="form.isInvalid"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="佣金结算(0未结算 1已结算)" name="isSettled">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入佣金结算(0未结算 1已结算)"
|
||||
v-model:value="form.isSettled"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结算时间" name="settleTime">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入结算时间"
|
||||
v-model:value="form.settleTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</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 {
|
||||
addClinicVisitRecord,
|
||||
updateClinicVisitRecord
|
||||
} from '@/api/clinic/clinicVisitRecord';
|
||||
import { ClinicVisitRecord } from '@/api/clinic/clinicVisitRecord/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?: ClinicVisitRecord | 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<ClinicVisitRecord>({
|
||||
id: undefined,
|
||||
userId: undefined,
|
||||
orderNo: undefined,
|
||||
firstUserId: undefined,
|
||||
secondUserId: undefined,
|
||||
thirdUserId: undefined,
|
||||
firstMoney: undefined,
|
||||
secondMoney: undefined,
|
||||
thirdMoney: undefined,
|
||||
price: undefined,
|
||||
orderPrice: undefined,
|
||||
settledPrice: undefined,
|
||||
degreePrice: undefined,
|
||||
payPrice: undefined,
|
||||
rate: undefined,
|
||||
month: undefined,
|
||||
isInvalid: undefined,
|
||||
isSettled: undefined,
|
||||
settleTime: undefined,
|
||||
comments: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
clinicVisitRecordName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写病例名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value
|
||||
? updateClinicVisitRecord
|
||||
: addClinicVisitRecord;
|
||||
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>
|
||||
42
src/views/clinic/clinicVisitRecord/components/search.vue
Normal file
42
src/views/clinic/clinicVisitRecord/components/search.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import type { GradeParam } from '@/api/user/grade/model';
|
||||
import { watch } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: GradeParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
}>();
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
349
src/views/clinic/clinicVisitRecord/index.vue
Normal file
349
src/views/clinic/clinicVisitRecord/index.vue
Normal file
@@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<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 === '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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<ClinicVisitRecordEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
@done="reload"
|
||||
/>
|
||||
</a-page-header>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { 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 { getPageTitle } from '@/utils/common';
|
||||
import ClinicVisitRecordEdit from './components/clinicVisitRecordEdit.vue';
|
||||
import {
|
||||
pageClinicVisitRecord,
|
||||
removeClinicVisitRecord,
|
||||
removeBatchClinicVisitRecord
|
||||
} from '@/api/clinic/clinicVisitRecord';
|
||||
import type {
|
||||
ClinicVisitRecord,
|
||||
ClinicVisitRecordParam
|
||||
} from '@/api/clinic/clinicVisitRecord/model';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<ClinicVisitRecord[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<ClinicVisitRecord | 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 pageClinicVisitRecord({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 完整的列配置(包含所有字段)
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: '主键ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '买家用户ID',
|
||||
dataIndex: 'userId',
|
||||
key: 'userId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
dataIndex: 'orderNo',
|
||||
key: 'orderNo',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(一级)',
|
||||
dataIndex: 'firstUserId',
|
||||
key: 'firstUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(二级)',
|
||||
dataIndex: 'secondUserId',
|
||||
key: 'secondUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销商用户id(三级)',
|
||||
dataIndex: 'thirdUserId',
|
||||
key: 'thirdUserId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(一级)',
|
||||
dataIndex: 'firstMoney',
|
||||
key: 'firstMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(二级)',
|
||||
dataIndex: 'secondMoney',
|
||||
key: 'secondMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '分销佣金(三级)',
|
||||
dataIndex: 'thirdMoney',
|
||||
key: 'thirdMoney',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
dataIndex: 'price',
|
||||
key: 'price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '订单总金额',
|
||||
dataIndex: 'orderPrice',
|
||||
key: 'orderPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算金额',
|
||||
dataIndex: 'settledPrice',
|
||||
key: 'settledPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '换算成度',
|
||||
dataIndex: 'degreePrice',
|
||||
key: 'degreePrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '实发金额',
|
||||
dataIndex: 'payPrice',
|
||||
key: 'payPrice',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '税率',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算月份',
|
||||
dataIndex: 'month',
|
||||
key: 'month',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '订单是否失效(0未失效 1已失效)',
|
||||
dataIndex: 'isInvalid',
|
||||
key: 'isInvalid',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '佣金结算(0未结算 1已结算)',
|
||||
dataIndex: 'isSettled',
|
||||
key: 'isSettled',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '结算时间',
|
||||
dataIndex: 'settleTime',
|
||||
key: 'settleTime',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'comments',
|
||||
key: 'comments',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
sorter: true,
|
||||
ellipsis: 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?: ClinicVisitRecordParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: ClinicVisitRecord) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: ClinicVisitRecord) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeClinicVisitRecord(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);
|
||||
removeBatchClinicVisitRecord(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: ClinicVisitRecord) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClinicVisitRecord'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
41
src/views/cms/clear-cache/index.vue
Normal file
41
src/views/cms/clear-cache/index.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="ele-body">
|
||||
<a-card :bordered="false">
|
||||
<div style="max-width: 960px; margin: 0 auto">
|
||||
<a-result :status="success ? 'success' : ''" :title="title">
|
||||
<template #extra>
|
||||
<a-space size="middle">
|
||||
<a-button danger @click="reload">清除缓存</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-result>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const success = ref<boolean>(false);
|
||||
const title = ref<string>();
|
||||
|
||||
const reload = () => {
|
||||
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId')).then(
|
||||
(msg) => {
|
||||
if (msg) {
|
||||
success.value = true;
|
||||
title.value = '操作成功';
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
reload();
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ClearCache'
|
||||
};
|
||||
</script>
|
||||
219
src/views/cms/cmsAd/components/Import.vue
Normal file
219
src/views/cms/cmsAd/components/Import.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<!-- 广告位导入备份弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="520"
|
||||
:footer="null"
|
||||
title="导入备份"
|
||||
:visible="visible"
|
||||
@update:visible="updateVisible"
|
||||
>
|
||||
<a-spin :spinning="loading">
|
||||
<a-upload-dragger
|
||||
accept=".xls,.xlsx"
|
||||
:show-upload-list="false"
|
||||
:customRequest="doUpload"
|
||||
style="padding: 24px 0; margin-bottom: 16px"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<cloud-upload-outlined />
|
||||
</p>
|
||||
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
||||
</a-upload-dragger>
|
||||
</a-spin>
|
||||
<div class="ele-text-center">
|
||||
<span>只能上传xls、xlsx文件;恢复时:有广告ID则更新,没有则新增</span>
|
||||
</div>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
||||
import { read, utils } from 'xlsx';
|
||||
import { addCmsAd, updateCmsAd } from '@/api/cms/cmsAd';
|
||||
import type { CmsAd } from '@/api/cms/cmsAd/model';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
defineProps<{
|
||||
// 是否打开弹窗
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
// 导入请求状态
|
||||
const loading = ref(false);
|
||||
|
||||
const COL = {
|
||||
adId: '广告ID',
|
||||
type: '类型',
|
||||
code: '唯一标识',
|
||||
categoryId: '栏目ID',
|
||||
categoryName: '栏目名称',
|
||||
name: '广告位名称',
|
||||
width: '宽',
|
||||
height: '高',
|
||||
style: '样式',
|
||||
images: '图片数据',
|
||||
path: '链接',
|
||||
sortNumber: '排序号',
|
||||
comments: '备注',
|
||||
status: '状态',
|
||||
lang: '语言',
|
||||
tenantId: '租户ID',
|
||||
merchantId: '商户ID'
|
||||
} as const;
|
||||
|
||||
const parseNumber = (val: any): number | undefined => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const n = Number(val);
|
||||
return Number.isFinite(n) ? n : undefined;
|
||||
};
|
||||
|
||||
const parseString = (val: any): string | undefined => {
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return String(val);
|
||||
};
|
||||
|
||||
const normalizeImages = (val: any): string => {
|
||||
const raw = parseString(val);
|
||||
if (!raw) {
|
||||
return '';
|
||||
}
|
||||
// 备份文件中图片数据优先使用 JSON;如果是 url,则补成编辑器保存时的数组格式
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return JSON.stringify(parsed ?? []);
|
||||
} catch (_e) {
|
||||
return JSON.stringify([
|
||||
{ uid: '', url: raw, status: 'done', title: '', path: '' }
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
/* 上传 */
|
||||
const doUpload = async ({ file }: any) => {
|
||||
if (
|
||||
![
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
].includes(file.type)
|
||||
) {
|
||||
message.error('只能选择 excel 文件');
|
||||
return false;
|
||||
}
|
||||
if (file.size / 1024 / 1024 > 10) {
|
||||
message.error('大小不能超过 10MB');
|
||||
return false;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const buffer = await file.arrayBuffer();
|
||||
const wb = read(buffer, { type: 'array' });
|
||||
const sheetName = wb.SheetNames?.[0];
|
||||
if (!sheetName) {
|
||||
throw new Error('文件中未找到工作表');
|
||||
}
|
||||
const sheet = wb.Sheets[sheetName];
|
||||
const rows = utils.sheet_to_json<Record<string, any>>(sheet, {
|
||||
defval: ''
|
||||
});
|
||||
if (!rows?.length) {
|
||||
throw new Error('文件内容为空');
|
||||
}
|
||||
if (!(COL.code in rows[0]) && !(COL.name in rows[0])) {
|
||||
throw new Error('文件格式不匹配,请使用“备份”导出的文件进行恢复');
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: `确定要恢复 ${rows.length} 条广告位吗?(有广告ID则更新,没有则新增)`,
|
||||
maskClosable: true,
|
||||
onOk: async () => {
|
||||
const hide = message.loading('恢复中..', 0);
|
||||
let ok = 0;
|
||||
let fail = 0;
|
||||
const errors: string[] = [];
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const row = rows[i] ?? {};
|
||||
const payload: CmsAd = {
|
||||
adId: parseNumber(row[COL.adId]),
|
||||
type: parseNumber(row[COL.type]),
|
||||
code: parseString(row[COL.code]),
|
||||
categoryId: parseNumber(row[COL.categoryId]),
|
||||
categoryName: parseString(row[COL.categoryName]),
|
||||
name: parseString(row[COL.name]),
|
||||
width: parseString(row[COL.width]),
|
||||
height: parseString(row[COL.height]),
|
||||
style: parseString(row[COL.style]),
|
||||
images: normalizeImages(row[COL.images]),
|
||||
path: parseString(row[COL.path]),
|
||||
sortNumber: parseNumber(row[COL.sortNumber]),
|
||||
comments: parseString(row[COL.comments]),
|
||||
status: parseNumber(row[COL.status]),
|
||||
lang: parseString(row[COL.lang]),
|
||||
tenantId: parseNumber(row[COL.tenantId]),
|
||||
merchantId: parseNumber(row[COL.merchantId])
|
||||
};
|
||||
|
||||
try {
|
||||
const saveOrUpdate = payload.adId ? updateCmsAd : addCmsAd;
|
||||
await saveOrUpdate(payload);
|
||||
ok++;
|
||||
} catch (e: any) {
|
||||
fail++;
|
||||
errors.push(
|
||||
`第${i + 1}行${payload.code ? `(${payload.code})` : ''}: ${
|
||||
e?.message || '失败'
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
hide();
|
||||
loading.value = false;
|
||||
if (fail > 0) {
|
||||
message.warning(`恢复完成:成功${ok},失败${fail}`);
|
||||
// 避免弹窗过长,只展示前几条
|
||||
Modal.error({
|
||||
title: '部分恢复失败',
|
||||
content: createVNode(
|
||||
'pre',
|
||||
{
|
||||
style:
|
||||
'white-space: pre-wrap; max-height: 320px; overflow: auto; margin: 0;'
|
||||
},
|
||||
errors.slice(0, 8).join('\n')
|
||||
)
|
||||
});
|
||||
} else {
|
||||
message.success(`恢复完成:成功${ok}`);
|
||||
}
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
},
|
||||
onCancel: () => {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
} catch (e: any) {
|
||||
loading.value = false;
|
||||
message.error(e?.message || '解析失败,请重试');
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/* 更新 visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
</script>
|
||||
410
src/views/cms/cmsAd/components/cmsAdEdit.vue
Normal file
410
src/views/cms/cmsAd/components/cmsAdEdit.vue
Normal file
@@ -0,0 +1,410 @@
|
||||
<!-- 编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
:width="1000"
|
||||
: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: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="
|
||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||
"
|
||||
>
|
||||
<a-form-item label="类型" name="type">
|
||||
<a-radio-group
|
||||
v-model:value="form.type"
|
||||
:disabled="isUpdate || !disabled"
|
||||
@change="onTypeChange"
|
||||
>
|
||||
<a-radio :value="1">轮播</a-radio>
|
||||
<a-radio :value="2">图片</a-radio>
|
||||
<a-radio :value="3">视频</a-radio>
|
||||
<a-radio :value="4">文本</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" name="name">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
style="width: 500px"
|
||||
placeholder="请输入广告名称"
|
||||
v-model:value="form.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="编号" name="code">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
style="width: 500px"
|
||||
placeholder="请输入广告唯一标识"
|
||||
v-model:value="form.code"
|
||||
/>
|
||||
</a-form-item>
|
||||
<template v-if="form.type == 1">
|
||||
<a-form-item label="多图" name="images">
|
||||
<div :class="`item-style ${form.style}`">
|
||||
<SelectFile
|
||||
:placeholder="`请选择图片`"
|
||||
:limit="9"
|
||||
:data="images"
|
||||
@done="chooseFile"
|
||||
@del="onDeleteItem"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 mt-2">
|
||||
<div
|
||||
class="w-[500px] space-y-2"
|
||||
v-for="(_, index) in images"
|
||||
:key="index"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="images[index].title"
|
||||
:placeholder="`请输入图片标题${index + 1}`"
|
||||
/>
|
||||
<a-input
|
||||
v-model:value="images[index].path"
|
||||
placeholder="https://"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="form.type == 2">
|
||||
<a-form-item label="单图" name="images">
|
||||
<div :class="`item-style ${form.style}`">
|
||||
<SelectFile
|
||||
:limit="1"
|
||||
:data="images"
|
||||
@done="chooseFile"
|
||||
@del="onDeleteItem"
|
||||
/>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="图片标题" name="title" v-if="images.length > 0">
|
||||
<a-input
|
||||
v-model:value="images[0].title"
|
||||
placeholder="请输入图片标题"
|
||||
style="width: 500px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图片链接" name="path" v-if="images.length > 0">
|
||||
<a-input
|
||||
v-model:value="images[0].path"
|
||||
placeholder="https://"
|
||||
style="width: 500px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="form.type == 3">
|
||||
<a-form-item
|
||||
label="视频"
|
||||
name="images"
|
||||
extra="请上传视频文件,仅支持mp4格式,大小200M以内"
|
||||
>
|
||||
<div :class="`item-style ${form.style}`">
|
||||
<SelectFile
|
||||
:placeholder="`请选择视频文件`"
|
||||
:limit="1"
|
||||
:data="images"
|
||||
@done="chooseFile"
|
||||
@del="onDeleteItem"
|
||||
/>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="视频标题" name="title" v-if="images.length > 0">
|
||||
<a-input
|
||||
v-model:value="images[0].title"
|
||||
placeholder="请输入视频标题"
|
||||
style="width: 500px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="视频链接" name="path" v-if="images.length > 0">
|
||||
<a-input
|
||||
v-model:value="images[0].path"
|
||||
placeholder="https://"
|
||||
style="width: 500px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<template v-if="form.type == 4">
|
||||
<a-form-item label="文本" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入广告内容"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<a-form-item label="链接" name="path" v-if="form.type == 4">
|
||||
<a-input v-model:value="form.path" placeholder="https://" />
|
||||
</a-form-item>
|
||||
<a-form-item label="尺寸">
|
||||
<a-space>
|
||||
<a-input-number
|
||||
allow-clear
|
||||
:maxlength="3000"
|
||||
placeholder="宽"
|
||||
v-model:value="form.width"
|
||||
/>
|
||||
<span>X</span>
|
||||
<a-input-number
|
||||
allow-clear
|
||||
:maxlength="2000"
|
||||
placeholder="高"
|
||||
v-model:value="form.height"
|
||||
/>
|
||||
</a-space>
|
||||
<div class="pt-2">
|
||||
<span class="text-gray-400"
|
||||
>广告位尺寸大小(默认值:100% * 500px)</span
|
||||
>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="位置">
|
||||
<a-tree-select
|
||||
allow-clear
|
||||
:tree-data="navigationList"
|
||||
tree-default-expand-all
|
||||
style="width: 500px"
|
||||
placeholder="请选择所属栏目"
|
||||
:value="form.categoryId || undefined"
|
||||
:listHeight="700"
|
||||
:dropdown-style="{ overflow: 'auto' }"
|
||||
@update:value="(value?: number) => (form.categoryId = value)"
|
||||
@change="onCategoryId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="style" name="style">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="font-bold text-red-500"
|
||||
v-model:value="form.style"
|
||||
/>
|
||||
<div class="pt-2 none">
|
||||
<a
|
||||
class="text-sm text-gray-400"
|
||||
href="https://tailwindcss.com/docs/padding"
|
||||
target="_blank"
|
||||
>Tailwind 使用说明</a
|
||||
>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="描述" name="comments" v-if="form.type != 4">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入广告描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" name="status">
|
||||
<a-radio-group v-model:value="form.status">
|
||||
<a-radio :value="0">开启</a-radio>
|
||||
<a-radio :value="1">关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import { addCmsAd, updateCmsAd } from '@/api/cms/cmsAd';
|
||||
import { CmsAd } from '@/api/cms/cmsAd/model';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
|
||||
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const disabled = ref(true);
|
||||
const useForm = Form.useForm;
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: CmsAd | null;
|
||||
// 栏目导航
|
||||
navigationList?: CmsNavigation[];
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
// 已上传数据
|
||||
const images = ref<any[]>([]);
|
||||
const { locale } = useI18n();
|
||||
// 是否显示最大化切换按钮
|
||||
const maxable = ref(true);
|
||||
// 表格选中数据
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<CmsAd>({
|
||||
adId: undefined,
|
||||
type: undefined,
|
||||
code: undefined,
|
||||
categoryId: undefined,
|
||||
name: '',
|
||||
style: '',
|
||||
images: '',
|
||||
imageList: undefined,
|
||||
width: '',
|
||||
height: '',
|
||||
path: '',
|
||||
status: 0,
|
||||
comments: '',
|
||||
lang: locale.value || undefined,
|
||||
sortNumber: 100,
|
||||
merchantId: undefined
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入标题',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择类型',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
images: [
|
||||
{
|
||||
required: true,
|
||||
message: '请上传图片或视频',
|
||||
trigger: 'blur',
|
||||
validator: (_rule: any, _: string) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (images.value.length == 0) {
|
||||
return reject('请上传图片或视频文件');
|
||||
}
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const { resetFields } = useForm(form, rules);
|
||||
|
||||
const chooseFile = (data: FileRecord) => {
|
||||
images.value.push({
|
||||
uid: data.id,
|
||||
url:
|
||||
data.downloadUrl +
|
||||
'?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90',
|
||||
status: 'done',
|
||||
title: '', // 初始化标题为空
|
||||
path: '' // 初始化链接为空
|
||||
});
|
||||
form.images =
|
||||
data.downloadUrl +
|
||||
'?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90';
|
||||
};
|
||||
|
||||
const onDeleteItem = (index: number) => {
|
||||
images.value.splice(index, 1);
|
||||
form.images = '';
|
||||
};
|
||||
|
||||
// 选择栏目
|
||||
const onCategoryId = (id: number) => {
|
||||
form.categoryId = id;
|
||||
};
|
||||
|
||||
const onTypeChange = () => {
|
||||
disabled.value = !disabled.value;
|
||||
};
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
if (!formRef.value) {
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const formData = {
|
||||
...form,
|
||||
images: JSON.stringify(images.value)
|
||||
};
|
||||
const saveOrUpdate = isUpdate.value ? updateCmsAd : addCmsAd;
|
||||
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);
|
||||
images.value = props.data.imageList;
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
images.value = [];
|
||||
disabled.value = true;
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
98
src/views/cms/cmsAd/components/search.vue
Normal file
98
src/views/cms/cmsAd/components/search.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>添加</span>
|
||||
</a-button>
|
||||
<a-button type="dashed" :disabled="exportLoading" @click="backup"
|
||||
>备份</a-button
|
||||
>
|
||||
<a-button type="dashed" @click="restore">恢复</a-button>
|
||||
<a-tree-select
|
||||
allow-clear
|
||||
:tree-data="navigationList"
|
||||
tree-default-expand-all
|
||||
style="width: 240px"
|
||||
:listHeight="700"
|
||||
placeholder="请选择栏目"
|
||||
:value="where.categoryId || undefined"
|
||||
:dropdown-style="{ overflow: 'auto' }"
|
||||
@update:value="(value?: number) => (where.categoryId = value)"
|
||||
@change="onCategoryId"
|
||||
/>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入关键词"
|
||||
style="width: 280px"
|
||||
v-model:value="where.keywords"
|
||||
@search="reload"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { watch } from 'vue';
|
||||
import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
|
||||
import { CmsAdParam } from '@/api/cms/cmsAd/model';
|
||||
import useSearch from '@/utils/use-search';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 选中的角色
|
||||
selection?: [];
|
||||
navigationList?: CmsNavigation[];
|
||||
exportLoading?: boolean;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: CmsAdParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
(e: 'batchMove'): void;
|
||||
(e: 'backup'): void;
|
||||
(e: 'restore'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<CmsAdParam>({
|
||||
adId: undefined,
|
||||
pageId: undefined,
|
||||
keywords: ''
|
||||
});
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 备份
|
||||
const backup = () => {
|
||||
emit('backup');
|
||||
};
|
||||
|
||||
// 恢复
|
||||
const restore = () => {
|
||||
emit('restore');
|
||||
};
|
||||
|
||||
// 按分类查询
|
||||
const onCategoryId = (id: number) => {
|
||||
where.categoryId = id;
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
433
src/views/cms/cmsAd/index.vue
Normal file
433
src/views/cms/cmsAd/index.vue
Normal file
@@ -0,0 +1,433 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="adId"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
tool-class="ele-toolbar-form"
|
||||
class="sys-org-table"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
@search="reload"
|
||||
:selection="selection"
|
||||
:navigationList="navigationList"
|
||||
:exportLoading="exportLoading"
|
||||
@backup="handleExport"
|
||||
@restore="openImport"
|
||||
@add="openEdit"
|
||||
@remove="removeBatch"
|
||||
@batchMove="openMove"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'type'">
|
||||
<a-tag v-if="record.type == 1" color="pink">轮播</a-tag>
|
||||
<a-tag v-if="record.type == 2" color="blue">图片</a-tag>
|
||||
<a-tag v-if="record.type == 3" color="cyan">视频</a-tag>
|
||||
<a-tag v-if="record.type == 4">文本</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'name'">
|
||||
<div>{{ record.name }}</div>
|
||||
<div class="text-gray-400">{{ record.code }}</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'categoryId'">
|
||||
<span class="text-gray-400">{{ record.categoryName }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'comments'">
|
||||
<span class="text-gray-400">{{ record.comments }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'images'">
|
||||
<div :class="`item ${record.style}`">
|
||||
<template
|
||||
v-if="record.type != 4"
|
||||
v-for="(item, index) in record.imageList"
|
||||
:key="index"
|
||||
>
|
||||
<a-image :src="item.url" :width="80" />
|
||||
</template>
|
||||
<template v-if="record.type == 4">
|
||||
{{ record.comments }}
|
||||
</template>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<CmsAdEdit
|
||||
v-model:visible="showEdit"
|
||||
:data="current"
|
||||
:navigationList="navigationList"
|
||||
@done="reload"
|
||||
/>
|
||||
|
||||
<!-- 导入备份弹窗 -->
|
||||
<Import v-model:visible="showImport" @done="reload" />
|
||||
</a-page-header>
|
||||
</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 { utils, writeFile } from 'xlsx';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import { toTreeData } from 'ele-admin-pro';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import Search from './components/search.vue';
|
||||
import CmsAdEdit from './components/cmsAdEdit.vue';
|
||||
import Import from './components/Import.vue';
|
||||
import {
|
||||
listCmsAd,
|
||||
pageCmsAd,
|
||||
removeBatchCmsAd,
|
||||
removeCmsAd
|
||||
} from '@/api/cms/cmsAd';
|
||||
import type { CmsAd, CmsAdParam } from '@/api/cms/cmsAd/model';
|
||||
import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
|
||||
import { listCmsNavigation } from '@/api/cms/cmsNavigation';
|
||||
import { getPageTitle } from '@/utils/common';
|
||||
import { getTenantId } from '@/utils/domain';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
// 国际化
|
||||
const { locale } = useI18n();
|
||||
// 表格选中数据
|
||||
const selection = ref<CmsAd[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<CmsAd | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
// 是否显示批量移动弹窗
|
||||
const showMove = ref(false);
|
||||
// 是否显示导入备份弹窗
|
||||
const showImport = ref(false);
|
||||
// 栏目数据
|
||||
const navigationList = ref<CmsNavigation[]>();
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
// 导出状态
|
||||
const exportLoading = ref(false);
|
||||
// 记录最新搜索条件,供备份导出使用
|
||||
const lastWhere = ref<CmsAdParam>({});
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.status = filters.status;
|
||||
}
|
||||
// where.lang = locale.value || undefined;
|
||||
return pageCmsAd({
|
||||
...where,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
};
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
title: 'ID',
|
||||
width: 90,
|
||||
dataIndex: 'adId'
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '广告图片',
|
||||
dataIndex: 'images',
|
||||
key: 'images'
|
||||
},
|
||||
{
|
||||
title: '栏目名称',
|
||||
dataIndex: 'categoryId',
|
||||
key: 'categoryId',
|
||||
align: 'center',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: CmsAdParam) => {
|
||||
if (where) {
|
||||
lastWhere.value = { ...where };
|
||||
}
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: CmsAd) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开批量移动弹窗 */
|
||||
const openMove = () => {
|
||||
showMove.value = true;
|
||||
};
|
||||
|
||||
/* 打开导入弹窗 */
|
||||
const openImport = () => {
|
||||
showImport.value = true;
|
||||
};
|
||||
|
||||
/* 备份导出 */
|
||||
const handleExport = async () => {
|
||||
if (exportLoading.value) {
|
||||
return;
|
||||
}
|
||||
exportLoading.value = true;
|
||||
message.loading('正在准备导出数据...', 0);
|
||||
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'广告ID',
|
||||
'类型',
|
||||
'唯一标识',
|
||||
'栏目ID',
|
||||
'栏目名称',
|
||||
'广告位名称',
|
||||
'宽',
|
||||
'高',
|
||||
'样式',
|
||||
'图片数据',
|
||||
'链接',
|
||||
'排序号',
|
||||
'备注',
|
||||
'状态',
|
||||
'语言',
|
||||
'租户ID',
|
||||
'商户ID'
|
||||
]
|
||||
];
|
||||
|
||||
try {
|
||||
const where: CmsAdParam = {
|
||||
...(lastWhere.value ?? {}),
|
||||
lang: locale.value || undefined
|
||||
};
|
||||
const list = await listCmsAd(where);
|
||||
if (!list || list.length === 0) {
|
||||
message.destroy();
|
||||
message.warning('没有数据可以导出');
|
||||
exportLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
list.forEach((d: CmsAd) => {
|
||||
const images = Array.isArray(d.imageList)
|
||||
? JSON.stringify(d.imageList)
|
||||
: typeof d.images === 'string'
|
||||
? d.images
|
||||
: JSON.stringify(d.images ?? []);
|
||||
array.push([
|
||||
`${d.adId || ''}`,
|
||||
`${d.type ?? ''}`,
|
||||
`${d.code || ''}`,
|
||||
`${d.categoryId ?? ''}`,
|
||||
`${d.categoryName || ''}`,
|
||||
`${d.name || ''}`,
|
||||
`${d.width || ''}`,
|
||||
`${d.height || ''}`,
|
||||
`${d.style || ''}`,
|
||||
`${images || ''}`,
|
||||
`${d.path || ''}`,
|
||||
`${d.sortNumber ?? ''}`,
|
||||
`${d.comments || ''}`,
|
||||
`${d.status ?? ''}`,
|
||||
`${d.lang || ''}`,
|
||||
`${d.tenantId ?? ''}`,
|
||||
`${d.merchantId ?? ''}`
|
||||
]);
|
||||
});
|
||||
|
||||
const sheetName = `bak_cms_ad_${getTenantId()}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
} as any;
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
sheet['!cols'] = [
|
||||
{ wch: 10 }, // 广告ID
|
||||
{ wch: 8 }, // 类型
|
||||
{ wch: 24 }, // 唯一标识
|
||||
{ wch: 10 }, // 栏目ID
|
||||
{ wch: 18 }, // 栏目名称
|
||||
{ wch: 24 }, // 广告位名称
|
||||
{ wch: 10 }, // 宽
|
||||
{ wch: 10 }, // 高
|
||||
{ wch: 20 }, // 样式
|
||||
{ wch: 60 }, // 图片数据(JSON)
|
||||
{ wch: 30 }, // 链接
|
||||
{ wch: 10 }, // 排序号
|
||||
{ wch: 24 }, // 备注
|
||||
{ wch: 8 }, // 状态
|
||||
{ wch: 10 }, // 语言
|
||||
{ wch: 10 }, // 租户ID
|
||||
{ wch: 10 } // 商户ID
|
||||
];
|
||||
|
||||
message.destroy();
|
||||
message.loading('正在生成Excel文件...', 0);
|
||||
setTimeout(() => {
|
||||
writeFile(workbook, `${sheetName}.xlsx`);
|
||||
exportLoading.value = false;
|
||||
message.destroy();
|
||||
message.success(`成功导出 ${list.length} 条记录`);
|
||||
}, 600);
|
||||
} catch (e: any) {
|
||||
exportLoading.value = false;
|
||||
message.destroy();
|
||||
message.error(e?.message || '导出失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: CmsAd) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeCmsAd(row.adId)
|
||||
.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);
|
||||
removeBatchCmsAd(selection.value.map((d) => d.adId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
// 加载栏目数据
|
||||
if (!navigationList.value) {
|
||||
listCmsNavigation({}).then((res) => {
|
||||
navigationList.value = toTreeData({
|
||||
data: res?.map((d) => {
|
||||
d.value = d.navigationId;
|
||||
d.label = d.title;
|
||||
if (!d.component) {
|
||||
d.disabled = true;
|
||||
}
|
||||
return d;
|
||||
}),
|
||||
idField: 'navigationId',
|
||||
parentIdField: 'parentId'
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: CmsAd) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openEdit(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'CmsAd'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
217
src/views/cms/cmsAdRecord/components/cmsAdRecordEdit.vue
Normal file
217
src/views/cms/cmsAdRecord/components/cmsAdRecordEdit.vue
Normal file
@@ -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="title">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入广告标题"
|
||||
v-model:value="form.title"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图片地址" name="path">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入图片地址"
|
||||
v-model:value="form.path"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="链接地址" name="url">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入链接地址"
|
||||
v-model:value="form.url"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="广告位ID" name="adId">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入广告位ID"
|
||||
v-model:value="form.adId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
|
||||
<a-input-number
|
||||
:min="0"
|
||||
:max="9999"
|
||||
class="ele-fluid"
|
||||
placeholder="请输入排序号"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" name="comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入描述"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态, 0正常, 1冻结" name="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 { addCmsAdRecord, updateCmsAdRecord } from '@/api/cms/cmsAdRecord';
|
||||
import { CmsAdRecord } from '@/api/cms/cmsAdRecord/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?: CmsAdRecord | 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<CmsAdRecord>({
|
||||
adRecordId: undefined,
|
||||
title: undefined,
|
||||
path: undefined,
|
||||
url: undefined,
|
||||
adId: undefined,
|
||||
tenantId: undefined,
|
||||
createTime: undefined,
|
||||
status: 0,
|
||||
comments: '',
|
||||
sortNumber: 100
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
cmsAdRecordName: [
|
||||
{
|
||||
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
|
||||
? updateCmsAdRecord
|
||||
: addCmsAdRecord;
|
||||
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
Reference in New Issue
Block a user