12
This commit is contained in:
parent
9f270c3741
commit
c8b7cff7e9
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* BusinessPage API - 业务介绍页管理 API
|
||||
* @module api/business/businessPage
|
||||
* @description 提供业务介绍页相关接口,包括列表、新增、编辑、删除、状态管理
|
||||
*/
|
||||
import { request, type ApiResponse } from '@/utils/request'
|
||||
import type { PagedRequest, PagedResult, UpdateStatusRequest } from '@/types/common'
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
|
||||
/** 业务介绍页项 */
|
||||
export interface BusinessPageItem {
|
||||
id: number
|
||||
title: string
|
||||
imageUrl: string
|
||||
hasActionButton: boolean
|
||||
actionButtonText?: string
|
||||
actionButtonLink?: string
|
||||
sort: number
|
||||
status: number
|
||||
statusName: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
/** 查询参数 */
|
||||
export interface BusinessPageQuery extends PagedRequest {
|
||||
title?: string
|
||||
status?: number
|
||||
}
|
||||
|
||||
/** 创建请求 */
|
||||
export interface CreateBusinessPageRequest {
|
||||
title: string
|
||||
imageUrl: string
|
||||
hasActionButton: boolean
|
||||
actionButtonText?: string
|
||||
actionButtonLink?: string
|
||||
sort?: number
|
||||
status?: number
|
||||
}
|
||||
|
||||
/** 更新请求 */
|
||||
export interface UpdateBusinessPageRequest extends CreateBusinessPageRequest {
|
||||
id: number
|
||||
}
|
||||
|
||||
|
||||
// ==================== API ====================
|
||||
|
||||
/** 获取业务介绍页列表 */
|
||||
export function getBusinessPageList(params: BusinessPageQuery): Promise<ApiResponse<PagedResult<BusinessPageItem>>> {
|
||||
return request<PagedResult<BusinessPageItem>>({
|
||||
url: '/admin/businessPage/getList',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 创建业务介绍页 */
|
||||
export function createBusinessPage(data: CreateBusinessPageRequest): Promise<ApiResponse<number>> {
|
||||
return request<number>({
|
||||
url: '/admin/businessPage/create',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 更新业务介绍页 */
|
||||
export function updateBusinessPage(data: UpdateBusinessPageRequest): Promise<ApiResponse<boolean>> {
|
||||
return request<boolean>({
|
||||
url: '/admin/businessPage/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除业务介绍页 */
|
||||
export function deleteBusinessPage(id: number): Promise<ApiResponse<boolean>> {
|
||||
return request<boolean>({
|
||||
url: '/admin/businessPage/delete',
|
||||
method: 'post',
|
||||
data: { id }
|
||||
})
|
||||
}
|
||||
|
||||
/** 更新业务介绍页状态 */
|
||||
export function updateBusinessPageStatus(data: UpdateStatusRequest): Promise<ApiResponse<boolean>> {
|
||||
return request<boolean>({
|
||||
url: '/admin/businessPage/updateStatus',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 更新业务介绍页排序 */
|
||||
export function updateBusinessPageSort(data: { id: number; sort: number }): Promise<ApiResponse<boolean>> {
|
||||
return request<boolean>({
|
||||
url: '/admin/businessPage/updateSort',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
|
@ -67,6 +67,12 @@ export const businessRoutes: RouteRecordRaw[] = [
|
|||
name: 'Promotion',
|
||||
component: () => import('@/views/business/content/promotion/index.vue'),
|
||||
meta: { title: '宣传图管理', permission: 'promotion:view', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'business-page',
|
||||
name: 'BusinessPage',
|
||||
component: () => import('@/views/business/content/business-page/index.vue'),
|
||||
meta: { title: '业务介绍页', permission: 'businessPage:view', keepAlive: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,430 @@
|
|||
<template>
|
||||
<div class="business-page-container">
|
||||
<!-- 页面标题和操作栏 -->
|
||||
<el-card class="page-header">
|
||||
<div class="header-content">
|
||||
<div class="header-left">
|
||||
<h2 class="page-title">业务介绍页管理</h2>
|
||||
<span class="page-description">管理小程序业务详情页内容,支持配置长图和操作按钮</span>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<el-button type="primary" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
新增介绍页
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 搜索表单 -->
|
||||
<el-card class="search-card">
|
||||
<el-form :model="queryParams" inline>
|
||||
<el-form-item label="标题">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<DictSelect
|
||||
v-model="queryParams.status"
|
||||
type="common_status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>搜索
|
||||
</el-button>
|
||||
<el-button @click="handleReset">
|
||||
<el-icon><Refresh /></el-icon>重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-card v-loading="state.loading" class="table-card">
|
||||
<el-table :data="state.tableData" row-key="id" stripe>
|
||||
<!-- 图片预览 -->
|
||||
<el-table-column label="图片" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
:src="row.imageUrl"
|
||||
:preview-src-list="[row.imageUrl]"
|
||||
fit="cover"
|
||||
style="width: 80px; height: 60px; border-radius: 4px;"
|
||||
preview-teleported
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-error"><el-icon><Picture /></el-icon></div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="title" label="标题" min-width="150" show-overflow-tooltip />
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-table-column label="操作按钮" width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.hasActionButton">
|
||||
<el-tag type="success" size="small">{{ row.actionButtonText || '按钮' }}</el-tag>
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">{{ row.actionButtonLink }}</div>
|
||||
</template>
|
||||
<el-tag v-else type="info" size="small">无按钮</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 状态 -->
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
:loading="row._statusLoading"
|
||||
@change="(val: number) => handleStatusChange(row, val)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="sort" label="排序" width="80" align="center" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="180" align="center" />
|
||||
|
||||
<!-- 操作 -->
|
||||
<el-table-column label="操作" width="150" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link size="small" @click="handleEdit(row)">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-button>
|
||||
<el-popconfirm
|
||||
title="确定要删除这条业务介绍页吗?"
|
||||
confirm-button-text="确定"
|
||||
cancel-button-text="取消"
|
||||
@confirm="handleDelete(row)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="danger" link size="small">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-wrapper">
|
||||
<el-pagination
|
||||
v-model:current-page="queryParams.pageIndex"
|
||||
v-model:page-size="queryParams.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="state.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog
|
||||
v-model="state.dialogVisible"
|
||||
:title="state.dialogTitle"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
@closed="handleDialogClosed"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="state.formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
label-position="right"
|
||||
>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="state.formData.title" placeholder="请输入标题" maxlength="100" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="介绍图片" prop="imageUrl" required>
|
||||
<ImageUpload
|
||||
v-model="state.formData.imageUrl"
|
||||
placeholder="点击上传介绍长图"
|
||||
tip="建议宽度750px,支持 jpg、png 格式"
|
||||
:max-size="10"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="操作按钮" prop="hasActionButton">
|
||||
<el-switch v-model="state.formData.hasActionButton" />
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="state.formData.hasActionButton">
|
||||
<el-form-item label="按钮文字" prop="actionButtonText">
|
||||
<el-input v-model="state.formData.actionButtonText" placeholder="如:立即参与" maxlength="50" />
|
||||
</el-form-item>
|
||||
<el-form-item label="按钮链接" prop="actionButtonLink">
|
||||
<el-input v-model="state.formData.actionButtonLink" placeholder="如:/pages/assessment/info/index" maxlength="500" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="state.formData.sort" :min="0" :max="9999" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="status" required>
|
||||
<DictSelect v-model="state.formData.status" type="common_status" placeholder="请选择状态" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="state.dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="state.formLoading" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 业务介绍页管理
|
||||
* @description 管理小程序业务详情页内容
|
||||
*/
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import { Plus, Search, Refresh, Edit, Delete, Picture } from '@element-plus/icons-vue'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import {
|
||||
getBusinessPageList,
|
||||
createBusinessPage,
|
||||
updateBusinessPage,
|
||||
deleteBusinessPage,
|
||||
updateBusinessPageStatus,
|
||||
type BusinessPageItem,
|
||||
type BusinessPageQuery,
|
||||
type CreateBusinessPageRequest,
|
||||
type UpdateBusinessPageRequest
|
||||
} from '@/api/business/businessPage'
|
||||
import { DictSelect, ImageUpload } from '@/components'
|
||||
|
||||
// ============ Types ============
|
||||
|
||||
interface FormData {
|
||||
id?: number
|
||||
title: string
|
||||
imageUrl: string
|
||||
hasActionButton: boolean
|
||||
actionButtonText: string
|
||||
actionButtonLink: string
|
||||
sort: number
|
||||
status: string
|
||||
}
|
||||
|
||||
interface PageState {
|
||||
loading: boolean
|
||||
tableData: (BusinessPageItem & { _statusLoading?: boolean })[]
|
||||
total: number
|
||||
dialogVisible: boolean
|
||||
dialogTitle: string
|
||||
formData: FormData
|
||||
formLoading: boolean
|
||||
isEdit: boolean
|
||||
}
|
||||
|
||||
// ============ Refs ============
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// ============ State ============
|
||||
|
||||
const queryParams = reactive({
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
title: '',
|
||||
status: undefined as string | undefined
|
||||
})
|
||||
|
||||
const state = reactive<PageState>({
|
||||
loading: false,
|
||||
tableData: [],
|
||||
total: 0,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新增介绍页',
|
||||
formData: getDefaultFormData(),
|
||||
formLoading: false,
|
||||
isEdit: false
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
|
||||
imageUrl: [{ required: true, message: '请上传介绍图片', trigger: 'change' }],
|
||||
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||||
}
|
||||
|
||||
// ============ Helpers ============
|
||||
|
||||
function getDefaultFormData(): FormData {
|
||||
return {
|
||||
title: '',
|
||||
imageUrl: '',
|
||||
hasActionButton: false,
|
||||
actionButtonText: '',
|
||||
actionButtonLink: '',
|
||||
sort: 0,
|
||||
status: '1'
|
||||
}
|
||||
}
|
||||
|
||||
// ============ API ============
|
||||
|
||||
async function loadList() {
|
||||
state.loading = true
|
||||
try {
|
||||
const params: BusinessPageQuery = {
|
||||
pageIndex: queryParams.pageIndex,
|
||||
pageSize: queryParams.pageSize
|
||||
}
|
||||
if (queryParams.title) params.title = queryParams.title
|
||||
if (queryParams.status !== undefined && queryParams.status !== '') {
|
||||
params.status = Number(queryParams.status)
|
||||
}
|
||||
const res = await getBusinessPageList(params)
|
||||
if (res.code === 0) {
|
||||
state.tableData = res.data?.list || []
|
||||
state.total = res.data?.total || 0
|
||||
} else {
|
||||
throw new Error(res.message || '获取列表失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '获取列表失败')
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// ============ Handlers ============
|
||||
|
||||
function handleSearch() { queryParams.pageIndex = 1; loadList() }
|
||||
function handleReset() { queryParams.title = ''; queryParams.status = undefined; queryParams.pageIndex = 1; loadList() }
|
||||
function handleSizeChange(size: number) { queryParams.pageSize = size; queryParams.pageIndex = 1; loadList() }
|
||||
function handleCurrentChange(page: number) { queryParams.pageIndex = page; loadList() }
|
||||
|
||||
function handleAdd() {
|
||||
state.isEdit = false
|
||||
state.dialogTitle = '新增介绍页'
|
||||
state.formData = getDefaultFormData()
|
||||
state.dialogVisible = true
|
||||
}
|
||||
|
||||
function handleEdit(row: BusinessPageItem) {
|
||||
state.isEdit = true
|
||||
state.dialogTitle = '编辑介绍页'
|
||||
state.formData = {
|
||||
id: row.id,
|
||||
title: row.title || '',
|
||||
imageUrl: row.imageUrl,
|
||||
hasActionButton: row.hasActionButton,
|
||||
actionButtonText: row.actionButtonText || '',
|
||||
actionButtonLink: row.actionButtonLink || '',
|
||||
sort: row.sort,
|
||||
status: String(row.status)
|
||||
}
|
||||
state.dialogVisible = true
|
||||
}
|
||||
|
||||
async function handleStatusChange(row: BusinessPageItem & { _statusLoading?: boolean }, status: number) {
|
||||
row._statusLoading = true
|
||||
try {
|
||||
const res = await updateBusinessPageStatus({ id: row.id, status })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(status === 1 ? '已启用' : '已禁用')
|
||||
} else {
|
||||
row.status = status === 1 ? 0 : 1
|
||||
throw new Error(res.message || '状态更新失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '状态更新失败')
|
||||
} finally {
|
||||
row._statusLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: BusinessPageItem) {
|
||||
try {
|
||||
const res = await deleteBusinessPage(row.id)
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功')
|
||||
if (state.tableData.length === 1 && queryParams.pageIndex > 1) queryParams.pageIndex--
|
||||
await loadList()
|
||||
} else {
|
||||
throw new Error(res.message || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!formRef.value) return
|
||||
try { await formRef.value.validate() } catch { return }
|
||||
|
||||
state.formLoading = true
|
||||
try {
|
||||
const fd = state.formData
|
||||
const data: CreateBusinessPageRequest | UpdateBusinessPageRequest = {
|
||||
title: fd.title,
|
||||
imageUrl: fd.imageUrl,
|
||||
hasActionButton: fd.hasActionButton,
|
||||
actionButtonText: fd.hasActionButton ? fd.actionButtonText : undefined,
|
||||
actionButtonLink: fd.hasActionButton ? fd.actionButtonLink : undefined,
|
||||
sort: fd.sort,
|
||||
status: Number(fd.status)
|
||||
}
|
||||
let res
|
||||
if (state.isEdit && fd.id) {
|
||||
res = await updateBusinessPage({ ...data, id: fd.id } as UpdateBusinessPageRequest)
|
||||
} else {
|
||||
res = await createBusinessPage(data)
|
||||
}
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(state.isEdit ? '更新成功' : '创建成功')
|
||||
state.dialogVisible = false
|
||||
await loadList()
|
||||
} else {
|
||||
throw new Error(res.message || (state.isEdit ? '更新失败' : '创建失败'))
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '操作失败')
|
||||
} finally {
|
||||
state.formLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleDialogClosed() {
|
||||
formRef.value?.resetFields()
|
||||
state.formData = getDefaultFormData()
|
||||
}
|
||||
|
||||
// ============ Lifecycle ============
|
||||
|
||||
onMounted(() => { loadList() })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.business-page-container { padding: 0; }
|
||||
.page-header { margin-bottom: 16px; }
|
||||
.header-content { display: flex; justify-content: space-between; align-items: center; }
|
||||
.header-left { display: flex; align-items: baseline; gap: 16px; }
|
||||
.page-title { margin: 0; font-size: 20px; font-weight: 600; color: var(--text-primary, #303133); }
|
||||
.page-description { font-size: 14px; color: var(--text-secondary, #909399); }
|
||||
.search-card { margin-bottom: 16px; }
|
||||
.search-card :deep(.el-card__body) { padding-bottom: 2px; }
|
||||
.table-card { min-height: 400px; }
|
||||
.image-error { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background: var(--el-fill-color-light); color: var(--el-text-color-placeholder); }
|
||||
.pagination-wrapper { display: flex; justify-content: flex-end; margin-top: 16px; }
|
||||
:deep(.el-table th.el-table__cell) { background-color: var(--bg-light, #f5f7fa); font-weight: 500; }
|
||||
:deep(.el-dialog__body) { padding-top: 20px; }
|
||||
</style>
|
||||
|
|
@ -10,7 +10,7 @@ import { get } from './request'
|
|||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function getBusinessDetail(businessId) {
|
||||
return get('/business/getDetail', { businessId })
|
||||
return get('/business/getDetail', { id: businessId })
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "首页",
|
||||
"enablePullDownRefresh": true
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<view class="home-page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" :style="navbarStyle">
|
||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="navbar-content" :style="{ height: navbarHeight + 'px' }">
|
||||
<text class="navbar-title">首页</text>
|
||||
</view>
|
||||
|
|
@ -11,7 +11,13 @@
|
|||
<view class="navbar-placeholder" :style="{ height: totalNavbarHeight + 'px' }"></view>
|
||||
|
||||
<!-- 页面内容 -->
|
||||
<view class="page-content">
|
||||
<scroll-view
|
||||
class="page-content"
|
||||
scroll-y
|
||||
refresher-enabled
|
||||
:refresher-triggered="isRefreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
>
|
||||
<!-- Banner 轮播图 -->
|
||||
<view class="banner-section" v-if="bannerList.length > 0">
|
||||
<swiper
|
||||
|
|
@ -37,28 +43,39 @@
|
|||
</swiper>
|
||||
</view>
|
||||
|
||||
<!-- 测评入口列表 -->
|
||||
<!-- 专业测评入口 -->
|
||||
<view class="assessment-section" v-if="assessmentList.length > 0">
|
||||
<view
|
||||
class="assessment-item"
|
||||
v-for="(item, index) in assessmentList"
|
||||
:key="index"
|
||||
@click="handleAssessmentClick(item)"
|
||||
>
|
||||
<image
|
||||
:src="item.imageUrl"
|
||||
mode="widthFix"
|
||||
class="assessment-image"
|
||||
/>
|
||||
<!-- 即将上线标签 -->
|
||||
<view v-if="item.status === 0" class="coming-soon-tag">
|
||||
<text>即将上线</text>
|
||||
<view class="section-header">
|
||||
<view class="section-indicator"></view>
|
||||
<text class="section-title">专业测评</text>
|
||||
</view>
|
||||
<view class="assessment-grid">
|
||||
<view
|
||||
class="assessment-card"
|
||||
v-for="(item, index) in assessmentList"
|
||||
:key="index"
|
||||
@click="handleAssessmentClick(item)"
|
||||
>
|
||||
<!-- 即将上线标签 -->
|
||||
<view v-if="item.status === 0" class="coming-soon-tag">
|
||||
<text>即将上线</text>
|
||||
</view>
|
||||
<image
|
||||
:src="item.imageUrl"
|
||||
mode="aspectFit"
|
||||
class="assessment-icon"
|
||||
/>
|
||||
<text class="assessment-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部宣传长图 -->
|
||||
<!-- 关于我们 - 宣传长图 -->
|
||||
<view class="promotion-section" v-if="promotionList.length > 0">
|
||||
<view class="section-header">
|
||||
<view class="section-indicator"></view>
|
||||
<text class="section-title">关于我们</text>
|
||||
</view>
|
||||
<image
|
||||
v-for="(item, index) in promotionList"
|
||||
:key="index"
|
||||
|
|
@ -75,13 +92,12 @@
|
|||
|
||||
<!-- 底部安全区域 -->
|
||||
<view class="safe-bottom"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { onPullDownRefresh } from '@dcloudio/uni-app'
|
||||
import { useUserStore } from '@/store/user.js'
|
||||
import { useNavbar } from '@/composables/useNavbar.js'
|
||||
import { getBannerList, getAssessmentList, getPromotionList } from '@/api/home.js'
|
||||
|
|
@ -92,15 +108,12 @@ const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
|
|||
|
||||
// 页面数据
|
||||
const pageLoading = ref(true)
|
||||
const isRefreshing = ref(false)
|
||||
const bannerList = ref([])
|
||||
const assessmentList = ref([])
|
||||
const promotionList = ref([])
|
||||
|
||||
// 导航栏样式
|
||||
const navbarStyle = computed(() => ({
|
||||
paddingTop: statusBarHeight.value + 'px',
|
||||
height: totalNavbarHeight.value + 'px'
|
||||
}))
|
||||
// 导航栏样式已直接在模板中绑定
|
||||
|
||||
/**
|
||||
* 加载Banner数据
|
||||
|
|
@ -211,12 +224,13 @@ function handleAssessmentClick(item) {
|
|||
}
|
||||
|
||||
/**
|
||||
* 下拉刷新
|
||||
* scroll-view 下拉刷新
|
||||
*/
|
||||
onPullDownRefresh(async () => {
|
||||
async function onRefresh() {
|
||||
isRefreshing.value = true
|
||||
await initPageData()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
isRefreshing.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面加载
|
||||
|
|
@ -260,8 +274,9 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
// 页面内容
|
||||
// 页面内容(scroll-view 需要固定高度)
|
||||
.page-content {
|
||||
height: calc(100vh - var(--navbar-height, 0px));
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
|
|
@ -270,11 +285,12 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
padding: 0 $spacing-lg;
|
||||
box-sizing: border-box;
|
||||
margin-top: $spacing-md;
|
||||
margin-top: $spacing-sm;
|
||||
|
||||
.banner-swiper {
|
||||
width: 100%;
|
||||
height: 320rpx;
|
||||
// 按设计图比例 750:360 ≈ 2:1,减去两侧 padding 后约 686rpx 宽,高度约 330rpx
|
||||
height: 330rpx;
|
||||
border-radius: $border-radius-lg;
|
||||
overflow: hidden;
|
||||
|
||||
|
|
@ -286,44 +302,76 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
|
||||
// 测评入口
|
||||
.assessment-section {
|
||||
padding: $spacing-lg;
|
||||
// 区块标题
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
.assessment-item {
|
||||
.section-indicator {
|
||||
width: 8rpx;
|
||||
height: 36rpx;
|
||||
background-color: $warning-color;
|
||||
border-radius: $border-radius-xs;
|
||||
margin-right: $spacing-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-bold;
|
||||
color: $text-color;
|
||||
}
|
||||
}
|
||||
|
||||
// 测评入口 - 横向排列
|
||||
.assessment-section {
|
||||
padding: $spacing-xl $spacing-lg $spacing-lg;
|
||||
|
||||
.assessment-grid {
|
||||
display: flex;
|
||||
gap: $spacing-md;
|
||||
}
|
||||
|
||||
.assessment-card {
|
||||
position: relative;
|
||||
margin-bottom: $spacing-md;
|
||||
border-radius: $border-radius-lg;
|
||||
overflow: hidden;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.assessment-image {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 200rpx;
|
||||
|
||||
.coming-soon-tag {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: $border-radius-round;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background-color: $warning-color;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 0 $border-radius-xl 0 $border-radius-lg;
|
||||
z-index: 1;
|
||||
|
||||
text {
|
||||
font-size: $font-size-xs;
|
||||
color: $text-white;
|
||||
}
|
||||
}
|
||||
|
||||
.assessment-icon {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: $border-radius-xl;
|
||||
}
|
||||
|
||||
.assessment-name {
|
||||
margin-top: $spacing-sm;
|
||||
font-size: $font-size-md;
|
||||
font-weight: $font-weight-bold;
|
||||
color: $text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 宣传长图
|
||||
// 关于我们 - 宣传长图
|
||||
.promotion-section {
|
||||
padding: 0 $spacing-lg;
|
||||
padding: $spacing-lg $spacing-lg 0;
|
||||
|
||||
.promotion-image {
|
||||
width: 100%;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user