feat(content): 首页更多区域模块化配置
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- home_navigations 表新增 Position 和 ActionType 字段 - 小程序 API 支持按 position 筛选导航列表 - 首页拆分专业测评和更多区域,动态渲染+QR弹窗 - 后台管理支持 Position/ActionType 配置和筛选 - ActionType=1 时 LinkUrl 必填验证 - 状态简化为 0=禁用/1=启用
This commit is contained in:
parent
0ee0870198
commit
9d4f9a0722
|
|
@ -0,0 +1,22 @@
|
||||||
|
-- ============================================================
|
||||||
|
-- 迁移脚本:home_navigations 表新增 Position 和 ActionType 列
|
||||||
|
-- 功能:首页「更多」区域模块化配置
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- 1. 新增列
|
||||||
|
ALTER TABLE home_navigations ADD Position INT NOT NULL DEFAULT 1;
|
||||||
|
ALTER TABLE home_navigations ADD ActionType INT NOT NULL DEFAULT 1;
|
||||||
|
|
||||||
|
-- 2. 现有记录设置为专业测评区域 + 跳转页面
|
||||||
|
UPDATE home_navigations SET Position = 1, ActionType = 1 WHERE IsDeleted = 0;
|
||||||
|
|
||||||
|
-- 3. 将原 Status=0 的"即将上线"记录改为 ActionType=3, Status=1
|
||||||
|
UPDATE home_navigations SET ActionType = 3, Status = 1 WHERE Status = 0 AND IsDeleted = 0;
|
||||||
|
-- 注意:Status=2 的记录也改为 ActionType=3
|
||||||
|
UPDATE home_navigations SET ActionType = 3, Status = 1 WHERE Status = 2 AND IsDeleted = 0;
|
||||||
|
|
||||||
|
-- 4. 插入「更多」区域初始数据
|
||||||
|
INSERT INTO home_navigations (Name, ImageUrl, LinkUrl, Sort, Status, Position, ActionType, CreateTime, UpdateTime, IsDeleted)
|
||||||
|
VALUES
|
||||||
|
(N'学习方案', NULL, NULL, 2, 1, 2, 3, GETDATE(), GETDATE(), 0),
|
||||||
|
(N'详细咨询', NULL, NULL, 1, 1, 2, 2, GETDATE(), GETDATE(), 0);
|
||||||
|
|
@ -440,6 +440,12 @@ public class ContentController : BusinessControllerBase
|
||||||
return ValidationError("导航名称不能为空");
|
return ValidationError("导航名称不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionType=1(跳转页面)时 LinkUrl 必填
|
||||||
|
if (request.ActionType == 1 && string.IsNullOrWhiteSpace(request.LinkUrl))
|
||||||
|
{
|
||||||
|
return Error(ErrorCodes.ParamError, "跳转链接不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var id = await _contentService.CreateNavigationAsync(request);
|
var id = await _contentService.CreateNavigationAsync(request);
|
||||||
|
|
@ -474,6 +480,12 @@ public class ContentController : BusinessControllerBase
|
||||||
return ValidationError("导航名称不能为空");
|
return ValidationError("导航名称不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionType=1(跳转页面)时 LinkUrl 必填
|
||||||
|
if (request.ActionType == 1 && string.IsNullOrWhiteSpace(request.LinkUrl))
|
||||||
|
{
|
||||||
|
return Error(ErrorCodes.ParamError, "跳转链接不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await _contentService.UpdateNavigationAsync(request);
|
var result = await _contentService.UpdateNavigationAsync(request);
|
||||||
|
|
@ -532,9 +544,9 @@ public class ContentController : BusinessControllerBase
|
||||||
return ValidationError("导航ID无效");
|
return ValidationError("导航ID无效");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.Status < 0 || request.Status > 2)
|
if (request.Status != 0 && request.Status != 1)
|
||||||
{
|
{
|
||||||
return ValidationError("状态值无效,只能为0(下线)、1(上线)或2(即将上线)");
|
return Error(ErrorCodes.ParamError, "状态值无效");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,17 @@ public class HomeNavigation
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状态:0即将上线 1已上线
|
/// 区域标识:1=专业测评区域,2=更多区域
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型:1=跳转页面,2=弹客服二维码,3=即将上线
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; } = 1;
|
public int Status { get; set; } = 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,17 @@ public class CreateHomeNavigationRequest
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状态:0即将上线 1已上线
|
/// 区域标识:1=专业测评区域,2=更多区域(默认1)
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型:1=跳转页面,2=弹客服二维码,3=即将上线(默认1)
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; } = 1;
|
public int Status { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,27 @@ public class HomeNavigationDto
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状态:0即将上线 1已上线
|
/// 区域标识
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域名称(专业测评区域/更多区域)
|
||||||
|
/// </summary>
|
||||||
|
public string PositionName { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型名称(跳转页面/弹客服二维码/即将上线)
|
||||||
|
/// </summary>
|
||||||
|
public string ActionTypeName { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; }
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,9 @@ public class HomeNavigationQueryRequest : PagedRequest
|
||||||
/// 状态筛选
|
/// 状态筛选
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? Status { get; set; }
|
public int? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域标识筛选
|
||||||
|
/// </summary>
|
||||||
|
public int? Position { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,17 @@ public class UpdateHomeNavigationRequest
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状态:0即将上线 1已上线
|
/// 区域标识:1=专业测评区域,2=更多区域
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型:1=跳转页面,2=弹客服二维码,3=即将上线
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; }
|
public int Status { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -564,13 +564,31 @@ public class ContentService : IContentService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 导航状态名称映射
|
/// 导航状态名称映射:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly Dictionary<int, string> NavigationStatusNames = new()
|
private static readonly Dictionary<int, string> NavigationStatusNames = new()
|
||||||
{
|
{
|
||||||
{ 0, "下线" },
|
{ 0, "禁用" },
|
||||||
{ 1, "上线" },
|
{ 1, "启用" }
|
||||||
{ 2, "即将上线" }
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导航区域标识名称映射
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Dictionary<int, string> NavigationPositionNames = new()
|
||||||
|
{
|
||||||
|
{ 1, "专业测评区域" },
|
||||||
|
{ 2, "更多区域" }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导航动作类型名称映射
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Dictionary<int, string> ActionTypeNames = new()
|
||||||
|
{
|
||||||
|
{ 1, "跳转页面" },
|
||||||
|
{ 2, "弹客服二维码" },
|
||||||
|
{ 3, "即将上线" }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -583,6 +601,26 @@ public class ContentService : IContentService
|
||||||
return NavigationStatusNames.TryGetValue(status, out var name) ? name : "未知";
|
return NavigationStatusNames.TryGetValue(status, out var name) ? name : "未知";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取导航区域名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">区域标识</param>
|
||||||
|
/// <returns>区域名称</returns>
|
||||||
|
private static string GetNavigationPositionName(int position)
|
||||||
|
{
|
||||||
|
return NavigationPositionNames.TryGetValue(position, out var name) ? name : "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取导航动作类型名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionType">动作类型</param>
|
||||||
|
/// <returns>动作类型名称</returns>
|
||||||
|
private static string GetActionTypeName(int actionType)
|
||||||
|
{
|
||||||
|
return ActionTypeNames.TryGetValue(actionType, out var name) ? name : "未知";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证 Position 值
|
/// 验证 Position 值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -616,6 +654,11 @@ public class ContentService : IContentService
|
||||||
query = query.Where(n => n.Status == request.Status.Value);
|
query = query.Where(n => n.Status == request.Status.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.Position.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(n => n.Position == request.Position.Value);
|
||||||
|
}
|
||||||
|
|
||||||
var total = await query.CountAsync();
|
var total = await query.CountAsync();
|
||||||
|
|
||||||
var items = await query
|
var items = await query
|
||||||
|
|
@ -630,15 +673,19 @@ public class ContentService : IContentService
|
||||||
ImageUrl = n.ImageUrl,
|
ImageUrl = n.ImageUrl,
|
||||||
LinkUrl = n.LinkUrl,
|
LinkUrl = n.LinkUrl,
|
||||||
Sort = n.Sort,
|
Sort = n.Sort,
|
||||||
|
Position = n.Position,
|
||||||
|
ActionType = n.ActionType,
|
||||||
Status = n.Status,
|
Status = n.Status,
|
||||||
CreateTime = n.CreateTime
|
CreateTime = n.CreateTime
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
// 在内存中映射状态名称(避免 EF Core LINQ 翻译问题)
|
// 在内存中映射名称(避免 EF Core LINQ 翻译问题)
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
item.StatusName = GetNavigationStatusName(item.Status);
|
item.StatusName = GetNavigationStatusName(item.Status);
|
||||||
|
item.PositionName = GetNavigationPositionName(item.Position);
|
||||||
|
item.ActionTypeName = GetActionTypeName(item.ActionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PagedResult<HomeNavigationDto>.Create(items, total, request.Page, request.PageSize);
|
return PagedResult<HomeNavigationDto>.Create(items, total, request.Page, request.PageSize);
|
||||||
|
|
@ -657,6 +704,8 @@ public class ContentService : IContentService
|
||||||
ImageUrl = n.ImageUrl,
|
ImageUrl = n.ImageUrl,
|
||||||
LinkUrl = n.LinkUrl,
|
LinkUrl = n.LinkUrl,
|
||||||
Sort = n.Sort,
|
Sort = n.Sort,
|
||||||
|
Position = n.Position,
|
||||||
|
ActionType = n.ActionType,
|
||||||
Status = n.Status,
|
Status = n.Status,
|
||||||
CreateTime = n.CreateTime
|
CreateTime = n.CreateTime
|
||||||
})
|
})
|
||||||
|
|
@ -667,8 +716,10 @@ public class ContentService : IContentService
|
||||||
throw new BusinessException(ErrorCodes.NavigationNotFound, "首页导航不存在");
|
throw new BusinessException(ErrorCodes.NavigationNotFound, "首页导航不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在内存中映射状态名称
|
// 在内存中映射名称
|
||||||
nav.StatusName = GetNavigationStatusName(nav.Status);
|
nav.StatusName = GetNavigationStatusName(nav.Status);
|
||||||
|
nav.PositionName = GetNavigationPositionName(nav.Position);
|
||||||
|
nav.ActionTypeName = GetActionTypeName(nav.ActionType);
|
||||||
|
|
||||||
return nav;
|
return nav;
|
||||||
}
|
}
|
||||||
|
|
@ -681,12 +732,20 @@ public class ContentService : IContentService
|
||||||
throw new BusinessException(ErrorCodes.ParamError, "导航名称不能为空");
|
throw new BusinessException(ErrorCodes.ParamError, "导航名称不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionType=1(跳转页面)时 LinkUrl 必填
|
||||||
|
if (request.ActionType == 1 && string.IsNullOrWhiteSpace(request.LinkUrl))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.ParamError, "跳转链接不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
var entity = new HomeNavigation
|
var entity = new HomeNavigation
|
||||||
{
|
{
|
||||||
Name = request.Name,
|
Name = request.Name,
|
||||||
ImageUrl = request.ImageUrl,
|
ImageUrl = request.ImageUrl,
|
||||||
LinkUrl = request.LinkUrl,
|
LinkUrl = request.LinkUrl,
|
||||||
Sort = request.Sort,
|
Sort = request.Sort,
|
||||||
|
Position = request.Position,
|
||||||
|
ActionType = request.ActionType,
|
||||||
Status = request.Status,
|
Status = request.Status,
|
||||||
CreateTime = DateTime.Now,
|
CreateTime = DateTime.Now,
|
||||||
UpdateTime = DateTime.Now,
|
UpdateTime = DateTime.Now,
|
||||||
|
|
@ -717,10 +776,18 @@ public class ContentService : IContentService
|
||||||
throw new BusinessException(ErrorCodes.ParamError, "导航名称不能为空");
|
throw new BusinessException(ErrorCodes.ParamError, "导航名称不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActionType=1(跳转页面)时 LinkUrl 必填
|
||||||
|
if (request.ActionType == 1 && string.IsNullOrWhiteSpace(request.LinkUrl))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.ParamError, "跳转链接不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
entity.Name = request.Name;
|
entity.Name = request.Name;
|
||||||
entity.ImageUrl = request.ImageUrl;
|
entity.ImageUrl = request.ImageUrl;
|
||||||
entity.LinkUrl = request.LinkUrl;
|
entity.LinkUrl = request.LinkUrl;
|
||||||
entity.Sort = request.Sort;
|
entity.Sort = request.Sort;
|
||||||
|
entity.Position = request.Position;
|
||||||
|
entity.ActionType = request.ActionType;
|
||||||
entity.Status = request.Status;
|
entity.Status = request.Status;
|
||||||
entity.UpdateTime = DateTime.Now;
|
entity.UpdateTime = DateTime.Now;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -308,10 +308,18 @@ export interface NavigationItem {
|
||||||
linkUrl: string
|
linkUrl: string
|
||||||
/** 排序值 */
|
/** 排序值 */
|
||||||
sort: number
|
sort: number
|
||||||
/** 状态 (0: 即将上线, 1: 已上线) */
|
/** 状态 (0: 禁用, 1: 启用) */
|
||||||
status: number
|
status: number
|
||||||
/** 状态名称 */
|
/** 状态名称 */
|
||||||
statusName: string
|
statusName: string
|
||||||
|
/** 区域标识 (1: 专业测评区域, 2: 更多区域) */
|
||||||
|
position: number
|
||||||
|
/** 区域名称 */
|
||||||
|
positionName: string
|
||||||
|
/** 动作类型 (1: 跳转页面, 2: 弹客服二维码, 3: 即将上线) */
|
||||||
|
actionType: number
|
||||||
|
/** 动作类型名称 */
|
||||||
|
actionTypeName: string
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
createTime: string
|
createTime: string
|
||||||
}
|
}
|
||||||
|
|
@ -324,6 +332,8 @@ export interface NavigationQuery extends PagedRequest {
|
||||||
name?: string
|
name?: string
|
||||||
/** 状态筛选 */
|
/** 状态筛选 */
|
||||||
status?: number
|
status?: number
|
||||||
|
/** 区域标识筛选 */
|
||||||
|
position?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -340,6 +350,10 @@ export interface CreateNavigationRequest {
|
||||||
sort: number
|
sort: number
|
||||||
/** 状态 */
|
/** 状态 */
|
||||||
status: number
|
status: number
|
||||||
|
/** 区域标识 (1: 专业测评区域, 2: 更多区域) */
|
||||||
|
position: number
|
||||||
|
/** 动作类型 (1: 跳转页面, 2: 弹客服二维码, 3: 即将上线) */
|
||||||
|
actionType: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,14 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||||
<el-option label="上线" :value="1" />
|
<el-option label="启用" :value="1" />
|
||||||
<el-option label="下线" :value="0" />
|
<el-option label="禁用" :value="0" />
|
||||||
<el-option label="即将上线" :value="2" />
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="区域">
|
||||||
|
<el-select v-model="queryParams.position" placeholder="请选择区域" clearable>
|
||||||
|
<el-option label="专业测评区域" :value="1" />
|
||||||
|
<el-option label="更多区域" :value="2" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
|
|
@ -74,6 +79,12 @@
|
||||||
<!-- 名称 -->
|
<!-- 名称 -->
|
||||||
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
|
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
|
||||||
|
|
||||||
|
<!-- 区域 -->
|
||||||
|
<el-table-column prop="positionName" label="区域" width="120" align="center" />
|
||||||
|
|
||||||
|
<!-- 动作类型 -->
|
||||||
|
<el-table-column prop="actionTypeName" label="动作类型" width="120" align="center" />
|
||||||
|
|
||||||
<!-- 跳转链接 -->
|
<!-- 跳转链接 -->
|
||||||
<el-table-column prop="linkUrl" label="跳转链接" min-width="200" show-overflow-tooltip>
|
<el-table-column prop="linkUrl" label="跳转链接" min-width="200" show-overflow-tooltip>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
|
|
@ -95,9 +106,8 @@
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item :command="1" :disabled="row.status === 1">上线</el-dropdown-item>
|
<el-dropdown-item :command="1" :disabled="row.status === 1">启用</el-dropdown-item>
|
||||||
<el-dropdown-item :command="0" :disabled="row.status === 0">下线</el-dropdown-item>
|
<el-dropdown-item :command="0" :disabled="row.status === 0">禁用</el-dropdown-item>
|
||||||
<el-dropdown-item :command="2" :disabled="row.status === 2">即将上线</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
|
@ -181,7 +191,22 @@
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="跳转链接" prop="linkUrl">
|
<el-form-item label="区域" prop="position" required>
|
||||||
|
<el-select v-model="state.formData.position" placeholder="请选择区域">
|
||||||
|
<el-option label="专业测评区域" :value="1" />
|
||||||
|
<el-option label="更多区域" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="动作类型" prop="actionType" required>
|
||||||
|
<el-select v-model="state.formData.actionType" placeholder="请选择动作类型">
|
||||||
|
<el-option label="跳转页面" :value="1" />
|
||||||
|
<el-option label="弹客服二维码" :value="2" />
|
||||||
|
<el-option label="即将上线" :value="3" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item v-if="state.formData.actionType === 1" label="跳转链接" prop="linkUrl">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="state.formData.linkUrl"
|
v-model="state.formData.linkUrl"
|
||||||
placeholder="请输入跳转链接,如:/pages/assessment/info/index"
|
placeholder="请输入跳转链接,如:/pages/assessment/info/index"
|
||||||
|
|
@ -200,9 +225,8 @@
|
||||||
|
|
||||||
<el-form-item label="状态" prop="status" required>
|
<el-form-item label="状态" prop="status" required>
|
||||||
<el-select v-model="state.formData.status" placeholder="请选择状态">
|
<el-select v-model="state.formData.status" placeholder="请选择状态">
|
||||||
<el-option label="上线" :value="1" />
|
<el-option label="启用" :value="1" />
|
||||||
<el-option label="下线" :value="0" />
|
<el-option label="禁用" :value="0" />
|
||||||
<el-option label="即将上线" :value="2" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
@ -246,6 +270,8 @@ interface NavigationFormData {
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
linkUrl: string
|
linkUrl: string
|
||||||
sort: number
|
sort: number
|
||||||
|
position: number
|
||||||
|
actionType: number
|
||||||
status: number
|
status: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,6 +316,15 @@ const formRules: FormRules = {
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: '请输入导航名称', trigger: 'blur' }
|
{ required: true, message: '请输入导航名称', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
|
position: [
|
||||||
|
{ required: true, message: '请选择区域', trigger: 'change' }
|
||||||
|
],
|
||||||
|
actionType: [
|
||||||
|
{ required: true, message: '请选择动作类型', trigger: 'change' }
|
||||||
|
],
|
||||||
|
linkUrl: [
|
||||||
|
{ required: true, message: '请输入跳转链接', trigger: 'blur' }
|
||||||
|
],
|
||||||
status: [
|
status: [
|
||||||
{ required: true, message: '请选择状态', trigger: 'change' }
|
{ required: true, message: '请选择状态', trigger: 'change' }
|
||||||
]
|
]
|
||||||
|
|
@ -303,19 +338,21 @@ function getDefaultFormData(): NavigationFormData {
|
||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
linkUrl: '',
|
linkUrl: '',
|
||||||
sort: 0,
|
sort: 0,
|
||||||
|
position: 1,
|
||||||
|
actionType: 1,
|
||||||
status: 1
|
status: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 状态文本映射 */
|
/** 状态文本映射 */
|
||||||
function statusLabel(status: number): string {
|
function statusLabel(status: number): string {
|
||||||
const map: Record<number, string> = { 0: '下线', 1: '上线', 2: '即将上线' }
|
const map: Record<number, string> = { 0: '禁用', 1: '启用' }
|
||||||
return map[status] ?? '未知'
|
return map[status] ?? '未知'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 状态标签颜色映射 */
|
/** 状态标签颜色映射 */
|
||||||
function statusTagType(status: number): '' | 'success' | 'info' | 'warning' | 'danger' {
|
function statusTagType(status: number): '' | 'success' | 'info' | 'warning' | 'danger' {
|
||||||
const map: Record<number, '' | 'success' | 'info' | 'warning' | 'danger'> = { 0: 'info', 1: 'success', 2: 'warning' }
|
const map: Record<number, '' | 'success' | 'info' | 'warning' | 'danger'> = { 0: 'danger', 1: 'success' }
|
||||||
return map[status] ?? 'info'
|
return map[status] ?? 'info'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,6 +369,9 @@ async function loadList() {
|
||||||
if (queryParams.status !== undefined && queryParams.status !== '') {
|
if (queryParams.status !== undefined && queryParams.status !== '') {
|
||||||
params.status = Number(queryParams.status)
|
params.status = Number(queryParams.status)
|
||||||
}
|
}
|
||||||
|
if (queryParams.position !== undefined && queryParams.position !== '') {
|
||||||
|
params.position = Number(queryParams.position)
|
||||||
|
}
|
||||||
|
|
||||||
const res = await getNavigationList(params)
|
const res = await getNavigationList(params)
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
|
|
@ -358,6 +398,7 @@ function handleSearch() {
|
||||||
function handleReset() {
|
function handleReset() {
|
||||||
queryParams.name = ''
|
queryParams.name = ''
|
||||||
queryParams.status = undefined
|
queryParams.status = undefined
|
||||||
|
queryParams.position = undefined
|
||||||
queryParams.page = 1
|
queryParams.page = 1
|
||||||
loadList()
|
loadList()
|
||||||
}
|
}
|
||||||
|
|
@ -389,6 +430,8 @@ function handleEdit(row: NavigationItem) {
|
||||||
imageUrl: row.imageUrl || '',
|
imageUrl: row.imageUrl || '',
|
||||||
linkUrl: row.linkUrl || '',
|
linkUrl: row.linkUrl || '',
|
||||||
sort: row.sort,
|
sort: row.sort,
|
||||||
|
position: row.position,
|
||||||
|
actionType: row.actionType,
|
||||||
status: row.status
|
status: row.status
|
||||||
}
|
}
|
||||||
state.dialogVisible = true
|
state.dialogVisible = true
|
||||||
|
|
@ -446,8 +489,10 @@ async function handleSubmit() {
|
||||||
const requestData: CreateNavigationRequest | UpdateNavigationRequest = {
|
const requestData: CreateNavigationRequest | UpdateNavigationRequest = {
|
||||||
name: formData.name,
|
name: formData.name,
|
||||||
imageUrl: formData.imageUrl || undefined,
|
imageUrl: formData.imageUrl || undefined,
|
||||||
linkUrl: formData.linkUrl || undefined,
|
linkUrl: formData.actionType === 1 ? (formData.linkUrl || undefined) : undefined,
|
||||||
sort: formData.sort,
|
sort: formData.sort,
|
||||||
|
position: formData.position,
|
||||||
|
actionType: formData.actionType,
|
||||||
status: formData.status
|
status: formData.status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,19 +89,22 @@ public class HomeController : ControllerBase
|
||||||
/// 获取首页导航入口列表
|
/// 获取首页导航入口列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// GET /api/home/getNavigationList
|
/// GET /api/home/getNavigationList?position=1
|
||||||
///
|
///
|
||||||
/// 返回所有启用状态的首页导航入口,按Sort降序排列
|
/// 返回启用状态的首页导航入口,按Sort降序排列
|
||||||
|
/// 支持按 position 筛选区域(1=专业测评,2=更多),不传返回全部
|
||||||
/// 不需要用户登录认证
|
/// 不需要用户登录认证
|
||||||
|
/// Requirements: 2.1, 2.2
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <param name="position">区域标识(可选):1=专业测评区域,2=更多区域</param>
|
||||||
/// <returns>导航入口列表</returns>
|
/// <returns>导航入口列表</returns>
|
||||||
[HttpGet("getNavigationList")]
|
[HttpGet("getNavigationList")]
|
||||||
[ProducesResponseType(typeof(ApiResponse<List<HomeNavigationDto>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(ApiResponse<List<HomeNavigationDto>>), StatusCodes.Status200OK)]
|
||||||
public async Task<ApiResponse<List<HomeNavigationDto>>> GetNavigationList()
|
public async Task<ApiResponse<List<HomeNavigationDto>>> GetNavigationList([FromQuery] int? position)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var navigations = await _homeService.GetNavigationListAsync();
|
var navigations = await _homeService.GetNavigationListAsync(position);
|
||||||
return ApiResponse<List<HomeNavigationDto>>.Success(navigations);
|
return ApiResponse<List<HomeNavigationDto>>.Success(navigations);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,8 @@ public interface IHomeService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取首页导航入口列表
|
/// 获取首页导航入口列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <param name="position">区域标识(可选),不传返回全部</param>
|
||||||
/// 返回所有启用状态的首页导航入口,按Sort降序排列
|
Task<List<HomeNavigationDto>> GetNavigationListAsync(int? position = null);
|
||||||
/// </remarks>
|
|
||||||
/// <returns>导航入口列表</returns>
|
|
||||||
Task<List<HomeNavigationDto>> GetNavigationListAsync();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取宣传图列表
|
/// 获取宣传图列表
|
||||||
|
|
|
||||||
|
|
@ -76,13 +76,20 @@ public class HomeService : IHomeService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<List<HomeNavigationDto>> GetNavigationListAsync()
|
public async Task<List<HomeNavigationDto>> GetNavigationListAsync(int? position = null)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("获取首页导航入口列表");
|
_logger.LogDebug("获取首页导航入口列表, position={Position}", position);
|
||||||
|
|
||||||
var navigations = await _dbContext.HomeNavigations
|
var query = _dbContext.HomeNavigations
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(n => n.Status != 0 && !n.IsDeleted)
|
.Where(n => !n.IsDeleted && n.Status == 1);
|
||||||
|
|
||||||
|
if (position.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(n => n.Position == position.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var navigations = await query
|
||||||
.OrderByDescending(n => n.Sort)
|
.OrderByDescending(n => n.Sort)
|
||||||
.Select(n => new HomeNavigationDto
|
.Select(n => new HomeNavigationDto
|
||||||
{
|
{
|
||||||
|
|
@ -90,7 +97,9 @@ public class HomeService : IHomeService
|
||||||
Name = n.Name,
|
Name = n.Name,
|
||||||
ImageUrl = n.ImageUrl ?? string.Empty,
|
ImageUrl = n.ImageUrl ?? string.Empty,
|
||||||
LinkUrl = n.LinkUrl,
|
LinkUrl = n.LinkUrl,
|
||||||
Status = n.Status
|
Status = n.Status,
|
||||||
|
Position = n.Position,
|
||||||
|
ActionType = n.ActionType
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,17 @@ public class HomeNavigation
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 状态:0即将上线 1已上线
|
/// 区域标识:1=专业测评区域,2=更多区域
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型:1=跳转页面,2=弹客服二维码,3=即将上线
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态:0=禁用,1=启用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; } = 1;
|
public int Status { get; set; } = 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,14 @@ public class HomeNavigationDto
|
||||||
/// 状态:0即将上线 1已上线
|
/// 状态:0即将上线 1已上线
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Status { get; set; }
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 区域标识
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动作类型
|
||||||
|
/// </summary>
|
||||||
|
public int ActionType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,12 @@ export function getAssessmentList() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取首页导航入口列表
|
* 获取首页导航入口列表
|
||||||
|
* @param {Object} [params] - 查询参数
|
||||||
|
* @param {number} [params.position] - 区域标识
|
||||||
* @returns {Promise<Object>}
|
* @returns {Promise<Object>}
|
||||||
*/
|
*/
|
||||||
export function getNavigationList() {
|
export function getNavigationList(params) {
|
||||||
return get('/home/getNavigationList')
|
return get('/home/getNavigationList', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 专业测评入口 -->
|
<!-- 专业测评入口 -->
|
||||||
<view class="section-card" v-if="navigationList.length > 0">
|
<view class="section-card" v-if="assessmentList.length > 0">
|
||||||
<view class="section-header">
|
<view class="section-header">
|
||||||
<view class="section-indicator"></view>
|
<view class="section-indicator"></view>
|
||||||
<text class="section-title">专业测评</text>
|
<text class="section-title">专业测评</text>
|
||||||
|
|
@ -52,21 +52,19 @@
|
||||||
<view class="assessment-grid">
|
<view class="assessment-grid">
|
||||||
<view
|
<view
|
||||||
class="assessment-card"
|
class="assessment-card"
|
||||||
v-for="(item, index) in navigationList"
|
v-for="(item, index) in assessmentList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="'assessment-card--' + index"
|
@click="handleCardClick(item)"
|
||||||
@click="handleNavigationClick(item)"
|
|
||||||
>
|
>
|
||||||
<!-- 即将上线标签 -->
|
<!-- 即将上线标签 -->
|
||||||
<view v-if="item.status === 2" class="coming-soon-tag">
|
<view v-if="item.actionType === 3" class="coming-soon-tag">
|
||||||
<text>即将上线</text>
|
<text>即将上线</text>
|
||||||
</view>
|
</view>
|
||||||
<image
|
<image
|
||||||
:src="item.imageUrl"
|
:src="item.imageUrl"
|
||||||
mode="aspectFit"
|
mode="aspectFill"
|
||||||
class="assessment-icon"
|
class="assessment-image"
|
||||||
/>
|
/>
|
||||||
<text class="assessment-name">{{ item.name }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -83,24 +81,22 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 更多 -->
|
<!-- 更多 -->
|
||||||
<view class="section-card">
|
<view class="section-card" v-if="moreList.length > 0">
|
||||||
<view class="section-header">
|
<view class="section-header">
|
||||||
<view class="section-indicator"></view>
|
<view class="section-indicator"></view>
|
||||||
<text class="section-title">更多</text>
|
<text class="section-title">更多</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="more-grid">
|
<view class="more-grid">
|
||||||
<view class="more-card more-card--plan" @click="goToStudyPlan">
|
<view
|
||||||
<text class="more-card__title">学习方案</text>
|
class="more-card"
|
||||||
|
v-for="(item, index) in moreList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ 'more-card--full': moreList.length % 2 === 1 && index === moreList.length - 1 }"
|
||||||
|
@click="handleCardClick(item)"
|
||||||
|
>
|
||||||
|
<text class="more-card__title">{{ item.name }}</text>
|
||||||
<image
|
<image
|
||||||
src="/static/icons/study-plan.png"
|
:src="item.imageUrl"
|
||||||
mode="aspectFit"
|
|
||||||
class="more-card__icon"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
<view class="more-card more-card--consult" @click="goToConsult">
|
|
||||||
<text class="more-card__title">详细咨询</text>
|
|
||||||
<image
|
|
||||||
src="/static/icons/consult.png"
|
|
||||||
mode="aspectFit"
|
mode="aspectFit"
|
||||||
class="more-card__icon"
|
class="more-card__icon"
|
||||||
/>
|
/>
|
||||||
|
|
@ -116,6 +112,15 @@
|
||||||
<!-- 底部安全间距 -->
|
<!-- 底部安全间距 -->
|
||||||
<view class="safe-bottom"></view>
|
<view class="safe-bottom"></view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 客服二维码弹窗 -->
|
||||||
|
<Popup
|
||||||
|
:visible="showQrPopup"
|
||||||
|
:imageUrl="qrcodeUrl"
|
||||||
|
title="扫码咨询"
|
||||||
|
:content="qrcodeUrl ? '' : '暂未配置客服二维码'"
|
||||||
|
@close="showQrPopup = false"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -124,7 +129,9 @@ import { ref, onMounted } from 'vue'
|
||||||
import { useUserStore } from '@/store/user.js'
|
import { useUserStore } from '@/store/user.js'
|
||||||
import { useNavbar } from '@/composables/useNavbar.js'
|
import { useNavbar } from '@/composables/useNavbar.js'
|
||||||
import { getBannerList, getNavigationList } from '@/api/home.js'
|
import { getBannerList, getNavigationList } from '@/api/home.js'
|
||||||
|
import { getContactInfo } from '@/api/system.js'
|
||||||
import Loading from '@/components/Loading/index.vue'
|
import Loading from '@/components/Loading/index.vue'
|
||||||
|
import Popup from '@/components/Popup/index.vue'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
|
const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
|
||||||
|
|
@ -133,7 +140,10 @@ const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
|
||||||
const pageLoading = ref(true)
|
const pageLoading = ref(true)
|
||||||
const isRefreshing = ref(false)
|
const isRefreshing = ref(false)
|
||||||
const bannerList = ref([])
|
const bannerList = ref([])
|
||||||
const navigationList = ref([])
|
const assessmentList = ref([])
|
||||||
|
const moreList = ref([])
|
||||||
|
const qrcodeUrl = ref('')
|
||||||
|
const showQrPopup = ref(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载Banner数据
|
* 加载Banner数据
|
||||||
|
|
@ -150,16 +160,44 @@ async function loadBannerList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载首页导航入口数据
|
* 加载专业测评区域数据(position=1)
|
||||||
*/
|
*/
|
||||||
async function loadNavigationList() {
|
async function loadAssessmentList() {
|
||||||
try {
|
try {
|
||||||
const res = await getNavigationList()
|
const res = await getNavigationList({ position: 1 })
|
||||||
if (res && res.code === 0 && res.data) {
|
if (res && res.code === 0 && res.data) {
|
||||||
navigationList.value = Array.isArray(res.data) ? res.data : (res.data.list || [])
|
assessmentList.value = Array.isArray(res.data) ? res.data : (res.data.list || [])
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载导航入口失败:', error)
|
console.error('加载专业测评数据失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载更多区域数据(position=2)
|
||||||
|
*/
|
||||||
|
async function loadMoreList() {
|
||||||
|
try {
|
||||||
|
const res = await getNavigationList({ position: 2 })
|
||||||
|
if (res && res.code === 0 && res.data) {
|
||||||
|
moreList.value = Array.isArray(res.data) ? res.data : (res.data.list || [])
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载更多区域数据失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载客服二维码URL
|
||||||
|
*/
|
||||||
|
async function loadContactInfo() {
|
||||||
|
try {
|
||||||
|
const res = await getContactInfo()
|
||||||
|
if (res && res.code === 0 && res.data) {
|
||||||
|
qrcodeUrl.value = res.data.qrcodeUrl || ''
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载客服二维码失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +210,9 @@ async function initPageData() {
|
||||||
userStore.restoreFromStorage()
|
userStore.restoreFromStorage()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
loadBannerList(),
|
loadBannerList(),
|
||||||
loadNavigationList()
|
loadAssessmentList(),
|
||||||
|
loadMoreList(),
|
||||||
|
loadContactInfo()
|
||||||
])
|
])
|
||||||
} finally {
|
} finally {
|
||||||
pageLoading.value = false
|
pageLoading.value = false
|
||||||
|
|
@ -199,13 +239,18 @@ function handleBannerClick(item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理导航入口点击
|
* 处理卡片点击(根据 ActionType 分发)
|
||||||
*/
|
*/
|
||||||
function handleNavigationClick(item) {
|
function handleCardClick(item) {
|
||||||
if (item.status === 2) {
|
if (item.actionType === 3) {
|
||||||
uni.showToast({ title: '该功能即将上线', icon: 'none', duration: 2000 })
|
uni.showToast({ title: '即将上线', icon: 'none', duration: 2000 })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (item.actionType === 2) {
|
||||||
|
showQrPopup.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// actionType === 1: 跳转页面
|
||||||
if (!item.linkUrl) return
|
if (!item.linkUrl) return
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: item.linkUrl,
|
url: item.linkUrl,
|
||||||
|
|
@ -222,20 +267,6 @@ function goToPlanner() {
|
||||||
uni.navigateTo({ url: '/pages/planner/list/index' })
|
uni.navigateTo({ url: '/pages/planner/list/index' })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转学习方案(业务详情页)
|
|
||||||
*/
|
|
||||||
function goToStudyPlan() {
|
|
||||||
uni.navigateTo({ url: '/pages/business/detail/index?type=study-plan' })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转详细咨询(业务详情页)
|
|
||||||
*/
|
|
||||||
function goToConsult() {
|
|
||||||
uni.navigateTo({ url: '/pages/business/detail/index?type=consult' })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下拉刷新
|
* 下拉刷新
|
||||||
*/
|
*/
|
||||||
|
|
@ -349,24 +380,10 @@ onMounted(() => {
|
||||||
.assessment-card {
|
.assessment-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 240rpx;
|
height: 240rpx;
|
||||||
border-radius: $border-radius-xl;
|
border-radius: $border-radius-xl;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
// 第一个卡片 - 红/橙渐变
|
|
||||||
&--0 {
|
|
||||||
background: linear-gradient(135deg, #FF7B6B, #FF5B5B);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第二个卡片 - 橙/黄渐变
|
|
||||||
&--1 {
|
|
||||||
background: linear-gradient(135deg, #FFD080, #FFB347);
|
|
||||||
}
|
|
||||||
|
|
||||||
.coming-soon-tag {
|
.coming-soon-tag {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -382,16 +399,9 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.assessment-icon {
|
.assessment-image {
|
||||||
width: 100rpx;
|
width: 100%;
|
||||||
height: 100rpx;
|
height: 100%;
|
||||||
margin-bottom: $spacing-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.assessment-name {
|
|
||||||
font-size: $font-size-md;
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
color: $text-white;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,14 +422,15 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更多 - 两列卡片
|
// 更多 - 网格布局,每行2个
|
||||||
.more-grid {
|
.more-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
gap: $spacing-md;
|
gap: $spacing-md;
|
||||||
}
|
}
|
||||||
|
|
||||||
.more-card {
|
.more-card {
|
||||||
flex: 1;
|
width: calc(50% - #{$spacing-md} / 2);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
@ -427,13 +438,12 @@ onMounted(() => {
|
||||||
padding: 0 $spacing-lg;
|
padding: 0 $spacing-lg;
|
||||||
border-radius: $border-radius-xl;
|
border-radius: $border-radius-xl;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: $bg-gray;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
&--plan {
|
// 奇数个时最后一个占满整行
|
||||||
background: linear-gradient(135deg, #FFF5EB, #FFE8D5);
|
&--full {
|
||||||
}
|
width: 100%;
|
||||||
|
|
||||||
&--consult {
|
|
||||||
background: linear-gradient(135deg, #FFE8EC, #FFD5DC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user