|
|
@@ -333,6 +333,62 @@
|
|
|
<el-table-column label="商品名称" align="center" prop="productName"/>
|
|
|
<el-table-column label="商品价格" align="center" prop="price"/>
|
|
|
<el-table-column label="库存" align="center" prop="stock"/>
|
|
|
+ <el-table-column label="上架时间" align="center" prop="onShelfTime" width="180">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-time-picker
|
|
|
+ v-model="scope.row.onShelfTime"
|
|
|
+ value-format="HH:mm:ss"
|
|
|
+ format="HH:mm:ss"
|
|
|
+ placeholder="选择时间"
|
|
|
+ size="mini"
|
|
|
+ :disabled="!form.duration || form.duration <= 0"
|
|
|
+ @change="(val) => handleProductTimeChange(scope.$index, 'onShelfTime', val)"
|
|
|
+ style="width: 100%"
|
|
|
+ ></el-time-picker>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="卡片弹出时间" align="center" prop="cardPopupTime" width="180">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-time-picker
|
|
|
+ v-model="scope.row.cardPopupTime"
|
|
|
+ value-format="HH:mm:ss"
|
|
|
+ format="HH:mm:ss"
|
|
|
+ placeholder="选择时间"
|
|
|
+ size="mini"
|
|
|
+ :disabled="!form.duration || form.duration <= 0"
|
|
|
+ @change="(val) => handleProductTimeChange(scope.$index, 'cardPopupTime', val)"
|
|
|
+ style="width: 100%"
|
|
|
+ ></el-time-picker>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="卡片关闭时间" align="center" prop="cardCloseTime" width="180">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-time-picker
|
|
|
+ v-model="scope.row.cardCloseTime"
|
|
|
+ value-format="HH:mm:ss"
|
|
|
+ format="HH:mm:ss"
|
|
|
+ placeholder="选择时间"
|
|
|
+ size="mini"
|
|
|
+ :disabled="!form.duration || form.duration <= 0"
|
|
|
+ @change="(val) => handleProductTimeChange(scope.$index, 'cardCloseTime', val)"
|
|
|
+ style="width: 100%"
|
|
|
+ ></el-time-picker>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="下架时间" align="center" prop="offShelfTime" width="180">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-time-picker
|
|
|
+ v-model="scope.row.offShelfTime"
|
|
|
+ value-format="HH:mm:ss"
|
|
|
+ format="HH:mm:ss"
|
|
|
+ placeholder="选择时间"
|
|
|
+ size="mini"
|
|
|
+ :disabled="!form.duration || form.duration <= 0"
|
|
|
+ @change="(val) => handleProductTimeChange(scope.$index, 'offShelfTime', val)"
|
|
|
+ style="width: 100%"
|
|
|
+ ></el-time-picker>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="操作" align="center" width="100px" fixed="right">
|
|
|
<template slot-scope="scope">
|
|
|
<el-button size="mini" type="text" icon="el-icon-delete"
|
|
|
@@ -342,18 +398,18 @@
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
</el-form-item>
|
|
|
- <el-row>
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item v-if="form.isProduct === 1" label="商品售卖时间" prop="listingStartTime">
|
|
|
- <el-input-number v-model="form.listingStartTime" :min="0" label="商品售卖时间"></el-input-number>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item v-if="form.isProduct === 1" label="结束售卖时间" prop="listingStartTime">
|
|
|
- <el-input-number v-model="form.listingEndTime" :min="0" label="结束售卖时间"></el-input-number>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+<!-- <el-row>-->
|
|
|
+<!-- <el-col :span="12">-->
|
|
|
+<!-- <el-form-item v-if="form.isProduct === 1" label="商品售卖时间" prop="listingStartTime">-->
|
|
|
+<!-- <el-input-number v-model="form.listingStartTime" :min="0" label="商品售卖时间"></el-input-number>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col :span="12">-->
|
|
|
+<!-- <el-form-item v-if="form.isProduct === 1" label="结束售卖时间" prop="listingStartTime">-->
|
|
|
+<!-- <el-input-number v-model="form.listingEndTime" :min="0" label="结束售卖时间"></el-input-number>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- </el-row>-->
|
|
|
</el-form>
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
@@ -800,6 +856,10 @@ export default {
|
|
|
price: val.price,
|
|
|
stock: val.stock,
|
|
|
id: val.productId, // 添加 id 字段,方便删除操作
|
|
|
+ onShelfTime: val.onShelfTime || '00:00:00', // 上架时间,默认 00:00:00
|
|
|
+ cardPopupTime: val.cardPopupTime || '00:00:00', // 卡片弹出时间,默认 00:00:00
|
|
|
+ cardCloseTime: val.cardCloseTime || '00:00:00', // 卡片关闭时间,默认 00:00:00
|
|
|
+ offShelfTime: val.offShelfTime || '00:00:00', // 下架时间,默认 00:00:00
|
|
|
};
|
|
|
// 检查商品是否已存在
|
|
|
const exists = this.form.courseProducts.some(item => item.productId === val.productId);
|
|
|
@@ -809,10 +869,166 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 添加商品到列表
|
|
|
- this.form.courseProducts.push(val);
|
|
|
+ this.form.courseProducts.push(productData);
|
|
|
this.$message.success("添加成功");
|
|
|
},
|
|
|
|
|
|
+ /**
|
|
|
+ * 将时间字符串(HH:mm:ss)转换为秒数
|
|
|
+ * @param {String} timeStr 时间字符串,格式:HH:mm:ss
|
|
|
+ * @returns {Number} 总秒数
|
|
|
+ */
|
|
|
+ timeToSeconds(timeStr) {
|
|
|
+ if (!timeStr || timeStr === '') return 0;
|
|
|
+ const parts = timeStr.split(':');
|
|
|
+ if (parts.length !== 3) return 0;
|
|
|
+ const hours = parseInt(parts[0]) || 0;
|
|
|
+ const minutes = parseInt(parts[1]) || 0;
|
|
|
+ const seconds = parseInt(parts[2]) || 0;
|
|
|
+ return hours * 3600 + minutes * 60 + seconds;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理商品时间字段变化,进行验证
|
|
|
+ * @param {Number} index 商品索引
|
|
|
+ * @param {String} fieldName 字段名称
|
|
|
+ * @param {String} value 时间值(HH:mm:ss格式)
|
|
|
+ */
|
|
|
+ handleProductTimeChange(index, fieldName, value) {
|
|
|
+ if (!this.form.duration || this.form.duration <= 0) {
|
|
|
+ this.$message.warning('请先上传视频并获取视频时长');
|
|
|
+ // 还原为 00:00:00
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const product = this.form.courseProducts[index];
|
|
|
+ if (product) {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const product = this.form.courseProducts[index];
|
|
|
+ if (!product) return;
|
|
|
+
|
|
|
+ const videoDurationSeconds = this.form.duration; // 视频时长(秒)
|
|
|
+ const currentTimeSeconds = this.timeToSeconds(value || '00:00:00');
|
|
|
+
|
|
|
+ // 验证:当前时间不能超过视频长度
|
|
|
+ if (currentTimeSeconds > videoDurationSeconds) {
|
|
|
+ this.$message.error(`${this.getFieldLabel(fieldName)}不能超过视频时长(${this.formatDuration(videoDurationSeconds)})`);
|
|
|
+ // 还原为 00:00:00
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证:关闭时间 - 弹出时间 不能大于视频长度
|
|
|
+ if (fieldName === 'cardCloseTime' && product.cardPopupTime) {
|
|
|
+ const popupSeconds = this.timeToSeconds(product.cardPopupTime);
|
|
|
+ const closeSeconds = this.timeToSeconds(value || '00:00:00');
|
|
|
+ const diffSeconds = closeSeconds - popupSeconds;
|
|
|
+ if (diffSeconds < 0) {
|
|
|
+ this.$message.error('卡片关闭时间不能早于卡片弹出时间');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (diffSeconds > videoDurationSeconds) {
|
|
|
+ this.$message.error('卡片关闭时间与弹出时间的差值不能超过视频时长');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证:当修改弹出时间时,需要验证关闭时间
|
|
|
+ if (fieldName === 'cardPopupTime' && product.cardCloseTime) {
|
|
|
+ const popupSeconds = this.timeToSeconds(value || '00:00:00');
|
|
|
+ const closeSeconds = this.timeToSeconds(product.cardCloseTime);
|
|
|
+ const diffSeconds = closeSeconds - popupSeconds;
|
|
|
+ if (diffSeconds < 0) {
|
|
|
+ this.$message.error('卡片弹出时间不能晚于卡片关闭时间');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (diffSeconds > videoDurationSeconds) {
|
|
|
+ this.$message.error('卡片关闭时间与弹出时间的差值不能超过视频时长');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证:下架时间 - 上架时间 不能大于视频长度
|
|
|
+ if (fieldName === 'offShelfTime' && product.onShelfTime) {
|
|
|
+ const onShelfSeconds = this.timeToSeconds(product.onShelfTime);
|
|
|
+ const offShelfSeconds = this.timeToSeconds(value || '00:00:00');
|
|
|
+ const diffSeconds = offShelfSeconds - onShelfSeconds;
|
|
|
+ if (diffSeconds < 0) {
|
|
|
+ this.$message.error('下架时间不能早于上架时间');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (diffSeconds > videoDurationSeconds) {
|
|
|
+ this.$message.error('下架时间与上架时间的差值不能超过视频时长');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证:当修改上架时间时,需要验证下架时间
|
|
|
+ if (fieldName === 'onShelfTime' && product.offShelfTime) {
|
|
|
+ const onShelfSeconds = this.timeToSeconds(value || '00:00:00');
|
|
|
+ const offShelfSeconds = this.timeToSeconds(product.offShelfTime);
|
|
|
+ const diffSeconds = offShelfSeconds - onShelfSeconds;
|
|
|
+ if (diffSeconds < 0) {
|
|
|
+ this.$message.error('上架时间不能晚于下架时间');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (diffSeconds > videoDurationSeconds) {
|
|
|
+ this.$message.error('下架时间与上架时间的差值不能超过视频时长');
|
|
|
+ this.$nextTick(() => {
|
|
|
+ product[fieldName] = '00:00:00';
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证:下架时间不能大于视频长度(已在上面验证)
|
|
|
+ // 验证:卡片关闭时间不能大于视频长度(已在上面验证)
|
|
|
+
|
|
|
+ // 更新值
|
|
|
+ product[fieldName] = value || '00:00:00';
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取字段中文标签
|
|
|
+ * @param {String} fieldName 字段名称
|
|
|
+ * @returns {String} 中文标签
|
|
|
+ */
|
|
|
+ getFieldLabel(fieldName) {
|
|
|
+ const labels = {
|
|
|
+ onShelfTime: '上架时间',
|
|
|
+ cardPopupTime: '卡片弹出时间',
|
|
|
+ cardCloseTime: '卡片关闭时间',
|
|
|
+ offShelfTime: '下架时间'
|
|
|
+ };
|
|
|
+ return labels[fieldName] || fieldName;
|
|
|
+ },
|
|
|
+
|
|
|
//选择结果
|
|
|
questionBankResult(val) {
|
|
|
|
|
|
@@ -1081,8 +1297,14 @@ export default {
|
|
|
// 检查 packageJson 是否包含商品数据,如果是则解析为 courseProducts
|
|
|
const parsedData = JSON.parse(this.form.packageJson);
|
|
|
if (Array.isArray(parsedData) && parsedData.length > 0 && parsedData[0].hasOwnProperty('productName')) {
|
|
|
- // 如果是商品数据格式,则设置到 courseProducts
|
|
|
- this.form.courseProducts = parsedData;
|
|
|
+ // 如果是商品数据格式,则设置到 courseProducts,并确保时间字段有默认值
|
|
|
+ this.form.courseProducts = parsedData.map(product => ({
|
|
|
+ ...product,
|
|
|
+ onShelfTime: product.onShelfTime || '00:00:00',
|
|
|
+ cardPopupTime: product.cardPopupTime || '00:00:00',
|
|
|
+ cardCloseTime: product.cardCloseTime || '00:00:00',
|
|
|
+ offShelfTime: product.offShelfTime || '00:00:00'
|
|
|
+ }));
|
|
|
} else {
|
|
|
// 否则按照原有逻辑设置到 packageList
|
|
|
this.packageList = parsedData;
|