1. 推广员功能增强
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
This commit is contained in:
@@ -119,6 +119,19 @@ export const modalFormProps: VbenFormProps = {
|
||||
defaultValue: 0, // 默认订阅
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '关闭', value: 0 },
|
||||
{ label: '开启', value: 1 },
|
||||
],
|
||||
},
|
||||
fieldName: 'enable_order_price_percent_adjust',
|
||||
label: '订单打折/涨幅',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
// 联系人姓名字段
|
||||
component: 'VbenInput',
|
||||
@@ -142,14 +155,10 @@ export const modalFormProps: VbenFormProps = {
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
// 业务码字段
|
||||
component: 'VbenInput',
|
||||
component: 'PromoterPicker',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: {
|
||||
placeholder: '请输入业务码',
|
||||
},
|
||||
fieldName: 'code',
|
||||
label: '业务码',
|
||||
label: '业务员',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
// 直接使用store的API接口
|
||||
import { getStoreList } from '#/views/system/store/api';
|
||||
|
||||
// 表格行数据类型定义
|
||||
interface RowType {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -12,29 +10,27 @@ interface RowType {
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
// 药店管理表格配置
|
||||
// 注意:查询时会自动添加type=1参数,只显示药店类型的数据
|
||||
export const gridOptions: VxeGridProps<RowType> = {
|
||||
// 复选框配置
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: '',
|
||||
},
|
||||
// 列配置
|
||||
columnConfig: {
|
||||
useKey: true,
|
||||
},
|
||||
// 行配置
|
||||
rowConfig: {
|
||||
useKey: true,
|
||||
},
|
||||
// 表格列定义
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 }, // 复选框列
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 100 }, // ID列
|
||||
{ field: 'name', align: 'left', title: '药店名称', width: 140 }, // 药店名称列(已从"诊所名称"改为"药店名称")
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{
|
||||
field: 'store_basic_info',
|
||||
align: 'left',
|
||||
title: '基础信息',
|
||||
width: 280,
|
||||
slots: { default: 'store_basic_info' },
|
||||
},
|
||||
{
|
||||
// 在线复诊配置列(合并委托诊所和负责人)
|
||||
field: 'online_consultation_config',
|
||||
align: 'left',
|
||||
title: '在线复诊配置',
|
||||
@@ -42,69 +38,37 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
slots: { default: 'online_consultation_config' },
|
||||
},
|
||||
{
|
||||
field: 'is_shipping_free',
|
||||
field: 'store_config_1',
|
||||
align: 'left',
|
||||
title: '是否包邮',
|
||||
slots: { default: 'is_shipping_free' },
|
||||
width: 120,
|
||||
title: '开关配置',
|
||||
width: 330,
|
||||
slots: { default: 'store_config_1' },
|
||||
},
|
||||
{
|
||||
field: 'bank_card_report_status',
|
||||
field: 'store_config_2',
|
||||
align: 'left',
|
||||
title: '银行卡报备',
|
||||
slots: { default: 'bank_card_report_status' },
|
||||
width: 120,
|
||||
title: '业务配置',
|
||||
width: 330,
|
||||
slots: { default: 'store_config_2' },
|
||||
},
|
||||
{
|
||||
// 订阅价格波动列(显示为开关)
|
||||
field: 'subscribe_price_change',
|
||||
align: 'left',
|
||||
title: '订阅价格',
|
||||
slots: { default: 'subscribe_price_change' },
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
field: 'see_rate',
|
||||
align: 'left',
|
||||
title: '查看毛利率',
|
||||
slots: { default: 'see_rate' },
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
// 药店二维码列(已从"诊所二维码"改为"药店二维码")
|
||||
field: 'qr_code',
|
||||
align: 'left',
|
||||
title: '药店二维码',
|
||||
slots: { default: 'qr_code' },
|
||||
width: 130,
|
||||
},
|
||||
{ field: 'position', title: '详细地址', width: 140 },
|
||||
{ field: 'new_admin.nick_name', title: '业务员', slots: { default: 'sales_admin' }, width: 160 },
|
||||
{ field: 'mobile', title: '联系人、电话', slots: { default: 'mobile' }, width: 140 },
|
||||
{
|
||||
field: 'erp_id',
|
||||
align: 'left',
|
||||
title: 'ERP ID',
|
||||
width: 140,
|
||||
slots: { default: 'erp_id_cell' },
|
||||
},
|
||||
{
|
||||
field: 'mes_id',
|
||||
align: 'left',
|
||||
title: 'MES ID',
|
||||
width: 140,
|
||||
slots: { default: 'mes_id_cell' },
|
||||
},
|
||||
{ field: 'position', title: '详细地址', width: 140 }, // 详细地址列
|
||||
{ field: 'new_admin.nick_name', title: '业务员', width: 140 }, // 业务员列
|
||||
{ field: 'mobile', title: '联系人、电话', slots: { default: 'mobile' }, width: 140 }, // 联系人电话列
|
||||
{
|
||||
// 营业时间列
|
||||
field: 'start_time',
|
||||
title: '营业时间',
|
||||
width: 140,
|
||||
slots: { default: 'start-time' },
|
||||
},
|
||||
{ field: 'created_at', title: '注册时间', width: 140 }, // 注册时间列
|
||||
{ field: 'created_at', title: '注册时间', width: 140 },
|
||||
{
|
||||
// 操作列
|
||||
type: 'html',
|
||||
title: '操作',
|
||||
width: 200,
|
||||
@@ -113,18 +77,14 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
},
|
||||
],
|
||||
keepSource: true,
|
||||
// 分页配置
|
||||
pagerConfig: {},
|
||||
// 代理配置(数据请求)
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
// 请求后端接口方法
|
||||
// 注意:会自动添加type=1参数,只查询药店类型的数据
|
||||
query: async ({ page }, formValues) => {
|
||||
return await getStoreList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
type: 1, // 固定为药店类型
|
||||
type: 1,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
@@ -132,20 +92,17 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
},
|
||||
height: 'auto',
|
||||
border: false,
|
||||
// 工具栏配置
|
||||
toolbarConfig: {
|
||||
// 是否显示搜索表单控制按钮
|
||||
// @ts-ignore 正式环境时有完整的类型声明
|
||||
search: true,
|
||||
refresh: true, // 刷新按钮
|
||||
print: false, // 打印按钮
|
||||
export: false, // 导出按钮
|
||||
zoom: true, // 最大化最小化按钮
|
||||
refresh: true,
|
||||
print: false,
|
||||
export: false,
|
||||
zoom: true,
|
||||
slots: {
|
||||
buttons: 'toolbar-buttons', // 工具栏按钮插槽
|
||||
buttons: 'toolbar-buttons',
|
||||
},
|
||||
custom: {
|
||||
// 自定义列-图标
|
||||
icon: 'vxe-icon-menu',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,11 +8,12 @@ import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Button, Image, message, Switch, Tag } from 'ant-design-vue';
|
||||
import { Button, Image, message, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { Icon } from '#/components/icon';
|
||||
import QrCodePreview from '#/components/modal/QrCodePreview.vue';
|
||||
import PromoterInfoCard from '#/components/promoter/PromoterInfoCard.vue';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
// 导入药店管理相关的API(直接使用store的API)
|
||||
@@ -24,9 +25,13 @@ import {
|
||||
updateStoreShippingFree,
|
||||
updateStoreSeeRateStatus,
|
||||
updateStoreSubscribeStatus,
|
||||
updateStoreOrderPricePercentAdjust,
|
||||
updateAllowInsuranceCategoryApi,
|
||||
toggleSalespersonSeePriceApi,
|
||||
} from '#/views/system/store/api';
|
||||
// 导入表单弹窗组件
|
||||
import FormModalDemo from './components/modal.vue';
|
||||
import StoreBasicInfoCell from '#/views/system/store/components/cells/StoreBasicInfoCell.vue';
|
||||
import StoreConfigTogglesCell from '#/views/system/store/components/cells/StoreConfigTogglesCell.vue';
|
||||
// 导入绑定在线复诊配置弹窗(使用store的组件)
|
||||
import BindConsultationModal from '#/views/system/store/components/BindConsultationModal.vue';
|
||||
import DrugPriceModal from '#/views/system/store/components/DrugPriceModal.vue';
|
||||
@@ -299,6 +304,27 @@ const updateSeeRate = (id: number) => {
|
||||
});
|
||||
};
|
||||
|
||||
const updateOrderPricePercentAdjust = (id: number) => {
|
||||
updateStoreOrderPricePercentAdjust({ id }).then(() => {
|
||||
message.success('修改成功!');
|
||||
gridApi.query();
|
||||
});
|
||||
};
|
||||
|
||||
const updateAllowInsurance = (id: number) => {
|
||||
updateAllowInsuranceCategoryApi({ id }).then(() => {
|
||||
message.success('修改成功!');
|
||||
gridApi.query();
|
||||
});
|
||||
};
|
||||
|
||||
const updateSalespersonSeePrice = (storeId: number) => {
|
||||
toggleSalespersonSeePriceApi({ store_id: storeId }).then(() => {
|
||||
message.success('修改成功!');
|
||||
gridApi.query();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量同步总仓库药品
|
||||
*/
|
||||
@@ -379,6 +405,47 @@ const batchSyncDrugPrice = () => {
|
||||
</template>
|
||||
</TableAction>
|
||||
</template>
|
||||
<template #store_basic_info="{ row }">
|
||||
<StoreBasicInfoCell
|
||||
:row="row"
|
||||
variant="pharmacy"
|
||||
:on-copy="copyText"
|
||||
:on-edit-external-field="showStoreExternalFieldModal"
|
||||
/>
|
||||
</template>
|
||||
<template #store_config_1="{ row }">
|
||||
<StoreConfigTogglesCell
|
||||
:row="row"
|
||||
section="switches"
|
||||
:get-bank-card-report-tag-color="getBankCardReportTagColor"
|
||||
:get-bank-card-report-tag-text="getBankCardReportTagText"
|
||||
:on-shipping-free="updateShippingFree"
|
||||
:on-subscribe="updateSubscribe"
|
||||
:on-see-rate="updateSeeRate"
|
||||
:on-order-price-adjust="updateOrderPricePercentAdjust"
|
||||
:on-bank-card-report="handleBankCardReportColumnClick"
|
||||
/>
|
||||
</template>
|
||||
<template #store_config_2="{ row }">
|
||||
<StoreConfigTogglesCell
|
||||
:row="row"
|
||||
section="business"
|
||||
show-insurance
|
||||
show-salesperson-see-price
|
||||
:get-bank-card-report-tag-color="getBankCardReportTagColor"
|
||||
:get-bank-card-report-tag-text="getBankCardReportTagText"
|
||||
:on-shipping-free="updateShippingFree"
|
||||
:on-subscribe="updateSubscribe"
|
||||
:on-see-rate="updateSeeRate"
|
||||
:on-order-price-adjust="updateOrderPricePercentAdjust"
|
||||
:on-bank-card-report="handleBankCardReportColumnClick"
|
||||
:on-allow-insurance="updateAllowInsurance"
|
||||
:on-salesperson-see-price="updateSalespersonSeePrice"
|
||||
/>
|
||||
</template>
|
||||
<template #sales_admin="{ row }">
|
||||
<PromoterInfoCard :admin="row.new_admin" size="compact" />
|
||||
</template>
|
||||
<template #mobile="{ row }">
|
||||
<div>
|
||||
药店联系人:{{ row.contact }}
|
||||
@@ -406,26 +473,6 @@ const batchSyncDrugPrice = () => {
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #erp_id_cell="{ row }">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="h-auto p-0"
|
||||
@click="showStoreExternalFieldModal(row, 'erp_id', 'ERP ID')"
|
||||
>
|
||||
{{ row.erp_id != null && row.erp_id !== '' ? row.erp_id : '-' }}
|
||||
</Button>
|
||||
</template>
|
||||
<template #mes_id_cell="{ row }">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="h-auto p-0"
|
||||
@click="showStoreExternalFieldModal(row, 'mes_id', 'MES ID')"
|
||||
>
|
||||
{{ row.mes_id != null && row.mes_id !== '' ? row.mes_id : '-' }}
|
||||
</Button>
|
||||
</template>
|
||||
<template #online_consultation_config="{ row }">
|
||||
<div
|
||||
v-if="row.is_internet_medical === 1 && row.online_consultation_doctor_name"
|
||||
@@ -446,43 +493,6 @@ const batchSyncDrugPrice = () => {
|
||||
绑定
|
||||
</Button>
|
||||
</template>
|
||||
<template #is_shipping_free="{ row }">
|
||||
<Switch
|
||||
:checked="row.is_shipping_free"
|
||||
:checked-value="1"
|
||||
:un-checked-value="0"
|
||||
checked-children="包邮"
|
||||
un-checked-children="不包邮"
|
||||
@click="updateShippingFree(row.id)"
|
||||
/>
|
||||
</template>
|
||||
<template #bank_card_report_status="{ row }">
|
||||
<Tag
|
||||
:color="getBankCardReportTagColor(row.bank_card_report_status)"
|
||||
style="cursor: pointer"
|
||||
@click="handleBankCardReportColumnClick(row)"
|
||||
>
|
||||
{{ getBankCardReportTagText(row) }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #subscribe_price_change="{ row }">
|
||||
<Tag
|
||||
:color="row.subscribe_price_change === 0 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateSubscribe(row.id)"
|
||||
>
|
||||
{{ row.subscribe_price_change === 0 ? '订阅' : '不订阅' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #see_rate="{ row }">
|
||||
<Tag
|
||||
:color="Number(row.see_rate) === 1 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateSeeRate(row.id)"
|
||||
>
|
||||
{{ Number(row.see_rate) === 1 ? '可查看' : '不可查看' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #start-time="{ row }">
|
||||
早:<Tag color="success">{{ row.start_time }}</Tag>
|
||||
<br />
|
||||
|
||||
@@ -44,11 +44,25 @@ export async function getPromoterOptions() {
|
||||
nick_name: string;
|
||||
avatar: string;
|
||||
code: string;
|
||||
phone: string;
|
||||
role_id: number;
|
||||
role_name: string;
|
||||
}[]>(`${prefix}promoter-options`);
|
||||
}
|
||||
|
||||
export async function getPromoterDetailApi(params: { id?: number; code?: string }) {
|
||||
return requestClient.get<{
|
||||
id: number;
|
||||
nick_name: string;
|
||||
avatar: string;
|
||||
code: string;
|
||||
phone: string;
|
||||
role_name: string;
|
||||
clinic_input_count: number;
|
||||
pharmacy_input_count: number;
|
||||
}>(`${prefix}promoter-detail`, { params });
|
||||
}
|
||||
|
||||
export async function auditStoreInput(data: {
|
||||
id: number;
|
||||
status: number; // 1=审核通过,2=审核拒绝
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Avatar, Button, message, Modal, Tag, Textarea } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
import PromoterInfoCard from '#/components/promoter/PromoterInfoCard.vue';
|
||||
|
||||
import { auditStoreInput, getStoreInputDetail } from './api';
|
||||
import AuditModal from './components/AuditModal.vue';
|
||||
@@ -132,6 +133,9 @@ const getStatusText = (status: number) => {
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #promoter_admin="{ row }">
|
||||
<PromoterInfoCard :admin="row.promoter_admin" size="compact" />
|
||||
</template>
|
||||
<template #audit_time="{ row }">
|
||||
<span v-if="row.audit_time">
|
||||
{{ new Date(row.audit_time * 1000).toLocaleString() }}
|
||||
|
||||
@@ -66,6 +66,12 @@ export const inputGridOptions: VxeGridProps<RowType> = {
|
||||
minWidth: 140,
|
||||
slots: { default: 'inputUser' },
|
||||
},
|
||||
{
|
||||
field: 'promoter_admin',
|
||||
title: '业务员',
|
||||
minWidth: 160,
|
||||
slots: { default: 'promoter_admin' },
|
||||
},
|
||||
{
|
||||
type: 'html',
|
||||
title: '操作',
|
||||
@@ -145,6 +151,12 @@ export const auditGridOptions: VxeGridProps<RowType> = {
|
||||
slots: { default: 'inputUser' },
|
||||
},
|
||||
{ field: 'auditAdmin.nick_name', title: '审核人' },
|
||||
{
|
||||
field: 'promoter_admin',
|
||||
title: '业务员',
|
||||
minWidth: 160,
|
||||
slots: { default: 'promoter_admin' },
|
||||
},
|
||||
{ field: 'audit_time', title: '审核时间', slots: { default: 'audit_time' } },
|
||||
{ field: 'contact', title: '联系人' },
|
||||
{ field: 'mobile', title: '联系电话' },
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Avatar, Button, message, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
import PromoterInfoCard from '#/components/promoter/PromoterInfoCard.vue';
|
||||
|
||||
import {
|
||||
createStoreInput,
|
||||
@@ -154,6 +155,9 @@ const getStatusText = (status: number) => {
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #promoter_admin="{ row }">
|
||||
<PromoterInfoCard :admin="row.promoter_admin" size="compact" />
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
|
||||
@@ -170,6 +170,10 @@ export async function updateAllowInsuranceCategoryApi(data: { id: number }) {
|
||||
return requestClient.post<any>(`${prefix}update-allow-insurance-category`, data);
|
||||
}
|
||||
|
||||
export async function updateStoreOrderPricePercentAdjust(data: { id: number }) {
|
||||
return requestClient.post<any>(`${prefix}update-order-price-percent-adjust`, data);
|
||||
}
|
||||
|
||||
export async function toggleSalespersonSeePriceApi(data: { store_id: number }) {
|
||||
return requestClient.post<any>('salesperson-store-config/toggle-see-price', data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<script lang="ts" setup>
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
defineProps<{
|
||||
row: Record<string, any>;
|
||||
variant: 'clinic' | 'pharmacy';
|
||||
onCopy: (text: string | number) => void;
|
||||
onEditExternalField: (
|
||||
row: Record<string, any>,
|
||||
field: 'erp_id' | 'mes_id',
|
||||
label: string,
|
||||
) => void;
|
||||
}>();
|
||||
|
||||
function getClinicTypeText(clinicType: number) {
|
||||
if (clinicType === 1) return '西医诊所';
|
||||
if (clinicType === 2) return '中医诊所';
|
||||
return '未设置';
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="store-basic-info">
|
||||
<div class="store-basic-info__name">{{ row.name || '-' }}</div>
|
||||
<div class="store-basic-info__grid">
|
||||
<div class="info-item">
|
||||
<span class="info-item__label">ID</span>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="info-item__action"
|
||||
@click="onCopy(row.id)"
|
||||
>
|
||||
{{ row.id }}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-item__label">ERP</span>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="info-item__action"
|
||||
@click="onEditExternalField(row, 'erp_id', 'ERP ID')"
|
||||
>
|
||||
{{ row.erp_id != null && row.erp_id !== '' ? row.erp_id : '-' }}
|
||||
</Button>
|
||||
</div>
|
||||
<template v-if="variant === 'clinic'">
|
||||
<div class="info-item">
|
||||
<span class="info-item__label">诊所类型</span>
|
||||
<span class="info-item__value">{{ getClinicTypeText(Number(row.clinic_type)) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-item__label">管理员</span>
|
||||
<template v-if="row.store_admin?.phone">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="info-item__action"
|
||||
@click="onCopy(row.store_admin.phone)"
|
||||
>
|
||||
{{ row.store_admin.phone }}
|
||||
</Button>
|
||||
</template>
|
||||
<span v-else class="info-item__value">-</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="info-item">
|
||||
<span class="info-item__label">MES</span>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="info-item__action"
|
||||
@click="onEditExternalField(row, 'mes_id', 'MES ID')"
|
||||
>
|
||||
{{ row.mes_id != null && row.mes_id !== '' ? row.mes_id : '-' }}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="info-item info-item--empty" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.store-basic-info {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.store-basic-info__name {
|
||||
font-weight: 500;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.store-basic-info__grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4px 8px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: rgb(107 114 128);
|
||||
}
|
||||
|
||||
.info-item--empty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.info-item__label {
|
||||
flex-shrink: 0;
|
||||
min-width: 48px;
|
||||
color: rgb(156 163 175);
|
||||
}
|
||||
|
||||
.info-item__value {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-item__action {
|
||||
height: auto;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,244 @@
|
||||
<script lang="ts" setup>
|
||||
import { Switch, Tag } from 'ant-design-vue';
|
||||
|
||||
defineProps<{
|
||||
row: Record<string, any>;
|
||||
section: 'switches' | 'business' | 'all';
|
||||
showClinicType?: boolean;
|
||||
showInsurance?: boolean;
|
||||
showSalespersonSeePrice?: boolean;
|
||||
getBankCardReportTagColor: (status: number) => string;
|
||||
getBankCardReportTagText: (row: Record<string, any>) => string;
|
||||
onShippingFree: (id: number) => void;
|
||||
onSubscribe: (id: number) => void;
|
||||
onSeeRate: (id: number) => void;
|
||||
onOrderPriceAdjust: (id: number) => void;
|
||||
onBankCardReport: (row: Record<string, any>) => void;
|
||||
onClinicType?: (row: Record<string, any>) => void;
|
||||
onAllowInsurance?: (id: number) => void;
|
||||
onSalespersonSeePrice?: (id: number) => void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="store-config-toggles">
|
||||
<template v-if="section === 'switches'">
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">是否包邮</span>
|
||||
<div class="config-item__control">
|
||||
<Switch
|
||||
:checked="row.is_shipping_free"
|
||||
:checked-value="1"
|
||||
:un-checked-value="0"
|
||||
checked-children="包邮"
|
||||
un-checked-children="不包邮"
|
||||
size="small"
|
||||
@click="onShippingFree(row.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">订阅价格</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="row.subscribe_price_change === 0 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onSubscribe(row.id)"
|
||||
>
|
||||
{{ row.subscribe_price_change === 0 ? '订阅' : '不订阅' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">查看毛利率</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.see_rate) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onSeeRate(row.id)"
|
||||
>
|
||||
{{ Number(row.see_rate) === 1 ? '可查看' : '不可查看' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">订单打折</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.enable_order_price_percent_adjust) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onOrderPriceAdjust(row.id)"
|
||||
>
|
||||
{{ Number(row.enable_order_price_percent_adjust) === 1 ? '开启' : '关闭' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="section === 'business'">
|
||||
<div v-if="showClinicType && onClinicType" class="config-item">
|
||||
<span class="config-item__label">诊所类型</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="row.clinic_type === 1 ? 'blue' : row.clinic_type === 2 ? 'green' : 'default'"
|
||||
class="config-item__tag clinic-type-tag"
|
||||
@click="onClinicType(row)"
|
||||
>
|
||||
{{ row.clinic_type === 1 ? '西医诊所' : row.clinic_type === 2 ? '中医诊所' : '未设置' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">银行卡报备</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="getBankCardReportTagColor(row.bank_card_report_status)"
|
||||
class="config-item__tag"
|
||||
@click="onBankCardReport(row)"
|
||||
>
|
||||
{{ getBankCardReportTagText(row) }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showInsurance && onAllowInsurance" class="config-item">
|
||||
<span class="config-item__label">医保可选</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.allow_insurance_category) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onAllowInsurance(row.id)"
|
||||
>
|
||||
{{ Number(row.allow_insurance_category) === 1 ? '可选医保' : '仅自费' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showSalespersonSeePrice && onSalespersonSeePrice" class="config-item">
|
||||
<span class="config-item__label">推广员可见价格</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.salesperson_see_price) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onSalespersonSeePrice(row.id)"
|
||||
>
|
||||
{{ Number(row.salesperson_see_price) === 1 ? '可见' : '不可见' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="section === 'all'">
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">是否包邮</span>
|
||||
<div class="config-item__control">
|
||||
<Switch
|
||||
:checked="row.is_shipping_free"
|
||||
:checked-value="1"
|
||||
:un-checked-value="0"
|
||||
checked-children="包邮"
|
||||
un-checked-children="不包邮"
|
||||
size="small"
|
||||
@click="onShippingFree(row.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">银行卡报备</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="getBankCardReportTagColor(row.bank_card_report_status)"
|
||||
class="config-item__tag"
|
||||
@click="onBankCardReport(row)"
|
||||
>
|
||||
{{ getBankCardReportTagText(row) }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">订阅价格</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="row.subscribe_price_change === 0 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onSubscribe(row.id)"
|
||||
>
|
||||
{{ row.subscribe_price_change === 0 ? '订阅' : '不订阅' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">查看毛利率</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.see_rate) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onSeeRate(row.id)"
|
||||
>
|
||||
{{ Number(row.see_rate) === 1 ? '可查看' : '不可查看' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<span class="config-item__label">订单打折</span>
|
||||
<div class="config-item__control">
|
||||
<Tag
|
||||
:color="Number(row.enable_order_price_percent_adjust) === 1 ? 'success' : 'default'"
|
||||
class="config-item__tag"
|
||||
@click="onOrderPriceAdjust(row.id)"
|
||||
>
|
||||
{{ Number(row.enable_order_price_percent_adjust) === 1 ? '开启' : '关闭' }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.store-config-toggles {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 6px 12px;
|
||||
}
|
||||
|
||||
.config-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.config-item__label {
|
||||
flex-shrink: 0;
|
||||
min-width: 72px;
|
||||
color: rgb(156 163 175);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.config-item__control {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.config-item__tag {
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.clinic-type-tag {
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.clinic-type-tag:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.clinic-type-tag:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
</style>
|
||||
@@ -114,6 +114,19 @@ export const modalFormProps: VbenFormProps = {
|
||||
label: '是否包邮',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '关闭', value: 0 },
|
||||
{ label: '开启', value: 1 },
|
||||
],
|
||||
},
|
||||
fieldName: 'enable_order_price_percent_adjust',
|
||||
label: '订单打折/涨幅',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
// 诊所类型(单选)
|
||||
component: 'RadioGroup',
|
||||
@@ -167,13 +180,10 @@ export const modalFormProps: VbenFormProps = {
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
component: 'PromoterPicker',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: {
|
||||
placeholder: '请输入业务码',
|
||||
},
|
||||
fieldName: 'code',
|
||||
label: '业务码',
|
||||
label: '业务员',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -23,14 +23,12 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
},
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 100 },
|
||||
{ field: 'name', align: 'left', title: '诊所名称', width: 140 },
|
||||
{
|
||||
field: 'clinic_type',
|
||||
field: 'store_basic_info',
|
||||
align: 'left',
|
||||
title: '诊所类型',
|
||||
width: 120,
|
||||
slots: { default: 'clinic_type' },
|
||||
title: '基础信息',
|
||||
width: 280,
|
||||
slots: { default: 'store_basic_info' },
|
||||
},
|
||||
{
|
||||
field: 'online_consultation_config',
|
||||
@@ -40,47 +38,18 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
slots: { default: 'online_consultation_config' },
|
||||
},
|
||||
{
|
||||
field: 'is_shipping_free',
|
||||
field: 'store_config_1',
|
||||
align: 'left',
|
||||
title: '是否包邮',
|
||||
slots: { default: 'is_shipping_free' },
|
||||
width: 120,
|
||||
title: '开关配置',
|
||||
width: 330,
|
||||
slots: { default: 'store_config_1' },
|
||||
},
|
||||
{
|
||||
field: 'bank_card_report_status',
|
||||
field: 'store_config_2',
|
||||
align: 'left',
|
||||
title: '银行卡报备',
|
||||
slots: { default: 'bank_card_report_status' },
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
// 订阅价格波动列(显示为开关)
|
||||
field: 'subscribe_price_change',
|
||||
align: 'left',
|
||||
title: '订阅价格',
|
||||
slots: { default: 'subscribe_price_change' },
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
field: 'see_rate',
|
||||
align: 'left',
|
||||
title: '查看毛利率',
|
||||
slots: { default: 'see_rate' },
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
field: 'allow_insurance_category',
|
||||
align: 'left',
|
||||
title: '医保可选',
|
||||
slots: { default: 'allow_insurance_category' },
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
field: 'salesperson_see_price',
|
||||
align: 'left',
|
||||
title: '推广员可见价格',
|
||||
slots: { default: 'salesperson_see_price' },
|
||||
width: 130,
|
||||
title: '业务配置',
|
||||
width: 330,
|
||||
slots: { default: 'store_config_2' },
|
||||
},
|
||||
{
|
||||
field: 'qr_code',
|
||||
@@ -89,24 +58,8 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
slots: { default: 'qr_code' },
|
||||
width: 130,
|
||||
},
|
||||
{
|
||||
field: 'erp_id',
|
||||
align: 'left',
|
||||
title: 'ERP ID',
|
||||
width: 140,
|
||||
slots: { default: 'erp_id_cell' },
|
||||
},
|
||||
// {
|
||||
// field: 'mes_id',
|
||||
// align: 'left',
|
||||
// title: 'MES ID',
|
||||
// width: 140,
|
||||
// slots: { default: 'mes_id_cell' },
|
||||
// },
|
||||
// { field: 'shouzimu', title: '诊所首字母' },
|
||||
{ field: 'position', title: '详细地址', width: 140 },
|
||||
{ field: 'new_admin.nick_name', title: '业务员', slots: { default: 'sales_admin' }, width: 140 },
|
||||
{ field: 'store_admin.phone', title: '管理员手机', slots: { default: 'store_admin_phone' }, width: 140 },
|
||||
{ field: 'new_admin.nick_name', title: '业务员', slots: { default: 'sales_admin' }, width: 160 },
|
||||
{ field: 'mobile', title: '联系人、电话', slots: { default: 'mobile' }, width: 140 },
|
||||
{
|
||||
field: 'start_time',
|
||||
@@ -127,13 +80,11 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
// 请求后端接口方法
|
||||
// 注意:会自动添加type=0参数,只查询诊所类型的数据
|
||||
query: async ({ page }, formValues) => {
|
||||
return await getStoreList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
type: 0, // 固定为诊所类型
|
||||
type: 0,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
@@ -142,19 +93,16 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
height: 'auto',
|
||||
border: false,
|
||||
toolbarConfig: {
|
||||
// 是否显示搜索表单控制按钮
|
||||
// @ts-ignore 正式环境时有完整的类型声明
|
||||
search: true,
|
||||
refresh: true, // 刷新
|
||||
print: false, // 打印
|
||||
export: false, // 导出
|
||||
// custom: true, // 自定义列
|
||||
zoom: true, // 最大化最小化
|
||||
refresh: true,
|
||||
print: false,
|
||||
export: false,
|
||||
zoom: true,
|
||||
slots: {
|
||||
buttons: 'toolbar-buttons',
|
||||
},
|
||||
custom: {
|
||||
// 自定义列-图标
|
||||
icon: 'vxe-icon-menu',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,11 +8,12 @@ import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Button, Image, message, Modal, Switch, Tag } from 'ant-design-vue';
|
||||
import { Button, Image, message, Modal, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { Icon } from '#/components/icon';
|
||||
import QrCodePreview from '#/components/modal/QrCodePreview.vue';
|
||||
import PromoterInfoCard from '#/components/promoter/PromoterInfoCard.vue';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import {
|
||||
@@ -26,8 +27,11 @@ import {
|
||||
updateStoreShippingFree,
|
||||
updateStoreSeeRateStatus,
|
||||
updateStoreSubscribeStatus,
|
||||
updateStoreOrderPricePercentAdjust,
|
||||
} from './api';
|
||||
import FormModalDemo from './components/modal.vue';
|
||||
import StoreBasicInfoCell from './components/cells/StoreBasicInfoCell.vue';
|
||||
import StoreConfigTogglesCell from './components/cells/StoreConfigTogglesCell.vue';
|
||||
import DrugPriceModal from './components/DrugPriceModal.vue';
|
||||
import BindConsultationModal from './components/BindConsultationModal.vue';
|
||||
import StoreExternalFieldModal from './components/StoreExternalFieldModal.vue';
|
||||
@@ -296,6 +300,13 @@ const updateSalespersonSeePrice = (storeId: number) => {
|
||||
});
|
||||
};
|
||||
|
||||
const updateOrderPricePercentAdjust = (id: number) => {
|
||||
updateStoreOrderPricePercentAdjust({ id }).then(() => {
|
||||
message.success('修改成功!');
|
||||
gridApi.query();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量同步总仓库药品
|
||||
*/
|
||||
@@ -408,14 +419,48 @@ const handleSwitchClinicType = (row: any) => {
|
||||
</template>
|
||||
</TableAction>
|
||||
</template>
|
||||
<template #sales_admin="{ row }">
|
||||
<div>
|
||||
<div>{{ row.new_admin?.nick_name || '-' }}</div>
|
||||
<div v-if="row.new_admin?.phone" class="text-xs text-gray-500">{{ row.new_admin.phone }}</div>
|
||||
</div>
|
||||
<template #store_basic_info="{ row }">
|
||||
<StoreBasicInfoCell
|
||||
:row="row"
|
||||
variant="clinic"
|
||||
:on-copy="copyText"
|
||||
:on-edit-external-field="showStoreExternalFieldModal"
|
||||
/>
|
||||
</template>
|
||||
<template #store_admin_phone="{ row }">
|
||||
{{ row.store_admin?.phone || '-' }}
|
||||
<template #store_config_1="{ row }">
|
||||
<StoreConfigTogglesCell
|
||||
:row="row"
|
||||
section="switches"
|
||||
:get-bank-card-report-tag-color="getBankCardReportTagColor"
|
||||
:get-bank-card-report-tag-text="getBankCardReportTagText"
|
||||
:on-shipping-free="updateShippingFree"
|
||||
:on-subscribe="updateSubscribe"
|
||||
:on-see-rate="updateSeeRate"
|
||||
:on-order-price-adjust="updateOrderPricePercentAdjust"
|
||||
:on-bank-card-report="handleBankCardReportColumnClick"
|
||||
/>
|
||||
</template>
|
||||
<template #store_config_2="{ row }">
|
||||
<StoreConfigTogglesCell
|
||||
:row="row"
|
||||
section="business"
|
||||
show-clinic-type
|
||||
show-insurance
|
||||
show-salesperson-see-price
|
||||
:get-bank-card-report-tag-color="getBankCardReportTagColor"
|
||||
:get-bank-card-report-tag-text="getBankCardReportTagText"
|
||||
:on-shipping-free="updateShippingFree"
|
||||
:on-subscribe="updateSubscribe"
|
||||
:on-see-rate="updateSeeRate"
|
||||
:on-order-price-adjust="updateOrderPricePercentAdjust"
|
||||
:on-bank-card-report="handleBankCardReportColumnClick"
|
||||
:on-clinic-type="handleSwitchClinicType"
|
||||
:on-allow-insurance="updateAllowInsurance"
|
||||
:on-salesperson-see-price="updateSalespersonSeePrice"
|
||||
/>
|
||||
</template>
|
||||
<template #sales_admin="{ row }">
|
||||
<PromoterInfoCard :admin="row.new_admin" size="compact" />
|
||||
</template>
|
||||
<template #mobile="{ row }">
|
||||
<div>
|
||||
@@ -444,37 +489,6 @@ const handleSwitchClinicType = (row: any) => {
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #erp_id_cell="{ row }">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="h-auto p-0"
|
||||
@click="showStoreExternalFieldModal(row, 'erp_id', 'ERP ID')"
|
||||
>
|
||||
{{ row.erp_id != null && row.erp_id !== '' ? row.erp_id : '-' }}
|
||||
</Button>
|
||||
</template>
|
||||
<template #mes_id_cell="{ row }">
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="h-auto p-0"
|
||||
@click="showStoreExternalFieldModal(row, 'mes_id', 'MES ID')"
|
||||
>
|
||||
{{ row.mes_id != null && row.mes_id !== '' ? row.mes_id : '-' }}
|
||||
</Button>
|
||||
</template>
|
||||
<template #type="{ row }">
|
||||
</template>
|
||||
<template #clinic_type="{ row }">
|
||||
<Tag
|
||||
:color="row.clinic_type === 1 ? 'blue' : row.clinic_type === 2 ? 'green' : 'default'"
|
||||
class="clinic-type-tag cursor-pointer"
|
||||
@click="handleSwitchClinicType(row)"
|
||||
>
|
||||
{{ row.clinic_type === 1 ? '西医诊所' : row.clinic_type === 2 ? '中医诊所' : '未设置' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #online_consultation_config="{ row }">
|
||||
<div
|
||||
v-if="row.is_internet_medical === 1 && row.online_consultation_doctor_name"
|
||||
@@ -495,61 +509,6 @@ const handleSwitchClinicType = (row: any) => {
|
||||
绑定
|
||||
</Button>
|
||||
</template>
|
||||
<template #is_shipping_free="{ row }">
|
||||
<Switch
|
||||
:checked="row.is_shipping_free"
|
||||
:checked-value="1"
|
||||
:un-checked-value="0"
|
||||
checked-children="包邮"
|
||||
un-checked-children="不包邮"
|
||||
@click="updateShippingFree(row.id)"
|
||||
/>
|
||||
</template>
|
||||
<template #bank_card_report_status="{ row }">
|
||||
<Tag
|
||||
:color="getBankCardReportTagColor(row.bank_card_report_status)"
|
||||
style="cursor: pointer"
|
||||
@click="handleBankCardReportColumnClick(row)"
|
||||
>
|
||||
{{ getBankCardReportTagText(row) }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #subscribe_price_change="{ row }">
|
||||
<Tag
|
||||
:color="row.subscribe_price_change === 0 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateSubscribe(row.id)"
|
||||
>
|
||||
{{ row.subscribe_price_change === 0 ? '订阅' : '不订阅' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #see_rate="{ row }">
|
||||
<Tag
|
||||
:color="Number(row.see_rate) === 1 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateSeeRate(row.id)"
|
||||
>
|
||||
{{ Number(row.see_rate) === 1 ? '可查看' : '不可查看' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #allow_insurance_category="{ row }">
|
||||
<Tag
|
||||
:color="Number(row.allow_insurance_category) === 1 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateAllowInsurance(row.id)"
|
||||
>
|
||||
{{ Number(row.allow_insurance_category) === 1 ? '可选医保' : '仅自费' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #salesperson_see_price="{ row }">
|
||||
<Tag
|
||||
:color="Number(row.salesperson_see_price) === 1 ? 'success' : 'default'"
|
||||
style="cursor: pointer"
|
||||
@click="updateSalespersonSeePrice(row.id)"
|
||||
>
|
||||
{{ Number(row.salesperson_see_price) === 1 ? '可见' : '不可见' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #start-time="{ row }">
|
||||
早:<Tag color="success">{{ row.start_time }}</Tag>
|
||||
<br />
|
||||
@@ -676,19 +635,4 @@ const handleSwitchClinicType = (row: any) => {
|
||||
.qr_code:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 诊所类型标签样式 */
|
||||
.clinic-type-tag {
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
17
apps/web-antd/src/views/system/system-config/api/index.ts
Normal file
17
apps/web-antd/src/views/system/system-config/api/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const prefix = 'system-config/';
|
||||
|
||||
export async function getSystemConfigList() {
|
||||
return requestClient.get<any>(`${prefix}list`);
|
||||
}
|
||||
|
||||
export async function saveSystemConfig(items: Array<{ config_key: string; config_value: string }>) {
|
||||
return requestClient.post<any>(`${prefix}save`, { items });
|
||||
}
|
||||
|
||||
export async function getPriceAdjustConfig(storeId?: number) {
|
||||
return requestClient.get<any>(`${prefix}price-adjust-config`, {
|
||||
params: storeId ? { store_id: storeId } : {},
|
||||
});
|
||||
}
|
||||
139
apps/web-antd/src/views/system/system-config/index.vue
Normal file
139
apps/web-antd/src/views/system/system-config/index.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
|
||||
|
||||
|
||||
import { Button, Card, Input, InputNumber, message, Radio, Space, Tag } from 'ant-design-vue';
|
||||
|
||||
|
||||
|
||||
import type { QuickDiscountOption } from '#/utils/pricePercentAdjust';
|
||||
|
||||
|
||||
|
||||
import { getSystemConfigList, saveSystemConfig } from './api';
|
||||
|
||||
|
||||
|
||||
defineOptions({ name: 'SystemConfig' });
|
||||
|
||||
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
const saving = ref(false);
|
||||
|
||||
const scope = ref<'both' | 'sale_only'>('sale_only');
|
||||
|
||||
const quickOptions = ref<QuickDiscountOption[]>([
|
||||
|
||||
{ name: '九五折', value: 95 },
|
||||
|
||||
{ name: '九折', value: 90 },
|
||||
|
||||
{ name: '八五折', value: 85 },
|
||||
|
||||
{ name: '八折', value: 80 },
|
||||
|
||||
{ name: '涨10%', value: 110 },
|
||||
|
||||
{ name: '涨20%', value: 120 },
|
||||
|
||||
]);
|
||||
|
||||
const newQuickName = ref('');
|
||||
|
||||
const newQuickValue = ref<number | null>(null);
|
||||
|
||||
|
||||
|
||||
function parseQuickOptions(raw: unknown): QuickDiscountOption[] {
|
||||
|
||||
if (typeof raw === 'string') {
|
||||
|
||||
try {
|
||||
|
||||
const parsed = JSON.parse(raw);
|
||||
|
||||
return parseQuickOptions(parsed);
|
||||
|
||||
} catch {
|
||||
|
||||
return quickOptions.value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!Array.isArray(raw)) return quickOptions.value;
|
||||
|
||||
const list: QuickDiscountOption[] = [];
|
||||
|
||||
for (const item of raw) {
|
||||
|
||||
if (item && typeof item === 'object' && 'value' in item) {
|
||||
|
||||
const val = Number((item as QuickDiscountOption).value);
|
||||
|
||||
if (val > 0) list.push({ name: String((item as QuickDiscountOption).name || `${val}%`), value: val });
|
||||
|
||||
} else if (typeof item === 'number' && item > 0) {
|
||||
|
||||
list.push({ name: `${item}%`, value: item });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list.length ? list : quickOptions.value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function load() {
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
|
||||
const list = await getSystemConfigList();
|
||||
|
||||
const rows = Array.isArray(list) ? list : list?.data || [];
|
||||
|
||||
for (const row of rows) {
|
||||
|
||||
if (row.config_key === 'order_price_adjust_scope') {
|
||||
|
||||
scope.value = row.config_value === 'both' ? 'both' : 'sale_only';
|
||||
|
||||
}
|
||||
|
||||
if (row.config_key === 'order_discount_quick_options') {
|
||||
|
||||
quickOptions.value = parseQuickOptions(row.config_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
||||
loading.value = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addQuick() {
|
||||
|
||||
const v = Number(newQuickValue.value);
|
||||
|
||||
const name = String(newQuickName.value || '').trim();
|
||||
Reference in New Issue
Block a user