Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	.env.development
This commit is contained in:
2025-11-20 22:29:42 +08:00
440 changed files with 49162 additions and 19543 deletions

View File

@@ -24,6 +24,7 @@
allow-clear
placeholder="请输入年级"
v-model:value="form.name"
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="排序" name="sortNumber">

View File

@@ -200,12 +200,12 @@ const columns = ref<ColumnItem[]>([
key: 'isInvoice',
align: 'center',
},
{
title: '订单状态',
dataIndex: 'orderStatus',
key: 'orderStatus',
align: 'center',
},
// {
// title: '订单状态',
// dataIndex: 'orderStatus',
// key: 'orderStatus',
// align: 'center',
// },
// {
// title: '支付时间',
// dataIndex: 'payTime',

View File

@@ -119,14 +119,8 @@
formId: undefined,
number: undefined,
totalPrice: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
bszxPayRankingId: undefined,
bszxPayRankingName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -119,14 +119,9 @@
formId: undefined,
number: undefined,
totalPrice: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
bszxPayRankingId: undefined,
bszxPayRankingName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -119,14 +119,7 @@
formId: undefined,
number: undefined,
totalPrice: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
bszxPayRankingId: undefined,
bszxPayRankingName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -11,20 +11,20 @@
:height="80"
:preview="false"
style="border-radius: 8px"
:src="siteStore.websiteLogo"
:src="siteStore.logo"
fallback="/logo.png"
/>
</a-col>
<a-col :span="14">
<div class="system-info">
<h2 class="ele-text-heading">{{ siteStore.websiteName }}</h2>
<p class="ele-text-secondary">{{ siteStore.websiteComments }}</p>
<h2 class="ele-text-heading">{{ siteStore.appName }}</h2>
<p class="ele-text-secondary">{{ siteStore.description }}</p>
<a-space>
<a-tag color="blue">版本 {{ systemInfo.version }}</a-tag>
<a-tag color="green">{{ systemInfo.status }}</a-tag>
<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.websiteDarkLogo" alt="小程序码" width="300" height="300"></p>
<p><img :src="siteStore.mpQrCode" alt="小程序码" width="300" height="300"></p>
</template>
<a-tag>
<QrcodeOutlined/>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑规格' : '添加规格'"
:title="isUpdate ? '编辑挂号' : '添加挂号'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,34 +19,43 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="规格名称" name="specName">
<a-input
allow-clear
placeholder="请输入规格名称"
v-model:value="form.specName"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
/>
</a-form-item>
<a-form-item label="创建用户" name="userId">
<a-input
allow-clear
placeholder="请输入创建用户"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="更新者" name="updater">
<a-input
allow-clear
placeholder="请输入更新者"
v-model:value="form.updater"
<!-- <a-form-item 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"
@@ -55,12 +64,6 @@
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1待修,2异常已修3异常未修" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
@@ -70,6 +73,20 @@
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>
@@ -78,8 +95,8 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsProductSpec, updateCmsProductSpec } from '@/api/cms/cmsProductSpec';
import { CmsProductSpec } from '@/api/cms/cmsProductSpec/model';
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';
@@ -97,7 +114,7 @@
//
visible: boolean;
//
data?: CmsProductSpec | null;
data?: ClinicAppointment | null;
}>();
const emit = defineEmits<{
@@ -114,21 +131,18 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsProductSpec>({
specId: undefined,
specName: undefined,
specValue: undefined,
const form = reactive<ClinicAppointment>({
id: undefined,
type: undefined,
reason: undefined,
evaluateTime: undefined,
doctorId: undefined,
userId: undefined,
updater: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
isDelete: undefined,
tenantId: undefined,
createTime: undefined,
cmsProductSpecId: undefined,
cmsProductSpecName: '',
status: 0,
comments: '',
updateTime: undefined,
sortNumber: 100
});
@@ -139,11 +153,11 @@
//
const rules = reactive({
cmsProductSpecName: [
clinicAppointmentName: [
{
required: true,
type: 'string',
message: '请填写规格名称',
message: '请填写挂号名称',
trigger: 'blur'
}
]
@@ -177,7 +191,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsProductSpec : addCmsProductSpec;
const saveOrUpdate = isUpdate.value ? updateClinicAppointment : addClinicAppointment;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsComponentsId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -21,6 +20,14 @@
/>
</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>
@@ -45,9 +52,8 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsComponentsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicAppointmentEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
@@ -61,17 +67,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsComponentsEdit from './components/cmsComponentsEdit.vue';
import { pageCmsComponents, removeCmsComponents, removeBatchCmsComponents } from '@/api/cms/cmsComponents';
import type { CmsComponents, CmsComponentsParam } from '@/api/cms/cmsComponents/model';
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<CmsComponents[]>([]);
const selection = ref<ClinicAppointment[]>([]);
//
const current = ref<CmsComponents | null>(null);
const current = ref<ClinicAppointment | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +97,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsComponents({
return pageClinicAppointment({
...where,
...orders,
page,
@@ -98,89 +105,63 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: 'ID',
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '组件标题',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '关联导航ID',
dataIndex: 'navigationId',
key: 'navigationId',
align: 'center',
},
{
title: '组件类型',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '页面关键词',
dataIndex: 'keywords',
key: 'keywords',
align: 'center',
},
{
title: '页面描述',
dataIndex: 'description',
key: 'description',
align: 'center',
},
{
title: '组件路径',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '组件图标',
dataIndex: 'icon',
key: 'icon',
align: 'center',
},
{
title: '用户ID',
title: '患者',
dataIndex: 'userId',
key: 'userId',
align: 'center',
key: 'userId'
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
title: '挂号医生',
dataIndex: 'doctorId',
key: 'doctorId'
},
// {
// title: '',
// dataIndex: 'type',
// key: 'type',
// width: 120
// },
{
title: '就诊原因',
dataIndex: 'reason',
key: 'reason',
ellipsis: true
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
ellipsis: true
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
width: 120
},
// {
// title: '',
// dataIndex: 'evaluateTime',
// key: 'evaluateTime',
// width: 120
// },
{
title: '创建时间',
title: '挂号时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
@@ -193,13 +174,13 @@
]);
/* 搜索 */
const reload = (where?: CmsComponentsParam) => {
const reload = (where?: ClinicAppointmentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsComponents) => {
const openEdit = (row?: ClinicAppointment) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -210,9 +191,9 @@
};
/* 删除单个 */
const remove = (row: CmsComponents) => {
const remove = (row: ClinicAppointment) => {
const hide = message.loading('请求中..', 0);
removeCmsComponents(row.cmsComponentsId)
removeClinicAppointment(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -237,7 +218,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsComponents(selection.value.map((d) => d.cmsComponentsId))
removeBatchClinicAppointment(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -257,7 +238,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsComponents) => {
const customRow = (record: ClinicAppointment) => {
return {
//
onClick: () => {
@@ -274,7 +255,7 @@
<script lang="ts">
export default {
name: 'CmsComponents'
name: 'ClinicAppointment'
};
</script>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑小程序端菜单' : '添加小程序端菜单'"
:title="isUpdate ? '编辑医生入驻申请' : '添加医生入驻申请'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,160 +19,13 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="上级id, 0是顶级" name="parentId">
<a-form-item label="类型 0医生" name="type">
<a-input
allow-clear
placeholder="请输入上级id, 0是顶级"
v-model:value="form.parentId"
/>
</a-form-item>
<a-form-item label="菜单名称" name="title">
<a-input
allow-clear
placeholder="请输入菜单名称"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="类型 0功能图标 1订单状态图标 2首页导航图标 3 商城导航图标 4管理人员功能图标" name="type">
<a-input
allow-clear
placeholder="请输入类型 0功能图标 1订单状态图标 2首页导航图标 3 商城导航图标 4管理人员功能图标"
placeholder="请输入类型 0医生"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="是否微信小程序菜单" name="isMpWeixin">
<a-input
allow-clear
placeholder="请输入是否微信小程序菜单"
v-model:value="form.isMpWeixin"
/>
</a-form-item>
<a-form-item label="菜单路由地址" name="path">
<a-input
allow-clear
placeholder="请输入菜单路由地址"
v-model:value="form.path"
/>
</a-form-item>
<a-form-item label="菜单组件地址, 目录可为空" name="component">
<a-input
allow-clear
placeholder="请输入菜单组件地址, 目录可为空"
v-model:value="form.component"
/>
</a-form-item>
<a-form-item label="打开位置" name="target">
<a-input
allow-clear
placeholder="请输入打开位置"
v-model:value="form.target"
/>
</a-form-item>
<a-form-item label="菜单图标" name="avatar">
<a-input
allow-clear
placeholder="请输入菜单图标"
v-model:value="form.avatar"
/>
</a-form-item>
<a-form-item label="图标颜色" name="color">
<a-input
allow-clear
placeholder="请输入图标颜色"
v-model:value="form.color"
/>
</a-form-item>
<a-form-item label="上传图标" name="icon">
<a-input
allow-clear
placeholder="请输入上传图标"
v-model:value="form.icon"
/>
</a-form-item>
<a-form-item label="是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)" name="hide">
<a-input
allow-clear
placeholder="请输入是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)"
v-model:value="form.hide"
/>
</a-form-item>
<a-form-item label="位置 0不限 1顶部 2底部" name="position">
<a-input
allow-clear
placeholder="请输入位置 0不限 1顶部 2底部"
v-model:value="form.position"
/>
</a-form-item>
<a-form-item label="0 第一行 1第二行" name="rows">
<a-input
allow-clear
placeholder="请输入0 第一行 1第二行"
v-model:value="form.rows"
/>
</a-form-item>
<a-form-item label="菜单侧栏选中的path" name="active">
<a-input
allow-clear
placeholder="请输入菜单侧栏选中的path"
v-model:value="form.active"
/>
</a-form-item>
<a-form-item label="其它路由元信息" name="meta">
<a-input
allow-clear
placeholder="请输入其它路由元信息"
v-model:value="form.meta"
/>
</a-form-item>
<a-form-item label="绑定的页面" name="pageId">
<a-input
allow-clear
placeholder="请输入绑定的页面"
v-model:value="form.pageId"
/>
</a-form-item>
<a-form-item label="绑定的文章分类ID" name="articleCategoryId">
<a-input
allow-clear
placeholder="请输入绑定的文章分类ID"
v-model:value="form.articleCategoryId"
/>
</a-form-item>
<a-form-item label="绑定的文章ID" name="articleId">
<a-input
allow-clear
placeholder="请输入绑定的文章ID"
v-model:value="form.articleId"
/>
</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="绑定的书籍标识" name="bookCode">
<a-input
allow-clear
placeholder="请输入绑定的书籍标识"
v-model:value="form.bookCode"
/>
</a-form-item>
<a-form-item label="绑定的商品分类ID" name="goodsCategoryId">
<a-input
allow-clear
placeholder="请输入绑定的商品分类ID"
v-model:value="form.goodsCategoryId"
/>
</a-form-item>
<a-form-item label="绑定的商品ID" name="goodsId">
<a-input
allow-clear
placeholder="请输入绑定的商品ID"
v-model:value="form.goodsId"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
@@ -180,34 +33,165 @@
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否管理人员可见" name="adminShow">
<a-form-item label="姓名" name="realName">
<a-input
allow-clear
placeholder="请输入是否管理人员可见"
v-model:value="form.adminShow"
placeholder="请输入姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="设为首页" name="home">
<a-form-item label="性别 1男 2女" name="gender">
<a-input
allow-clear
placeholder="请输入设为首页"
v-model:value="form.home"
placeholder="请输入性别 1男 2女"
v-model:value="form.gender"
/>
</a-form-item>
<a-form-item label="分组名称" name="groupName">
<a-form-item label="手机号" name="mobile">
<a-input
allow-clear
placeholder="请输入分组名称"
v-model:value="form.groupName"
placeholder="请输入手机号"
v-model:value="form.mobile"
/>
</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 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">
@@ -218,11 +202,12 @@
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 label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
</ele-modal>
@@ -232,8 +217,8 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsMpMenu, updateCmsMpMenu } from '@/api/cms/cmsMpMenu';
import { CmsMpMenu } from '@/api/cms/cmsMpMenu/model';
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';
@@ -251,7 +236,7 @@
//
visible: boolean;
//
data?: CmsMpMenu | null;
data?: ClinicDoctorApply | null;
}>();
const emit = defineEmits<{
@@ -268,38 +253,37 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsMpMenu>({
menuId: undefined,
parentId: undefined,
title: undefined,
const form = reactive<ClinicDoctorApply>({
applyId: undefined,
type: undefined,
isMpWeixin: undefined,
path: undefined,
component: undefined,
target: undefined,
avatar: undefined,
color: undefined,
icon: undefined,
hide: undefined,
position: undefined,
rows: undefined,
active: undefined,
meta: undefined,
pageId: undefined,
articleCategoryId: undefined,
articleId: undefined,
formId: undefined,
bookCode: undefined,
goodsCategoryId: undefined,
goodsId: undefined,
userId: undefined,
adminShow: undefined,
home: undefined,
groupName: undefined,
comments: undefined,
status: 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
});
@@ -310,11 +294,11 @@
//
const rules = reactive({
cmsMpMenuName: [
clinicDoctorApplyName: [
{
required: true,
type: 'string',
message: '请填写小程序端菜单名称',
message: '请填写医生入驻申请名称',
trigger: 'blur'
}
]
@@ -348,7 +332,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsMpMenu : addCmsMpMenu;
const saveOrUpdate = isUpdate.value ? updateClinicDoctorApply : addClinicDoctorApply;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsMpMenuId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,13 +44,12 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsMpMenuEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicDoctorApplyEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
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';
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsMpMenuEdit from './components/cmsMpMenuEdit.vue';
import { pageCmsMpMenu, removeCmsMpMenu, removeBatchCmsMpMenu } from '@/api/cms/cmsMpMenu';
import type { CmsMpMenu, CmsMpMenuParam } from '@/api/cms/cmsMpMenu/model';
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<CmsMpMenu[]>([]);
const selection = ref<ClinicDoctorApply[]>([]);
//
const current = ref<CmsMpMenu | null>(null);
const current = ref<ClinicDoctorApply | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsMpMenu({
return pageClinicDoctorApply({
...where,
...orders,
page,
@@ -98,197 +97,189 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'menuId',
key: 'menuId',
align: 'center',
title: '主键ID',
dataIndex: 'applyId',
key: 'applyId',
width: 90,
},
{
title: '上级id, 0是顶级',
dataIndex: 'parentId',
key: 'parentId',
align: 'center',
},
{
title: '菜单名称',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '类型 0功能图标 1订单状态图标 2首页导航图标 3 商城导航图标 4管理人员功能图标',
title: '类型 0医生',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '是否微信小程序菜单',
dataIndex: 'isMpWeixin',
key: 'isMpWeixin',
align: 'center',
},
{
title: '菜单路由地址',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '菜单组件地址, 目录可为空',
dataIndex: 'component',
key: 'component',
align: 'center',
},
{
title: '打开位置',
dataIndex: 'target',
key: 'target',
align: 'center',
},
{
title: '菜单图标',
dataIndex: 'avatar',
key: 'avatar',
align: 'center',
},
{
title: '图标颜色',
dataIndex: 'color',
key: 'color',
align: 'center',
},
{
title: '上传图标',
dataIndex: 'icon',
key: 'icon',
align: 'center',
},
{
title: '是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)',
dataIndex: 'hide',
key: 'hide',
align: 'center',
},
{
title: '位置 0不限 1顶部 2底部',
dataIndex: 'position',
key: 'position',
align: 'center',
},
{
title: '0 第一行 1第二行',
dataIndex: 'rows',
key: 'rows',
align: 'center',
},
{
title: '菜单侧栏选中的path',
dataIndex: 'active',
key: 'active',
align: 'center',
},
{
title: '其它路由元信息',
dataIndex: 'meta',
key: 'meta',
align: 'center',
},
{
title: '绑定的页面',
dataIndex: 'pageId',
key: 'pageId',
align: 'center',
},
{
title: '绑定的文章分类ID',
dataIndex: 'articleCategoryId',
key: 'articleCategoryId',
align: 'center',
},
{
title: '绑定的文章ID',
dataIndex: 'articleId',
key: 'articleId',
align: 'center',
},
{
title: '绑定的表单ID',
dataIndex: 'formId',
key: 'formId',
align: 'center',
},
{
title: '绑定的书籍标识',
dataIndex: 'bookCode',
key: 'bookCode',
align: 'center',
},
{
title: '绑定的商品分类ID',
dataIndex: 'goodsCategoryId',
key: 'goodsCategoryId',
align: 'center',
},
{
title: '绑定的商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
width: 120
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
width: 120
},
{
title: '是否管理人员可见',
dataIndex: 'adminShow',
key: 'adminShow',
align: 'center',
title: '姓名',
dataIndex: 'realName',
key: 'realName',
ellipsis: true
},
{
title: '设为首页',
dataIndex: 'home',
key: 'home',
align: 'center',
title: '性别 1男 2女',
dataIndex: 'gender',
key: 'gender',
width: 120
},
{
title: '分组名称',
dataIndex: 'groupName',
key: 'groupName',
align: 'center',
title: '手机号',
dataIndex: 'mobile',
key: 'mobile',
ellipsis: true
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
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',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
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: '操作',
@@ -301,13 +292,13 @@
]);
/* 搜索 */
const reload = (where?: CmsMpMenuParam) => {
const reload = (where?: ClinicDoctorApplyParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsMpMenu) => {
const openEdit = (row?: ClinicDoctorApply) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -318,9 +309,9 @@
};
/* 删除单个 */
const remove = (row: CmsMpMenu) => {
const remove = (row: ClinicDoctorApply) => {
const hide = message.loading('请求中..', 0);
removeCmsMpMenu(row.cmsMpMenuId)
removeClinicDoctorApply(row.applyId)
.then((msg) => {
hide();
message.success(msg);
@@ -345,7 +336,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsMpMenu(selection.value.map((d) => d.cmsMpMenuId))
removeBatchClinicDoctorApply(selection.value.map((d) => d.applyId))
.then((msg) => {
hide();
message.success(msg);
@@ -365,7 +356,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsMpMenu) => {
const customRow = (record: ClinicDoctorApply) => {
return {
//
onClick: () => {
@@ -382,7 +373,7 @@
<script lang="ts">
export default {
name: 'CmsMpMenu'
name: 'ClinicDoctorApply'
};
</script>

View File

@@ -0,0 +1,318 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsSpecValueId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,13 +44,12 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsSpecValueEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicDoctorMedicalRecordEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
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';
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsSpecValueEdit from './components/cmsSpecValueEdit.vue';
import { pageCmsSpecValue, removeCmsSpecValue, removeBatchCmsSpecValue } from '@/api/cms/cmsSpecValue';
import type { CmsSpecValue, CmsSpecValueParam } from '@/api/cms/cmsSpecValue/model';
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<CmsSpecValue[]>([]);
const selection = ref<ClinicDoctorMedicalRecord[]>([]);
//
const current = ref<CmsSpecValue | null>(null);
const current = ref<ClinicDoctorMedicalRecord | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsSpecValue({
return pageClinicDoctorMedicalRecord({
...where,
...orders,
page,
@@ -98,47 +97,41 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: '规格值ID',
dataIndex: 'specValueId',
key: 'specValueId',
align: 'center',
title: '主键ID',
dataIndex: 'id',
key: 'id',
width: 90,
},
{
title: '规格组ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
title: '买家用户ID',
dataIndex: 'userId',
key: 'userId',
width: 120
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
title: '订单编号',
dataIndex: 'orderNo',
key: 'orderNo',
ellipsis: true
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
@@ -151,13 +144,13 @@
]);
/* 搜索 */
const reload = (where?: CmsSpecValueParam) => {
const reload = (where?: ClinicDoctorMedicalRecordParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsSpecValue) => {
const openEdit = (row?: ClinicDoctorMedicalRecord) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -168,9 +161,9 @@
};
/* 删除单个 */
const remove = (row: CmsSpecValue) => {
const remove = (row: ClinicDoctorMedicalRecord) => {
const hide = message.loading('请求中..', 0);
removeCmsSpecValue(row.cmsSpecValueId)
removeClinicDoctorMedicalRecord(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -195,7 +188,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsSpecValue(selection.value.map((d) => d.cmsSpecValueId))
removeBatchClinicDoctorMedicalRecord(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -215,7 +208,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsSpecValue) => {
const customRow = (record: ClinicDoctorMedicalRecord) => {
return {
//
onClick: () => {
@@ -232,7 +225,7 @@
<script lang="ts">
export default {
name: 'CmsSpecValue'
name: 'ClinicDoctorMedicalRecord'
};
</script>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑页面组件表' : '添加页面组件表'"
:title="isUpdate ? '编辑医生' : '添加医生'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,83 +19,88 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="关联导航ID" name="navigationId">
<!-- <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="请输入关联导航ID"
v-model:value="form.navigationId"
placeholder="请输入姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="组件" name="title">
<a-form-item label="部门" name="departmentId">
<a-input
allow-clear
placeholder="请输入组件"
v-model:value="form.title"
placeholder="请输入部门"
v-model:value="form.departmentId"
/>
</a-form-item>
<a-form-item label="组件标识" name="dictCode">
<a-form-item label="专业领域" name="specialty">
<a-input
allow-clear
placeholder="请输入组件标识"
v-model:value="form.dictCode"
placeholder="请输入专业领域"
v-model:value="form.specialty"
/>
</a-form-item>
<a-form-item label="组件样式" name="styles">
<a-form-item label="职务级别" name="position">
<a-input
allow-clear
placeholder="请输入组件样式"
v-model:value="form.styles"
placeholder="请输入职务级别"
v-model:value="form.position"
/>
</a-form-item>
<a-form-item label="卡片阴影显示时机" name="shadow">
<a-form-item label="执业资格" name="qualification">
<a-input
allow-clear
placeholder="请输入卡片阴影显示时机"
v-model:value="form.shadow"
placeholder="请输入执业资格"
v-model:value="form.qualification"
/>
</a-form-item>
<a-form-item label="页面关键词" name="keywords">
<a-form-item label="医生简介" name="introduction">
<a-input
allow-clear
placeholder="请输入页面关键词"
v-model:value="form.keywords"
placeholder="请输入医生简介"
v-model:value="form.introduction"
/>
</a-form-item>
<a-form-item label="页面描述" name="description">
<a-form-item label="挂号费" name="consultationFee">
<a-input
allow-clear
placeholder="请输入页面描述"
v-model:value="form.description"
placeholder="请输入挂号费"
v-model:value="form.consultationFee"
/>
</a-form-item>
<a-form-item label="页面路由地址" name="path">
<a-form-item label="工作年限" name="workYears">
<a-input
allow-clear
placeholder="请输入页面路由地址"
v-model:value="form.path"
placeholder="请输入工作年限"
v-model:value="form.workYears"
/>
</a-form-item>
<a-form-item label="缩列图" name="photo">
<a-form-item label="问诊人数" name="consultationCount">
<a-input
allow-clear
placeholder="请输入缩列图"
v-model:value="form.photo"
placeholder="请输入问诊人数"
v-model:value="form.consultationCount"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-form-item label="专属二维码" name="qrcode">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</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"
placeholder="请输入专属二维码"
v-model:value="form.qrcode"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
@@ -106,11 +111,14 @@
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 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>
@@ -120,8 +128,8 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsDesignRecord, updateCmsDesignRecord } from '@/api/cms/cmsDesignRecord';
import { CmsDesignRecord } from '@/api/cms/cmsDesignRecord/model';
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';
@@ -139,7 +147,7 @@
//
visible: boolean;
//
data?: CmsDesignRecord | null;
data?: ClinicDoctorUser | null;
}>();
const emit = defineEmits<{
@@ -156,27 +164,25 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsDesignRecord>({
const form = reactive<ClinicDoctorUser>({
id: undefined,
navigationId: undefined,
title: undefined,
dictCode: undefined,
styles: undefined,
shadow: undefined,
keywords: undefined,
description: undefined,
path: undefined,
photo: undefined,
type: undefined,
userId: undefined,
sortNumber: undefined,
realName: undefined,
departmentId: undefined,
specialty: undefined,
position: undefined,
qualification: undefined,
introduction: undefined,
consultationFee: undefined,
workYears: undefined,
consultationCount: undefined,
qrcode: undefined,
comments: undefined,
status: undefined,
isDelete: undefined,
tenantId: undefined,
createTime: undefined,
cmsDesignRecordId: undefined,
cmsDesignRecordName: '',
status: 0,
comments: '',
updateTime: undefined,
sortNumber: 100
});
@@ -187,11 +193,11 @@
//
const rules = reactive({
cmsDesignRecordName: [
clinicDoctorUserName: [
{
required: true,
type: 'string',
message: '请填写页面组件表名称',
message: '请填写医生名称',
trigger: 'blur'
}
]
@@ -225,7 +231,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsDesignRecord : addCmsDesignRecord;
const saveOrUpdate = isUpdate.value ? updateClinicDoctorUser : addClinicDoctorUser;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsDocsId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,13 +44,12 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsDocsEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicDoctorUserEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
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';
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsDocsEdit from './components/cmsDocsEdit.vue';
import { pageCmsDocs, removeCmsDocs, removeBatchCmsDocs } from '@/api/cms/cmsDocs';
import type { CmsDocs, CmsDocsParam } from '@/api/cms/cmsDocs/model';
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<CmsDocs[]>([]);
const selection = ref<ClinicDoctorUser[]>([]);
//
const current = ref<CmsDocs | null>(null);
const current = ref<ClinicDoctorUser | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsDocs({
return pageClinicDoctorUser({
...where,
...orders,
page,
@@ -98,95 +97,89 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: '文档ID',
dataIndex: 'docsId',
key: 'docsId',
align: 'center',
width: 90,
},
{
title: '文档标题',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '上级目录',
dataIndex: 'parentId',
key: 'parentId',
align: 'center',
},
{
title: '书籍ID',
dataIndex: 'bookId',
key: 'bookId',
align: 'center',
},
{
title: '可见性(public,private,protected)',
dataIndex: 'visibility',
key: 'visibility',
align: 'center',
},
{
title: '虚拟阅读量(仅用作展示)',
dataIndex: 'virtualViews',
key: 'virtualViews',
align: 'center',
},
{
title: '实际阅读量',
dataIndex: 'actualViews',
key: 'actualViews',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
width: 90,
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
title: '姓名',
dataIndex: 'realName',
key: 'realName',
ellipsis: true
},
// {
// title: '',
// dataIndex: 'departmentId',
// key: 'departmentId',
// width: 120
// },
{
title: '专业领域',
dataIndex: 'specialty',
key: 'specialty',
ellipsis: true
},
{
title: '排序(数字越小越靠前)',
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',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
width: 120
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '修改时间',
dataIndex: 'updateTime',
key: 'updateTime',
align: 'center',
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
@@ -199,13 +192,13 @@
]);
/* 搜索 */
const reload = (where?: CmsDocsParam) => {
const reload = (where?: ClinicDoctorUserParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsDocs) => {
const openEdit = (row?: ClinicDoctorUser) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -216,9 +209,9 @@
};
/* 删除单个 */
const remove = (row: CmsDocs) => {
const remove = (row: ClinicDoctorUser) => {
const hide = message.loading('请求中..', 0);
removeCmsDocs(row.cmsDocsId)
removeClinicDoctorUser(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -243,7 +236,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsDocs(selection.value.map((d) => d.cmsDocsId))
removeBatchClinicDoctorUser(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -263,7 +256,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsDocs) => {
const customRow = (record: ClinicDoctorUser) => {
return {
//
onClick: () => {
@@ -280,7 +273,7 @@
<script lang="ts">
export default {
name: 'CmsDocs'
name: 'ClinicDoctorUser'
};
</script>

View File

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

View File

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

View File

@@ -0,0 +1,278 @@
<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>

View File

@@ -0,0 +1,319 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -0,0 +1,338 @@
<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>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑链接' : '添加链接'"
:title="isUpdate ? '编辑药品库' : '添加药品库'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,41 +19,61 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="名" name="type">
<a-form-item label="名" name="name">
<a-input
allow-clear
placeholder="演示地址"
v-model:value="form.type"
placeholder="请输入药名"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="内容" name="domain">
<a-form-item label="拼音" name="pinyin">
<a-input
allow-clear
placeholder="https://nbg-admin.websoft.top"
v-model:value="form.domain"
placeholder="请输入拼音"
v-model:value="form.pinyin"
/>
</a-form-item>
<a-form-item label="账号" name="account">
<a-form-item label="分类" name="category">
<a-input
allow-clear
placeholder="请输入账号"
v-model:value="form.account"
placeholder="请输入分类"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="密码" name="password">
<a-input-password
<a-form-item label="规格" name="specification">
<a-input
allow-clear
placeholder="请输入密码"
v-model:value="form.password"
placeholder="请输入规格"
v-model:value="form.specification"
/>
</a-form-item>
<a-form-item label="二维码">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
<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">
@@ -72,13 +92,12 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject } from 'ele-admin-pro';
import { addCmsProductUrl, updateCmsProductUrl } from '@/api/cms/cmsProductUrl';
import { CmsProductUrl } from '@/api/cms/cmsProductUrl/model';
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';
import {FileRecord} from "@/api/system/file/model";
//
const isUpdate = ref(false);
@@ -91,9 +110,7 @@
//
visible: boolean;
//
data?: CmsProductUrl | null;
// ID
productId?: number;
data?: ClinicMedicine | null;
}>();
const emit = defineEmits<{
@@ -110,20 +127,21 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsProductUrl>({
const form = reactive<ClinicMedicine>({
id: undefined,
productId: undefined,
type: undefined,
domain: undefined,
account: undefined,
password: undefined,
qrcode: undefined,
merchantId: undefined,
name: undefined,
pinyin: undefined,
category: undefined,
specification: undefined,
unit: undefined,
content: undefined,
pricePerUnit: undefined,
isActive: undefined,
userId: undefined,
comments: undefined,
status: undefined,
createTime: undefined,
tenantId: undefined,
sortNumber: 100
createTime: undefined,
updateTime: undefined
});
/* 更新visible */
@@ -133,19 +151,11 @@
//
const rules = reactive({
type: [
clinicMedicineName: [
{
required: true,
type: 'string',
message: '请填写按钮名称',
trigger: 'blur'
}
],
domain: [
{
required: true,
type: 'string',
message: '请填写链接地址或上传图片',
message: '请填写药品库名称',
trigger: 'blur'
}
]
@@ -163,10 +173,9 @@
.then(() => {
loading.value = true;
const formData = {
...form,
productId: props?.productId
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsProductUrl : addCmsProductUrl;
const saveOrUpdate = isUpdate.value ? updateClinicMedicine : addClinicMedicine;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
@@ -182,19 +191,6 @@
.catch(() => {});
};
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.qrcode = data.downloadUrl;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
};
watch(
() => props.visible,
(visible) => {
@@ -202,13 +198,6 @@
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.qrcode){
images.value.push({
uid: Number(props.data.id),
url: props.data.qrcode,
status: 'done'
});
}
isUpdate.value = true;
} else {
isUpdate.value = false;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsDocsBookId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,13 +44,12 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsDocsBookEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicMedicineEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
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';
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsDocsBookEdit from './components/cmsDocsBookEdit.vue';
import { pageCmsDocsBook, removeCmsDocsBook, removeBatchCmsDocsBook } from '@/api/cms/cmsDocsBook';
import type { CmsDocsBook, CmsDocsBookParam } from '@/api/cms/cmsDocsBook/model';
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<CmsDocsBook[]>([]);
const selection = ref<ClinicMedicine[]>([]);
//
const current = ref<CmsDocsBook | null>(null);
const current = ref<ClinicMedicine | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsDocsBook({
return pageClinicMedicine({
...where,
...orders,
page,
@@ -98,71 +97,77 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'bookId',
key: 'bookId',
align: 'center',
title: '主键ID',
dataIndex: 'id',
key: 'id',
width: 90,
},
{
title: '书籍名称',
title: '药名',
dataIndex: 'name',
key: 'name',
align: 'center',
ellipsis: true
},
{
title: '书籍标识',
dataIndex: 'code',
key: 'code',
align: 'center',
title: '拼音',
dataIndex: 'pinyin',
key: 'pinyin',
ellipsis: true
},
{
title: '封面图',
dataIndex: 'photo',
key: 'photo',
align: 'center',
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',
align: 'center',
},
{
title: '文档内容',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
@@ -175,13 +180,13 @@
]);
/* 搜索 */
const reload = (where?: CmsDocsBookParam) => {
const reload = (where?: ClinicMedicineParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsDocsBook) => {
const openEdit = (row?: ClinicMedicine) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -192,9 +197,9 @@
};
/* 删除单个 */
const remove = (row: CmsDocsBook) => {
const remove = (row: ClinicMedicine) => {
const hide = message.loading('请求中..', 0);
removeCmsDocsBook(row.cmsDocsBookId)
removeClinicMedicine(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -219,7 +224,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsDocsBook(selection.value.map((d) => d.cmsDocsBookId))
removeBatchClinicMedicine(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -239,7 +244,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsDocsBook) => {
const customRow = (record: ClinicMedicine) => {
return {
//
onClick: () => {
@@ -256,7 +261,7 @@
<script lang="ts">
export default {
name: 'CmsDocsBook'
name: 'ClinicMedicine'
};
</script>

View File

@@ -0,0 +1,318 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -0,0 +1,338 @@
<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>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑规格' : '添加规格'"
:title="isUpdate ? '编辑药品库存' : '添加药品库存'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,34 +19,41 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="规格名称" name="specName">
<a-form-item label="药品" name="medicineId">
<a-input
allow-clear
placeholder="请输入规格名称"
v-model:value="form.specName"
placeholder="请输入药品"
v-model:value="form.medicineId"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-form-item label="库存数量" name="stockQuantity">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
placeholder="请输入库存数量"
v-model:value="form.stockQuantity"
/>
</a-form-item>
<a-form-item label="创建用户" name="userId">
<a-form-item label="最小库存预警" name="minStockLevel">
<a-input
allow-clear
placeholder="请输入创建用户"
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="updater">
<a-input
allow-clear
placeholder="请输入更新者"
v-model:value="form.updater"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
@@ -55,19 +62,11 @@
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1待修,2异常已修3异常未修" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
<a-form-item label="修改时间" name="updateTime">
<a-input
allow-clear
placeholder="请输入修改时间"
v-model:value="form.updateTime"
/>
</a-form-item>
</a-form>
@@ -78,8 +77,8 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsSpec, updateCmsSpec } from '@/api/cms/cmsSpec';
import { CmsSpec } from '@/api/cms/cmsSpec/model';
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';
@@ -97,7 +96,7 @@
//
visible: boolean;
//
data?: CmsSpec | null;
data?: ClinicMedicineStock | null;
}>();
const emit = defineEmits<{
@@ -114,22 +113,17 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsSpec>({
specId: undefined,
specName: undefined,
specValue: undefined,
const form = reactive<ClinicMedicineStock>({
id: undefined,
medicineId: undefined,
stockQuantity: undefined,
minStockLevel: undefined,
lastUpdated: undefined,
userId: undefined,
updater: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
cmsSpecId: undefined,
cmsSpecName: '',
status: 0,
comments: '',
sortNumber: 100
updateTime: undefined,
comments: ''
});
/* 更新visible */
@@ -139,11 +133,11 @@
//
const rules = reactive({
cmsSpecName: [
clinicMedicineStockName: [
{
required: true,
type: 'string',
message: '请填写规格名称',
message: '请填写药品库存名称',
trigger: 'blur'
}
]
@@ -177,7 +171,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsSpec : addCmsSpec;
const saveOrUpdate = isUpdate.value ? updateClinicMedicineStock : addClinicMedicineStock;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsProductSpecId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,13 +44,12 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsProductSpecEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicMedicineStockEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
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';
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsProductSpecEdit from './components/cmsProductSpecEdit.vue';
import { pageCmsProductSpec, removeCmsProductSpec, removeBatchCmsProductSpec } from '@/api/cms/cmsProductSpec';
import type { CmsProductSpec, CmsProductSpecParam } from '@/api/cms/cmsProductSpec/model';
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<CmsProductSpec[]>([]);
const selection = ref<ClinicMedicineStock[]>([]);
//
const current = ref<CmsProductSpec | null>(null);
const current = ref<ClinicMedicineStock | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsProductSpec({
return pageClinicMedicineStock({
...where,
...orders,
page,
@@ -98,65 +97,69 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: '规格ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
title: '主键ID',
dataIndex: 'id',
key: 'id',
width: 90,
},
{
title: '规格名称',
dataIndex: 'specName',
key: 'specName',
align: 'center',
title: '药品',
dataIndex: 'medicineId',
key: 'medicineId',
width: 120
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
title: '库存数量',
dataIndex: 'stockQuantity',
key: 'stockQuantity',
width: 120
},
{
title: '创建用户',
title: '最小库存预警',
dataIndex: 'minStockLevel',
key: 'minStockLevel',
width: 120
},
{
title: '上次更新时间',
dataIndex: 'lastUpdated',
key: 'lastUpdated',
width: 120
},
{
title: '买家用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '更新者',
dataIndex: 'updater',
key: 'updater',
align: 'center',
width: 120
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0正常, 1待修,2异常已修3异常未修',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
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: '操作',
@@ -169,13 +172,13 @@
]);
/* 搜索 */
const reload = (where?: CmsProductSpecParam) => {
const reload = (where?: ClinicMedicineStockParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductSpec) => {
const openEdit = (row?: ClinicMedicineStock) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -186,9 +189,9 @@
};
/* 删除单个 */
const remove = (row: CmsProductSpec) => {
const remove = (row: ClinicMedicineStock) => {
const hide = message.loading('请求中..', 0);
removeCmsProductSpec(row.cmsProductSpecId)
removeClinicMedicineStock(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -213,7 +216,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsProductSpec(selection.value.map((d) => d.cmsProductSpecId))
removeBatchClinicMedicineStock(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -233,7 +236,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsProductSpec) => {
const customRow = (record: ClinicMedicineStock) => {
return {
//
onClick: () => {
@@ -250,7 +253,7 @@
<script lang="ts">
export default {
name: 'CmsProductSpec'
name: 'ClinicMedicineStock'
};
</script>

View File

@@ -0,0 +1,744 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -0,0 +1,656 @@
<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>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑微信公众号' : '添加微信公众号'"
:title="isUpdate ? '编辑患者' : '添加患者'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,41 +19,64 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="上级id, 0是顶级" name="parentId">
<!-- <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="请输入上级id, 0是顶级"
v-model:value="form.parentId"
placeholder="请输入姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="菜单名称" name="name">
<a-form-item label="手机号" name="phone">
<a-input
allow-clear
placeholder="请输入菜单名称"
v-model:value="form.name"
placeholder="请输入手机号"
disabled
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="类型" name="type">
<a-input
allow-clear
placeholder="请输入类型"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item label="菜单值" name="key">
<a-input
allow-clear
placeholder="请输入菜单值"
v-model:value="form.key"
/>
</a-form-item>
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
<a-form-item label="年龄" name="age">
<a-input-number
:min="0"
:max="9999"
:max="999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
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">
@@ -64,11 +87,14 @@
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 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>
@@ -77,14 +103,13 @@
<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 { addCmsMpOfficialMenu, updateCmsMpOfficialMenu } from '@/api/cms/cmsMpOfficialMenu';
import { CmsMpOfficialMenu } from '@/api/cms/cmsMpOfficialMenu/model';
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';
import { FileRecord } from '@/api/system/file/model';
//
const isUpdate = ref(false);
@@ -97,7 +122,7 @@
//
visible: boolean;
//
data?: CmsMpOfficialMenu | null;
data?: ClinicPatientUser | null;
}>();
const emit = defineEmits<{
@@ -114,21 +139,20 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsMpOfficialMenu>({
const form = reactive<ClinicPatientUser>({
id: undefined,
parentId: undefined,
name: undefined,
type: undefined,
key: undefined,
sortNumber: undefined,
userId: undefined,
realName: undefined,
phone: undefined,
age: undefined,
height: undefined,
weight: undefined,
allergyHistory: undefined,
qrcode: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
createTime: undefined,
cmsMpOfficialMenuId: undefined,
cmsMpOfficialMenuName: '',
status: 0,
comments: '',
sortNumber: 100
});
@@ -139,30 +163,16 @@
//
const rules = reactive({
cmsMpOfficialMenuName: [
clinicPatientUserName: [
{
required: true,
type: 'string',
message: '请填写微信公众号名称',
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);
/* 保存编辑 */
@@ -177,7 +187,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsMpOfficialMenu : addCmsMpOfficialMenu;
const saveOrUpdate = isUpdate.value ? updateClinicPatientUser : addClinicPatientUser;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
@@ -200,13 +210,6 @@
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;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsDesignRecordId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -24,6 +23,19 @@
<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>
@@ -45,9 +57,8 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsDesignRecordEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicPatientUserEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
@@ -61,17 +72,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsDesignRecordEdit from './components/cmsDesignRecordEdit.vue';
import { pageCmsDesignRecord, removeCmsDesignRecord, removeBatchCmsDesignRecord } from '@/api/cms/cmsDesignRecord';
import type { CmsDesignRecord, CmsDesignRecordParam } from '@/api/cms/cmsDesignRecord/model';
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<CmsDesignRecord[]>([]);
const selection = ref<ClinicPatientUser[]>([]);
//
const current = ref<CmsDesignRecord | null>(null);
const current = ref<ClinicPatientUser | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +102,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsDesignRecord({
return pageClinicPatientUser({
...where,
...orders,
page,
@@ -98,101 +110,83 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '关联导航ID',
dataIndex: 'navigationId',
key: 'navigationId',
align: 'center',
},
{
title: '组件',
dataIndex: 'title',
key: 'title',
align: 'center',
},
{
title: '组件标识',
dataIndex: 'dictCode',
key: 'dictCode',
align: 'center',
},
{
title: '组件样式',
dataIndex: 'styles',
key: 'styles',
align: 'center',
},
{
title: '卡片阴影显示时机',
dataIndex: 'shadow',
key: 'shadow',
align: 'center',
},
{
title: '页面关键词',
dataIndex: 'keywords',
key: 'keywords',
align: 'center',
},
{
title: '页面描述',
dataIndex: 'description',
key: 'description',
align: 'center',
},
{
title: '页面路由地址',
dataIndex: 'path',
key: 'path',
align: 'center',
},
{
title: '缩列图',
dataIndex: 'photo',
key: 'photo',
align: 'center',
},
{
title: '用户ID',
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: '排序(数字越小越靠前)',
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',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0正常, 1冻结',
dataIndex: 'status',
key: 'status',
align: 'center',
width: 90
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 180,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
},
{
title: '操作',
@@ -205,13 +199,13 @@
]);
/* 搜索 */
const reload = (where?: CmsDesignRecordParam) => {
const reload = (where?: ClinicPatientUserParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsDesignRecord) => {
const openEdit = (row?: ClinicPatientUser) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -222,9 +216,9 @@
};
/* 删除单个 */
const remove = (row: CmsDesignRecord) => {
const remove = (row: ClinicPatientUser) => {
const hide = message.loading('请求中..', 0);
removeCmsDesignRecord(row.cmsDesignRecordId)
removeClinicPatientUser(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -249,7 +243,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsDesignRecord(selection.value.map((d) => d.cmsDesignRecordId))
removeBatchClinicPatientUser(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -269,7 +263,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsDesignRecord) => {
const customRow = (record: ClinicPatientUser) => {
return {
//
onClick: () => {
@@ -286,7 +280,7 @@
<script lang="ts">
export default {
name: 'CmsDesignRecord'
name: 'ClinicPatientUser'
};
</script>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑商品sku列表' : '添加商品sku列表'"
:title="isUpdate ? '编辑处方主表' : '添加处方主表'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,95 +19,105 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="商品ID" name="goodsId">
<a-form-item label="患者" name="userId">
<a-input
allow-clear
placeholder="请输入商品ID"
v-model:value="form.goodsId"
placeholder="请输入患者"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="商品属性索引值 (attr_value|attr_value[|....])" name="sku">
<a-form-item label="医生" name="doctorId">
<a-input
allow-clear
placeholder="请输入商品属性索引值 (attr_value|attr_value[|....])"
v-model:value="form.sku"
placeholder="请输入医生"
v-model:value="form.doctorId"
/>
</a-form-item>
<a-form-item
label="商品图片"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商品价格" name="price">
<a-form-item label="订单编号" name="orderNo">
<a-input
allow-clear
placeholder="请输入商品价格"
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="salePrice">
<a-form-item label="实付金额" name="payPrice">
<a-input
allow-clear
placeholder="请输入市场价格"
v-model:value="form.salePrice"
placeholder="请输入实付金额"
v-model:value="form.payPrice"
/>
</a-form-item>
<a-form-item label="成本价" name="cost">
<a-form-item label="订单是否失效(0未失效 1已失效)" name="isInvalid">
<a-input
allow-clear
placeholder="请输入成本价"
v-model:value="form.cost"
placeholder="请输入订单是否失效(0未失效 1已失效)"
v-model:value="form.isInvalid"
/>
</a-form-item>
<a-form-item label="库存" name="stock">
<a-form-item label="结算(0未结算 1已结算)" name="isSettled">
<a-input
allow-clear
placeholder="请输入库存"
v-model:value="form.stock"
placeholder="请输入结算(0未结算 1已结算)"
v-model:value="form.isSettled"
/>
</a-form-item>
<a-form-item label="sku编码" name="skuNo">
<a-form-item label="结算时间" name="settleTime">
<a-input
allow-clear
placeholder="请输入sku编码"
v-model:value="form.skuNo"
placeholder="请输入结算时间"
v-model:value="form.settleTime"
/>
</a-form-item>
<a-form-item label="商品条码" name="barCode">
<a-input
allow-clear
placeholder="请输入商品条码"
v-model:value="form.barCode"
/>
</a-form-item>
<a-form-item label="重量" name="weight">
<a-input
allow-clear
placeholder="请输入重量"
v-model:value="form.weight"
/>
</a-form-item>
<a-form-item label="体积" name="volume">
<a-input
allow-clear
placeholder="请输入体积"
v-model:value="form.volume"
/>
</a-form-item>
<a-form-item label="唯一值" name="uuid">
<a-input
allow-clear
placeholder="请输入唯一值"
v-model:value="form.uuid"
/>
</a-form-item>
<a-form-item label="状态, 0正常, 1异常" name="status">
<a-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>
@@ -121,6 +131,13 @@
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>
@@ -129,8 +146,8 @@
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsProductSku, updateCmsProductSku } from '@/api/cms/cmsProductSku';
import { CmsProductSku } from '@/api/cms/cmsProductSku/model';
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';
@@ -148,7 +165,7 @@
//
visible: boolean;
//
data?: CmsProductSku | null;
data?: ClinicPrescription | null;
}>();
const emit = defineEmits<{
@@ -165,29 +182,27 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsProductSku>({
const form = reactive<ClinicPrescription>({
id: undefined,
goodsId: undefined,
sku: undefined,
image: undefined,
userId: undefined,
doctorId: undefined,
orderNo: undefined,
visitRecordId: undefined,
prescriptionType: undefined,
diagnosis: undefined,
treatmentPlan: undefined,
decoctionInstructions: undefined,
orderPrice: undefined,
price: undefined,
salePrice: undefined,
cost: undefined,
stock: undefined,
skuNo: undefined,
barCode: undefined,
weight: undefined,
volume: undefined,
uuid: undefined,
status: undefined,
comments: undefined,
payPrice: undefined,
isInvalid: undefined,
isSettled: undefined,
settleTime: undefined,
tenantId: undefined,
createTime: undefined,
cmsProductSkuId: undefined,
cmsProductSkuName: '',
updateTime: undefined,
status: 0,
comments: '',
sortNumber: 100
comments: ''
});
/* 更新visible */
@@ -197,30 +212,16 @@
//
const rules = reactive({
cmsProductSkuName: [
clinicPrescriptionName: [
{
required: true,
type: 'string',
message: '请填写商品sku列表名称',
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);
/* 保存编辑 */
@@ -235,7 +236,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsProductSku : addCmsProductSku;
const saveOrUpdate = isUpdate.value ? updateClinicPrescription : addClinicPrescription;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
@@ -258,13 +259,6 @@
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;

View File

@@ -1,10 +1,9 @@
<template>
<div class="page">
<div class="ele-body">
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsProductSkuId"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
@@ -45,9 +44,8 @@
</a-card>
<!-- 编辑弹窗 -->
<CmsProductSkuEdit v-model:visible="showEdit" :data="current" @done="reload" />
</div>
</div>
<ClinicPrescriptionEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
@@ -61,17 +59,18 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CmsProductSkuEdit from './components/cmsProductSkuEdit.vue';
import { pageCmsProductSku, removeCmsProductSku, removeBatchCmsProductSku } from '@/api/cms/cmsProductSku';
import type { CmsProductSku, CmsProductSkuParam } from '@/api/cms/cmsProductSku/model';
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<CmsProductSku[]>([]);
const selection = ref<ClinicPrescription[]>([]);
//
const current = ref<CmsProductSku | null>(null);
const current = ref<ClinicPrescription | null>(null);
//
const showEdit = ref(false);
//
@@ -90,7 +89,7 @@
if (filters) {
where.status = filters.status;
}
return pageCmsProductSku({
return pageClinicPrescription({
...where,
...orders,
page,
@@ -98,107 +97,129 @@
});
};
//
//
const columns = ref<ColumnItem[]>([
{
title: '主键ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商品ID',
dataIndex: 'goodsId',
key: 'goodsId',
align: 'center',
title: '患者',
dataIndex: 'userId',
key: 'userId',
width: 120
},
{
title: '商品属性索引值 (attr_value|attr_value[|....])',
dataIndex: 'sku',
key: 'sku',
align: 'center',
title: '医生',
dataIndex: 'doctorId',
key: 'doctorId',
width: 120
},
{
title: '商品图片',
dataIndex: 'image',
key: 'image',
align: 'center',
title: '订单编号',
dataIndex: 'orderNo',
key: 'orderNo',
ellipsis: true
},
{
title: '商品价格',
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',
align: 'center',
width: 120
},
{
title: '市场价格',
dataIndex: 'salePrice',
key: 'salePrice',
align: 'center',
},
{
title: '成本价',
dataIndex: 'cost',
key: 'cost',
align: 'center',
},
{
title: '库存',
dataIndex: 'stock',
key: 'stock',
align: 'center',
},
{
title: 'sku编码',
dataIndex: 'skuNo',
key: 'skuNo',
align: 'center',
},
{
title: '商品条码',
dataIndex: 'barCode',
key: 'barCode',
align: 'center',
},
{
title: '重量',
dataIndex: 'weight',
key: 'weight',
align: 'center',
},
{
title: '体积',
dataIndex: 'volume',
key: 'volume',
align: 'center',
},
{
title: '唯一值',
dataIndex: 'uuid',
key: 'uuid',
align: 'center',
},
{
title: '状态, 0正常, 1异常',
dataIndex: 'status',
key: 'status',
align: 'center',
title: '实付金额',
dataIndex: '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, 123',
// dataIndex: 'status',
// key: 'status',
// width: 120
// },
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 200,
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
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: '操作',
@@ -211,13 +232,13 @@
]);
/* 搜索 */
const reload = (where?: CmsProductSkuParam) => {
const reload = (where?: ClinicPrescriptionParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductSku) => {
const openEdit = (row?: ClinicPrescription) => {
current.value = row ?? null;
showEdit.value = true;
};
@@ -228,9 +249,9 @@
};
/* 删除单个 */
const remove = (row: CmsProductSku) => {
const remove = (row: ClinicPrescription) => {
const hide = message.loading('请求中..', 0);
removeCmsProductSku(row.cmsProductSkuId)
removeClinicPrescription(row.id)
.then((msg) => {
hide();
message.success(msg);
@@ -255,7 +276,7 @@
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCmsProductSku(selection.value.map((d) => d.cmsProductSkuId))
removeBatchClinicPrescription(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
@@ -275,7 +296,7 @@
};
/* 自定义行属性 */
const customRow = (record: CmsProductSku) => {
const customRow = (record: ClinicPrescription) => {
return {
//
onClick: () => {
@@ -292,7 +313,7 @@
<script lang="ts">
export default {
name: 'CmsProductSku'
name: 'ClinicPrescription'
};
</script>

View File

@@ -5,7 +5,7 @@
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑组件' : '添加组件'"
:title="isUpdate ? '编辑处方明细表' : '添加处方明细表'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -19,63 +19,70 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="组件标题" name="title">
<a-form-item label="关联处方" name="prescriptionId">
<a-input
allow-clear
placeholder="请输入组件标题"
v-model:value="form.title"
placeholder="请输入关联处方"
v-model:value="form.prescriptionId"
/>
</a-form-item>
<a-form-item label="关联导航ID" name="navigationId">
<a-form-item label="订单编号" name="prescriptionNo">
<a-input
allow-clear
placeholder="请输入关联导航ID"
v-model:value="form.navigationId"
placeholder="请输入订单编号"
v-model:value="form.prescriptionNo"
/>
</a-form-item>
<a-form-item label="组件类型" name="type">
<a-form-item label="关联药品" name="medicineId">
<a-input
allow-clear
placeholder="请输入组件类型"
v-model:value="form.type"
placeholder="请输入关联药品"
v-model:value="form.medicineId"
/>
</a-form-item>
<a-form-item label="页面关键词" name="keywords">
<a-form-item label="剂量如“10g”" name="dosage">
<a-input
allow-clear
placeholder="请输入页面关键词"
v-model:value="form.keywords"
placeholder="请输入剂量如“10g”"
v-model:value="form.dosage"
/>
</a-form-item>
<a-form-item label="页面描述" name="description">
<a-form-item label="用法频率(如“每日三次”)" name="usageFrequency">
<a-input
allow-clear
placeholder="请输入页面描述"
v-model:value="form.description"
placeholder="请输入用法频率(如“每日三次”)"
v-model:value="form.usageFrequency"
/>
</a-form-item>
<a-form-item label="组件路径" name="path">
<a-form-item label="服用天数" name="days">
<a-input
allow-clear
placeholder="请输入组件路径"
v-model:value="form.path"
placeholder="请输入服用天数"
v-model:value="form.days"
/>
</a-form-item>
<a-form-item label="组件图标" name="icon">
<a-form-item label="购买数量" name="amount">
<a-input
allow-clear
placeholder="请输入组件图标"
v-model:value="form.icon"
placeholder="请输入购买数量"
v-model:value="form.amount"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-form-item label="单价" name="unitPrice">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
placeholder="请输入单价"
v-model:value="form.unitPrice"
/>
</a-form-item>
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
<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"
@@ -92,11 +99,19 @@
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 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>
@@ -105,14 +120,13 @@
<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 { addCmsComponents, updateCmsComponents } from '@/api/cms/cmsComponents';
import { CmsComponents } from '@/api/cms/cmsComponents/model';
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';
import { FileRecord } from '@/api/system/file/model';
//
const isUpdate = ref(false);
@@ -125,7 +139,7 @@
//
visible: boolean;
//
data?: CmsComponents | null;
data?: ClinicPrescriptionItem | null;
}>();
const emit = defineEmits<{
@@ -142,24 +156,21 @@
const images = ref<ItemType[]>([]);
//
const form = reactive<CmsComponents>({
const form = reactive<ClinicPrescriptionItem>({
id: undefined,
title: undefined,
navigationId: undefined,
type: undefined,
keywords: undefined,
description: undefined,
path: undefined,
icon: undefined,
prescriptionId: undefined,
prescriptionNo: undefined,
medicineId: undefined,
dosage: undefined,
usageFrequency: undefined,
days: undefined,
amount: undefined,
unitPrice: undefined,
quantity: undefined,
userId: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
updateTime: undefined,
createTime: undefined,
cmsComponentsId: undefined,
cmsComponentsName: '',
status: 0,
comments: '',
sortNumber: 100
});
@@ -171,30 +182,16 @@
//
const rules = reactive({
cmsComponentsName: [
clinicPrescriptionItemName: [
{
required: true,
type: 'string',
message: '请填写组件名称',
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);
/* 保存编辑 */
@@ -209,7 +206,7 @@
const formData = {
...form
};
const saveOrUpdate = isUpdate.value ? updateCmsComponents : addCmsComponents;
const saveOrUpdate = isUpdate.value ? updateClinicPrescriptionItem : addClinicPrescriptionItem;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
@@ -232,13 +229,6 @@
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;

View File

@@ -0,0 +1,296 @@
<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>

View File

@@ -0,0 +1,318 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -0,0 +1,338 @@
<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>

View File

@@ -0,0 +1,297 @@
<!-- 编辑弹窗 -->
<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>

View File

@@ -0,0 +1,338 @@
<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>

View File

@@ -19,15 +19,6 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<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="type">
<a-radio-group
v-model:value="form.type"
@@ -40,6 +31,24 @@
<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}`">
@@ -51,14 +60,18 @@
@del="onDeleteItem"
/>
</div>
<a-space class="flex flex-col gap-2">
<div class="w-[500px]" v-for="(item, index) in images" :key="index">
<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>
</a-space>
</div>
</a-form-item>
</template>
<template v-if="form.type == 2">
@@ -72,6 +85,20 @@
/>
</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
@@ -89,6 +116,20 @@
/>
</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
@@ -129,13 +170,13 @@
<span class="text-gray-400">广告位尺寸大小(默认值100% * 500px)</span>
</div>
</a-form-item>
<a-form-item label="栏目">
<a-form-item label="位置">
<a-tree-select
allow-clear
:tree-data="navigationList"
tree-default-expand-all
style="width: 500px;"
placeholder="请选择栏目"
placeholder="请选择所属栏目"
:value="form.categoryId || undefined"
:listHeight="700"
:dropdown-style="{ overflow: 'auto' }"
@@ -143,15 +184,14 @@
@change="onCategoryId"
/>
</a-form-item>
<a-form-item label="样式" name="style">
<a-form-item label="style" name="style">
<a-input
allow-clear
placeholder="w-full border-solid border-gray-800 p-2 shadow-lg rounded-lg my-10"
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
Css使用教程</a>
<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">
@@ -188,7 +228,7 @@ 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, type Rule} from 'ant-design-vue/es/form';
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";
@@ -229,6 +269,7 @@ const formRef = ref<FormInstance | null>(null);
const form = reactive<CmsAd>({
adId: undefined,
type: undefined,
code: undefined,
categoryId: undefined,
name: '',
style: '',
@@ -250,11 +291,10 @@ const updateVisible = (value: boolean) => {
};
// 表单验证规则
const rules = reactive({
const rules = {
name: [
{
required: true,
type: 'string',
message: '请输入标题',
trigger: 'blur'
}
@@ -262,7 +302,6 @@ const rules = reactive({
type: [
{
required: true,
type: 'number',
message: '请选择类型',
trigger: 'blur'
}
@@ -270,10 +309,9 @@ const rules = reactive({
images: [
{
required: true,
type: 'string',
message: '请上传图片或视频',
trigger: 'blur',
validator: (_rule: Rule, value: string) => {
validator: (_rule: any, _: string) => {
return new Promise<void>((resolve, reject) => {
if (images.value.length == 0) {
return reject('请上传图片或视频文件');
@@ -283,7 +321,7 @@ const rules = reactive({
}
}
]
});
};
const {resetFields} = useForm(form, rules);
@@ -291,7 +329,9 @@ 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'
status: 'done',
title: '', // 初始化标题为空
path: '' // 初始化链接为空
});
form.images = data.downloadUrl + '?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90';
};

View File

@@ -1,7 +1,7 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="add">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
@@ -45,9 +45,6 @@
{}
);
// 网站ID
const websiteId = localStorage.getItem('WebsiteId')
const emit = defineEmits<{
(e: 'search', where?: CmsAdParam): void;
(e: 'add'): void;

View File

@@ -27,8 +27,9 @@
<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 === 'pageId'">
<span class="text-gray-400">{{ record.pageName }}</span>
<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>
@@ -93,7 +94,6 @@ 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 Extra from "@/views/cms/cmsNavigation/components/extra.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);

View File

@@ -120,13 +120,8 @@
path: undefined,
url: undefined,
adId: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
createTime: undefined,
cmsAdRecordId: undefined,
cmsAdRecordName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -165,6 +165,13 @@
v-model:value="form.pdfUrl"
/>
</a-form-item>
<a-form-item label="编号" name="code">
<a-input
allow-clear
placeholder="code"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="文章来源" name="source">
<source-select
v-model:value="form.source"
@@ -326,6 +333,8 @@ const form = reactive<CmsArticle>({
articleId: undefined,
// 文章模型
model: 'detail',
// 文章标识
code: undefined,
// 封面图
image: '',
// 文章标题
@@ -403,7 +412,7 @@ const rules = reactive({
type: 'string',
message: '请输入文章内容',
trigger: 'blur',
validator: async (_rule: RuleObject, value: string) => {
validator: async (_rule: RuleObject, _: string) => {
if (content.value == '') {
return Promise.reject('请输入文字内容');
}
@@ -413,15 +422,6 @@ const rules = reactive({
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
// 选择栏目
const onCategoryId = (id: number) => {
form.categoryId = id;
@@ -431,10 +431,6 @@ const onCategoryId = (id: number) => {
}
};
const onChange = () => {
// 加载文章多规格
};
// 📝 编辑器类型切换处理
const onEditorTypeChange = (e: any) => {
const newEditorType = e.target.value;
@@ -558,11 +554,6 @@ const onEditor = (value: any) => {
editor.value = value.target.value;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
const onComments = () => {
if (form.comments == undefined) {
form.comments = htmlToText(content.value);

View File

@@ -1,7 +1,7 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="add">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined/>
</template>
@@ -68,8 +68,8 @@
@search="reload"
/>
<a-button type="text" @click="reset">重置</a-button>
<a-button type="text" :disabled="!websiteId" @click="handleExport">导出xls</a-button>
<a-button type="text" :disabled="!websiteId" @click="openImport">导入xls</a-button>
<a-button type="text" @click="handleExport">导出xls</a-button>
<a-button type="text" @click="openImport">导入xls</a-button>
</a-space>
<!-- 导入弹窗 -->
@@ -88,7 +88,7 @@ import {CmsNavigation} from '@/api/cms/cmsNavigation/model';
import dayjs from 'dayjs';
import Import from "./Import.vue";
import {useWebsiteSettingStore} from "@/store/modules/setting";
import {openUrl, push} from "@/utils/common";
import {openUrl} from "@/utils/common";
const props = withDefaults(
defineProps<{
@@ -112,7 +112,6 @@ const xlsFileName = ref<string>();
const articleList = ref<CmsArticle[]>([]);
// 是否显示用户导入弹窗
const showImport = ref(false);
const websiteId = localStorage.getItem('WebsiteId')
// 表单数据
const {where, resetFields} = useSearch<CmsArticleParam>({

View File

@@ -139,7 +139,6 @@ import type {CmsArticle, CmsArticleParam} from '@/api/cms/cmsArticle/model';
import {formatNumber} from 'ele-admin-pro/es';
import router from '@/router';
import {toTreeData} from 'ele-admin-pro';
import {toDateString} from 'ele-admin-pro';
import {
detail,
getPageTitle
@@ -149,8 +148,6 @@ import {CmsNavigation} from '@/api/cms/cmsNavigation/model';
import {CmsArticleCategory} from '@/api/cms/cmsArticleCategory/model';
import {listCmsArticleCategory} from '@/api/cms/cmsArticleCategory';
import Qrcode from '@/components/QrCode/index.vue';
import {getCmsWebsiteSetting} from '@/api/cms/cmsWebsiteSetting';
import {useWebsiteSettingStore} from '@/store/modules/setting';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
@@ -174,8 +171,6 @@ const navigationList = ref<CmsNavigation[]>();
const categoryList = ref<CmsArticleCategory[]>();
// 是否显示二维码
const showQrcode = ref(false);
// 网站设置信息
const setting = useWebsiteSettingStore();
// 表格数据源
const datasource: DatasourceFunction = ({page, limit, where, orders}) => {
@@ -272,7 +267,6 @@ const columns = ref<ColumnItem[]>([
key: 'createTime',
align: 'center',
width: 180,
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd'),
sorter: true
},
{
@@ -435,24 +429,11 @@ if (!categoryList.value) {
});
}
const getSetting = () => {
// 网站设置信息
getCmsWebsiteSetting(Number(localStorage.getItem('WebsiteId'))).then(
(res) => {
if (res.editor) {
setting.value = res;
localStorage.setItem('Editor', res.editor);
}
}
);
};
watch(
() => router.currentRoute.value.query,
(query) => {
if (query) {
categoryId.value = Number(query.id);
getSetting();
reload();
}
},

View File

@@ -207,18 +207,12 @@
pageId: undefined,
userId: undefined,
count: undefined,
sortNumber: undefined,
comments: undefined,
hide: undefined,
recommend: undefined,
showIndex: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
cmsArticleCategoryId: undefined,
cmsArticleCategoryName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -166,15 +166,10 @@
toUserId: undefined,
replyCommentId: undefined,
replyUserId: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
cmsArticleCommentId: undefined,
cmsArticleCommentName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -181,14 +181,7 @@
parentId: undefined,
userId: undefined,
home: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
cmsDesignId: undefined,
cmsDesignName: '',
status: 0,
comments: '',
sortNumber: 100

View File

@@ -1,227 +0,0 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsDocsContentId"
: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>
<!-- 编辑弹窗 -->
<CmsDocsContentEdit 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 CmsDocsContentEdit from './components/cmsDocsContentEdit.vue';
import { pageCmsDocsContent, removeCmsDocsContent, removeBatchCmsDocsContent } from '@/api/cms/cmsDocsContent';
import type { CmsDocsContent, CmsDocsContentParam } from '@/api/cms/cmsDocsContent/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsDocsContent[]>([]);
// 当前编辑数据
const current = ref<CmsDocsContent | 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 pageCmsDocsContent({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '文档ID',
dataIndex: 'docsId',
key: 'docsId',
align: 'center',
},
{
title: '文档内容',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsDocsContentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsDocsContent) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsDocsContent) => {
const hide = message.loading('请求中..', 0);
removeCmsDocsContent(row.cmsDocsContentId)
.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);
removeBatchCmsDocsContent(selection.value.map((d) => d.cmsDocsContentId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsDocsContent) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsDocsContent'
};
</script>
<style lang="less" scoped></style>

View File

@@ -131,7 +131,6 @@ const { form, resetFields, assignFields } = useFormData<CmsLink>({
name: '',
url: '',
sortNumber: 100,
lang: getLang(),
categoryId: undefined,
comments: undefined
});

View File

@@ -1,7 +1,7 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="add">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
@@ -13,18 +13,18 @@
>
移动
</a-button>
<a-tree-select
allow-clear
:tree-data="navigationList"
tree-default-expand-all
style="width: 280px"
:listHeight="700"
placeholder="请选择栏目"
:value="where.categoryId || undefined"
:dropdown-style="{ overflow: 'auto' }"
@update:value="(value?: number) => (where.categoryId = value)"
@change="onCategoryId"
/>
<!-- <a-tree-select-->
<!-- allow-clear-->
<!-- :tree-data="navigationList"-->
<!-- tree-default-expand-all-->
<!-- style="width: 280px"-->
<!-- :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="请输入关键词"
@@ -52,9 +52,6 @@
{}
);
// 网站ID
const websiteId = localStorage.getItem('WebsiteId')
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;

View File

@@ -23,7 +23,8 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'icon'">
<a-image :src="record.icon" :width="50"/>
<a-image :src="record.icon" :width="50"
fallback="https://file.wsdns.cn/20230218/550e610d43334dd2a7f66d5b20bd58eb.svg"/>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
@@ -124,17 +125,6 @@ const columns = ref<ColumnItem[]>([
// hideInSetting: true,
// customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
// },
{
title: '链接名称',
dataIndex: 'name',
key: 'name'
},
{
title: '所属栏目',
dataIndex: 'categoryName',
align: 'center',
width: 180,
},
{
title: '图标',
dataIndex: 'icon',
@@ -142,6 +132,11 @@ const columns = ref<ColumnItem[]>([
align: 'center',
width: 120,
},
{
title: '链接名称',
dataIndex: 'name',
key: 'name'
},
{
title: '链接地址',
dataIndex: 'url',
@@ -151,6 +146,13 @@ const columns = ref<ColumnItem[]>([
title: '备注',
dataIndex: 'comments'
},
{
title: '所属栏目',
dataIndex: 'categoryName',
align: 'center',
width: 180,
hideInTable: true
},
{
title: '状态',
dataIndex: 'status',

View File

@@ -84,10 +84,10 @@
/>
</a-space>
</a-form-item>
<a-form-item label="CSS样式" name="style">
<a-form-item label="style" name="style">
<a-input
allow-clear
placeholder="CSS样式"
placeholder="style"
v-model:value="form.style"
/>
<div class="pt-2">

View File

@@ -1,7 +1,7 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap;">
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="add">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
@@ -30,8 +30,6 @@
(e: 'batchMove'): void;
}>();
const websiteId = localStorage.getItem('WebsiteId')
// 新增
const add = () => {
emit('add');

View File

@@ -1,284 +0,0 @@
<!-- 编辑弹窗 -->
<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="avatar">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="小程序码" name="mpQrcode">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="mpQrcode"
@done="chooseMpQrcode"
@del="onDeleteMpQrcode"
/>
</a-form-item>
<a-form-item label="小程序名称" name="mpName">
<a-input
allow-clear
placeholder="请输入小程序名称"
v-model:value="form.mpName"
/>
</a-form-item>
<a-form-item label="小程序ID" name="appId">
<a-input
allow-clear
placeholder="请输入小程序ID"
v-model:value="form.appId"
/>
</a-form-item>
<a-form-item label="小程序密钥" name="appSecret">
<a-input
allow-clear
placeholder="请输入小程序密钥"
type="password"
v-model:value="form.appSecret"
/>
</a-form-item>
<a-form-item label="主体信息" name="companyName">
<a-input
allow-clear
placeholder="请输入主体信息"
v-model:value="form.companyName"
/>
</a-form-item>
<a-form-item label="小程序备案" name="icpNo">
<a-input
allow-clear
placeholder="请输入小程序备案"
v-model:value="form.icpNo"
/>
</a-form-item>
<a-form-item label="登录邮箱" name="email">
<a-input
allow-clear
placeholder="请输入登录邮箱"
v-model:value="form.email"
/>
</a-form-item>
<a-form-item label="原始ID" name="ghId">
<a-input
allow-clear
placeholder="请输入原始ID"
v-model:value="form.ghId"
/>
</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="authentication">
<a-radio-group v-model:value="form.authentication">
<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 { addCmsMp, updateCmsMp } from '@/api/cms/cmsMp';
import { CmsMp } from '@/api/cms/cmsMp/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?: CmsMp | 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 mpQrcode = ref<ItemType[]>([]);
// 用户信息
const form = reactive<CmsMp>({
mpId: undefined,
type: undefined,
appId: undefined,
appSecret: undefined,
mpName: undefined,
shortName: undefined,
avatar: undefined,
mpQrcode: undefined,
authentication: undefined,
companyName: undefined,
icpNo: undefined,
email: undefined,
password: undefined,
ghId: undefined,
mainPath: undefined,
expirationTime: undefined,
comments: undefined,
userId: undefined,
status: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
cmsMpName: [
{
required: true,
type: 'string',
message: '请填写小程序信息名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.avatar = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.avatar = '';
};
const chooseMpQrcode = (data: FileRecord) => {
mpQrcode.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.mpQrcode = data.downloadUrl;
};
const onDeleteMpQrcode = (index: number) => {
mpQrcode.value.splice(index, 1);
form.mpQrcode = '';
};
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 ? updateCmsMp : addCmsMp;
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.avatar){
images.value.push({
uid: uuid(),
url: props.data.avatar,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -1,242 +0,0 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsMpId"
: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 === 'avatar'">
<a-image :src="record.avatar" :width="50" />
</template>
<template v-if="column.key === 'mpQrcode'">
<a-image :src="record.mpQrcode" :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>
<!-- 编辑弹窗 -->
<CmsMpEdit 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 CmsMpEdit from './components/cmsMpEdit.vue';
import { pageCmsMp, removeCmsMp, removeBatchCmsMp } from '@/api/cms/cmsMp';
import type { CmsMp, CmsMpParam } from '@/api/cms/cmsMp/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsMp[]>([]);
// 当前编辑数据
const current = ref<CmsMp | 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 pageCmsMp({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '小程序名称',
dataIndex: 'mpName',
key: 'mpName',
align: 'center'
},
{
title: '头像',
dataIndex: 'avatar',
key: 'avatar',
align: 'center'
},
{
title: '小程序码',
dataIndex: 'mpQrcode',
key: 'mpQrcode',
align: 'center'
},
{
title: '主体信息',
dataIndex: 'companyName',
key: 'companyName',
align: 'center'
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
hideInTable: true
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsMpParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsMp) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsMp) => {
const hide = message.loading('请求中..', 0);
removeCmsMp(row.cmsMpId)
.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);
removeBatchCmsMp(selection.value.map((d) => d.cmsMpId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsMp) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsMp'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,378 +0,0 @@
<!-- 编辑弹窗 -->
<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="adType">
<a-select
ref="select"
:disabled="isUpdate"
v-model:value="form.adType"
style="width: 120px"
>
<a-select-option value="图片广告">图片广告</a-select-option>
<a-select-option value="幻灯片">幻灯片</a-select-option>
<a-select-option value="视频广告">视频广告</a-select-option>
</a-select>
</a-form-item>
<template v-if="form.adType == '幻灯片'">
<a-form-item label="图片" name="images">
<SelectFile
:placeholder="`请选择图片`"
:limit="9"
:data="images"
@done="chooseFile"
@del="onDeleteItem"
/>
</a-form-item>
</template>
<template v-if="form.adType == '图片广告'">
<a-form-item label="图片" name="images">
<SelectFile
:limit="1"
:data="images"
@done="chooseFile"
@del="onDeleteItem"
/>
</a-form-item>
</template>
<template v-if="form.adType == '视频广告'">
<a-form-item
label="上传视频"
name="images"
extra="请上传视频文件仅支持mp4格式大小200M以内"
>
<SelectFile
:placeholder="`请选择视频文件`"
:limit="1"
:data="images"
@done="chooseFile"
@del="onDeleteItem"
/>
</a-form-item>
</template>
<a-form-item label="位置" name="pageId">
<SelectMpPages
:placeholder="`请选择页面`"
v-model:value="form.pageName"
@done="choosePageId"
/>
</a-form-item>
<a-form-item label="路由/链接地址" name="path">
<template v-if="form.adType == '幻灯片' && images.length > 0">
<template v-for="(item, index) in images" :key="index">
<a-input
allow-clear
:maxlength="100"
:placeholder="`请输入地址${index + 1}`"
v-model:value="pathList[index]"
/>
</template>
</template>
<template v-else>
<a-input
allow-clear
:maxlength="100"
placeholder="请输入路由/链接地址"
v-model:value="form.path"
/>
</template>
</a-form-item>
<a-form-item label="图标背景色" v-if="data && data.adId === 278">
<div class="flex justify-start items-start flex-wrap">
<div class="flex flex-col justify-center items-center" v-for="(item, index) in colors" :key="index">
<div
@click="changeShowColorPicker(index)"
class=" w-10 h-10 rounded-full m-2 cursor-pointer border-2 border-solid flex justify-center items-center text-red-600"
:class="[item ? 'border-none' : 'border-red-300']"
:style="{backgroundColor: item ?? 'red'}"
>{{ item ? '' : '选色' }}
</div>
<span v-if="item" class="text-sm cursor-pointer" @click="clearColor(index)">清除</span>
</div>
</div>
<!-- <Vue3ColorPicker v-if="showColorPicker" v-model="colors[showColorPickerIndex]" mode="solid"-->
<!-- :showColorList="false" :showEyeDrop="false" type="RGBA"/>-->
</a-form-item>
<a-form-item label="标题" name="name">
<a-input
allow-clear
:maxlength="100"
placeholder="请输入广告标题"
v-model:value="form.name"
/>
</a-form-item>
<a-form-item label="广告描述" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入广告描述"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="排序号" name="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="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 {addCmsMpAd, updateCmsMpAd} from '@/api/cms/cmsMpAd';
import {CmsMpAd} from '@/api/cms/cmsMpAd/model';
import {useThemeStore} from '@/store/modules/theme';
import {storeToRefs} from 'pinia';
import {FormInstance, type Rule, RuleObject} 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 {CmsMpPages} from '@/api/cms/cmsMpPages/model';
// import {Vue3ColorPicker} from "@cyhnkckali/vue3-color-picker";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const {styleResponsive} = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: CmsMpAd | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 已上传数据
const images = ref<ItemType[]>([]);
const pathList = ref<any[]>([]);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 用户信息
const form = reactive<CmsMpAd>({
adId: undefined,
pageId: 0,
pageName: '',
name: '',
adType: '图片广告',
images: '',
colors: '',
width: '',
height: '',
path: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
adType: [
{
required: true,
type: 'string',
message: '请选择广告类型',
trigger: 'blur'
}
],
images: [
{
required: true,
type: 'string',
message: '请上传图片或视频',
trigger: 'blur',
validator: (_rule: Rule, value: 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,
status: 'done'
});
form.images = data.downloadUrl;
colors.value.push('')
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
colors.value.splice(index, 1);
form.images = '';
};
const choosePageId = (data: CmsMpPages) => {
form.pageName = data.title;
form.pageId = data.id;
};
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form,
images: JSON.stringify(images.value),
colors: JSON.stringify(colors.value),
path:
form.adType == '幻灯片' ? JSON.stringify(pathList.value) : form.path
};
const saveOrUpdate = isUpdate.value ? updateCmsMpAd : addCmsMpAd;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
};
const colors = ref<string[]>([])
const showColorPicker = ref(false)
const showColorPickerIndex = ref<number>(-1)
const changeShowColorPicker = (index: number) => {
if (showColorPickerIndex.value === index) showColorPicker.value = !showColorPicker.value
else {
showColorPickerIndex.value = index
showColorPicker.value = true
}
}
const clearColor = (index) => {
showColorPicker.value = false
colors.value[index] = ''
}
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignObject(form, props.data);
images.value = [];
pathList.value = [];
colors.value = []
if (props.data.images) {
const arr = JSON.parse(props.data.images);
arr.map((d) => {
images.value.push({
uid: d.uid,
url: d.url,
status: 'done'
});
});
}
if (props.data.colors) {
colors.value = JSON.parse(props.data.colors);
} else {
colors.value = []
for (let i = 0; i < images.value.length; i++) {
colors.value.push('')
}
}
if (props.data.adType == '幻灯片') {
const arr = JSON.parse(props.data.path);
arr.map((d) => {
pathList.value.push(d);
});
}
isUpdate.value = true;
} else {
images.value = [];
isUpdate.value = false;
}
} else {
resetFields();
}
},
{immediate: true}
);
</script>
<style lang="less">
.tab-pane {
min-height: 300px;
}
.ml-10 {
margin-left: 5px;
}
.upload-text {
margin-right: 70px;
}
.icon-bg {
width: 50px;
height: 50px;
display: block;
border-radius: 50px;
background: url('data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%221%22%20x1%3D%220%22%20x2%3D%221%22%20y1%3D%220%22%20y2%3D%220%22%20gradientTransform%3D%22matrix(6.123233995736766e-17%2C%201%2C%20-0.024693877551020406%2C%206.123233995736766e-17%2C%200.5%2C%200)%22%3E%3Cstop%20stop-color%3D%22%230a060d%22%20stop-opacity%3D%221%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23660061%22%20stop-opacity%3D%221%22%20offset%3D%220.95%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E');
}
</style>

View File

@@ -1,250 +0,0 @@
<template>
<div class="page">
<div class="ele-body">
<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"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'adType'">
<a-tag>{{ record.adType }}</a-tag>
</template>
<template v-if="column.key === 'images'">
<template
v-for="(item, index) in JSON.parse(record.images)"
:key="index"
>
<a-image :src="item.url" :width="80" />
</template>
<span></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 v-if="record.adId !== 278"
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<MpAdEdit 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 type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import MpAdEdit from './components/mpAdEdit.vue';
import { pageCmsMpAd, removeCmsMpAd, removeBatchCmsMpAd } from '@/api/cms/cmsMpAd';
import type { CmsMpAd, CmsMpAdParam } from '@/api/cms/cmsMpAd/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsMpAd[]>([]);
// 当前编辑数据
const current = ref<CmsMpAd | 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 pageCmsMpAd({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
width: 90,
dataIndex: 'adId'
},
{
title: '类型',
dataIndex: 'adType',
key: 'adType',
width: 120
},
{
title: '广告图片',
dataIndex: 'images',
key: 'images'
},
{
title: '跳转路径',
dataIndex: 'path',
key: 'path',
width: 280,
ellipsis: true
},
// {
// title: '位置',
// dataIndex: 'pageName',
// key: 'pageName',
// width: 120
// },
{
title: '描述',
dataIndex: 'comments',
key: 'path',
width: 280,
ellipsis: true
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
width: 120
},
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsMpAdParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsMpAd) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsMpAd) => {
const hide = message.loading('请求中..', 0);
removeCmsMpAd(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);
removeBatchCmsMpAd(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;
};
/* 自定义行属性 */
const customRow = (record: CmsMpAd) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'MpAd'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,178 +0,0 @@
<!-- 分组编辑弹窗 -->
<template>
<ele-modal
:width="460"
:visible="visible"
:confirm-loading="loading"
:title="isUpdate ? '修改分组' : '添加分组'"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 5, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="分组标识" name="dictCode">
<a-input
allow-clear
:maxlength="20"
disabled
placeholder="请输入分组标识"
v-model:value="form.dictCode"
/>
</a-form-item>
<a-form-item label="分组名称" name="dictDataName">
<a-input
allow-clear
:maxlength="20"
placeholder="请输入分组名称"
v-model:value="form.dictDataName"
/>
</a-form-item>
<a-form-item label="排序" name="sortNumber">
<a-input-number
:min="0"
:max="99999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="备注">
<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 { message } from 'ant-design-vue/es';
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import { addDictData, updateDictData } from '@/api/system/dict-data';
import { DictData } from '@/api/system/dict-data/model';
import {removeSiteInfoCache} from "@/api/cms/cmsWebsite";
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: DictData | null;
// 字典ID
dictId?: number | 0;
}>();
//
const formRef = ref<FormInstance | null>(null);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 表单数据
const { form, resetFields, assignFields } = useFormData<DictData>({
dictId: undefined,
dictDataId: undefined,
dictDataName: '',
dictCode: 'mpGroup',
dictDataCode: '',
sortNumber: 100,
comments: ''
});
// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
dictDataCode: [
{
required: true,
message: '请输入分组名称',
type: 'string',
trigger: 'blur'
}
],
dictCode: [
{
required: true,
message: '请输入分组标识',
type: 'string',
trigger: 'blur'
}
]
});
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const saveOrUpdate = isUpdate.value ? updateDictData : addDictData;
form.dictDataCode = form.dictDataName;
form.dictId = props.dictId;
saveOrUpdate(form)
.then((msg) => {
loading.value = false;
message.success(msg);
// 清除字典缓存
removeSiteInfoCache(form.dictCode + ':' + form.tenantId);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignFields(props.data);
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
formRef.value?.clearValidate();
}
}
);
</script>

View File

@@ -1,228 +0,0 @@
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="dictDataId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 800 }"
cache-key="appDictTable"
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
placement="topRight"
title="确定要删除此分组吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<dict-edit
v-model:visible="showEdit"
:dictId="dictId"
:data="current"
@done="reload"
/>
</div>
</template>
<script lang="ts" setup>
import { createVNode, ref, watch } from 'vue';
import { message, Modal } from 'ant-design-vue/es';
import {
PlusOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro/es';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import { messageLoading } from 'ele-admin-pro/es';
import DictEdit from './components/dict-edit.vue';
import {
pageDictData,
removeDictData,
removeDictDataBatch
} from '@/api/system/dict-data';
import { DictParam } from '@/api/system/dict/model';
import { DictData } from '@/api/system/dict-data/model';
import { addDict, listDictionaries } from '@/api/system/dict';
import { Dictionary } from '@/api/system/dictionary/model';
import router from '@/router';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
const dictId = ref(0);
const pageId = ref(0);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'dictDataId',
width: 80,
hideInTable: true
},
{
title: '分组名称',
dataIndex: 'dictDataName',
showSorterTooltip: false
},
{
title: '备注',
dataIndex: 'comments',
sorter: true,
showSorterTooltip: false
},
{
title: '排序号',
width: 180,
align: 'center',
dataIndex: 'sortNumber'
},
{
title: '操作',
key: 'action',
width: 180,
align: 'center'
}
]);
// 表格选中数据
const selection = ref<DictData[]>([]);
// 当前编辑数据
const current = ref<Dictionary | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
where.dictCode = 'mpGroup';
return pageDictData({ ...where, ...orders, page, limit });
};
/* 搜索 */
const reload = (where?: DictParam) => {
selection.value = [];
tableRef?.value?.reload({ page: 1, where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: DictData) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 删除单个 */
const remove = (row: DictData) => {
const hide = messageLoading('请求中..', 0);
removeDictData(row.dictDataId)
.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 = messageLoading('请求中..', 0);
removeDictDataBatch(selection.value.map((d) => d.dictDataId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// 初始化字典
const loadDict = () => {
listDictionaries({ dictCode: 'mpGroup' }).then(async (data) => {
if (data?.length == 0) {
await addDict({ dictCode: 'mpGroup', dictName: '链接分组' });
}
await listDictionaries({ dictCode: 'mpGroup' }).then((list) => {
list?.map((d) => {
dictId.value = Number(d.dictId);
});
});
});
};
loadDict();
/* 自定义行属性 */
const customRow = (record: DictData) => {
return {
onDblclick: () => {
openEdit(record);
}
};
};
watch(
() => router.currentRoute.value.params.id,
(id) => {
if (id) {
if (id == ':id') {
pageId.value = 0;
} else {
pageId.value = Number(id);
}
}
reload();
},
{ immediate: true }
);
</script>
<script lang="ts">
export default {
name: 'TaskDictData'
};
</script>

View File

@@ -1,195 +0,0 @@
<!-- 分包编辑弹窗 -->
<template>
<ele-modal
:width="460"
:visible="visible"
:confirm-loading="loading"
:title="isUpdate ? '修改分包' : '添加分包'"
:body-style="{ paddingBottom: '8px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 5, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="标识" name="dictCode">
<a-input
allow-clear
:maxlength="20"
disabled
placeholder="请输入标识"
v-model:value="form.dictCode"
/>
</a-form-item>
<!-- <a-form-item label="名称" name="dictDataName">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- :maxlength="20"-->
<!-- placeholder="分包"-->
<!-- v-model:value="form.dictDataName"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="名称" name="dictDataCode">
<a-input
allow-clear
:maxlength="20"
placeholder="pages"
v-model:value="form.dictDataCode"
/>
</a-form-item>
<a-form-item label="排序" name="sortNumber">
<a-input-number
:min="0"
:max="99999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="备注">
<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 { message } from 'ant-design-vue/es';
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import { addDictData, updateDictData } from '@/api/system/dict-data';
import { DictData } from '@/api/system/dict-data/model';
import {removeSiteInfoCache} from "@/api/cms/cmsWebsite";
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: DictData | null;
// 字典ID
dictId?: number | 0;
}>();
//
const formRef = ref<FormInstance | null>(null);
// 是否是修改
const isUpdate = ref(false);
// 提交状态
const loading = ref(false);
// 表单数据
const { form, resetFields, assignFields } = useFormData<DictData>({
dictId: undefined,
dictDataId: undefined,
dictDataName: '',
dictCode: 'mpPackage',
dictDataCode: '',
sortNumber: 100,
comments: ''
});
// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
dictDataCode: [
{
required: true,
message: '请输入分包英文名',
type: 'string',
trigger: 'blur'
}
],
// dictDataName: [
// {
// required: true,
// message: '请输入分包名称',
// type: 'string',
// trigger: 'blur'
// }
// ],
dictCode: [
{
required: true,
message: '请输入分包标识',
type: 'string',
trigger: 'blur'
}
]
});
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const saveOrUpdate = isUpdate.value ? updateDictData : addDictData;
// form.dictDataCode = form.dictDataName;
form.dictId = props.dictId;
form.dictDataName = form.dictDataCode;
saveOrUpdate(form)
.then((msg) => {
loading.value = false;
message.success(msg);
// 清除字典缓存
removeSiteInfoCache(form.dictCode + ':' + form.tenantId);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
watch(
() => props.visible,
(visible) => {
if (visible) {
if (props.data) {
assignFields(props.data);
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
formRef.value?.clearValidate();
}
}
);
</script>

View File

@@ -1,223 +0,0 @@
<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<template #extra>
<Extra/>
</template>
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="dictDataId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 800 }"
cache-key="appDictTable"
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined/>
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-space v-if="record.dictDataName !== 'MainPackage'">
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical"/>
<a-popconfirm
placement="topRight"
title="确定要删除此分包吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<dict-edit
v-model:visible="showEdit"
:dictId="dictId"
:data="current"
@done="reload"
/>
</a-page-header>
</template>
<script lang="ts" setup>
import {createVNode, ref} from 'vue';
import {message, Modal} from 'ant-design-vue/es';
import {
PlusOutlined,
DeleteOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import type {EleProTable} from 'ele-admin-pro/es';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import {messageLoading} from 'ele-admin-pro/es';
import DictEdit from './components/dict-edit.vue';
import {
pageDictData,
removeDictData,
removeDictDataBatch
} from '@/api/system/dict-data';
import {DictParam} from '@/api/system/dict/model';
import {DictData} from '@/api/system/dict-data/model';
import {addDict, listDictionaries} from '@/api/system/dict';
import {Dictionary} from '@/api/system/dictionary/model';
import {getPageTitle} from "@/utils/common";
import Extra from "@/views/cms/cmsNavigation/components/extra.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
const dictId = ref(0);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'dictDataId',
width: 80,
hideInTable: true
},
{
title: '分包',
dataIndex: 'dictDataCode',
showSorterTooltip: false
},
// {
// title: '英文名',
// dataIndex: 'dictDataCode',
// showSorterTooltip: false
// },
{
title: '备注',
dataIndex: 'comments',
showSorterTooltip: false
},
{
title: '排序号',
width: 180,
align: 'center',
dataIndex: 'sortNumber'
},
{
title: '操作',
key: 'action',
width: 180,
align: 'center'
}
]);
// 表格选中数据
const selection = ref<DictData[]>([]);
// 当前编辑数据
const current = ref<Dictionary | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 表格数据源
const datasource: DatasourceFunction = ({page, limit, where, orders}) => {
where.dictCode = 'mpPackage';
return pageDictData({...where, ...orders, page, limit});
};
/* 搜索 */
const reload = (where?: DictParam) => {
selection.value = [];
tableRef?.value?.reload({page: 1, where});
};
/* 打开编辑弹窗 */
const openEdit = (row?: DictData) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 删除单个 */
const remove = (row: DictData) => {
const hide = messageLoading('请求中..', 0);
removeDictData(row.dictDataId)
.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 = messageLoading('请求中..', 0);
removeDictDataBatch(selection.value.map((d) => d.dictDataId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// 初始化字典
const loadDict = () => {
listDictionaries({dictCode: 'mpPackage'}).then(async (data) => {
if (data?.length == 0) {
await addDict({dictCode: 'mpPackage', dictName: '链接分包'});
}
await listDictionaries({dictCode: 'mpPackage'}).then((list) => {
list?.map((d) => {
dictId.value = Number(d.dictId);
});
});
});
};
loadDict();
/* 自定义行属性 */
const customRow = (record: DictData) => {
return {
onDblclick: () => {
if (record.dictDataName === 'package') {
openEdit(record);
}
}
};
};
</script>
<script lang="ts">
export default {
name: 'TaskDictData'
};
</script>

View File

@@ -1,281 +0,0 @@
<!-- 编辑弹窗 -->
<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="parentId">
<a-tree-select
allow-clear
:tree-data="pages"
tree-default-expand-all
placeholder="请选择上级分类"
:value="form.parentId || undefined"
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
@update:value="(value?: number) => (form.parentId = value)"
/>
</a-form-item>
<a-form-item label="页面名称" name="title">
<a-input
allow-clear
placeholder="商品详情"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item label="页面路径" name="path" :extra="pathExtra">
<a-input
allow-clear
placeholder="/package/goods/detail"
v-model:value="form.path"
/>
</a-form-item>
<a-form-item label="分包" name="subpackage">
<DictSelect
dict-code="mpPackage"
:placeholder="`选择分包`"
style="width: 200px"
v-model:value="form.subpackage"
@done="chooseSubpackage"
/>
</a-form-item>
<a-form-item label="图标" name="icon">
<SelectFile
:placeholder="`请选择图标`"
:limit="2"
:data="icon"
@done="chooseFile"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="排序" name="sortNumber">
<a-input-number
:min="0"
:max="99999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="备注" name="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 {addCmsMpPages, updateCmsMpPages} from '@/api/cms/cmsMpPages';
import {CmsMpPages} from '@/api/cms/cmsMpPages/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 {DictData} from "@/api/system/dict-data/model";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const {styleResponsive} = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 上级分类id
parentId?: number;
// 分包名称
packageName?: string;
// 修改回显的数据
data?: CmsMpPages | null;
// 页面列表
pages?: CmsMpPages[] | 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 icon = ref<ItemType[]>([]);
const selectedIconPath = ref<ItemType[]>([]);
const pathExtra = ref<string>()
// 用户信息
const form = reactive<CmsMpPages>({
id: undefined,
parentId: undefined,
title: undefined,
path: undefined,
home: undefined,
subpackage: undefined,
icon: undefined,
iconPath: '',
selectedIconPath: '',
sortNumber: 100,
comments: undefined,
status: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
title: [
{
required: true,
type: 'string',
message: '页面名称',
trigger: 'blur'
}
],
path: [
{
required: true,
type: 'string',
message: '请填写路径',
trigger: 'blur'
}
],
subpackage: [
{
required: true,
type: 'string',
message: '请选择分包',
trigger: 'blur'
}
]
});
const chooseFile = (data: FileRecord) => {
icon.value.push({
uid: data.id,
url: data.downloadUrl,
status: 'done'
});
};
const onDeleteItem = (index: number) => {
icon.value.splice(index, 1);
};
const chooseSubpackage = (item: DictData) => {
form.subpackage = item.dictDataCode;
form.path = `/${form.subpackage}/`;
pathExtra.value = `请补填完整的页面路径`
}
const {resetFields} = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form,
icon: JSON.stringify(icon.value)
};
const saveOrUpdate = isUpdate.value ? updateCmsMpPages : addCmsMpPages;
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) {
icon.value = [];
if (props.parentId) {
form.parentId = props.parentId;
}
if (props.data) {
assignObject(form, props.data);
if(props.data.icon){
const arr = JSON.parse(props.data.icon);
arr.map(d => {
icon.value.push({
uid: uuid(),
url: d.url,
status: 'done'
});
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{immediate: true}
);
</script>
<script lang="ts">
import * as icons from '@/layout/menu-icons';
export default {
components: icons,
data() {
return {
iconData: [
{
title: '已引入的图标',
icons: Object.keys(icons)
}
]
};
}
};
</script>

View File

@@ -1,345 +0,0 @@
<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"
:need-page="false"
:expand-icon-column-index="1"
:expanded-row-keys="expandedRowKeys"
tool-class="ele-toolbar-form"
class="sys-org-table"
cache-key="proCmsMpPagesTable"
@done="onDone"
@expand="onExpand"
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined/>
</template>
<span>新建</span>
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="expandAll">
展开
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="foldAll">
折叠
</a-button>
<!-- 搜索表单 -->
<a-input-search
allow-clear
v-model:value="searchText"
placeholder="请输入搜索关键词"
@search="reload"
@pressEnter="reload"
/>
<a-button
type="text"
@click="openUrl('/mp-package')"
>分包管理
</a-button
>
<a-button type="text" class="ele-btn-icon" @click="clearSiteInfoCache">
清除缓存
</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'title'">
{{ record.title }}
</template>
<template v-if="column.key === 'icon'">
<template v-if="record.icon" v-for="(item,index) in JSON.parse(record.icon)">
<a-image v-if="item.url" :id="index" :src="item.url" :width="50"/>
</template>
</template>
<template v-if="column.key === 'path'">
<span class="ele-text-placeholder">{{ record.path }}</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 === 'subpackage'">
<a-tag v-if="record.subpackage === 'pages'" color="orange"
>主包
</a-tag
>
<a-tag v-else> {{ record.subpackage }}</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(null, record.id,record.subpackage)">添加</a>
<!-- <a-divider type="vertical"/>-->
<!-- <a @click="openUrl(`/mp-field/${record.id}`)">参数</a>-->
<!-- <a-divider type="vertical"/>-->
<!-- <a @click="openUrl(`/mp-group/${record.id}`)">组件</a>-->
<!-- <a-divider type="vertical" />-->
<!-- <a @click="openUrl(`/mp-design/${record.id}`)">设计</a>-->
<a-divider type="vertical"/>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical"/>
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
<!-- <template #footer>-->
<!-- <div class="ele-text-secondary"-->
<!-- >页面设计可以替换图标和文字仓库地址http://git.gxwebsoft.com/websoft/nbg-uniapp.git</div-->
<!-- >-->
<!-- </template>-->
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<MpPagesEdit
v-model:visible="showEdit"
:parent-id="parentId"
:packageName="packageName"
:pages="pages"
: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, PlusOutlined} from '@ant-design/icons-vue';
import type {EleProTable, toTreeData} from 'ele-admin-pro';
import {toDateString} from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem, EleProTableDone
} from 'ele-admin-pro/es/ele-pro-table/types';
import MpPagesEdit from './components/mpPagesEdit.vue';
import {
pageCmsMpPages,
removeCmsMpPages,
removeBatchCmsMpPages,
listCmsMpPages
} from '@/api/cms/cmsMpPages';
import type {CmsMpPages, CmsMpPagesParam} from '@/api/cms/cmsMpPages/model';
import {copyText, getPageTitle, openUrl} from '@/utils/common';
import Extra from "@/views/cms/cmsNavigation/components/extra.vue";
import {eachTreeData} from "ele-admin-pro/es";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 页面列表
const pages = ref<CmsMpPages[]>([]);
// 表格选中数据
const selection = ref<CmsMpPages[]>([]);
// 上级分类id
const parentId = ref<number>();
// 当前编辑数据
const current = ref<CmsMpPages | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 表格展开的行
const expandedRowKeys = ref<number[]>([]);
// 当前选中的包
const packageName = ref<any>();
// 表格数据源
const datasource: DatasourceFunction = ({where}) => {
return listCmsMpPages({
...where
});
};
/* 表格渲染完成回调 */
const onDone: EleProTableDone<CmsMpPages> = ({data}) => {
pages.value = data;
};
/* 数据转为树形结构 */
const parseData = (data: CmsMpPages[]) => {
return toTreeData({
data: data.map((d) => {
return {...d, key: d.id, value: d.id};
}),
idField: 'id',
parentIdField: 'parentId'
});
};
/* 展开全部 */
const expandAll = () => {
let keys: number[] = [];
eachTreeData(pages.value, (d) => {
if (d.children && d.children.length && d.id) {
keys.push(d.id);
}
});
expandedRowKeys.value = keys;
};
/* 折叠全部 */
const foldAll = () => {
expandedRowKeys.value = [];
};
/* 点击展开图标时触发 */
const onExpand = (expanded: boolean, record: CmsMpPages) => {
if (expanded) {
expandedRowKeys.value = [
...expandedRowKeys.value,
record.id as number
];
} else {
expandedRowKeys.value = expandedRowKeys.value.filter(
(d) => d !== record.id
);
}
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
width: 80
},
{
title: '页面名称',
dataIndex: 'title',
key: 'title'
},
{
title: '页面路径',
dataIndex: 'path',
key: 'path'
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
sorter: true,
hideInTable: true,
ellipsis: true,
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 280,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsMpPagesParam) => {
selection.value = [];
tableRef?.value?.reload({where: where});
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsMpPages | null, id?: number, mod?: string) => {
current.value = row ?? null;
packageName.value = mod ?? undefined;
parentId.value = id;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsMpPages) => {
const hide = message.loading('请求中..', 0);
removeCmsMpPages(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);
removeBatchCmsMpPages(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: CmsMpPages) => {
return {
// 行点击事件
onClick: () => {
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
import * as MenuIcons from '@/layout/menu-icons';
export default {
name: 'CmsMpPages',
components: MenuIcons
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,276 +0,0 @@
<template>
<a-drawer
width="70%"
:visible="visible"
:title="`${data?.title}`"
placement="left"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
:confirm-loading="loading"
:footer="null"
>
<ele-pro-table
ref="tableRef"
row-key="navigationId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
:categoryId="categoryId"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'isStatus'">
<a-tag v-if="record.isStatus === 1" color="green">开启</a-tag>
<a-tag v-if="record.isStatus === 2" color="red">关闭</a-tag>
</template>
<template v-if="column.key === 'isFree'">
<a-tag v-if="record.isFree === 1" color="green">免费</a-tag>
<a-tag v-if="record.isFree === 2" color="orange">收费</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="moveUp(record)">上移<ArrowUpOutlined /></a>
<a-divider type="vertical" />
<a @click="openEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
<!-- 编辑弹窗 -->
<DesignRecordEdit
v-model:visible="showEdit"
:merchant="data"
:categoryId="categoryId"
:data="current"
@done="reload"
/>
</a-drawer>
</template>
<script lang="ts" setup>
import { createVNode, ref, watch } from 'vue';
import { message, Modal } from 'ant-design-vue';
import {
ArrowUpOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import DesignRecordEdit from './components/designRecordEdit.vue';
import {
removeCmsDesignRecord,
removeBatchCmsDesignRecord,
updateCmsDesignRecord
} from '@/api/cms/cmsDesignRecord';
import type { CmsDesignRecord } from '@/api/cms/cmsDesignRecord/model';
import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
import { pageCmsDesignRecord } from '@/api/cms/cmsDesignRecord';
import { CmsDesignRecordParam } from '@/api/cms/cmsDesignRecord/model';
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
categoryId?: number | null;
// 导航信息
data?: CmsNavigation;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsDesignRecord[]>([]);
// 当前编辑数据
const current = ref<CmsDesignRecord | 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.navigationId = props.categoryId;
return pageCmsDesignRecord({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
key: 'navigationId',
width: 48,
align: 'center',
fixed: 'left',
hideInSetting: true,
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: '组件',
dataIndex: 'title',
key: 'title'
},
{
title: '排序',
dataIndex: 'sortNumber',
key: 'sortNumber',
width: 120,
align: 'center'
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsDesignRecordParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsDesignRecord) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsDesignRecord) => {
const hide = message.loading('请求中..', 0);
removeCmsDesignRecord(row.periodId)
.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);
removeBatchCmsDesignRecord(selection.value.map((d) => d.periodId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// 上移
const moveUp = (row?: CmsDesignRecord) => {
updateCmsDesignRecord({
periodId: row?.periodId,
sortNumber: Number(row?.sortNumber) - 1
}).then((msg) => {
message.success(msg);
reload();
});
};
/* 自定义行属性 */
const customRow = (record: CmsDesignRecord) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
watch(
() => props.categoryId,
(categoryId) => {
if (categoryId) {
reload();
}
}
);
</script>
<script lang="ts">
export default {
name: 'DesignRecord'
};
</script>
<style lang="less" scoped></style>

View File

@@ -64,7 +64,7 @@
<a-textarea
:rows="4"
:maxlength="200"
placeholder="CSS样式"
placeholder="style"
v-model:value="form.style"
/>
<a class="text-sm text-gray-400" href="https://www.tailwindcss.cn/docs/installation" target="_blank">Tailwind Css使用教程</a>

View File

@@ -75,9 +75,8 @@
<!-- />-->
<!-- </a-form-item>-->
<a-form-item
:label="form.model == 'links' ? '链接地址' : '路由地址'"
:label="'path'"
name="path"
v-if="form.model == 'links'"
>
<a-input
allow-clear
@@ -86,10 +85,18 @@
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="css样式" name="style" v-if="isUpdate">
<a-form-item label="code" name="code" v-if="isUpdate">
<a-input
allow-clear
placeholder="CSS"
placeholder="code"
v-model:value="form.code"
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="style" name="style" v-if="isUpdate">
<a-input
allow-clear
placeholder="style"
v-model:value="form.style"
@pressEnter="save"
/>
@@ -252,7 +259,7 @@ const loading = ref(false);
// 已上传数据
const images = ref<ItemType[]>([]);
const password = ref();
const pathPlaceholder = ref<string>('请输入链接地址');
const pathPlaceholder = ref<string>('/pages/index/index');
const lang = ref(localStorage.getItem('i18n-lang'));
const zhCmsNavigationList = ref<CmsNavigation[]>([]);

View File

@@ -1,17 +1,16 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="openEdit()">
<a-button type="primary" class="ele-btn-icon" @click="emit('add')">
<template #icon>
<plus-outlined/>
</template>
<span>新建</span>
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="expandAll">
展开
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="foldAll">
折叠
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="handleExport">备份</a-button>
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="openImport">恢复</a-button>
<a-button type="dashed" @click="openUrl('/website/model')"
>模型管理
</a-button>
<a-divider type="vertical"/>
<a-radio-group v-model:value="position" @change="reload">
@@ -41,23 +40,26 @@
@search="reload"
@pressEnter="reload"
/>
<a-button
type="text"
@click="openUrl('/website/model')"
>模型管理
</a-button
>
<a-button type="text" class="ele-btn-icon" @click="clearSiteInfoCache">
清除缓存
</a-button>
</a-space>
<!-- 导入弹窗 -->
<import v-model:visible="showImport" @done="reload"/>
</template>
<script lang="ts" setup>
import {PlusOutlined} from '@ant-design/icons-vue';
import type {GradeParam} from '@/api/user/grade/model';
import {watch} from 'vue';
import {watch, ref} from 'vue';
import {openUrl} from "@/utils/common";
import {hasRole} from "@/utils/permission";
import {utils, writeFile} from 'xlsx';
import {message} from 'ant-design-vue';
import {listCmsNavigation} from "@/api/cms/cmsNavigation";
import {getTenantId} from "@/utils/domain";
import Import from "./Import.vue";
// 是否显示导入弹窗
const showImport = ref(false);
const searchText = ref('');
const props = withDefaults(
defineProps<{
@@ -70,18 +72,113 @@ const props = withDefaults(
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>
// 表单数据
const where = ref({
keywords: '',
model: '',
position: 0
});
const position = ref(0);
const reload = () => {
// 更新搜索关键词
where.value.keywords = searchText.value;
emit('search', where.value);
};
/* 打开编辑弹窗 */
const openImport = () => {
showImport.value = true;
};
// 导出
const handleExport = async () => {
const array: (string | number)[][] = [
[
'上级id',
'菜单名称',
'模型',
'标识',
'菜单路由地址',
'菜单组件地址',
'打开位置',
'菜单图标',
'banner图片',
'图标颜色',
'是否隐藏',
'可见类型',
'访问密码',
'位置',
'仅在顶部显示',
'仅在底部显示',
'菜单侧栏选中的path',
'其它路由元信息',
'css样式',
'是否推荐',
'排序',
'备注',
'状态'
]
];
// 按搜索结果导出
await listCmsNavigation(where.value)
.then((list) => {
list?.forEach((d) => {
array.push([
`${d.parentId || ''}`,
`${d.title || ''}`,
`${d.model || ''}`,
`${d.code || ''}`,
`${d.path || ''}`,
`${d.component || ''}`,
`${d.target || ''}`,
`${d.icon || ''}`,
`${d.banner || ''}`,
`${d.color || ''}`,
`${d.hide || 0}`,
`${d.permission || 0}`,
`${d.password || ''}`,
`${d.position || 0}`,
`${d.top || 0}`,
`${d.bottom || 0}`,
`${d.active || ''}`,
`${d.meta || ''}`,
`${d.style || ''}`,
`${d.recommend ? 1 : 0}`,
`${d.sortNumber || 0}`,
`${d.comments || ''}`,
`${d.status || 0}`
]);
});
const sheetName = `bak_navigation_${getTenantId()}`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${sheetName}.xlsx`
);
}, 1000);
})
.catch((msg) => {
message.error(msg);
});
};
</script>

View File

@@ -22,17 +22,39 @@
>
<template #toolbar>
<a-space>
<a-button type="primary" class="ele-btn-icon" :disabled="!websiteId" @click="openEdit()">
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined/>
<PlusOutlined/>
</template>
<span>新建</span>
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="expandAll">
展开
</a-button>
<a-button type="dashed" class="ele-btn-icon" @click="foldAll">
折叠
<template v-if="expandedRowKeys.length == 0">
<a-button type="dashed" class="ele-btn-icon" @click="expandAll">
<template #icon>
<PlusSquareOutlined />
</template>
展开
</a-button>
</template>
<template v-else>
<a-button type="dashed" class="ele-btn-icon" @click="foldAll">
<template #icon>
<MinusSquareOutlined />
</template>
折叠
</a-button>
</template>
<a-divider type="vertical"/>
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="handleExport">备份</a-button>
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="openImport">恢复</a-button>
<a-button
type="dashed"
@click="push('/website/model')"
>模型管理
</a-button
>
<a-button type="dashed" class="ele-btn-icon" @click="clearSiteInfoCache">
清除缓存
</a-button>
<a-divider type="vertical"/>
<a-radio-group v-model:value="position" @change="reload">
@@ -40,7 +62,6 @@
<a-radio-button :value="2">底部</a-radio-button>
<a-radio-button :value="0">不限</a-radio-button>
</a-radio-group>
<a-divider type="vertical"/>
<a-select
v-model:value="modelName"
style="width: 150px"
@@ -60,15 +81,6 @@
@search="reload"
@pressEnter="reload"
/>
<a-button
type="text"
@click="push('/website/model')"
>模型管理
</a-button
>
<a-button type="text" class="ele-btn-icon" @click="clearSiteInfoCache">
清除缓存
</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record, index }">
@@ -76,7 +88,7 @@
<a-space>
<a-avatar v-if="record.icon" :size="22" :src="record.icon"/>
<a @click="push({
path: `/website/article`,
path: `/article`,
query: {
id: record.navigationId,
name: record.title,
@@ -212,20 +224,13 @@
:category-id="categoryId"
@done="reload"
/>
<!-- 页面组件弹窗 -->
<Components
v-model:visible="showDesignRecordEdit"
:data="current"
:category-id="categoryId"
@done="reload"
/>
</a-page-header>
</template>
<script lang="ts" setup>
import {ref} from 'vue';
import {message} from 'ant-design-vue/es';
import {PlusOutlined, CopyOutlined, FileWordOutlined} from '@ant-design/icons-vue';
import {PlusOutlined, CopyOutlined, FileWordOutlined, MinusOutlined, MinusSquareOutlined, PlusSquareOutlined} from '@ant-design/icons-vue';
import type {
DatasourceFunction,
ColumnItem,
@@ -242,7 +247,6 @@ import type {EleProTable} from 'ele-admin-pro/es';
import {useI18n} from 'vue-i18n';
import CmsNavigationEdit from './components/navigation-edit.vue';
import DesignEdit from './components/design-edit.vue';
import Components from './components/components.vue';
import {
listCmsNavigation,
removeCmsNavigation
@@ -258,12 +262,12 @@ import Extra from "./components/extra.vue";
import {useRouter} from 'vue-router';
import {listCmsModel} from "@/api/cms/cmsModel";
import {CmsModel} from "@/api/cms/cmsModel/model";
import {hasRole} from "@/utils/permission";
const {push} = useRouter();
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
const modelList = ref<CmsModel[]>([])
const websiteId = localStorage.getItem('WebsiteId')
const currentId = ref<number>();
const modelName = ref<string>();
// 国际化
@@ -367,8 +371,6 @@ const design = ref<CmsDesign>();
const showEdit = ref(false);
// 编辑内容
const showDesignEdit = ref(false);
// 页面组件
const showDesignRecordEdit = ref(false);
// 上级分类id
const parentId = ref<number>();
const categoryId = ref<number>();
@@ -431,6 +433,7 @@ const parseData = (data: CmsNavigation[]) => {
/* 表格渲染完成回调 */
const onDone: EleProTableDone<CmsNavigation> = ({data}) => {
navigationData.value = data;
expandAll()
};
/* 刷新表格 */

View File

@@ -1,625 +0,0 @@
<!-- 编辑弹窗 -->
<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-tabs type="card" v-model:active-key="active" @change="onChange">
<a-tab-pane tab="基本信息" key="base">
<a-form-item label="类型" name="title">
<a-radio-group v-model:value="form.type">
<a-radio-button :value="0"
>产品
</a-radio-button
>
<a-radio-button :value="1"
>插件
</a-radio-button
>
</a-radio-group>
</a-form-item>
<a-form-item label="所属栏目" name="categoryId">
<a-tree-select
allow-clear
:tree-data="navigationList"
tree-default-expand-all
placeholder="请选择栏目"
:value="form.categoryId || undefined"
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
@update:value="(value?: number) => (form.categoryId = value)"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}名称`" name="title">
<a-input
allow-clear
:placeholder="`内容管理系统`"
v-model:value="form.title"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}标识`" name="code">
<a-input
allow-clear
placeholder="cms"
v-model:value="form.code"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}描述`" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="基础模块,包含菜单、角色、用户、字典、支付、云存储、短信等配置"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}图标`" name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}截图`" name="files">
<SelectFile
:placeholder="`请选择视频文件`"
:limit="6"
:data="files"
@done="chooseFile"
@del="onDeleteFile"
/>
</a-form-item>
<template v-if="form.type === 1">
<a-divider style="margin-bottom: 20px"/>
<a-form-item :label="`关联菜单ID`" name="menuId">
<a-input-number
allow-clear
style="width: 220px"
placeholder="请输入管理菜单的ID"
v-model:value="form.menuId"
/>
</a-form-item>
</template>
<!-- <a-form-item :label="`插件入口`" name="path">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="/system/menu"-->
<!-- v-model:value="form.path"-->
<!-- />-->
<!-- </a-form-item>-->
<a-divider style="margin-bottom: 20px"/>
<a-form-item label="单位" name="unitName">
<a-input
allow-clear
style="width: 220px"
placeholder="(套)"
v-model:value="form.unitName"
/>
</a-form-item>
<a-form-item label="价格" name="price">
<a-input-number
:min="0"
allow-clear
style="width: 220px"
placeholder="请输入销售价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="库存" name="stock">
<a-input-number
allow-clear
style="width: 220px"
placeholder="请输入库存"
v-model:value="form.stock"
/>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
style="width: 220px"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
<a-form-item label="交付方式" name="deliveryMethod">
<a-radio-group v-model:value="form.deliveryMethod">
<a-radio-button :value="0"
>不启用
</a-radio-button
>
<a-radio-button :value="1"
>SaaS交付
</a-radio-button
>
<a-radio-button :value="2"
>源码交付
</a-radio-button
>
</a-radio-group>
<!-- <a-space>-->
<!-- <div><a-switch v-model:checked="form.deliveryMethod" /></div>-->
<!-- <template v-if="form.deliveryMethod">-->
<!-- <span class="text-gray-400 px-4">字典名称deliveryMethod</span>-->
<!-- </template>-->
<!-- </a-space>-->
</a-form-item>
<a-form-item label="计费方式" name="durationMethod">
<a-radio-group v-model:value="form.durationMethod">
<a-radio-button :value="0"
>一次性
</a-radio-button
>
<a-radio-button :value="1"
>按年
</a-radio-button
>
<a-radio-button :value="2"
>按月
</a-radio-button
>
<a-radio-button :value="3"
>按天
</a-radio-button
>
</a-radio-group>
</a-form-item>
<a-form-item label="最多可购买数" name="canBuyNumber">
<a-input-number
allow-clear
style="width: 220px"
:min="1"
placeholder="最多可购买数量"
v-model:value="form.canBuyNumber"
/>
</a-form-item>
<a-form-item label="标签" name="tag">
<a-radio-group v-model:value="form.tag">
<a-radio-button value="0"
>不显示
</a-radio-button
>
<a-radio-button value="1"
>免费
</a-radio-button
>
<a-radio-button value="2"
>开源
</a-radio-button
>
<a-radio-button value="3"
>付费
</a-radio-button
>
</a-radio-group>
</a-form-item>
<a-form-item label="是否官方自营" name="official">
<a-switch
checked-children=""
un-checked-children=""
:checked="form.official"
@update:checked="updateOfficial"
/>
</a-form-item>
<a-form-item :label="`${form.type == 0 ? '产品' : '插件'}详情`" name="content">
<!-- 编辑器 -->
<tinymce-editor
ref="editorRef"
class="content"
v-model:value="content"
:disabled="disabled"
:init="config"
placeholder="图片直接粘贴自动上传"
@paste="onPaste"
/>
</a-form-item>
</a-tab-pane>
<template v-if="isUpdate">
<a-tab-pane tab="产品规格" key="spec">
<Spec :productId="form.productId"/>
</a-tab-pane>
<a-tab-pane tab="链接管理" key="links">
<CmsProductUrl :productId="form.productId"/>
</a-tab-pane>
<a-tab-pane tab="产品参数" key="parameter">
<CmsProductParameter :productId="form.productId"/>
</a-tab-pane>
<a-tab-pane tab="评论管理" key="comment">
<CmsProductComment :productId="form.productId"/>
</a-tab-pane>
</template>
</a-tabs>
</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 {addCmsProduct, updateCmsProduct} from '@/api/cms/cmsProduct';
import {CmsProduct} from '@/api/cms/cmsProduct/model';
import {useThemeStore} from '@/store/modules/theme';
import {storeToRefs} from 'pinia';
import {FormInstance, RuleObject} 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 TinymceEditor from "@/components/TinymceEditor/index.vue";
import {uploadFile, uploadOss} from "@/api/system/file";
// import Spec from './spec.vue';
import CmsProductUrl from '@/views/cms/cmsProductUrl/index.vue';
import CmsProductParameter from '@/views/cms/cmsProductParameter/index.vue';
import CmsProductComment from '@/views/cms/cmsProductComment/index.vue';
import {Navigation} from "@/api/cms/navigation/model";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const {styleResponsive} = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: CmsProduct | null;
// 栏目数据
navigationList?: Navigation[];
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
const content = ref('');
const disabled = ref(false);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
const images = ref<ItemType[]>([]);
const files = ref<ItemType[]>([]);
// 当前选项卡
const active = ref('base');
// 用户信息
const form = reactive<CmsProduct>({
productId: undefined,
type: 0,
code: undefined,
title: undefined,
image: undefined,
content: undefined,
parentId: 0,
parentName: '',
categoryId: 0,
categoryName: '',
menuId: 0,
path: undefined,
tag: undefined,
specs: undefined,
position: undefined,
unitName: undefined,
price: undefined,
salePrice: undefined,
deductStockType: undefined,
deliveryMethod: undefined,
durationMethod: 0,
serverMethod: undefined,
packageMethod: undefined,
canBuyNumber: 1,
files: undefined,
sales: undefined,
stock: 1000,
official: undefined,
gainIntegral: undefined,
recommend: undefined,
merchantId: undefined,
isShow: undefined,
status: undefined,
userId: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
categoryId: [
{
required: true,
type: 'number',
message: '请所属栏目',
trigger: 'blur'
}
],
title: [
{
required: true,
type: 'string',
message: '请填写产品名称',
trigger: 'blur'
}
],
code: [
{
required: true,
type: 'string',
message: '请填写产品/插件标识',
trigger: 'blur'
}
],
menuId: [
{
required: true,
type: 'number',
message: '请选择菜单ID',
trigger: 'blur'
}
],
path: [
{
required: true,
type: 'string',
message: '请填写插件入口地址',
trigger: 'blur'
}
],
price: [
{
required: true,
type: 'number',
message: '请填写产品价格',
trigger: 'blur'
}
],
stock: [
{
required: true,
type: 'number',
message: '请填写库存数量',
trigger: 'blur'
}
],
unitName: [
{
required: true,
type: 'string',
message: '请填写单位名称',
trigger: 'blur'
}
],
content: [
{
required: true,
type: "string",
message: "请输入产品详情",
trigger: "blur",
validator: async (_rule: RuleObject, value: string) => {
if (content.value == "") {
return Promise.reject("请输入文字内容");
}
return Promise.resolve();
}
}
],
comments: [
{
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 chooseFile = (data: FileRecord) => {
files.value.push({
uid: data.id,
url: data.url,
status: 'done'
});
};
const onDeleteFile = (index: number) => {
files.value.splice(index, 1);
};
const updateOfficial = () => {
form.official = !form.official;
}
const onChange = () => {
// 加载多规格
form.productId = props.data?.productId
};
const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
const config = ref({
height: 500,
images_upload_handler: (blobInfo, success, error) => {
const file = blobInfo.blob();
const formData = new FormData();
formData.append('file', file, file.name);
uploadOss(file).then(res => {
success(res.path)
}).catch((msg) => {
error(msg);
})
},
// 自定义文件上传(这里使用把选择的文件转成 blob 演示)
file_picker_callback: (callback: any, _value: any, meta: any) => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
// 设定文件可选类型
if (meta.filetype === 'image') {
input.setAttribute('accept', 'image/*');
} else if (meta.filetype === 'media') {
input.setAttribute('accept', 'video/*,.pdf');
}
input.onchange = () => {
const file = input.files?.[0];
if (!file) {
return;
}
if (meta.filetype === 'media') {
if (file.size / 1024 / 1024 > 200) {
editorRef.value?.alert({content: '大小不能超过 200MB'});
return;
}
if (file.type.startsWith('application/pdf')) {
uploadOss(file).then(res => {
const addPath = `<a href="${res.downloadUrl}" target="_blank">${res.name}</a>`;
content.value = content.value + addPath
})
return;
}
if (!file.type.startsWith('video/')) {
editorRef.value?.alert({content: '只能选择视频文件'});
return;
}
uploadOss(file).then(res => {
callback(res.path)
});
}
};
input.click();
}
});
/* 粘贴图片上传服务器并插入编辑器 */
const onPaste = (e) => {
const items = (e.clipboardData || e.originalEvent.clipboardData).items;
let hasFile = false;
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
let file = items[i].getAsFile();
const item: ItemType = {
file,
uid: (file as any).lastModified,
name: file.name
};
uploadFile(<File>item.file)
.then((result) => {
const addPath = `<p><img class="content-img" src="${result.url}"></p>`;
content.value = content.value + addPath
})
.catch((e) => {
message.error(e.message);
});
hasFile = true;
}
}
if (hasFile) {
e.preventDefault();
}
}
const {resetFields} = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form,
content: content.value,
files: JSON.stringify(files.value),
};
const saveOrUpdate = isUpdate.value ? updateCmsProduct : addCmsProduct;
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 = [];
files.value = [];
content.value = '';
if (props.data) {
assignObject(form, props.data);
if (props.data.image) {
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
});
}
if (props.data.files) {
files.value = JSON.parse(props.data.files);
}
if (props.data.content) {
content.value = props.data.content
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{immediate: true}
);
</script>

View File

@@ -1,190 +0,0 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
<a-button
danger
type="primary"
class="ele-btn-icon"
:disabled="selection?.length === 0"
@click="removeBatch"
>
<template #icon>
<DeleteOutlined />
</template>
<span>批量删除</span>
</a-button>
<a-radio-group v-model:value="where.official" @change="handleSearch">
<a-radio-button :value="1"
>自营
</a-radio-button
>
<a-radio-button :value="0"
>市场
</a-radio-button
>
</a-radio-group>
<a-radio-group v-model:value="type" @change="handleSearch">
<a-radio-button :value="0"
>产品</a-radio-button
>
<a-radio-button :value="1"
>插件</a-radio-button
>
</a-radio-group>
<a-radio-group v-model:value="type" @change="handleSearch">
<a-radio-button value="已发布"
>已发布({{ articleCount?.totalNum }})</a-radio-button
>
<a-radio-button value="待审核"
>待审核({{ articleCount?.totalNum2 }})</a-radio-button
>
<a-radio-button value="已驳回"
>已驳回({{ articleCount?.totalNum3 }})</a-radio-button
>
</a-radio-group>
<a-tree-select
allow-clear
:tree-data="navigationList"
tree-default-expand-all
style="width: 280px"
placeholder="请选择栏目"
:value="where.categoryId || undefined"
:dropdown-style="{ maxHeight: '360px', 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"
@pressEnter="reload"
@search="reload"
/>
<a-button @click="reset">重置</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { ref, watch } from 'vue';
import type { ArticleCount } from '@/api/cms/article/model';
import useSearch from '@/utils/use-search';
import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
import { getCount } from '@/api/cms/cmsProduct';
import { CmsProductParam } from '@/api/cms/cmsProduct/model';
import { listCmsNavigation } from '@/api/cms/cmsNavigation';
import { toTreeData } from 'ele-admin-pro';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
merchantId?: number;
navigationList?: CmsNavigation[];
categoryId?: number;
model?: string;
}>(),
{}
);
const type = ref<string>();
// 统计数据
const articleCount = ref<ArticleCount>();
// 栏目数据
const navigationList = ref<CmsNavigation[]>();
// 表单数据
const { where, resetFields } = useSearch<CmsProductParam>({
productId: undefined,
type: undefined,
official: undefined,
status: undefined,
keywords: ''
});
const emit = defineEmits<{
(e: 'search', where?: CmsProductParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
const handleSearch = (e) => {
const text = e.target.value;
if (text === '已发布') {
where.status = 0;
}
if (text === '待审核') {
where.status = 1;
}
if (text === '已驳回') {
where.status = 2;
}
where.type = text
emit('search', where);
};
const reload = () => {
emit('search', where);
};
// 按分类查询
const onCategoryId = (id: number) => {
where.categoryId = id;
emit('search', where);
};
/* 重置 */
const reset = () => {
resetFields();
type.value = undefined;
reload();
};
// 加载栏目数据
if (!navigationList.value) {
listCmsNavigation({}).then((res) => {
navigationList.value = toTreeData({
data: res?.map((d) => {
d.value = d.navigationId;
d.label = d.title;
return d;
}),
idField: 'navigationId',
parentIdField: 'parentId'
});
});
}
// 统计数据
getCount(where).then((data: any) => {
articleCount.value = data;
});
watch(
() => props.merchantId,
() => {
if (props.categoryId) {
where.categoryId = props.categoryId;
}
reload();
},
{ immediate: true }
);
</script>

View File

@@ -1,222 +0,0 @@
<!-- 搜索表单 -->
<template>
<a-form-item label="交付方式" name="specs">
<a-radio-group v-model:value="form.specs">
<a-radio :value="0">单规格</a-radio>
</a-radio-group>
</a-form-item>
<a-radio-group v-model:value="form.deliveryMethod">
<a-radio-button :value="2"
>不限
</a-radio-button
>
<a-radio-button :value="0"
>SaaS交付
</a-radio-button
>
<a-radio-button :value="1"
>源码交付
</a-radio-button
>
</a-radio-group>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue';
import type {ArticleCount} from '@/api/cms/article/model';
import useSearch from '@/utils/use-search';
import {CmsNavigation} from '@/api/cms/cmsNavigation/model';
import {getCount} from '@/api/cms/cmsProduct';
import {CmsProduct, CmsProductParam} from '@/api/cms/cmsProduct/model';
import {listCmsNavigation} from '@/api/cms/cmsNavigation';
import {toTreeData} from 'ele-admin-pro';
import {CmsSpecValue} from "@/api/cms/cmsSpecValue/model";
import {GoodsSku} from "@/api/shop/goodsSku/model";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
merchantId?: number;
navigationList?: CmsNavigation[];
categoryId?: number;
model?: string;
form?: CmsProduct;
}>(),
{}
);
const type = ref<string>();
// 统计数据
const articleCount = ref<ArticleCount>();
// 栏目数据
const navigationList = ref<CmsNavigation[]>();
const spec = ref<CmsSpecValue[]>([]);
const skuList = ref<GoodsSku[]>([]);
// 表单数据
const {where, resetFields} = useSearch<CmsProductParam>({
productId: undefined,
type: undefined,
status: undefined,
keywords: ''
});
const emit = defineEmits<{
(e: 'search', where?: CmsProductParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 用户信息
const form = reactive<CmsProduct>({
productId: undefined,
type: undefined,
code: undefined,
title: undefined,
image: undefined,
content: undefined,
parentId: undefined,
categoryId: 661,
menuId: undefined,
path: undefined,
specs: 0,
position: undefined,
unitName: undefined,
price: 0,
salePrice: undefined,
deductStockType: undefined,
files: undefined,
sales: undefined,
stock: undefined,
gainIntegral: undefined,
recommend: undefined,
merchantId: undefined,
isShow: undefined,
status: undefined,
userId: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
comments: '',
sortNumber: 100
});
// 新增
const add = () => {
emit('add');
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
const handleSearch = (e) => {
const text = e.target.value;
if (text === '已发布') {
where.status = 0;
}
if (text === '待审核') {
where.status = 1;
}
if (text === '已驳回') {
where.status = 2;
}
where.type = text
emit('search', where);
};
const reload = () => {
emit('search', where);
};
const chooseSkuImage = (data: FileRecord) => {
const index = data?.index;
skuList.value[index].images?.push({
uid: uuid(),
url: data.path,
status: 'done'
});
skuList.value[index].image = data.path;
}
const onDeleteSkuItem = (index: number) => {
images.value.splice(index, 1);
};
const onChange = (text: string) => {
// 加载商品多规格
if (text == 'spec') {
const goodsId = props.data?.goodsId;
if (goodsId) {
listGoodsSpec({goodsId}).then(data => {
const specValue = data[0].specValue;
if (specValue) {
spec.value = JSON.parse(specValue).map(d => {
console.log(d);
return {
value: d.value,
detail: d.detail
};
})
}
console.log(spec.value);
})
listGoodsSku({goodsId}).then(data => {
skuList.value = data;
})
}
}
};
const onSpec = (row: CmsSpec) => {
form.specName = row.specName;
goodsSpec.value = row;
if (row.specValue) {
spec.value = JSON.parse(row?.specValue);
}
}
/* 重置 */
const reset = () => {
resetFields();
type.value = undefined;
reload();
};
// 加载栏目数据
if (!navigationList.value) {
listCmsNavigation({}).then((res) => {
navigationList.value = toTreeData({
data: res?.map((d) => {
d.value = d.navigationId;
d.label = d.title;
return d;
}),
idField: 'navigationId',
parentIdField: 'parentId'
});
});
}
// 统计数据
getCount(where).then((data: any) => {
articleCount.value = data;
});
watch(
() => props.merchantId,
() => {
if (props.categoryId) {
where.categoryId = props.categoryId;
}
reload();
},
{immediate: true}
);
</script>

View File

@@ -1,356 +0,0 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="productId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
v-model:selection="selection"
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 === 'title'">
<span
class="cursor-pointer"
@click="openSpmUrl(`/item`, record, record.productId)"
>{{ record.title }}</span
>
</template>
<template v-if="column.key ==='categoryName'">
<span class="cursor-pointer" @click="openSpmUrl(`/product`,record,record.categoryId, true)">{{ record.categoryName }}</span>
</template>
<template v-if="column.key === 'price'">
<span class="text-orange-500">{{ record.price }}</span>
</template>
<template v-if="column.key === 'salePrice'">
<span class="text-orange-500">{{ record.salePrice }}</span>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green" class="cursor-pointer" @click="updateStatus(record)">
上架
</a-tag>
<a-tag v-if="record.status === 1" color="red" class="cursor-pointer" @click="updateStatus(record)">下架
</a-tag>
</template>
<template v-if="column.key === 'recommend'">
<a-space @click="onRecommend(record)">
<span v-if="record.recommend === 1" class="ele-text-success"
><CheckOutlined
/></span>
<span v-else class="ele-text-placeholder"><CloseOutlined/></span>
</a-space>
</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>
<!-- 编辑弹窗 -->
<CmsProductEdit
v-model:visible="showEdit"
:data="current"
:navigationList="navigationList"
@done="reload"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import {createVNode, ref} from 'vue';
import {message, Modal} from 'ant-design-vue';
import {CheckOutlined, CloseOutlined, ExclamationCircleOutlined} from '@ant-design/icons-vue';
import type {EleProTable, toTreeData} 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 CmsProductEdit from './components/cmsProductEdit.vue';
import {
pageCmsProduct,
removeCmsProduct,
removeBatchCmsProduct, updateCmsProduct
} from '@/api/cms/cmsProduct';
import type {CmsProduct, CmsProductParam} from '@/api/cms/cmsProduct/model';
import {openSpmUrl} from '@/utils/common';
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
import {listCmsNavigation} from "@/api/cms/cmsNavigation";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProduct[]>([]);
// 当前编辑数据
const current = ref<CmsProduct | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 加载状态
const loading = ref(true);
// 栏目数据
const navigationList = ref<CmsNavigation[]>();
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
if (filters) {
where.status = filters.status;
}
return pageCmsProduct({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '编号',
dataIndex: 'productId',
key: 'productId',
align: 'center',
width: 90
},
{
title: '产品名称',
dataIndex: 'title',
key: 'title',
width: 280
},
{
title: '封面图',
dataIndex: 'image',
key: 'image',
align: 'center'
},
{
title: '所属栏目',
dataIndex: 'categoryName',
align: 'center',
key: 'categoryName'
},
{
title: '产品编码',
dataIndex: 'code',
key: 'code',
hideInTable: true,
align: 'center'
},
{
title: '单位',
dataIndex: 'unitName',
key: 'unitName',
align: 'center'
},
{
title: '进货价格',
dataIndex: 'price',
key: 'price',
align: 'center',
hideInTable: true
},
{
title: '销售价格',
dataIndex: 'salePrice',
key: 'salePrice',
align: 'center'
},
{
title: '销量',
dataIndex: 'sales',
key: 'sales',
align: 'center'
},
{
title: '推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center'
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center'
},
{
title: '排序',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center'
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsProductParam) => {
selection.value = [];
tableRef?.value?.reload({where: where});
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProduct) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProduct) => {
const hide = message.loading('请求中..', 0);
removeCmsProduct(row.productId)
.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);
removeBatchCmsProduct(selection.value.map((d) => d.productId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
const onRecommend = (row: CmsProduct) => {
updateCmsProduct({
...row,
recommend: row.recommend == 1 ? 0 : 1
}).then((msg) => {
message.success(msg);
reload();
});
};
const updateStatus = (item: CmsProduct) => {
item.status = item.status === 1 ? 0 : 1
updateCmsProduct(item).then(res => {
message.success(res);
})
}
/* 查询 */
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;
return d;
}),
idField: 'navigationId',
parentIdField: 'parentId'
});
});
}
};
/* 自定义行属性 */
const customRow = (record: CmsProduct) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProduct'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,182 +0,0 @@
<!-- 编辑弹窗 -->
<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="nickname">
{{ form.nickname }}
</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="1">精选</a-radio>
<a-radio :value="0">普通</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 { addCmsProductComment, updateCmsProductComment } from '@/api/cms/cmsProductComment';
import { CmsProductComment } from '@/api/cms/cmsProductComment/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?: CmsProductComment | 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<CmsProductComment>({
id: undefined,
productId: undefined,
userId: undefined,
nickname: undefined,
avatar: undefined,
image: undefined,
tenantId: undefined,
createTime: undefined,
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
cmsProductCommentName: [
{
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 ? updateCmsProductComment : addCmsProductComment;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -1,68 +0,0 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-input-search
allow-clear
placeholder="请输入关键词"
v-model:value="where.keywords"
@pressEnter="search"
@search="search"
/>
<a-button
danger
type="primary"
class="ele-btn-icon"
:disabled="selection?.length === 0"
@click="removeBatch"
>
<template #icon>
<DeleteOutlined />
</template>
<span>批量删除</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import {watch} from 'vue';
import {CmsProductCommentParam} from "@/api/cms/cmsProductComment/model";
import useSearch from "@/utils/use-search";
import {DeleteOutlined} from "@ant-design/icons-vue";
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: CmsProductCommentParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 表单数据
const { where } = useSearch<CmsProductCommentParam>({
keywords: '',
userId: undefined
});
// 新增
const search = () => {
emit('search',where);
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
watch(
() => props.selection,
() => {
}
);
</script>

View File

@@ -1,247 +0,0 @@
<template>
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
v-model:selection="selection"
:customRow="customRow"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'nickname'">
<a-space class="flex ">
<span>{{ record.nickname }}</span>
</a-space>
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 1" color="green">精选</a-tag>
<a-tag v-if="record.status === 0">隐藏</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>
<!-- 编辑弹窗 -->
<CmsProductCommentEdit v-model:visible="showEdit" :data="current" @done="reload" />
</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, toTreeData} 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 CmsProductCommentEdit from './components/cmsProductCommentEdit.vue';
import {
removeCmsProductComment,
removeBatchCmsProductComment,
listCmsProductComment, pageCmsProductComment
} from '@/api/cms/cmsProductComment';
import type { CmsProductComment, CmsProductCommentParam } from '@/api/cms/cmsProductComment/model';
const props = withDefaults(
defineProps<{
productId?: number;
}>(),
{}
);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductComment[]>([]);
// 当前编辑数据
const current = ref<CmsProductComment | 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;
}
if(props.productId){
where.productId = props.productId;
}
return pageCmsProductComment({
...where,
...orders,
page,
limit
});
};
/* 数据转为树形结构 */
const parseData = (data: CmsProductComment[]) => {
return toTreeData({
data: data?.map((d) => {
return { ...d, key: d.userId, value: d.userId };
}),
idField: 'userId',
parentIdField: 'parentId'
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '昵称',
dataIndex: 'nickname',
key: 'nickname',
align: 'center',
},
{
title: '评论内容',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '精选',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '评论时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsProductCommentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductComment) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductComment) => {
const hide = message.loading('请求中..', 0);
removeCmsProductComment(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);
removeBatchCmsProductComment(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: CmsProductComment) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductComment'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,217 +0,0 @@
<template>
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:need-page="false"
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>
<!-- 编辑弹窗 -->
<CmsProductParameterEdit v-model:visible="showEdit" :data="current" :productId="productId" @done="reload"/>
</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 CmsProductParameterEdit from './components/cmsProductParameterEdit.vue';
import {
pageCmsProductParameter,
removeCmsProductParameter,
removeBatchCmsProductParameter
} from '@/api/cms/cmsProductParameter';
import type {CmsProductParameter, CmsProductParameterParam} from '@/api/cms/cmsProductParameter/model';
const props = withDefaults(
defineProps<{
productId?: number;
}>(),
{}
);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductParameter[]>([]);
// 当前编辑数据
const current = ref<CmsProductParameter | 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.productId = props.productId;
return pageCmsProductParameter({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '参数名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '参数内容',
dataIndex: 'value',
key: 'value',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsProductParameterParam) => {
selection.value = [];
tableRef?.value?.reload({where: where});
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductParameter) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductParameter) => {
const hide = message.loading('请求中..', 0);
removeCmsProductParameter(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);
removeBatchCmsProductParameter(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: CmsProductParameter) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductParameter'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,197 +0,0 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="800"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑规格值' : '添加规格值'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
:wrapper-col="
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="规格组ID" name="specId">
<a-input
allow-clear
placeholder="请输入规格组ID"
v-model:value="form.specId"
/>
</a-form-item>
<a-form-item label="规格值" name="specValue">
<a-input
allow-clear
placeholder="请输入规格值"
v-model:value="form.specValue"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入描述"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import { addCmsProductSpecValue, updateCmsProductSpecValue } from '@/api/cms/cmsProductSpecValue';
import { CmsProductSpecValue } from '@/api/cms/cmsProductSpecValue/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?: CmsProductSpecValue | 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<CmsProductSpecValue>({
specValueId: undefined,
specId: undefined,
specValue: undefined,
comments: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
cmsProductSpecValueId: undefined,
cmsProductSpecValueName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
cmsProductSpecValueName: [
{
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 ? updateCmsProductSpecValue : addCmsProductSpecValue;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignObject(form, props.data);
if(props.data.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>

View File

@@ -1,239 +0,0 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsProductSpecValueId"
: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>
<!-- 编辑弹窗 -->
<CmsProductSpecValueEdit 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 CmsProductSpecValueEdit from './components/cmsProductSpecValueEdit.vue';
import { pageCmsProductSpecValue, removeCmsProductSpecValue, removeBatchCmsProductSpecValue } from '@/api/cms/cmsProductSpecValue';
import type { CmsProductSpecValue, CmsProductSpecValueParam } from '@/api/cms/cmsProductSpecValue/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductSpecValue[]>([]);
// 当前编辑数据
const current = ref<CmsProductSpecValue | 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 pageCmsProductSpecValue({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '规格值ID',
dataIndex: 'specValueId',
key: 'specValueId',
align: 'center',
width: 90,
},
{
title: '规格组ID',
dataIndex: 'specId',
key: 'specId',
align: 'center',
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsProductSpecValueParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductSpecValue) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductSpecValue) => {
const hide = message.loading('请求中..', 0);
removeCmsProductSpecValue(row.cmsProductSpecValueId)
.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);
removeBatchCmsProductSpecValue(selection.value.map((d) => d.cmsProductSpecValueId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsProductSpecValue) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductSpecValue'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,218 +0,0 @@
<template>
<ele-pro-table
ref="tableRef"
row-key="cmsProductUrlId"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:need-page="false"
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 === 'qrcode'">
<a-image :src="record.qrcode" :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>
<!-- 编辑弹窗 -->
<CmsProductUrlEdit v-model:visible="showEdit" :data="current" :productId="productId" @done="reload" />
</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 CmsProductUrlEdit from './components/cmsProductUrlEdit.vue';
import { pageCmsProductUrl, removeCmsProductUrl, removeBatchCmsProductUrl } from '@/api/cms/cmsProductUrl';
import type { CmsProductUrl, CmsProductUrlParam } from '@/api/cms/cmsProductUrl/model';
const props = withDefaults(
defineProps<{
productId?: number;
}>(),
{}
);
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductUrl[]>([]);
// 当前编辑数据
const current = ref<CmsProductUrl | 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.productId = props.productId;
return pageCmsProductUrl({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '名称',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '内容',
dataIndex: 'domain',
key: 'domain',
align: 'center',
},
{
title: '二维码',
dataIndex: 'qrcode',
key: 'qrcode',
align: 'center',
},
{
title: '操作',
key: 'action',
width: 120,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsProductUrlParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductUrl) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductUrl) => {
const hide = message.loading('请求中..', 0);
removeCmsProductUrl(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);
removeBatchCmsProductUrl(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: CmsProductUrl) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductUrl'
};
</script>
<style lang="less" scoped></style>

View File

@@ -1,231 +0,0 @@
<template>
<ele-pro-table
ref="tableRef"
row-key="cmsSpecId"
: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 === 'specValue'">
<a-space direction="vertical">
<template
v-for="(item, index) in JSON.parse(record.specValue)"
:key="index"
>
<div class="text-left">
<span class="text-gray-400 mr-2">{{ item.value }} :</span>
<ele-tag
shape="round"
size="small"
v-for="(sub, subIndex) in item.detail"
:key="subIndex"
>
{{ sub }}
</ele-tag>
</div>
</template>
</a-space>
</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>
<!-- 编辑弹窗 -->
<CmsSpecEdit v-model:visible="showEdit" :data="current" @done="reload" />
</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 CmsSpecEdit from './components/cmsSpecEdit.vue';
import { pageCmsSpec, removeCmsSpec, removeBatchCmsSpec } from '@/api/cms/cmsSpec';
import type { CmsSpec, CmsSpecParam } from '@/api/cms/cmsSpec/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsSpec[]>([]);
// 当前编辑数据
const current = ref<CmsSpec | 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 pageCmsSpec({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '规格名称',
dataIndex: 'specName',
key: 'specName',
align: 'center',
},
{
title: '规格值',
dataIndex: 'specValue',
key: 'specValue',
align: 'center',
},
// {
// title: '备注',
// dataIndex: 'comments',
// key: 'comments',
// align: 'center',
// },
{
title: '操作',
key: 'action',
width: 180,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: CmsSpecParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsSpec) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsSpec) => {
const hide = message.loading('请求中..', 0);
removeCmsSpec(row.specId)
.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);
removeBatchCmsSpec(selection.value.map((d) => d.specId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsSpec) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsSpec'
};
</script>
<style lang="less" scoped></style>

View File

@@ -49,13 +49,13 @@
</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="AppSecret" name="websiteSecret" v-if="form.type == 20">-->
<!-- <a-input-password-->
<!-- allow-clear-->
<!-- placeholder="请输入AppSecret"-->
<!-- v-model:value="form.websiteSecret"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="小程序描述" name="comments">
<a-textarea
:rows="4"
@@ -64,9 +64,13 @@
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="账号类型" name="type">
{{ form.websiteType }}
</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="avatar">
<SelectFile
:placeholder="`请选择图片`"
@@ -140,6 +144,7 @@ import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types';
import {FileRecord} from '@/api/system/file/model';
import {updateCmsDomain} from '@/api/cms/cmsDomain';
import {updateTenant} from "@/api/system/tenant";
import {decrypt, encrypt} from "@/utils/common";
// 是否是修改
const isUpdate = ref(false);
@@ -177,6 +182,7 @@ const form = reactive<CmsWebsite>({
websiteLogo: undefined,
websiteName: undefined,
websiteCode: undefined,
websiteSecret: undefined,
type: 20,
files: undefined,
keywords: '',
@@ -243,6 +249,14 @@ const rules = reactive({
trigger: 'blur'
}
],
websiteSecret: [
{
required: true,
type: 'string',
message: '请填写小程序密钥',
trigger: 'blur'
}
],
adminUrl: [
{
required: true,
@@ -326,6 +340,7 @@ const save = () => {
...form,
type: 20,
adminUrl: `mp.websoft.top`,
websiteSecret: form.websiteSecret ? encrypt(form.websiteSecret) : undefined,
files: JSON.stringify(files.value),
};
saveOrUpdate(formData)
@@ -387,6 +402,9 @@ watch(
if (props.data.websiteCode) {
oldDomain.value = props.data.websiteCode;
}
if(props.data.websiteSecret){
form.websiteSecret = decrypt(props.data.websiteSecret);
}
isUpdate.value = true;
} else {
isUpdate.value = false;

View File

@@ -19,12 +19,13 @@
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'websiteLogo'">
<a-image :src="record.websiteLogo" :width="50"/>
<a-image :src="record.websiteLogo" :width="50" fallback="https://file.wsdns.cn/20230218/550e610d43334dd2a7f66d5b20bd58eb.svg"/>
</template>
<template v-if="column.key === 'websiteName'">
<div class="font-medium">{{ record.websiteName }}</div>
</template>
<template v-if="column.key === 'websiteCode'">
<div class="text-gray-400">{{ record.tenantId }}</div>
<div class="text-gray-400">
{{ record.websiteCode }}
</div>
@@ -74,11 +75,11 @@
<a-tag v-if="record.status > 0 && record.soon < 0" color="orange">即将过期</a-tag>
</template>
<template v-if="column.key === 'action'">
<a @click="onShare(record)" class="text-green-600">
<QrcodeOutlined />
二维码
</a>
<a-divider type="vertical"/>
<!-- <a @click="onShare(record)" class="text-green-600">-->
<!-- <QrcodeOutlined />-->
<!-- 二维码-->
<!-- </a>-->
<!-- <a-divider type="vertical"/>-->
<a @click="openEdit(record)">
编辑
</a>
@@ -107,16 +108,16 @@
<WebsiteEdit v-model:visible="showEdit" :data="current" @done="reload"/>
<!-- 二维码 -->
<Qrcode v-model:visible="showQrcode" :data="`${qrcode}`" @done="hideShare" title="二维码"/>
<!-- <Qrcode v-model:visible="showQrcode" :data="`${qrcode}`" @done="hideShare" title="二维码"/>-->
</a-spin>
</a-page-header>
</template>
<script lang="ts" setup>
import {createVNode, ref} from 'vue';
import {message, Modal} from 'ant-design-vue';
import {ExclamationCircleOutlined, QrcodeOutlined} from '@ant-design/icons-vue';
import {ref} from 'vue';
import {message} from 'ant-design-vue';
// import {QrcodeOutlined} from '@ant-design/icons-vue';
import type {EleProTable} from 'ele-admin-pro';
import {toDateString} from 'ele-admin-pro';
import type {
@@ -124,11 +125,9 @@ import type {
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import WebsiteEdit from './components/websiteEdit.vue';
import Qrcode from '@/components/QrCode/index.vue';
// import Qrcode from '@/components/QrCode/index.vue';
import {
pageCmsWebsite,
removeCmsWebsite,
removeBatchCmsWebsite,
updateCmsWebsite
} from '@/api/cms/cmsWebsite';
import type {CmsWebsite, CmsWebsiteParam} from '@/api/cms/cmsWebsite/model';
@@ -148,8 +147,6 @@ const selection = ref<CmsWebsite[]>([]);
const current = ref<CmsWebsite | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 是否显示二维码
const showQrcode = ref(false);
// 二维码内容
@@ -181,9 +178,9 @@ const datasource: DatasourceFunction = ({
// 表格列配置
const columns = ref<ColumnItem[]>([
// {
// title: 'ID',
// dataIndex: 'websiteId',
// key: 'websiteId',
// title: 'AppID',
// dataIndex: 'tenantId',
// key: 'tenantId',
// width: 90
// },
{
@@ -199,17 +196,15 @@ const columns = ref<ColumnItem[]>([
key: 'websiteName',
align: 'center'
},
{
title: '小程序信息',
dataIndex: 'websiteCode',
key: 'websiteCode',
align: 'center'
},
// {
// title: '小程序信息',
// dataIndex: 'websiteCode',
// key: 'websiteCode'
// },
{
title: '小程序描述',
dataIndex: 'comments',
key: 'comments',
align: 'center'
key: 'comments'
},
// {
// title: '当前版本',
@@ -265,11 +260,6 @@ const openEdit = (row?: CmsWebsite) => {
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
const updateType = (row: CmsWebsite) => {
updateCmsWebsite(row).then((msg) => {
message.success(msg);
@@ -286,48 +276,6 @@ const hideShare = () => {
showQrcode.value = false;
}
/* 删除单个 */
const remove = (row: CmsWebsite) => {
const hide = message.loading('请求中..', 0);
removeCmsWebsite(row.websiteId)
.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);
removeBatchCmsWebsite(selection.value.map((d) => d.websiteId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
// 查询订单

View File

@@ -0,0 +1,82 @@
<!-- 用户导入弹窗 -->
<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>导入备份文件</span>-->
<!-- </div>-->
</ele-modal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { message } from 'ant-design-vue/es';
import { CloudUploadOutlined } from '@ant-design/icons-vue';
import {importWebsiteField} from "@/api/cms/cmsWebsiteField";
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
defineProps<{
// 是否打开弹窗
visible: boolean;
}>();
// 导入请求状态
const loading = ref(false);
/* 上传 */
const doUpload = ({ file }) => {
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;
importWebsiteField(file)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
return false;
};
/* 更新 visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
</script>

View File

@@ -62,10 +62,10 @@
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="css样式" name="style">
<a-form-item label="style" name="style">
<a-input
allow-clear
placeholder="请输入css样式"
placeholder="style"
v-model:value="form.style"
/>
</a-form-item>

View File

@@ -13,33 +13,34 @@
ref="formRef"
:model="form"
:rules="rules"
:label-col="{ md: { span: 4 }, sm: { span: 4 }, xs: { span: 24 } }"
:label-col="{ md: { span: 3 }, sm: { span: 4 }, xs: { span: 24 } }"
:wrapper-col="{ md: { span: 19 }, sm: { span: 20 }, xs: { span: 24 } }"
>
<a-form-item label="字段名称" name="name">
<a-form-item label="名称" name="name">
<div class="w-full flex justify-between">
<a-input
allow-clear
:maxlength="100"
placeholder="siteName"
class="px-5 mr-2"
placeholder="name"
:disabled="isUpdate"
v-model:value="form.name"
/>
<SelectWebsiteField
:placeholder="`从模板选择`"
class="input-item"
v-model:value="form.name"
@done="chooseData"
/>
<!-- <SelectWebsiteField-->
<!-- :placeholder="`从模板选择`"-->
<!-- class="input-item"-->
<!-- v-model:value="form.name"-->
<!-- @done="chooseData"-->
<!-- />-->
</div>
</a-form-item>
<a-form-item label="字段类型" name="type">
<a-form-item label="内容" name="type">
<a-space direction="vertical" class="w-full">
<div class="p-1">
<div class="p-1" v-if="!isUpdate">
<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 :value="3">开关</a-radio>
</a-radio-group>
</div>
<template v-if="form.type == 1">
@@ -55,7 +56,7 @@
请选择或上传图片
</div>
</template>
<template v-if="form.type == 2">
<template v-else-if="form.type == 2">
<SelectFile
:placeholder="`请选择视频`"
:limit="1"
@@ -68,34 +69,33 @@
请选择或上传视频
</div>
</template>
<template v-else-if="form.type === 3">
<a-switch v-model:checked="form.value"/>
</template>
<template v-else>
<a-input placeholder="字段内容" v-model:value="form.value" />
</template>
</a-space>
</a-form-item>
<a-form-item label="字段内容" name="value">
<a-textarea
:rows="4"
:maxlength="2000"
placeholder="XXXX有限公司"
v-model:value="form.value"
/>
</a-form-item>
<a-form-item label="字段描述" name="comments">
<a-form-item label="备注" name="comments">
<a-textarea
:rows="2"
:maxlength="200"
placeholder="网站名称"
:maxlength="2000"
placeholder="备注"
v-model:value="form.comments"
/>
</a-form-item>
<a-form-item label="CSS样式" name="style">
<a-input
allow-clear
placeholder="CSS样式"
v-model:value="form.style"
/>
<div class="pt-2">
<a class="text-sm text-gray-500" href="https://www.tailwindcss.cn/docs/installation" target="_blank">Tailwind Css使用教程</a>
</div>
<a-form-item label="加密" name="encrypted" extra="私密信息需要加密保存" v-if="form.type === 0">
<a-switch v-model:checked="form.encrypted"></a-switch>
</a-form-item>
<!-- <a-form-item label="预留" name="style">-->
<!-- <a-input-->
<!-- allow-clear-->
<!-- placeholder="预留字段"-->
<!-- style="width: 325px"-->
<!-- v-model:value="form.style"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item label="排序" name="sortNumber">
<a-input-number
:min="0"
@@ -109,182 +109,207 @@
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { FormInstance } from 'ant-design-vue/es/form';
import useFormData from '@/utils/use-form-data';
import {
addCmsWebsiteField,
updateCmsWebsiteField
} from '@/api/cms/cmsWebsiteField';
import { message } from 'ant-design-vue/es';
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FileRecord } from '@/api/system/file/model';
import { uuid } from 'ele-admin-pro';
import { useI18n } from 'vue-i18n';
import { CmsWebsiteField } from '@/api/cms/cmsWebsiteField/model';
import {ref, reactive, watch} from 'vue';
import {FormInstance} from 'ant-design-vue/es/form';
import useFormData from '@/utils/use-form-data';
import {
addCmsWebsiteField,
updateCmsWebsiteField
} from '@/api/cms/cmsWebsiteField';
import {message} from 'ant-design-vue/es';
import {removeSiteInfoCache} from '@/api/cms/cmsWebsite';
import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types';
import {FileRecord} from '@/api/system/file/model';
import {uuid} from 'ele-admin-pro';
import {useI18n} from 'vue-i18n';
import {CmsWebsiteField} from '@/api/cms/cmsWebsiteField/model';
import {decrypt, encrypt} from "@/utils/common";
// 是否是修改
const isUpdate = ref(false);
// 是否是修改
const isUpdate = ref(false);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
websiteId: number | null | undefined;
// 修改回显的数据
data?: CmsWebsiteField | null;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
websiteId: number | null | undefined;
// 修改回显的数据
data?: CmsWebsiteField | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
const images = ref<ItemType[]>([]);
const formRef = ref<FormInstance | null>(null);// 国际化
const { locale } = useI18n();
// 提交状态
const loading = ref(false);
const images = ref<ItemType[]>([]);
const formRef = ref<FormInstance | null>(null);// 国际化
const {locale} = useI18n();
const { form, resetFields, assignFields } = useFormData<CmsWebsiteField>({
id: undefined,
type: 0,
template: undefined,
name: undefined,
value: undefined,
modifyRange: undefined,
defaultValue: undefined,
comments: '',
style: '',
lang: '',
sortNumber: 100
});
const {form, resetFields, assignFields} = useFormData<CmsWebsiteField>({
id: undefined,
type: 0,
template: undefined,
name: undefined,
value: undefined,
modifyRange: undefined,
defaultValue: undefined,
comments: '',
style: '',
lang: '',
encrypted: false,
sortNumber: 100
});
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请输入字段名称(英语)'
}
],
type: [
{
required: true,
type: 'number',
message: '请选择字段类型'
}
],
value: [
{
required: true,
type: 'string',
message: '请填写字段值'
}
]
// comments: [
// {
// required: true,
// type: 'string',
// message: '请输入字段'
// }
// ],
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.value = data.downloadUrl;
form.type = 1;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.type = 0;
};
const chooseData = (data: CmsWebsiteField) => {
form.name = data.name;
form.value = data.defaultValue;
if (data.type == 1) {
images.value.push({
uid: `${data.id}`,
url: data.defaultValue,
status: 'done'
});
// 表单验证规则
const rules = reactive({
name: [
{
required: true,
type: 'string',
message: '请输入名称'
}
};
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
],
comments: [
{
required: true,
type: 'string',
message: '请输入字段备注'
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const data = {
...form,
// name: form.name?.toUpperCase(),
websiteId: props.websiteId,
lang: locale.value
};
const saveOrUpdate = isUpdate.value
? updateCmsWebsiteField
: addCmsWebsiteField;
saveOrUpdate(data)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
// 清除缓存
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId'));
if (form.name == 'i18n') {
localStorage.setItem('i18n','1');
window.location.reload();
}
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
],
type: [
{
required: true,
type: 'number',
message: '请选择字段类型'
}
],
value: [
{
required: true,
type: 'string',
message: '请填写字段值'
}
]
// comments: [
// {
// required: true,
// type: 'string',
// message: '请输入字段'
// }
// ],
});
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignFields(props.data);
form.comments = props.data.comments;
if (form.type == 1) {
images.value.push({
uid: uuid(),
url: props.data.value,
status: 'done'
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.value = data.downloadUrl;
form.type = 1;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.type = 0;
};
// const chooseData = (data: CmsWebsiteField) => {
// form.name = data.name;
// form.value = data.defaultValue;
// form.comments = data.comments;
// if (data.type == 1) {
// images.value.push({
// uid: `${data.id}`,
// url: data.defaultValue,
// status: 'done'
// });
// }
// };
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
// 3 开关
if (form.type == 3) {
form.value = form.value ? '1' : '0';
}
const data = {
...form,
// name: form.name?.toUpperCase(),
websiteId: props.websiteId,
lang: locale.value
};
// 加密处理
if (data.encrypted) {
data.value = encrypt(data.value);
}
const saveOrUpdate = isUpdate.value
? updateCmsWebsiteField
: addCmsWebsiteField;
saveOrUpdate(data)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
// 清除缓存
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId'));
if (form.name == 'i18n') {
localStorage.setItem('i18n', '1');
window.location.reload();
}
isUpdate.value = true;
} else {
isUpdate.value = false;
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {
});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
images.value = [];
if (props.data) {
assignFields(props.data);
form.comments = props.data.comments;
if (form.type == 1) {
images.value.push({
uid: uuid(),
url: props.data.value,
status: 'done'
});
}
if (form.type == 3) {
form.value = props.data.value == '1';
}
if (form.encrypted) {
form.value = decrypt(props.data.value);
}
isUpdate.value = true;
} else {
resetFields();
isUpdate.value = false;
}
} else {
resetFields();
}
);
}
);
</script>

View File

@@ -1,15 +1,114 @@
<template>
<a-button @click="add" type="primary" :disabled="!websiteId">添加字段</a-button>
<a-space>
<a-button @click="add" type="primary">添加字段</a-button>
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="handleExport">备份</a-button>
<a-button type="dashed" :disabled="!hasRole('superAdmin')" @click="openImport">恢复</a-button>
<a-input-search
allow-clear
placeholder="请输入关键词"
style="width: 280px"
v-model:value="where.keywords"
@search="reload"
/>
</a-space>
<!-- 导入弹窗 -->
<import v-model:visible="showImport" @done="reload"/>
</template>
<script lang="ts" setup>
const emit = defineEmits<{
(e: 'add'): void;
}>();
import {ref} from 'vue';
import {CmsWebsiteField, CmsWebsiteFieldParam} from "@/api/cms/cmsWebsiteField/model";
import useSearch from "@/utils/use-search";
import {hasRole} from "@/utils/permission";
import {utils, writeFile} from 'xlsx';
import {message} from 'ant-design-vue';
import Import from "./Import.vue";
import {listCmsWebsiteField} from "@/api/cms/cmsWebsiteField";
import {getTenantId} from "@/utils/domain";
const add = () => {
emit('add');
};
const websiteId = localStorage.getItem('WebsiteId')
// 是否显示导入弹窗
const showImport = ref(false);
const loading = ref(false);
const xlsFileName = ref<string>();
const fields = ref<CmsWebsiteField[]>([]);
const emit = defineEmits<{
(e: 'search', where?: CmsWebsiteFieldParam): void;
(e: 'add'): void;
}>();
const add = () => {
emit('add');
};
// 表单数据
const {where} = useSearch<CmsWebsiteFieldParam>({
keywords: ''
});
const reload = () => {
emit('search', where);
};
/* 打开编辑弹窗 */
const openImport = () => {
showImport.value = true;
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
[
'类型',
'名称',
'值',
'加密',
'备注'
]
];
// 按搜索结果导出
await listCmsWebsiteField(where)
.then((list) => {
fields.value = list;
list?.forEach((d: CmsWebsiteField) => {
array.push([
`${d.type}`,
`${d.name}`,
`${d.value}`,
`${d.encrypted ? '1' : '0'}`,
`${d.comments}`
]);
});
const sheetName = `bak_config_${getTenantId()}`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${
where.createTimeEnd ? xlsFileName.value + '_' : ''
}${sheetName}.xlsx`
);
loading.value = false;
}, 1000);
})
.catch((msg) => {
message.error(msg);
loading.value = false;
})
.finally(() => {
});
};
</script>

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