|
@@ -25,26 +25,33 @@
|
|
|
<div class="table-scroll-wrap-sm">
|
|
<div class="table-scroll-wrap-sm">
|
|
|
<el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
|
|
<el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
|
|
|
<el-table-column prop="id" label="ID" width="60" />
|
|
<el-table-column prop="id" label="ID" width="60" />
|
|
|
- <el-table-column label="封面" width="80">
|
|
|
|
|
|
|
+ <el-table-column label="类型" width="80">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <img v-if="row.coverImage" :src="row.coverImage" style="width:50px;height:35px;object-fit:cover;border-radius:4px;" />
|
|
|
|
|
- <span v-else style="color:#999">无</span>
|
|
|
|
|
|
|
+ <el-tag size="mini" :type="typeTag(row.bannerType)">{{ typeLabel(row.bannerType) }}</el-tag>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column prop="title" label="标题" min-width="160" show-overflow-tooltip>
|
|
|
|
|
|
|
+ <el-table-column label="标题" min-width="120" show-overflow-tooltip>
|
|
|
<template slot="header"><span class="sort-header" @click.stop="onSortClick('title')">标题<span v-if="sortIndex('title') !== null" class="sort-index" :class="sortClass('title') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('title') }}</span>{{ sortIcon('title') }}</span></template>
|
|
<template slot="header"><span class="sort-header" @click.stop="onSortClick('title')">标题<span v-if="sortIndex('title') !== null" class="sort-index" :class="sortClass('title') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('title') }}</span>{{ sortIcon('title') }}</span></template>
|
|
|
|
|
+ <template slot-scope="{ row }">{{ row.title }}</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="类型" width="80">
|
|
|
|
|
|
|
+ <el-table-column label="关联内容" width="160">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <el-tag size="mini" :type="typeTag(row.bannerType)">{{ typeLabel(row.bannerType) }}</el-tag>
|
|
|
|
|
|
|
+ <div v-if="row.bannerType === 'activity' && row.refId">
|
|
|
|
|
+ <el-tag size="mini" type="primary">活动 #{{ row.refId }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else-if="row.bannerType === 'product' && row.refId">
|
|
|
|
|
+ <el-tag size="mini" type="info">商品 #{{ row.refId }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else-if="row.bannerType === 'link' && row.linkUrl">
|
|
|
|
|
+ <el-tag size="mini" type="info">{{ row.linkUrl }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else style="color:#bbb">-</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="关联" width="120">
|
|
|
|
|
|
|
+ <el-table-column label="封面" width="80">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <span v-if="row.bannerType === 'activity' && row.refId">活动 #{{ row.refId }}</span>
|
|
|
|
|
- <span v-else-if="row.bannerType === 'product' && row.refId">商品 #{{ row.refId }}</span>
|
|
|
|
|
- <span v-else-if="row.bannerType === 'link' && row.linkUrl" style="font-size:12px;color:#999;overflow:hidden;text-overflow:ellipsis;display:block;max-width:110px;">{{ row.linkUrl }}</span>
|
|
|
|
|
- <span v-else style="color:#bbb">-</span>
|
|
|
|
|
|
|
+ <img v-if="row.coverImage" :src="row.coverImage" style="width:50px;height:35px;object-fit:cover;border-radius:4px;" />
|
|
|
|
|
+ <span v-else style="color:#999">无</span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="排序" width="80">
|
|
<el-table-column label="排序" width="80">
|
|
@@ -52,7 +59,7 @@
|
|
|
<el-input-number v-model="row.sortOrder" :min="0" :max="999" size="mini" @change="onSortChange(row)" controls-position="right" />
|
|
<el-input-number v-model="row.sortOrder" :min="0" :max="999" size="mini" @change="onSortChange(row)" controls-position="right" />
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="投放时间" width="200">
|
|
|
|
|
|
|
+ <el-table-column label="投放时间" width="180">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
<span v-if="row.startTime || row.endTime">{{ formatDate(row.startTime) }} ~ {{ formatDate(row.endTime) }}</span>
|
|
<span v-if="row.startTime || row.endTime">{{ formatDate(row.startTime) }} ~ {{ formatDate(row.endTime) }}</span>
|
|
|
<span v-else style="color:#bbb">不限</span>
|
|
<span v-else style="color:#bbb">不限</span>
|
|
@@ -88,11 +95,12 @@
|
|
|
</el-card>
|
|
</el-card>
|
|
|
|
|
|
|
|
<!-- 编辑弹窗 -->
|
|
<!-- 编辑弹窗 -->
|
|
|
- <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px" :close-on-click-modal="false">
|
|
|
|
|
- <el-form :model="form" :rules="rules" ref="bannerForm" label-width="100px">
|
|
|
|
|
|
|
+ <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="800px" :close-on-click-modal="false">
|
|
|
|
|
+ <el-form :model="form" :rules="rules" ref="bannerForm" label-width="150px">
|
|
|
<el-form-item label="标题" prop="title">
|
|
<el-form-item label="标题" prop="title">
|
|
|
<el-input v-model="form.title" placeholder="展示标题,最多50字" maxlength="50" show-word-limit />
|
|
<el-input v-model="form.title" placeholder="展示标题,最多50字" maxlength="50" show-word-limit />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
<el-form-item label="类型" prop="bannerType">
|
|
<el-form-item label="类型" prop="bannerType">
|
|
|
<el-select v-model="form.bannerType" placeholder="选择类型" style="width:100%;">
|
|
<el-select v-model="form.bannerType" placeholder="选择类型" style="width:100%;">
|
|
|
<el-option label="活动" value="activity" />
|
|
<el-option label="活动" value="activity" />
|
|
@@ -100,21 +108,70 @@
|
|
|
<el-option label="链接" value="link" />
|
|
<el-option label="链接" value="link" />
|
|
|
</el-select>
|
|
</el-select>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="form.bannerType !== 'link'" label="关联内容" prop="refId">
|
|
|
|
|
- <el-input-number v-model="form.refId" :min="1" placeholder="活动/商品 ID" style="width:100%;" />
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 活动选择器 -->
|
|
|
|
|
+ <el-form-item v-if="form.bannerType === 'activity'" label="关联活动">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="form.refId"
|
|
|
|
|
+ placeholder="搜索活动"
|
|
|
|
|
+ filterable
|
|
|
|
|
+ :remote="true"
|
|
|
|
|
+ :remote-method="searchActivities"
|
|
|
|
|
+ style="width:100%"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option key="" label="-- 请选择 --" value="">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 商品选择器 -->
|
|
|
|
|
+ <el-form-item v-if="form.bannerType === 'product'" label="关联商品">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="form.refId"
|
|
|
|
|
+ placeholder="搜索商品"
|
|
|
|
|
+ filterable
|
|
|
|
|
+ :remote="true"
|
|
|
|
|
+ :remote-method="searchProducts"
|
|
|
|
|
+ style="width:100%"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option key="" label="-- 请选择 --" value="">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="form.bannerType === 'link'" label="跳转链接" prop="linkUrl">
|
|
|
|
|
- <el-input v-model="form.linkUrl" placeholder="完整 URL 或小程序页面路径" />
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 链接类型表单 -->
|
|
|
|
|
+ <el-form-item v-if="form.bannerType === 'link'" label="跳转链接">
|
|
|
|
|
+ <el-input v-model="form.linkUrl" placeholder="小程序页面路径(如 /pages/activity/activity-detail/activity-detail?id=123)" />
|
|
|
|
|
+ <el-button type="success" size="mini" @click="selectMiniPage">选择小程序页面</el-button>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 封面图 -->
|
|
|
<el-form-item label="封面图">
|
|
<el-form-item label="封面图">
|
|
|
- <el-input v-model="form.coverImage" placeholder="图片 URL" />
|
|
|
|
|
|
|
+ <el-upload
|
|
|
|
|
+ :action="uploadActionUrl"
|
|
|
|
|
+ :headers="uploadHeaders"
|
|
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
|
|
+ :on-error="handleUploadError"
|
|
|
|
|
+ :before-upload="beforeUpload"
|
|
|
|
|
+ :show-file-list="false"
|
|
|
|
|
+ accept="image/jpeg,image/png,image/gif,image/webp"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img v-if="form.coverImage" :src="form.coverImage" class="cover-preview" />
|
|
|
|
|
+ <el-button v-else type="primary" plain>+ 上传封面</el-button>
|
|
|
|
|
+ </el-upload>
|
|
|
<div v-if="form.coverImage" style="margin-top:8px;">
|
|
<div v-if="form.coverImage" style="margin-top:8px;">
|
|
|
- <el-image :src="form.coverImage" style="width:100px;height:60px;" fit="cover" />
|
|
|
|
|
|
|
+ <el-image :src="form.coverImage" style="width:200px;height:120px;" fit="cover" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <el-button v-if="form.coverImage" size="mini" type="text" style="margin-left:10px;" @click="form.coverImage = ''">清除</el-button>
|
|
|
|
|
+ <div style="margin-top:4px;font-size:12px;color:#999;">建议尺寸 750×320rpx(约 2.35:1),单张不超过 5MB</div>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
<el-form-item label="排序">
|
|
<el-form-item label="排序">
|
|
|
<el-input-number v-model="form.sortOrder" :min="0" :max="999" style="width:100px;" />
|
|
<el-input-number v-model="form.sortOrder" :min="0" :max="999" style="width:100px;" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
<el-form-item label="投放时间">
|
|
<el-form-item label="投放时间">
|
|
|
<el-date-picker
|
|
<el-date-picker
|
|
|
v-model="form.startTime"
|
|
v-model="form.startTime"
|
|
@@ -134,6 +191,7 @@
|
|
|
style="margin-left:8px;"
|
|
style="margin-left:8px;"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+
|
|
|
<el-form-item label="启用">
|
|
<el-form-item label="启用">
|
|
|
<el-switch v-model="form.enabled" :active-value="1" :inactive-value="0" />
|
|
<el-switch v-model="form.enabled" :active-value="1" :inactive-value="0" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
@@ -148,6 +206,24 @@
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import { getHomeBannerList, saveHomeBanner, deleteHomeBanner, batchDeleteHomeBanner, toggleHomeBanner, updateBannerSort } from '@/api/homeBanner'
|
|
import { getHomeBannerList, saveHomeBanner, deleteHomeBanner, batchDeleteHomeBanner, toggleHomeBanner, updateBannerSort } from '@/api/homeBanner'
|
|
|
|
|
+import { getActivityList } from '@/api/activity'
|
|
|
|
|
+import { getProductList } from '@/api/admin'
|
|
|
|
|
+
|
|
|
|
|
+// 小程序已注册页面(供链接类型选择)
|
|
|
|
|
+const MINI_PAGES = [
|
|
|
|
|
+ { path: '/pages/activity/index', label: '活动中心' },
|
|
|
|
|
+ { path: '/pages/discover/index', label: '发现' },
|
|
|
|
|
+ { path: '/pages/shop/index/index', label: '商城' },
|
|
|
|
|
+ { path: '/pages/article-center/index', label: '知识分享' },
|
|
|
|
|
+ { path: '/pages/diet/index', label: '饮食' },
|
|
|
|
|
+ { path: '/pages/health/report-list', label: '健康报告' },
|
|
|
|
|
+ { path: '/pages/energy/index', label: '五维能量' },
|
|
|
|
|
+ { path: '/pages/membership/index', label: '会员中心' },
|
|
|
|
|
+ { path: '/pages/promotion/index', label: '财富中心' },
|
|
|
|
|
+ { path: '/pages/tianpan/index', label: '家庭天盘' },
|
|
|
|
|
+ { path: '/pages/assessment/apply', label: '申请测评' },
|
|
|
|
|
+ { path: '/pages/tasks/tasks', label: '任务列表' }
|
|
|
|
|
+]
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
data() {
|
|
data() {
|
|
@@ -159,8 +235,6 @@ export default {
|
|
|
total: 0,
|
|
total: 0,
|
|
|
filterStatus: '',
|
|
filterStatus: '',
|
|
|
filterType: '',
|
|
filterType: '',
|
|
|
- sortCol: 'id',
|
|
|
|
|
- sortDir: 'asc',
|
|
|
|
|
dialogVisible: false,
|
|
dialogVisible: false,
|
|
|
submitLoading: false,
|
|
submitLoading: false,
|
|
|
editId: null,
|
|
editId: null,
|
|
@@ -182,20 +256,39 @@ export default {
|
|
|
refId: [
|
|
refId: [
|
|
|
{
|
|
{
|
|
|
required: true,
|
|
required: true,
|
|
|
- message: '请输入关联 ID',
|
|
|
|
|
|
|
+ message: '请选择关联内容',
|
|
|
trigger: 'blur',
|
|
trigger: 'blur',
|
|
|
validator: (rule, value, callback) => {
|
|
validator: (rule, value, callback) => {
|
|
|
if (this.form.bannerType === 'link') {
|
|
if (this.form.bannerType === 'link') {
|
|
|
callback()
|
|
callback()
|
|
|
} else if (!value || value <= 0) {
|
|
} else if (!value || value <= 0) {
|
|
|
- callback(new Error('请输入有效ID'))
|
|
|
|
|
|
|
+ callback(new Error('请选择关联内容'))
|
|
|
} else {
|
|
} else {
|
|
|
callback()
|
|
callback()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ ],
|
|
|
|
|
+ // 封面图必填(产品类型)
|
|
|
|
|
+ coverImage: [
|
|
|
|
|
+ {
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ message: '请上传封面图',
|
|
|
|
|
+ trigger: 'change'
|
|
|
|
|
+ }
|
|
|
]
|
|
]
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ // 活动搜索状态
|
|
|
|
|
+ activitySearchKeyword: '',
|
|
|
|
|
+ activityLoading: false,
|
|
|
|
|
+ activityOptions: [],
|
|
|
|
|
+ activityPage: 1,
|
|
|
|
|
+ // 商品搜索状态
|
|
|
|
|
+ productSearchKeyword: '',
|
|
|
|
|
+ productLoading: false,
|
|
|
|
|
+ productOptions: [],
|
|
|
|
|
+ productPage: 1,
|
|
|
|
|
+ showPagePicker: false
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -204,6 +297,14 @@ export default {
|
|
|
},
|
|
},
|
|
|
dialogTitle() {
|
|
dialogTitle() {
|
|
|
return this.editId ? '编辑广告位' : '新增广告位'
|
|
return this.editId ? '编辑广告位' : '新增广告位'
|
|
|
|
|
+ },
|
|
|
|
|
+ uploadActionUrl() {
|
|
|
|
|
+ const baseURL = process.env.VUE_APP_BASE_API || ''
|
|
|
|
|
+ return baseURL + '/api/admin/articles/upload/image'
|
|
|
|
|
+ },
|
|
|
|
|
+ uploadHeaders() {
|
|
|
|
|
+ const token = localStorage.getItem('token')
|
|
|
|
|
+ return token ? { Authorization: 'Bearer ' + token } : {}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
mounted() {
|
|
mounted() {
|
|
@@ -259,6 +360,16 @@ export default {
|
|
|
startTime: row.startTime || null,
|
|
startTime: row.startTime || null,
|
|
|
endTime: row.endTime || null
|
|
endTime: row.endTime || null
|
|
|
}
|
|
}
|
|
|
|
|
+ // 根据类型预填搜索结果
|
|
|
|
|
+ if (row.bannerType === 'activity') {
|
|
|
|
|
+ this.activitySearchKeyword = ''
|
|
|
|
|
+ this.activityOptions = []
|
|
|
|
|
+ this.loadActivityOptions()
|
|
|
|
|
+ } else if (row.bannerType === 'product') {
|
|
|
|
|
+ this.productSearchKeyword = ''
|
|
|
|
|
+ this.productOptions = []
|
|
|
|
|
+ this.loadProductOptions()
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
this.editId = null
|
|
this.editId = null
|
|
|
this.form = {
|
|
this.form = {
|
|
@@ -273,6 +384,8 @@ export default {
|
|
|
startTime: null,
|
|
startTime: null,
|
|
|
endTime: null
|
|
endTime: null
|
|
|
}
|
|
}
|
|
|
|
|
+ this.activityOptions = []
|
|
|
|
|
+ this.productOptions = []
|
|
|
}
|
|
}
|
|
|
this.dialogVisible = true
|
|
this.dialogVisible = true
|
|
|
this.$nextTick(function() {
|
|
this.$nextTick(function() {
|
|
@@ -331,6 +444,86 @@ export default {
|
|
|
onSortChange(row) {
|
|
onSortChange(row) {
|
|
|
updateBannerSort({ id: row.id, sortOrder: row.sortOrder }).catch(function() {})
|
|
updateBannerSort({ id: row.id, sortOrder: row.sortOrder }).catch(function() {})
|
|
|
},
|
|
},
|
|
|
|
|
+
|
|
|
|
|
+ // --- 活动搜索 ---
|
|
|
|
|
+ searchActivities: async function(query) {
|
|
|
|
|
+ this.activityLoading = true
|
|
|
|
|
+ this.activityOptions = []
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getActivityList({
|
|
|
|
|
+ keyword: query || undefined,
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ size: 20
|
|
|
|
|
+ })
|
|
|
|
|
+ const data = (res && res.data) || {}
|
|
|
|
|
+ this.activityOptions = data.records || []
|
|
|
|
|
+ this.activityPage = 1
|
|
|
|
|
+ this.activityLoading = false
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('[HomeBanner] 搜索活动失败', e)
|
|
|
|
|
+ this.activityLoading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ loadActivityOptions() {
|
|
|
|
|
+ this.searchActivities(this.activitySearchKeyword)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 商品搜索
|
|
|
|
|
+ searchProducts: async function(query) {
|
|
|
|
|
+ this.productLoading = true
|
|
|
|
|
+ this.productOptions = []
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getProductList({
|
|
|
|
|
+ keyword: query || undefined,
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ size: 20
|
|
|
|
|
+ })
|
|
|
|
|
+ const data = (res && res.data) || {}
|
|
|
|
|
+ this.productOptions = data.records || []
|
|
|
|
|
+ this.productPage = 1
|
|
|
|
|
+ this.productLoading = false
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('[HomeBanner] 搜索商品失败', e)
|
|
|
|
|
+ this.productLoading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ loadProductOptions() {
|
|
|
|
|
+ this.searchProducts(this.productSearchKeyword)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ handleUploadSuccess(res) {
|
|
|
|
|
+ if (res && res.code === 200 && res.data && res.data.url) {
|
|
|
|
|
+ this.form.coverImage = res.data.url
|
|
|
|
|
+ this..success('上传成功')
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this..error('上传失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ handleUploadError(err) {
|
|
|
|
|
+ console.error('[HomeBanner] 上传失败', err)
|
|
|
|
|
+ this..error('图片上传失败,请重试')
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeUpload(file) {
|
|
|
|
|
+ const isImage = file.type.startsWith('image/jpeg') || file.type.startsWith('image/png') || file.type.startsWith('image/gif') || file.type.startsWith('image/webp')
|
|
|
|
|
+ if (!isImage) {
|
|
|
|
|
+ this..error('只能上传图片格式(jpg/png/gif/webp)')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ const isLt5M = file.size / 1024 / 1024 < 5
|
|
|
|
|
+ if (!isLt5M) {
|
|
|
|
|
+ this..error('图片大小不能超过 5MB')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ return true
|
|
|
|
|
+ },
|
|
|
|
|
+ selectMiniPage() {
|
|
|
|
|
+ this.showPagePicker = true
|
|
|
|
|
+ },
|
|
|
|
|
+ selectPage(path) {
|
|
|
|
|
+ this.form.linkUrl = path
|
|
|
|
|
+ this.showPagePicker = false
|
|
|
|
|
+ },
|
|
|
|
|
+ // --- 工具方法 ---
|
|
|
typeLabel(type) {
|
|
typeLabel(type) {
|
|
|
var map = { activity: '活动', product: '商品', link: '链接' }
|
|
var map = { activity: '活动', product: '商品', link: '链接' }
|
|
|
return map[type] || type || '-'
|
|
return map[type] || type || '-'
|
|
@@ -372,12 +565,27 @@ export default {
|
|
|
},
|
|
},
|
|
|
formatTime(t) {
|
|
formatTime(t) {
|
|
|
if (!t) return '-'
|
|
if (!t) return '-'
|
|
|
- // 兼容字符串格式和 timestamp
|
|
|
|
|
var ts = t
|
|
var ts = t
|
|
|
if (typeof t === 'string' && t.indexOf('T') > -1) {
|
|
if (typeof t === 'string' && t.indexOf('T') > -1) {
|
|
|
ts = new Date(t).getTime()
|
|
ts = new Date(t).getTime()
|
|
|
}
|
|
}
|
|
|
return this.formatDate(ts)
|
|
return this.formatDate(ts)
|
|
|
|
|
+ },
|
|
|
|
|
+ // 选择小程序页面
|
|
|
|
|
+ selectMiniPage() {
|
|
|
|
|
+ this.$message.info('小程序页面选择功能待后端开发')
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeUpload(file) {
|
|
|
|
|
+ const isJPG = file.type === 'image/jpeg'
|
|
|
|
|
+ const isPNG = file.type === 'image/png'
|
|
|
|
|
+ const isGIF = file.type === 'image/gif'
|
|
|
|
|
+ const isQQ = file.type === 'image/webp'
|
|
|
|
|
+ if (!isJPG && !isPNG && !isGIF && !isQQ) {
|
|
|
|
|
+ this.$message.error('只能上传 jpg/png/gif/webp 格式的图片!')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$message.warning('上传图片受限,请使用后台上传接口上传封面图')
|
|
|
|
|
+ return false
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -400,8 +608,4 @@ export default {
|
|
|
gap: 12px;
|
|
gap: 12px;
|
|
|
flex-wrap: wrap;
|
|
flex-wrap: wrap;
|
|
|
}
|
|
}
|
|
|
-.pagination-wrap {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- justify-content: flex-end;
|
|
|
|
|
-}
|
|
|
|
|
</style>
|
|
</style>
|