|
|
@@ -7,7 +7,7 @@
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="商品名称" prop="productName">
|
|
|
- <el-input
|
|
|
+ <el-inputa
|
|
|
v-model="queryParams.productName"
|
|
|
placeholder="请输入商品名称"
|
|
|
clearable
|
|
|
@@ -329,6 +329,13 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="销量" align="center" prop="sales" />
|
|
|
<el-table-column label="库存" align="center" prop="stock" />
|
|
|
+ <el-table-column label="活动类型" align="center" prop="activityType" width="100">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag v-if="scope.row.activityType === 6" type="danger" size="small">秒杀</el-tag>
|
|
|
+ <el-tag v-else-if="scope.row.activityType === 7" type="warning" size="small">限时折扣</el-tag>
|
|
|
+ <el-tag v-else type="info" size="small">无</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="类型" align="center" prop="productType" >
|
|
|
<template slot-scope="scope">
|
|
|
<el-tag prop="productType" v-for="(item, index) in productTypeOptions" v-if="scope.row.productType==item.dictValue">{{item.dictLabel}}</el-tag>
|
|
|
@@ -343,6 +350,14 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
|
|
<template slot-scope="scope">
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-s-flag"
|
|
|
+ @click="handleSetActivity(scope.row)"
|
|
|
+ v-hasPermi="['store:storeProduct:edit']"
|
|
|
+ v-if="scope.row.isAudit === '1'"
|
|
|
+ >设置活动</el-button>
|
|
|
<el-button
|
|
|
size="mini"
|
|
|
type="text"
|
|
|
@@ -960,6 +975,131 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
+ <!-- 设置活动弹窗 -->
|
|
|
+ <el-dialog title="设置活动" :visible.sync="activityDialogVisible" width="780px" append-to-body :close-on-click-modal="false">
|
|
|
+ <!-- 活动进行中提示 -->
|
|
|
+ <el-alert
|
|
|
+ v-if="activityIsOngoing"
|
|
|
+ :title="'当前商品正在' + (activityOngoingType === 6 ? '秒杀' : '限时折扣') + '活动中,活动进行期间无法修改活动设置'"
|
|
|
+ type="error"
|
|
|
+ :closable="false"
|
|
|
+ show-icon
|
|
|
+ style="margin-bottom:15px;"
|
|
|
+ />
|
|
|
+
|
|
|
+ <el-form ref="activityForm" :model="activityForm" :rules="activityRules" label-width="100px" :disabled="activityIsOngoing">
|
|
|
+ <!-- 活动类型 -->
|
|
|
+ <el-form-item label="活动类型" prop="activityType">
|
|
|
+ <el-radio-group v-model="activityForm.activityType">
|
|
|
+ <el-radio :label="0">不参与活动</el-radio>
|
|
|
+ <el-radio :label="6">
|
|
|
+ <i class="el-icon-lightning" style="color:#F56C6C;margin-right:2px;"></i>秒杀
|
|
|
+ </el-radio>
|
|
|
+ <el-radio :label="7">
|
|
|
+ <i class="el-icon-time" style="color:#E6A23C;margin-right:2px;"></i>限时折扣
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 统一活动时间(所有规格共用) -->
|
|
|
+ <template v-if="activityForm.activityType === 6 || activityForm.activityType === 7">
|
|
|
+ <el-form-item label="活动时间" prop="startTime">
|
|
|
+ <el-date-picker v-model="activityForm.startTime" type="datetime" placeholder="开始时间" value-format="yyyy-MM-dd HH:mm:ss" style="width:200px" size="small"/>
|
|
|
+ <span style="margin:0 8px;color:#909399;">至</span>
|
|
|
+ <el-date-picker v-model="activityForm.endTime" type="datetime" placeholder="结束时间" value-format="yyyy-MM-dd HH:mm:ss" style="width:200px" size="small"/>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="activityForm.activityType === 6 || activityForm.activityType === 7">
|
|
|
+ <!-- 选择参与规格 -->
|
|
|
+ <el-divider content-position="left">
|
|
|
+ <span style="font-size:14px;font-weight:500;">选择参与规格</span>
|
|
|
+ </el-divider>
|
|
|
+ <div class="spec-select-list">
|
|
|
+ <div
|
|
|
+ v-for="(spec, idx) in activityAllSpecs"
|
|
|
+ :key="idx"
|
|
|
+ :class="['spec-select-item', spec.selected ? 'spec-select-active' : '']"
|
|
|
+ @click="toggleSpecSelect(spec)"
|
|
|
+ >
|
|
|
+ <el-popover placement="right" trigger="hover" v-if="spec.image">
|
|
|
+ <img slot="reference" :src="spec.image" class="spec-thumb" />
|
|
|
+ <img :src="spec.image" style="max-width:200px;max-height:200px;" />
|
|
|
+ </el-popover>
|
|
|
+ <div class="spec-select-info">
|
|
|
+ <span class="spec-select-name">{{ spec.specName }}</span>
|
|
|
+ <span class="spec-select-detail">¥{{ spec.price }} · 库存{{ spec.specStock }}</span>
|
|
|
+ </div>
|
|
|
+ <i :class="spec.selected ? 'el-icon-circle-check' : 'el-icon-circle-plus-outline'" :style="{color: spec.selected ? '#409EFF' : '#C0C4CC', fontSize: '20px'}"></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 已选规格活动设置 -->
|
|
|
+ <template v-if="selectedSpecList.length > 0">
|
|
|
+ <el-divider content-position="left">
|
|
|
+ <span style="font-size:14px;font-weight:500;">规格活动设置</span>
|
|
|
+ <span style="font-size:12px;color:#909399;margin-left:8px;">已选 {{ selectedSpecList.length }} 项</span>
|
|
|
+ </el-divider>
|
|
|
+ <div class="activity-spec-list">
|
|
|
+ <div v-for="(spec, idx) in selectedSpecList" :key="idx" class="activity-spec-card">
|
|
|
+ <div class="spec-card-header">
|
|
|
+ <div class="spec-header-left">
|
|
|
+ <el-popover placement="right" trigger="hover" v-if="spec.image">
|
|
|
+ <img slot="reference" :src="spec.image" class="spec-thumb" />
|
|
|
+ <img :src="spec.image" style="max-width:200px;max-height:200px;" />
|
|
|
+ </el-popover>
|
|
|
+ <span class="spec-name">{{ spec.specName }}</span>
|
|
|
+ <i class="el-icon-remove-outline" style="color:#F56C6C;font-size:16px;cursor:pointer;margin-left:8px;" title="移除" @click="toggleSpecSelect(spec)"></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="spec-detail-row">
|
|
|
+ <span class="spec-detail-item">售价 <b>¥{{ spec.price }}</b></span>
|
|
|
+ <span class="spec-detail-item">代理价 <b>¥{{ spec.agentPrice }}</b></span>
|
|
|
+ <span class="spec-detail-item">成本价 <b>¥{{ spec.cost }}</b></span>
|
|
|
+ <span class="spec-detail-item">原价 <b>¥{{ spec.otPrice }}</b></span>
|
|
|
+ <span class="spec-detail-item">库存 <b>{{ spec.specStock }}</b></span>
|
|
|
+ <span class="spec-detail-item" v-if="spec.barCode">编号 <b>{{ spec.barCode }}</b></span>
|
|
|
+ </div>
|
|
|
+ <el-row :gutter="16" class="spec-card-body">
|
|
|
+ <!-- 秒杀价 -->
|
|
|
+ <el-col :span="12" v-if="activityForm.activityType === 6">
|
|
|
+ <div class="spec-field">
|
|
|
+ <label>秒杀价</label>
|
|
|
+ <el-input-number v-model="spec.flashPrice" :precision="2" :min="0" :max="spec.originalPrice" size="small" placeholder="秒杀价" style="width:100%" controls-position="right"/>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <!-- 折扣设置 -->
|
|
|
+ <el-col :span="8" v-if="activityForm.activityType === 7">
|
|
|
+ <div class="spec-field">
|
|
|
+ <label>折扣 <span style="color:#E6A23C;font-weight:500;">{{ spec.discountValue ? spec.discountValue.toFixed(1) : '10.0' }}折</span></label>
|
|
|
+ <el-slider v-model="spec.discountValue" :min="1" :max="10" :step="0.1" :show-tooltip="false" @change="handleSpecDiscountChange(spec)"/>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8" v-if="activityForm.activityType === 7">
|
|
|
+ <div class="spec-field">
|
|
|
+ <label>折扣价</label>
|
|
|
+ <el-input-number v-model="spec.discountPrice" :precision="2" :min="0" size="small" placeholder="折扣价" style="width:100%" controls-position="right" @change="handleSpecDiscountPriceChange(spec)"/>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div v-else style="text-align:center;padding:20px 0;color:#C0C4CC;font-size:13px;">
|
|
|
+ 请在上方选择需要参与活动的规格
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-form-item label="备注" style="margin-top:15px;">
|
|
|
+ <el-input v-model="activityForm.remark" type="textarea" :rows="2" placeholder="请输入备注" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer" v-if="!activityIsOngoing">
|
|
|
+ <el-button @click="activityDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitActivityForm" :loading="activitySubmitLoading">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -986,6 +1126,8 @@ import singleImg from '@/components/Material/single'
|
|
|
import { getCompanyList } from "@/api/company/company";
|
|
|
import { listStore } from '@/api/hisStore/store'
|
|
|
import {list as getAppMallOptions} from "@/api/course/coursePlaySourceConfig";
|
|
|
+import { getActivityByProductId, saveActivity } from "@/api/hisStore/productActivity";
|
|
|
+import { listStoreProductAttrValue } from "@/api/hisStore/storeProductAttrValue";
|
|
|
export default {
|
|
|
name: "HisStoreProduct",
|
|
|
components: {
|
|
|
@@ -1005,6 +1147,11 @@ export default {
|
|
|
this.form.drugImage = val.join(',');
|
|
|
}
|
|
|
},
|
|
|
+ computed: {
|
|
|
+ selectedSpecList() {
|
|
|
+ return this.activityAllSpecs.filter(s => s.selected);
|
|
|
+ }
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
isMedicalMall: this.$store.state.user.medicalMallConfig.medicalMall,
|
|
|
@@ -1084,6 +1231,24 @@ export default {
|
|
|
// 企业列表
|
|
|
companyOptions:[],
|
|
|
storeOptions:[],
|
|
|
+ // 活动设置相关
|
|
|
+ activityDialogVisible: false,
|
|
|
+ activityIsOngoing: false,
|
|
|
+ activityOngoingType: null,
|
|
|
+ activityCurrentProduct: null,
|
|
|
+ activitySubmitLoading: false,
|
|
|
+ activityForm: {
|
|
|
+ activityType: 0,
|
|
|
+ startTime: null,
|
|
|
+ endTime: null,
|
|
|
+ remark: null
|
|
|
+ },
|
|
|
+ activitySpecList: [],
|
|
|
+ activityAllSpecs: [],
|
|
|
+ activityRules: {
|
|
|
+ activityType: [{ required: true, message: '请选择活动类型', trigger: 'change' }],
|
|
|
+ startTime: [{ required: true, message: '请选择活动开始时间', trigger: 'change' }]
|
|
|
+ },
|
|
|
// 遮罩层
|
|
|
loading: true,
|
|
|
// 选中数组
|
|
|
@@ -1816,6 +1981,246 @@ export default {
|
|
|
this.msgSuccess("复制成功");
|
|
|
}).catch(function() {});
|
|
|
},
|
|
|
+ /** 设置活动按钮操作 */
|
|
|
+ handleSetActivity(row) {
|
|
|
+ // // 校验审核状态:只有审核通过的商品才能设置活动
|
|
|
+ // if (row.isAudit !== 1) {
|
|
|
+ // this.$message.warning('商品审核通过后才能设置活动');
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ this.activityCurrentProduct = row;
|
|
|
+ this.activityIsOngoing = false;
|
|
|
+ this.activityOngoingType = null;
|
|
|
+ this.activityForm = {
|
|
|
+ activityType: 0,
|
|
|
+ startTime: null,
|
|
|
+ endTime: null,
|
|
|
+ remark: null
|
|
|
+ };
|
|
|
+ this.activitySpecList = [];
|
|
|
+ this.activityAllSpecs = [];
|
|
|
+
|
|
|
+ // 先查询已有活动设置
|
|
|
+ getActivityByProductId(row.productId).then(res => {
|
|
|
+ const activityList = res.data || [];
|
|
|
+ this.activityIsOngoing = res.isOngoing || false;
|
|
|
+ this.activityOngoingType = res.ongoingActivityType || null;
|
|
|
+
|
|
|
+ if (activityList.length > 0) {
|
|
|
+ // 回显已有活动设置
|
|
|
+ const first = activityList[0];
|
|
|
+ this.activityForm.activityType = first.activityType || 0;
|
|
|
+ this.activityForm.remark = first.remark;
|
|
|
+ this.activityForm.startTime = first.startTime || null;
|
|
|
+ this.activityForm.endTime = first.endTime || null;
|
|
|
+ } else {
|
|
|
+ // 从商品表获取activityType
|
|
|
+ this.activityForm.activityType = row.activityType || 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加载商品规格数据
|
|
|
+ this.loadActivitySpecList(row.productId, activityList);
|
|
|
+
|
|
|
+ this.activityDialogVisible = true;
|
|
|
+ }).catch(() => {
|
|
|
+ // 查询失败时仍然打开弹窗,使用商品行数据
|
|
|
+ this.activityForm.activityType = row.activityType || 0;
|
|
|
+ this.loadActivitySpecList(row.productId, []);
|
|
|
+ this.activityDialogVisible = true;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 加载活动规格列表 */
|
|
|
+ loadActivitySpecList(productId, existActivityList) {
|
|
|
+ // 先获取商品基本信息(确定specType),再获取规格值列表
|
|
|
+ getStoreProduct(productId).then(res => {
|
|
|
+ const productData = res.data;
|
|
|
+ listStoreProductAttrValue({ productId: productId, pageNum: 1, pageSize: 999 }).then(attrRes => {
|
|
|
+ const attrValues = attrRes.rows || [];
|
|
|
+ let specList = attrValues.map(v => ({
|
|
|
+ specId: v.id,
|
|
|
+ specName: v.sku || ('规格' + v.id),
|
|
|
+ image: v.image || productData.image || null,
|
|
|
+ price: v.price || 0,
|
|
|
+ agentPrice: v.agentPrice || 0,
|
|
|
+ cost: v.cost || 0,
|
|
|
+ otPrice: v.otPrice || 0,
|
|
|
+ specStock: v.stock || 0,
|
|
|
+ barCode: v.barCode || '',
|
|
|
+ originalPrice: v.price || 0,
|
|
|
+ startTime: null,
|
|
|
+ endTime: null,
|
|
|
+ flashPrice: null,
|
|
|
+ discountValue: 10,
|
|
|
+ discount: null,
|
|
|
+ discountPrice: null,
|
|
|
+ stock: null,
|
|
|
+ selected: false
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 回显已有活动数据
|
|
|
+ this.mergeExistActivity(specList, existActivityList);
|
|
|
+ this.activityAllSpecs = specList;
|
|
|
+ })
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 切换规格选中状态 */
|
|
|
+ toggleSpecSelect(spec) {
|
|
|
+ spec.selected = !spec.selected;
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 合并已有活动数据到规格列表 */
|
|
|
+ mergeExistActivity(specList, existActivityList) {
|
|
|
+ if (existActivityList && existActivityList.length > 0) {
|
|
|
+ specList.forEach(spec => {
|
|
|
+ const matched = existActivityList.find(a => {
|
|
|
+ if (spec.specId !== null) {
|
|
|
+ return a.specId === spec.specId;
|
|
|
+ } else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (matched) {
|
|
|
+ spec.selected = true;
|
|
|
+ spec.flashPrice = matched.flashPrice;
|
|
|
+ spec.discount = matched.discount;
|
|
|
+ spec.discountPrice = matched.discountPrice;
|
|
|
+ spec.stock = matched.stock;
|
|
|
+ spec.originalPrice = matched.originalPrice || spec.originalPrice;
|
|
|
+ spec.startTime = matched.startTime;
|
|
|
+ spec.endTime = matched.endTime;
|
|
|
+ // 折扣值转换:discount存的是0.8格式,滑块需要8格式
|
|
|
+ if (matched.discount) {
|
|
|
+ spec.discountValue = Number((matched.discount * 10).toFixed(1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 折扣滑块变化时计算折扣价 */
|
|
|
+ handleSpecDiscountChange(row) {
|
|
|
+ if (row.originalPrice && row.discountValue) {
|
|
|
+ const discount = row.discountValue / 10;
|
|
|
+ row.discount = discount;
|
|
|
+ row.discountPrice = Math.round(row.originalPrice * discount * 100) / 100;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 折扣价变化时反算折扣 */
|
|
|
+ handleSpecDiscountPriceChange(row) {
|
|
|
+ if (row.originalPrice && row.discountPrice) {
|
|
|
+ const discount = row.discountPrice / row.originalPrice;
|
|
|
+ row.discount = Math.round(discount * 1000) / 1000;
|
|
|
+ row.discountValue = Math.round(discount * 100) / 10;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 提交活动设置 */
|
|
|
+ submitActivityForm() {
|
|
|
+ this.$refs['activityForm'].validate(valid => {
|
|
|
+ if (!valid) return;
|
|
|
+
|
|
|
+ const { activityType, remark } = this.activityForm;
|
|
|
+
|
|
|
+ if (activityType === 0) {
|
|
|
+ // 不参与活动,直接保存
|
|
|
+ this.activitySubmitLoading = true;
|
|
|
+ saveActivity({
|
|
|
+ productId: this.activityCurrentProduct.productId,
|
|
|
+ activityType: 0,
|
|
|
+ activityList: []
|
|
|
+ }).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('活动设置已清除');
|
|
|
+ this.activityDialogVisible = false;
|
|
|
+ this.getList();
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || '保存失败');
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.activitySubmitLoading = false;
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验统一活动时间
|
|
|
+ if (!this.activityForm.startTime) {
|
|
|
+ this.$message.warning('请选择活动开始时间');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!this.activityForm.endTime) {
|
|
|
+ this.$message.warning('请选择活动结束时间');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验规格活动数据
|
|
|
+ let hasError = false;
|
|
|
+ const activityList = this.selectedSpecList.map(spec => {
|
|
|
+ const item = {
|
|
|
+ specId: spec.specId,
|
|
|
+ originalPrice: spec.originalPrice,
|
|
|
+ stock: spec.stock,
|
|
|
+ startTime: this.activityForm.startTime,
|
|
|
+ endTime: this.activityForm.endTime
|
|
|
+ };
|
|
|
+ if (activityType === 6) {
|
|
|
+ // 秒杀
|
|
|
+ if (!spec.flashPrice && spec.flashPrice !== 0) {
|
|
|
+ this.$message.warning('请填写规格【' + spec.specName + '】的秒杀价');
|
|
|
+ hasError = true;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ item.flashPrice = spec.flashPrice;
|
|
|
+ } else if (activityType === 7) {
|
|
|
+ // 限时折扣
|
|
|
+ if (!spec.discount && spec.discount !== 0) {
|
|
|
+ this.$message.warning('请填写规格【' + spec.specName + '】的折扣');
|
|
|
+ hasError = true;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ item.discount = spec.discount;
|
|
|
+ item.discountPrice = spec.discountPrice;
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (!spec.stock && spec.stock !== 0) {
|
|
|
+ // this.$message.warning('请填写规格【' + spec.specName + '】的活动库存');
|
|
|
+ // hasError = true;
|
|
|
+ // return null;
|
|
|
+ // }
|
|
|
+
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (hasError) return;
|
|
|
+
|
|
|
+ // 过滤掉null
|
|
|
+ const validList = activityList.filter(item => item !== null);
|
|
|
+ if (validList.length === 0) {
|
|
|
+ this.$message.warning('请至少设置一个规格的活动信息');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.activitySubmitLoading = true;
|
|
|
+ saveActivity({
|
|
|
+ productId: this.activityCurrentProduct.productId,
|
|
|
+ activityType: activityType,
|
|
|
+ activityList: validList
|
|
|
+ }).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('活动设置保存成功');
|
|
|
+ this.activityDialogVisible = false;
|
|
|
+ this.getList();
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || '保存失败');
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.activitySubmitLoading = false;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
/** 导出按钮操作 */
|
|
|
handleExport() {
|
|
|
const queryParams = this.queryParams;
|
|
|
@@ -1832,3 +2237,135 @@ export default {
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* 规格选择列表 */
|
|
|
+.spec-select-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+.spec-select-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 8px 12px;
|
|
|
+ border: 1px dashed #DCDFE6;
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s;
|
|
|
+ background: #fff;
|
|
|
+ min-width: 160px;
|
|
|
+}
|
|
|
+.spec-select-item:hover {
|
|
|
+ border-color: #409EFF;
|
|
|
+ background: #ECF5FF;
|
|
|
+}
|
|
|
+.spec-select-active {
|
|
|
+ border-style: solid;
|
|
|
+ border-color: #409EFF;
|
|
|
+ background: #ECF5FF;
|
|
|
+}
|
|
|
+.spec-select-info {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 2px;
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+.spec-select-name {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+}
|
|
|
+.spec-select-detail {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+
|
|
|
+/* 活动规格卡片列表 */
|
|
|
+.activity-spec-list {
|
|
|
+ max-height: 400px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 5px;
|
|
|
+}
|
|
|
+.activity-spec-card {
|
|
|
+ border: 1px solid #EBEEF5;
|
|
|
+ border-radius: 6px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ background: #FAFAFA;
|
|
|
+ transition: all 0.2s;
|
|
|
+}
|
|
|
+.activity-spec-card:hover {
|
|
|
+ border-color: #409EFF;
|
|
|
+ box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
|
|
|
+}
|
|
|
+.spec-card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 10px 16px;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+ background: #F5F7FA;
|
|
|
+ border-radius: 6px 6px 0 0;
|
|
|
+}
|
|
|
+.spec-card-header .spec-name {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+.spec-header-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+.spec-thumb {
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ border-radius: 4px;
|
|
|
+ object-fit: cover;
|
|
|
+ border: 1px solid #EBEEF5;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+.spec-card-header .spec-info {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.spec-card-header .spec-info b {
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+.spec-detail-row {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 4px 16px;
|
|
|
+ padding: 8px 16px;
|
|
|
+ background: #F5F7FA;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+}
|
|
|
+.spec-detail-item {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+.spec-detail-item b {
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+.spec-card-body {
|
|
|
+ padding: 12px 16px 8px;
|
|
|
+}
|
|
|
+.spec-field {
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+.spec-field label {
|
|
|
+ display: block;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ line-height: 1;
|
|
|
+}
|
|
|
+</style>
|