Files
xk-doctor-wx/subPackages/sub_platform_admin/store/detail.vue
2026-06-09 17:02:13 +08:00

201 lines
7.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<store-page-layout title="门店详情" :show-back="true">
<view class="page" v-if="store.id">
<view class="hero-card">
<text class="name">{{ store.name }}</text>
<text class="sub">ID {{ store.id }} · {{ clinicTypeText(store.clinic_type) }}</text>
<text class="addr">{{ store.position || '暂无地址' }}</text>
</view>
<view class="section">
<text class="section-title">门店配置</text>
<view class="switch-row">
<text>推广员可见价格</text>
<switch :checked="Number(store.salesperson_see_price) === 1" color="#6ACDBB" @change="toggleSeePrice" />
</view>
<view class="switch-row">
<text>包邮</text>
<switch :checked="Number(store.is_shipping_free) === 1" color="#6ACDBB" @change="toggleShipping" />
</view>
<view class="switch-row">
<text>订阅价格波动</text>
<switch :checked="Number(store.subscribe_price_change) === 0" color="#6ACDBB" @change="toggleSubscribe" />
</view>
<view class="switch-row">
<text>查看毛利率</text>
<switch :checked="Number(store.see_rate) === 1" color="#6ACDBB" @change="toggleSeeRate" />
</view>
<view class="switch-row">
<text>开方可选医保</text>
<switch :checked="Number(store.allow_insurance_category) === 1" color="#6ACDBB" @change="toggleInsurance" />
</view>
<view class="picker-row">
<text>诊所类型</text>
<picker :range="clinicTypeLabels" :value="clinicTypeIndex" @change="onClinicType">
<view class="picker-val">{{ clinicTypeLabels[clinicTypeIndex] }}</view>
</picker>
</view>
</view>
<view class="section">
<text class="section-title">快捷操作</text>
<view class="action-grid">
<view class="action-btn" @click="goEdit">编辑资料</view>
<view class="action-btn" @click="goDrugPrice">修改药品价格</view>
<view class="action-btn" @click="goConsultation">在线复诊配置</view>
<view class="action-btn" @click="goPromoters">管理推广员</view>
<view class="action-btn" @click="openQr">诊所二维码</view>
<view class="action-btn warn" @click="openPc">开通后台</view>
</view>
</view>
<view v-if="store.online_consultation_doctor_name || store.delegate_store_name" class="section">
<text class="section-title">在线复诊</text>
<text v-if="store.delegate_store_name" class="info-line">委托诊所{{ store.delegate_store_name }}</text>
<text v-if="store.online_consultation_doctor_name" class="info-line">负责人{{ store.online_consultation_doctor_name }}</text>
</view>
</view>
</store-page-layout>
</template>
<script>
import StorePageLayout from '@/subPackages/sub_platform_admin/components/store-page-layout.vue';
import {
getPlatformStoreDetail,
toggleSalespersonSeePrice,
updateStoreShippingFree,
updateStoreSubscribeStatus,
updateStoreSeeRate,
updateStoreAllowInsurance,
updateStoreClinicType,
openStorePcWindows,
openStoreQrCode,
} from '@/api/platformStore.js';
import { openQrCodePreview, buildClinicQrPayload } from '@/utils/qrCodePreview.js';
const ROOT = '/subPackages/sub_platform_admin/store';
const MANAGE_ROOT = '/subPackages/sub_salesperson_manage';
export default {
components: { StorePageLayout },
data() {
return {
storeId: 0,
store: {},
clinicTypeLabels: ['未设置', '西医诊所', '中医诊所'],
};
},
computed: {
clinicTypeIndex() {
return Number(this.store.clinic_type) || 0;
},
},
onLoad(options) {
this.storeId = Number(options.id || 0);
this.loadDetail();
},
methods: {
clinicTypeText(type) {
return this.clinicTypeLabels[Number(type) || 0] || '未设置';
},
async loadDetail() {
if (!this.storeId) return;
const wrap = await getPlatformStoreDetail(this.storeId);
if (wrap && wrap.ok) {
this.store = wrap.data || {};
}
},
async toggleSeePrice() {
const wrap = await toggleSalespersonSeePrice(this.storeId);
if (wrap && wrap.ok && wrap.data) {
this.store.salesperson_see_price = wrap.data.see_price;
}
},
async toggleShipping() {
const wrap = await updateStoreShippingFree(this.storeId);
if (wrap && wrap.ok) await this.loadDetail();
},
async toggleSubscribe() {
const wrap = await updateStoreSubscribeStatus(this.storeId);
if (wrap && wrap.ok) await this.loadDetail();
},
async toggleSeeRate() {
const wrap = await updateStoreSeeRate(this.storeId);
if (wrap && wrap.ok) await this.loadDetail();
},
async toggleInsurance() {
const wrap = await updateStoreAllowInsurance(this.storeId);
if (wrap && wrap.ok) await this.loadDetail();
},
async onClinicType(e) {
const idx = Number(e.detail.value);
if (idx <= 0) return;
const wrap = await updateStoreClinicType(this.storeId, idx);
if (wrap && wrap.ok) {
this.store.clinic_type = idx;
uni.showToast({ title: '已更新', icon: 'success' });
}
},
goEdit() {
uni.navigateTo({ url: `${ROOT}/edit?id=${this.storeId}` });
},
goDrugPrice() {
uni.navigateTo({ url: `${ROOT}/drug-price?id=${this.storeId}&name=${encodeURIComponent(this.store.name || '')}` });
},
goConsultation() {
uni.navigateTo({ url: `${ROOT}/consultation?id=${this.storeId}` });
},
goPromoters() {
uni.navigateTo({ url: `${MANAGE_ROOT}/index?mode=platform&store_id=${this.storeId}` });
},
async openQr() {
uni.showLoading({ title: '生成中' });
try {
const wrap = await openStoreQrCode(this.storeId);
if (wrap && wrap.ok) {
await this.loadDetail();
const payload = buildClinicQrPayload(this.store);
openQrCodePreview({ type: 'clinic', title: this.store.name, payload: payload.payload });
}
} finally {
uni.hideLoading();
}
},
async openPc() {
uni.showModal({
title: '开通后台',
content: '确定为该诊所开通 PC 后台账号?',
success: async (res) => {
if (!res.confirm) return;
const wrap = await openStorePcWindows(this.storeId);
if (wrap && wrap.ok) {
uni.showToast({ title: '开通成功', icon: 'success' });
}
},
});
},
},
};
</script>
<style lang="scss" scoped>
.page { padding: 24rpx; }
.hero-card { background: linear-gradient(135deg, #6acdbb, #4db6a8); border-radius: 20rpx; padding: 32rpx; color: #fff; margin-bottom: 24rpx; }
.name { display: block; font-size: 36rpx; font-weight: 700; }
.sub, .addr { display: block; font-size: 24rpx; margin-top: 8rpx; opacity: 0.9; }
.section { background: #fff; border-radius: 20rpx; padding: 24rpx; margin-bottom: 20rpx; }
.section-title { display: block; font-size: 28rpx; font-weight: 600; margin-bottom: 16rpx; }
.switch-row, .picker-row {
display: flex; justify-content: space-between; align-items: center;
padding: 20rpx 0; border-bottom: 1rpx solid #f0f0f0; font-size: 28rpx;
}
.picker-val { color: #6ACDBB; }
.action-grid { display: flex; flex-wrap: wrap; gap: 16rpx; }
.action-btn {
flex: 1; min-width: 40%; text-align: center; padding: 20rpx;
background: #f0fbf8; color: #6ACDBB; border-radius: 12rpx; font-size: 26rpx;
}
.action-btn.warn { background: #FEF3C7; color: #D97706; }
.info-line { display: block; font-size: 26rpx; color: #666; margin-bottom: 8rpx; }
</style>