1. 特色方功能迭代
This commit is contained in:
9
.cursor/rules/Code-Standards.mdc
Normal file
9
.cursor/rules/Code-Standards.mdc
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
description:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
|
||||
2. 注意不要生成太多的空行,上一部分代码和下一部分代码中间的空行不要大于2行
|
||||
3. 有封装好的方法、组件需要复用,不要重复造轮子
|
||||
4. 小程序端的抽屉全部需要用page-container来防止用户意外退出页面
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -118,3 +118,4 @@ dist
|
||||
/.idea/
|
||||
/database/
|
||||
/utils/utils.js
|
||||
/.cursor/skills/
|
||||
|
||||
3
.idea/inspectionProfiles/Project_Default.xml
generated
3
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -14,7 +14,7 @@
|
||||
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myValues">
|
||||
<value>
|
||||
<list size="16">
|
||||
<list size="17">
|
||||
<item index="0" class="java.lang.String" itemvalue="nobr" />
|
||||
<item index="1" class="java.lang.String" itemvalue="noembed" />
|
||||
<item index="2" class="java.lang.String" itemvalue="comment" />
|
||||
@@ -31,6 +31,7 @@
|
||||
<item index="13" class="java.lang.String" itemvalue="u-form-item" />
|
||||
<item index="14" class="java.lang.String" itemvalue="u-checkbox-group" />
|
||||
<item index="15" class="java.lang.String" itemvalue="u-checkbox" />
|
||||
<item index="16" class="java.lang.String" itemvalue="u-parse" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
|
||||
@@ -49,13 +49,25 @@ export async function createSpecialPrescriptionPatientRecordApi(params) {
|
||||
return await post('/special-prescription/create-patient-record', params, 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存特色方挂号上下文(merge 已有值,避免后续页面未传 sku_id 时覆盖为 0)
|
||||
* @param ctx {{ special_prescription_id, dose_count?, sku_id?, doctor_id? }}
|
||||
*/
|
||||
export function saveSpecialPrescriptionRegisterContext(ctx) {
|
||||
if (!ctx || !ctx.special_prescription_id) return
|
||||
uni.setStorageSync(SPECIAL_PRESCRIPTION_STORAGE_KEY, {
|
||||
const prev = getSpecialPrescriptionRegisterContext() || {}
|
||||
const merged = {
|
||||
special_prescription_id: ctx.special_prescription_id,
|
||||
dose_count: ctx.dose_count || 1,
|
||||
doctor_id: ctx.doctor_id || '',
|
||||
})
|
||||
dose_count: ctx.dose_count != null ? ctx.dose_count : (prev.dose_count || 1),
|
||||
doctor_id: ctx.doctor_id != null ? ctx.doctor_id : (prev.doctor_id || ''),
|
||||
}
|
||||
// 未传 sku_id 字段时保留 storage 已有值,防止中间页覆盖为 0
|
||||
if (Object.prototype.hasOwnProperty.call(ctx, 'sku_id')) {
|
||||
merged.sku_id = Number(ctx.sku_id) || 0
|
||||
} else {
|
||||
merged.sku_id = Number(prev.sku_id) || 0
|
||||
}
|
||||
uni.setStorageSync(SPECIAL_PRESCRIPTION_STORAGE_KEY, merged)
|
||||
}
|
||||
|
||||
export function getSpecialPrescriptionRegisterContext() {
|
||||
@@ -80,6 +92,7 @@ export async function tryCreateSpecialPrescriptionPatientRecord(registerId) {
|
||||
register_id: registerId,
|
||||
special_prescription_id: ctx.special_prescription_id,
|
||||
dose_count: ctx.dose_count || 1,
|
||||
sku_id: ctx.sku_id || 0,
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
doctor_id: ctx.doctor_id,
|
||||
})
|
||||
|
||||
@@ -191,11 +191,16 @@ export default {
|
||||
}
|
||||
this.delegateStoreId = e.delegate_store_id || '';
|
||||
if (e.special_prescription_id) {
|
||||
saveSpecialPrescriptionRegisterContext({
|
||||
const spCtx = {
|
||||
special_prescription_id: e.special_prescription_id,
|
||||
dose_count: e.special_prescription_dose_count || 1,
|
||||
doctor_id: e.id || '',
|
||||
});
|
||||
};
|
||||
// 仅 URL 带参时才写入 sku_id,避免 0 覆盖 detail 页已保存的 SKU
|
||||
if (e.special_prescription_sku_id != null && e.special_prescription_sku_id !== '') {
|
||||
spCtx.sku_id = Number(e.special_prescription_sku_id);
|
||||
}
|
||||
saveSpecialPrescriptionRegisterContext(spCtx);
|
||||
}
|
||||
this.setNavTitle(STEP1_TITLE);
|
||||
},
|
||||
|
||||
@@ -32,11 +32,15 @@
|
||||
onLoad(e) {
|
||||
this.register_id = e.id
|
||||
if (e.special_prescription_id) {
|
||||
saveSpecialPrescriptionRegisterContext({
|
||||
const spCtx = {
|
||||
special_prescription_id: e.special_prescription_id,
|
||||
dose_count: e.special_prescription_dose_count || 1,
|
||||
doctor_id: e.doctor_id || '',
|
||||
})
|
||||
}
|
||||
if (e.special_prescription_sku_id != null && e.special_prescription_sku_id !== '') {
|
||||
spCtx.sku_id = Number(e.special_prescription_sku_id)
|
||||
}
|
||||
saveSpecialPrescriptionRegisterContext(spCtx)
|
||||
}
|
||||
this.bindSpecialPrescriptionRecord()
|
||||
},
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
<MessageNotification />
|
||||
|
||||
<view v-if="loading" class="loading-wrap">
|
||||
<u-loading mode="circle" size="48"></u-loading>
|
||||
<u-loading mode="circle" size="48" color="#4175EE"></u-loading>
|
||||
</view>
|
||||
|
||||
<block v-else-if="detail.id">
|
||||
<!-- 顶部轮播 -->
|
||||
<!-- STREAMING_CHUNK:渲染顶部轮播图 -->
|
||||
<view class="swiper-section">
|
||||
<swiper
|
||||
class="swiper"
|
||||
indicator-dots
|
||||
autoplay
|
||||
circular
|
||||
indicator-color="rgba(0,0,0,0.1)"
|
||||
indicator-active-color="#4175EE"
|
||||
indicator-color="rgba(255,255,255,0.6)"
|
||||
indicator-active-color="#ffffff"
|
||||
>
|
||||
<swiper-item v-for="(img, index) in displayImages" :key="index">
|
||||
<image
|
||||
@@ -28,9 +28,13 @@
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<!-- STREAMING_CHUNK:渲染上浮卡片式基本信息 -->
|
||||
<view class="info-container-price">
|
||||
<view class="basic-info">
|
||||
<view class="price-row">
|
||||
<!-- 价格区:渐变背景装饰 -->
|
||||
<view class="price-panel">
|
||||
<view class="price-bg-decor"></view>
|
||||
<view class="price-content">
|
||||
<view class="price-left" v-if="detail.price_available !== false">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="amount">{{ detail.price_per_dose }}</text>
|
||||
@@ -39,19 +43,35 @@
|
||||
<view class="price-left price-left--unavailable" v-else>
|
||||
<text class="amount">暂无报价</text>
|
||||
</view>
|
||||
<text class="sales" v-if="detail.sales_count">已售 {{ detail.sales_count }}</text>
|
||||
<view class="sales-box" v-if="detail.sales_count">
|
||||
<u-icon name="shopping-cart" size="24" color="#FF8D1A"></u-icon>
|
||||
<text class="sales-text">已售 {{ detail.sales_count }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="title">{{ detail.name }}</view>
|
||||
<!-- 标题与标签区 -->
|
||||
<view class="title-panel">
|
||||
<view class="title">
|
||||
<text class="title-text">{{ detail.name }}</text>
|
||||
</view>
|
||||
|
||||
<view class="tag-row" v-if="detail.tags && detail.tags.length">
|
||||
<text class="tag" v-for="(tag, idx) in detail.tags" :key="idx">{{ tag }}</text>
|
||||
<view class="tag-item" v-for="(tag, idx) in detail.tags" :key="idx">
|
||||
<text class="tag-text">{{ tag }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-container">
|
||||
|
||||
<!-- 图文介绍 -->
|
||||
<!-- STREAMING_CHUNK:渲染图文介绍 -->
|
||||
<view class="intro-section" v-if="detail.intro_text || (detail.introduction_images && detail.introduction_images.length)">
|
||||
<view class="section-title">详情介绍</view>
|
||||
<view class="section-title">
|
||||
<view class="title-decor-line"></view>
|
||||
<text class="title-text">详情介绍</text>
|
||||
</view>
|
||||
<view class="intro-text" v-if="detail.intro_text">
|
||||
<u-parse :html="detail.intro_text"></u-parse>
|
||||
</view>
|
||||
@@ -66,16 +86,19 @@
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作 -->
|
||||
<!-- STREAMING_CHUNK:渲染适度抬高的悬浮操作按钮 -->
|
||||
<view class="footer-spacer"></view>
|
||||
<view class="footer safe-area-inset-bottom">
|
||||
<view class="floating-action-bar safe-area-inset-bottom">
|
||||
<button
|
||||
class="register-btn"
|
||||
:class="{ 'register-btn--disabled': detail.price_available === false }"
|
||||
class="register-btn-float"
|
||||
:class="{ 'register-btn-float--disabled': detail.price_available === false }"
|
||||
:disabled="detail.price_available === false"
|
||||
@click="goRegister"
|
||||
>去挂号选方</button>
|
||||
>
|
||||
<text>去挂号选方</text>
|
||||
</button>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
@@ -84,45 +107,98 @@
|
||||
</view>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<page-container :show="registerDrawerShow" :overlay="false" @leave="onPageBackGuardLeave" />
|
||||
<page-container :v-if="registerDrawerShow" :overlay="false" @leave="onPageBackGuardLeave" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- STREAMING_CHUNK:渲染包含自定义项的SKU抽屉 -->
|
||||
<u-popup
|
||||
v-model="registerDrawerShow"
|
||||
mode="bottom"
|
||||
border-radius="24"
|
||||
border-radius="32"
|
||||
safe-area-inset-bottom
|
||||
closeable
|
||||
close-icon-color="#999"
|
||||
@close="onRegisterDrawerClose"
|
||||
>
|
||||
<view class="register-drawer">
|
||||
<view class="drawer-header">
|
||||
<text class="drawer-title">确认贴数</text>
|
||||
<view class="drawer-close" @tap="closeRegisterDrawer">
|
||||
<u-icon name="close" size="32" color="#999"></u-icon>
|
||||
<image class="header-img" :src="displayImages[0]" mode="aspectFill"></image>
|
||||
<view class="header-info">
|
||||
<view class="header-price">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="amount">{{ unitPrice }}</text>
|
||||
<text class="unit">/贴</text>
|
||||
</view>
|
||||
<text class="header-stock">
|
||||
已选:{{ selectedSkuId === 0 ? '自定义贴数' : (selectedSku ? selectedSku.sku_name : '') }} {{ doseCount }}贴
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="drawer-dose-row">
|
||||
<text class="dose-label">贴数</text>
|
||||
<scroll-view scroll-y class="drawer-scroll-area">
|
||||
<view class="drawer-section">
|
||||
<text class="section-label">规格选择</text>
|
||||
<view class="sku-list">
|
||||
<!-- STREAMING_CHUNK:自定义贴数 SKU 胶囊 (带动态价格) -->
|
||||
<view
|
||||
class="sku-item"
|
||||
:class="{ 'sku-item--active': Number(selectedSkuId) === 0 }"
|
||||
@tap="selectCustomSku"
|
||||
>
|
||||
<text class="sku-name">自定义贴数</text>
|
||||
<text class="sku-price" v-if="detail.price_available !== false && customSkuDisplayPrice > 0">
|
||||
¥{{ customSkuDisplayPrice }}
|
||||
</text>
|
||||
|
||||
<view class="active-triangle" v-if="Number(selectedSkuId) === 0">
|
||||
<u-icon name="checkbox-mark" size="16" color="#fff" class="triangle-icon"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 真实的 SKU 列表 -->
|
||||
<view
|
||||
v-for="sku in detail.skus"
|
||||
:key="sku.id"
|
||||
class="sku-item"
|
||||
:class="{ 'sku-item--active': Number(selectedSkuId) === Number(sku.id) }"
|
||||
@tap="selectSku(sku)"
|
||||
>
|
||||
<text class="sku-name">{{ sku.sku_name }}</text>
|
||||
<text class="sku-price" v-if="sku.sale_price > 0">¥{{ sku.sale_price }}</text>
|
||||
|
||||
<view class="active-triangle" v-if="Number(selectedSkuId) === Number(sku.id)">
|
||||
<u-icon name="checkbox-mark" size="16" color="#fff" class="triangle-icon"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步进器部分 -->
|
||||
<view class="drawer-section dose-section">
|
||||
<text class="section-label">贴数</text>
|
||||
<u-number-box
|
||||
v-model="doseCount"
|
||||
:min="1"
|
||||
:max="99"
|
||||
integer
|
||||
:input-width="90"
|
||||
:input-height="56"
|
||||
bg-color="#F5F7FA"
|
||||
@change="onDoseCountChange"
|
||||
></u-number-box>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="drawer-price-row">
|
||||
<text class="price-label">单价</text>
|
||||
<text class="price-value">¥{{ detail.price_per_dose }}/贴</text>
|
||||
</view>
|
||||
|
||||
<view class="drawer-total-row">
|
||||
<view class="drawer-footer">
|
||||
<view class="total-info">
|
||||
<text class="total-label">预估金额</text>
|
||||
<text class="total-price">¥{{ totalPrice }}</text>
|
||||
<view class="total-price-box">
|
||||
<text class="total-symbol">¥</text>
|
||||
<text class="total-price">{{ totalPrice }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<button class="confirm-btn" @click="confirmRegister">确认挂号</button>
|
||||
</view>
|
||||
|
||||
<button class="confirm-btn" @click="confirmRegister">确认并挂号</button>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
@@ -131,6 +207,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* STREAMING_CHUNK:引入依赖文件 */
|
||||
import {
|
||||
getSpecialPrescriptionDetailApi,
|
||||
saveSpecialPrescriptionRegisterContext,
|
||||
@@ -143,12 +220,14 @@ export default {
|
||||
id: '',
|
||||
detail: {},
|
||||
doseCount: 1,
|
||||
selectedSkuId: 0,
|
||||
loading: true,
|
||||
registerDrawerShow: false,
|
||||
defaultCover: 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/* STREAMING_CHUNK:计算属性 */
|
||||
displayImages() {
|
||||
const images = []
|
||||
if (this.detail.cover_image) {
|
||||
@@ -163,16 +242,42 @@ export default {
|
||||
}
|
||||
return images.length ? images : [this.defaultCover]
|
||||
},
|
||||
hasSkus() {
|
||||
return Array.isArray(this.detail.skus) && this.detail.skus.length > 0
|
||||
},
|
||||
selectedSku() {
|
||||
if (!this.hasSkus || Number(this.selectedSkuId) === 0) return null
|
||||
return this.detail.skus.find((item) => Number(item.id) === Number(this.selectedSkuId)) || null
|
||||
},
|
||||
unitPrice() {
|
||||
return parseFloat(this.detail.price_per_dose || 0).toFixed(2)
|
||||
},
|
||||
// 为自定义贴数单独提供展示价格
|
||||
customSkuDisplayPrice() {
|
||||
return parseFloat(this.detail.price_per_dose || 0).toFixed(2)
|
||||
},
|
||||
totalPrice() {
|
||||
if (this.detail.price_available === false) {
|
||||
return '0.00'
|
||||
}
|
||||
if (this.selectedSku && Number(this.selectedSku.sale_price) > 0) {
|
||||
return parseFloat(this.selectedSku.sale_price || 0).toFixed(2)
|
||||
}
|
||||
return calculateSpecialPrescriptionEstimatedTotal(
|
||||
this.detail.price_per_dose,
|
||||
this.doseCount,
|
||||
)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
/* STREAMING_CHUNK:监听器处理 */
|
||||
doseCount(newVal) {
|
||||
if (this._suppressDoseSkuClear) {
|
||||
return
|
||||
}
|
||||
this.selectedSkuId = 0
|
||||
},
|
||||
},
|
||||
onLoad(e) {
|
||||
this.id = e.id || ''
|
||||
if (this.id) {
|
||||
@@ -182,6 +287,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* STREAMING_CHUNK:核心方法与生命周期 */
|
||||
getStoreId() {
|
||||
return uni.getStorageSync('store_id') || '11001'
|
||||
},
|
||||
@@ -194,6 +300,7 @@ export default {
|
||||
})
|
||||
if (res.data?.code === 0 || res.data?.code === '0') {
|
||||
this.detail = res.data.result || {}
|
||||
this.initSkuSelection()
|
||||
} else {
|
||||
this.$refs.uToast && this.$refs.uToast.show({
|
||||
title: res.data?.message || '加载失败',
|
||||
@@ -207,6 +314,46 @@ export default {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
initSkuSelection() {
|
||||
const skus = this.detail.skus || []
|
||||
if (skus.length > 0 && this.detail.default_sku_id) {
|
||||
const defaultId = Number(this.detail.default_sku_id || 0)
|
||||
const defaultSku = skus.find((item) => Number(item.is_default) === 1)
|
||||
|| skus.find((item) => Number(item.id) === defaultId)
|
||||
|
||||
if (defaultSku) {
|
||||
this._suppressDoseSkuClear = true
|
||||
this.selectedSkuId = Number(defaultSku.id)
|
||||
this.doseCount = defaultSku.dose_count || 1
|
||||
this.$nextTick(() => {
|
||||
this._suppressDoseSkuClear = false
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.selectedSkuId = 0
|
||||
this.doseCount = 1
|
||||
},
|
||||
selectCustomSku() {
|
||||
this.selectedSkuId = 0
|
||||
},
|
||||
selectSku(sku) {
|
||||
this._suppressDoseSkuClear = true
|
||||
if (Number(this.selectedSkuId) === Number(sku.id)) {
|
||||
this.selectedSkuId = 0
|
||||
} else {
|
||||
this.selectedSkuId = Number(sku.id)
|
||||
this.doseCount = sku.dose_count || 1
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this._suppressDoseSkuClear = false
|
||||
})
|
||||
},
|
||||
onDoseCountChange(e) {
|
||||
if (this._suppressDoseSkuClear) return
|
||||
this.selectedSkuId = 0
|
||||
},
|
||||
previewImage(index) {
|
||||
uni.previewImage({
|
||||
urls: this.displayImages,
|
||||
@@ -268,9 +415,14 @@ export default {
|
||||
return
|
||||
}
|
||||
|
||||
const skuId = this.selectedSku
|
||||
? Number(this.selectedSku.id)
|
||||
: 0
|
||||
|
||||
const ctx = {
|
||||
special_prescription_id: this.detail.id,
|
||||
dose_count: this.doseCount,
|
||||
sku_id: skuId,
|
||||
doctor_id: doctorId,
|
||||
}
|
||||
saveSpecialPrescriptionRegisterContext(ctx)
|
||||
@@ -278,23 +430,38 @@ export default {
|
||||
this._suppressPageBackGuardLeave = true
|
||||
this.registerDrawerShow = false
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/doctor/doctor-userinfo?id=${doctorId}&r_type=0&special_prescription_id=${ctx.special_prescription_id}&special_prescription_dose_count=${ctx.dose_count}`,
|
||||
})
|
||||
let url = `/subPackages/doctor/doctor-userinfo?id=${doctorId}&r_type=0&special_prescription_id=${ctx.special_prescription_id}&special_prescription_dose_count=${ctx.dose_count}`
|
||||
if (ctx.sku_id) {
|
||||
url += `&special_prescription_sku_id=${ctx.sku_id}`
|
||||
}
|
||||
uni.navigateTo({ url })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* STREAMING_CHUNK:定义全局样式与主题变量 */
|
||||
$sp-primary: #4175EE;
|
||||
$sp-primary-light: rgba(65, 117, 238, 0.1);
|
||||
$sp-gradient: linear-gradient(90deg, #4175EE 0%, #298DFF 100%);
|
||||
$sp-primary-light: #EBF1FF;
|
||||
$sp-price: #FF4F23;
|
||||
$sp-price-bg: linear-gradient(135deg, #FFF1EB 0%, #FFFAFA 100%);
|
||||
$sp-text-main: #222222;
|
||||
$sp-text-sub: #666666;
|
||||
$sp-text-muted: #999999;
|
||||
$sp-bg: #F4F5F7;
|
||||
$sp-gradient-btn: linear-gradient(90deg, #5C8CFF 0%, #3567E8 100%);
|
||||
|
||||
view, text, scroll-view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background: #F5F7FA;
|
||||
padding-bottom: 140rpx;
|
||||
background: $sp-bg;
|
||||
/* 调整底部留白,适应稍微降低的悬浮按钮 */
|
||||
padding-bottom: calc(150rpx + env(safe-area-inset-bottom));
|
||||
//padding-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.loading-wrap,
|
||||
@@ -302,241 +469,438 @@ $sp-gradient: linear-gradient(90deg, #4175EE 0%, #298DFF 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 60vh;
|
||||
min-height: 70vh;
|
||||
}
|
||||
|
||||
/* 轮播图样式 */
|
||||
.swiper-section {
|
||||
.swiper {
|
||||
height: 750rpx;
|
||||
width: 100%;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.swiper-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
/* 详情页面装饰增强 */
|
||||
.info-container-price {
|
||||
position: relative;
|
||||
margin-top: -32rpx;
|
||||
z-index: 10;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
/* 详情页面装饰增强 */
|
||||
.info-container {
|
||||
position: relative;
|
||||
margin-top: -32rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.price-row {
|
||||
.basic-info {
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.price-panel {
|
||||
position: relative;
|
||||
padding: 32rpx 24rpx;
|
||||
background: $sp-price-bg;
|
||||
|
||||
.price-bg-decor {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 200rpx;
|
||||
height: 100%;
|
||||
background: radial-gradient(circle at 100% 0%, rgba(255, 79, 35, 0.08) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.price-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.price-left {
|
||||
color: #FF5722;
|
||||
color: $sp-price;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.symbol {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 48rpx;
|
||||
font-size: 56rpx;
|
||||
font-weight: 800;
|
||||
font-family: 'DIN Alternate', sans-serif;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.unit {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 4rpx;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
&--unavailable .amount {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
font-size: 36rpx;
|
||||
color: $sp-text-muted;
|
||||
}
|
||||
}
|
||||
|
||||
.sales-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(255, 141, 26, 0.1);
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 24rpx;
|
||||
|
||||
.sales-text {
|
||||
font-size: 22rpx;
|
||||
color: #E67A15;
|
||||
margin-left: 6rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sales {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
.title-panel {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
color: $sp-text-main;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
|
||||
.tag {
|
||||
font-size: 22rpx;
|
||||
color: $sp-primary;
|
||||
background: $sp-primary-light;
|
||||
padding: 4rpx 16rpx;
|
||||
.tag-item {
|
||||
position: relative;
|
||||
background: #FAFAFA;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 12rpx;
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
.tag-text {
|
||||
font-size: 22rpx;
|
||||
color: $sp-text-sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro-section {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 32rpx 24rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 32rpx;
|
||||
position: relative;
|
||||
|
||||
.title-decor-line {
|
||||
position: absolute;
|
||||
bottom: 4rpx;
|
||||
width: 120rpx;
|
||||
height: 12rpx;
|
||||
background: linear-gradient(90deg, rgba(65, 117, 238, 0.3) 0%, transparent 100%);
|
||||
border-radius: 6rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 16rpx;
|
||||
border-left: 6rpx solid $sp-primary;
|
||||
color: $sp-text-main;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-images {
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.intro-img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
color: $sp-text-sub;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* STREAMING_CHUNK:底部适度抬高悬浮操作按钮 */
|
||||
.footer-spacer {
|
||||
height: 120rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
.footer {
|
||||
.floating-action-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
padding: 16rpx 32rpx;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
left: 32rpx;
|
||||
right: 32rpx;
|
||||
/* 调整悬浮高度:降低到 16rpx,更加稳重 */
|
||||
//bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
bottom: 50rpx;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.register-btn {
|
||||
.register-btn-float {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: $sp-gradient;
|
||||
height: 96rpx;
|
||||
background: $sp-gradient-btn;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 44rpx;
|
||||
border-radius: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
box-shadow: 0 12rpx 24rpx rgba(65, 117, 238, 0.3);
|
||||
transition: all 0.3s;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
&::after { border: none; }
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 6rpx 12rpx rgba(65, 117, 238, 0.2);
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background: #e0e0e0;
|
||||
color: #999;
|
||||
background: #E2E4E8;
|
||||
color: #B0B5C1;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 抽屉与包含自定义的精简版SKU样式 */
|
||||
.register-drawer {
|
||||
padding: 32rpx;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 75vh;
|
||||
|
||||
.drawer-header {
|
||||
width: 100%;
|
||||
padding: 32rpx;
|
||||
border-bottom: 1rpx solid #F2F3F5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 32rpx;
|
||||
position: relative;
|
||||
padding-right: 80rpx;
|
||||
|
||||
.header-img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 12rpx;
|
||||
background: $sp-bg;
|
||||
margin-right: 24rpx;
|
||||
border: 1rpx solid #EBEBEB;
|
||||
}
|
||||
|
||||
.drawer-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.drawer-close {
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.drawer-dose-row {
|
||||
.header-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24rpx;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 12rpx;
|
||||
|
||||
.dose-label {
|
||||
.header-price {
|
||||
color: $sp-price;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.symbol { font-size: 28rpx; font-weight: 600; }
|
||||
.amount { font-size: 48rpx; font-weight: 800; font-family: 'DIN Alternate', sans-serif;}
|
||||
.unit { font-size: 24rpx; color: $sp-text-muted; margin-left: 4rpx;}
|
||||
}
|
||||
|
||||
.header-stock {
|
||||
font-size: 24rpx;
|
||||
color: $sp-text-sub;
|
||||
background: #F7F7F7;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 8rpx;
|
||||
display: inline-block;
|
||||
align-self: flex-start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-scroll-area {
|
||||
width: 100%;
|
||||
max-height: 50vh;
|
||||
padding: 0 32rpx 40rpx;
|
||||
}
|
||||
|
||||
.drawer-section {
|
||||
margin-top: 32rpx;
|
||||
|
||||
.section-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
font-weight: 600;
|
||||
color: $sp-text-main;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-price-row {
|
||||
.sku-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.sku-item {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background: #F5F6F8;
|
||||
border: 2rpx solid transparent;
|
||||
padding: 14rpx 28rpx;
|
||||
border-radius: 40rpx;
|
||||
transition: all 0.2s;
|
||||
overflow: hidden;
|
||||
|
||||
.sku-name {
|
||||
font-size: 26rpx;
|
||||
color: $sp-text-main;
|
||||
}
|
||||
|
||||
.sku-name + .sku-price {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.sku-price {
|
||||
font-size: 24rpx;
|
||||
color: $sp-text-sub;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&--active {
|
||||
background: $sp-primary-light;
|
||||
border-color: $sp-primary;
|
||||
|
||||
.sku-name {
|
||||
color: $sp-primary;
|
||||
font-weight: 600;
|
||||
}
|
||||
.sku-price {
|
||||
color: $sp-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.active-triangle {
|
||||
position: absolute;
|
||||
right: -2rpx;
|
||||
bottom: -2rpx;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-bottom: 32rpx solid $sp-primary;
|
||||
border-left: 32rpx solid transparent;
|
||||
|
||||
.triangle-icon {
|
||||
position: absolute;
|
||||
right: 2rpx;
|
||||
bottom: -28rpx;
|
||||
transform: scale(0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dose-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
padding-top: 16rpx;
|
||||
|
||||
.price-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
.section-label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-total-row {
|
||||
.drawer-footer {
|
||||
width: 100%;
|
||||
padding: 20rpx 32rpx;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #F2F3F5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 0 32rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
|
||||
.total-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.total-label {
|
||||
font-size: 24rpx;
|
||||
color: $sp-text-sub;
|
||||
}
|
||||
|
||||
.total-price-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
color: $sp-price;
|
||||
}
|
||||
|
||||
.total-symbol {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 40rpx;
|
||||
font-size: 44rpx;
|
||||
font-weight: 800;
|
||||
color: #FF5722;
|
||||
font-family: 'DIN Alternate', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: $sp-gradient;
|
||||
margin: 0;
|
||||
width: 280rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: $sp-gradient-btn;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 44rpx;
|
||||
border-radius: 40rpx;
|
||||
border: none;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
&::after { border: none; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user