细节修改

This commit is contained in:
18631081161 2026-01-25 03:18:04 +08:00
parent bf2da0c6d2
commit 4dcb830b93
24 changed files with 314 additions and 127 deletions

View File

@ -127,3 +127,17 @@ export function getMemberIcons() {
export function setMemberIcons(icons: MemberIconsConfig) {
return request.post('/admin/config/memberIcons', icons)
}
/**
*
*/
export function getMemberEntryImage() {
return request.get('/admin/config/memberEntryImage')
}
/**
*
*/
export function setMemberEntryImage(imageUrl: string) {
return request.post('/admin/config/memberEntryImage', { imageUrl })
}

View File

@ -56,12 +56,15 @@ const internalPageOptions = [
{ label: '会员中心', value: '/pages/member/index' },
{ label: '填写资料', value: '/pages/profile/edit' },
{ label: '实名认证', value: '/pages/realname/index' },
{ label: '我的收藏', value: '/pages/favorite/index' },
{ label: '浏览记录', value: '/pages/history/index' },
{ label: '设置页面', value: '/pages/settings/index' },
{ label: '关于我们', value: '/pages/about/index' },
{ label: '用户协议', value: '/pages/agreement/user' },
{ label: '隐私政策', value: '/pages/agreement/privacy' }
{ label: '看过我', value: '/pages/interact/viewedMe' },
{ label: '收藏我', value: '/pages/interact/favoritedMe' },
{ label: '解锁我', value: '/pages/interact/unlockedMe' },
{ label: '我看过的', value: '/pages/interact/myViewed' },
{ label: '我收藏的', value: '/pages/interact/myFavorite' },
{ label: '我解锁的', value: '/pages/interact/myUnlocked' },
{ label: '联系我们', value: '/pages/butler/index' },
{ label: '用户协议', value: '/pages/agreement/index?type=user' },
{ label: '隐私政策', value: '/pages/agreement/index?type=privacy' }
]
//

View File

@ -147,6 +147,29 @@
</div>
</el-form-item>
<!-- 会员入口图设置 -->
<el-form-item label="会员入口图">
<div class="banner-upload">
<el-upload
class="banner-uploader"
:action="uploadUrl"
:headers="uploadHeaders"
:show-file-list="false"
:on-success="handleMemberEntryImageSuccess"
:before-upload="beforeAvatarUpload"
accept="image/*"
>
<img v-if="configForm.memberEntryImage" :src="getFullUrl(configForm.memberEntryImage)" class="banner-preview" />
<el-icon v-else class="banner-uploader-icon"><Plus /></el-icon>
</el-upload>
<div class="avatar-tip">
<p>建议尺寸686x120像素</p>
<p>支持格式JPGPNG</p>
<p>小程序"我的"页面会员入口横幅图片</p>
</div>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveBasicConfig" :loading="saving">
保存配置
@ -213,7 +236,9 @@ import {
getButlerQrcode,
setButlerQrcode,
getMemberIcons,
setMemberIcons
setMemberIcons,
getMemberEntryImage,
setMemberEntryImage
} from '@/api/config'
import { useUserStore } from '@/stores/user'
@ -229,7 +254,8 @@ const configForm = ref({
butlerQrcode: '',
unlimitedMemberIcon: '',
sincereMemberIcon: '',
familyMemberIcon: ''
familyMemberIcon: '',
memberEntryImage: ''
})
const agreementForm = ref({
@ -255,11 +281,12 @@ const getFullUrl = (url) => {
const loadConfig = async () => {
try {
const [avatarRes, bannerRes, qrcodeRes, memberIconsRes] = await Promise.all([
const [avatarRes, bannerRes, qrcodeRes, memberIconsRes, memberEntryRes] = await Promise.all([
getDefaultAvatar(),
getSearchBanner(),
getButlerQrcode(),
getMemberIcons()
getMemberIcons(),
getMemberEntryImage()
])
if (avatarRes) {
configForm.value.defaultAvatar = avatarRes.avatarUrl || ''
@ -275,6 +302,9 @@ const loadConfig = async () => {
configForm.value.sincereMemberIcon = memberIconsRes.sincereMemberIcon || ''
configForm.value.familyMemberIcon = memberIconsRes.familyMemberIcon || ''
}
if (memberEntryRes) {
configForm.value.memberEntryImage = memberEntryRes.imageUrl || ''
}
} catch (error) {
console.error('加载配置失败:', error)
}
@ -353,6 +383,15 @@ const handleFamilyMemberIconSuccess = (response) => {
}
}
const handleMemberEntryImageSuccess = (response) => {
if (response.code === 0 && response.data) {
configForm.value.memberEntryImage = response.data.url
ElMessage.success('上传成功')
} else {
ElMessage.error(response.message || '上传失败')
}
}
const beforeAvatarUpload = (file) => {
const isImage = file.type.startsWith('image/')
const isLt2M = file.size / 1024 / 1024 < 2
@ -381,6 +420,9 @@ const saveBasicConfig = async () => {
if (configForm.value.butlerQrcode) {
promises.push(setButlerQrcode(configForm.value.butlerQrcode))
}
if (configForm.value.memberEntryImage) {
promises.push(setMemberEntryImage(configForm.value.memberEntryImage))
}
//
const memberIcons = {
unlimitedMemberIcon: configForm.value.unlimitedMemberIcon || undefined,

View File

@ -134,17 +134,8 @@ const handleEditMemberLevel = () => {
//
const handleConfirmMemberLevel = async () => {
try {
const { memberLevel, memberExpireTime } = memberLevelForm.value
// 23
if (memberLevel > 1 && !memberExpireTime) {
ElMessage.warning('请选择会员到期时间')
return
}
await updateMemberLevel(
userId.value,
memberLevel,
memberLevel > 1 ? memberExpireTime : undefined
)
const { memberLevel } = memberLevelForm.value
await updateMemberLevel(userId.value, memberLevel, undefined)
ElMessage.success('修改成功')
memberLevelDialogVisible.value = false
fetchUserDetail()
@ -670,23 +661,6 @@ onMounted(() => {
/>
</el-select>
</el-form-item>
<el-form-item
v-if="memberLevelForm.memberLevel > 1"
label="到期时间"
>
<el-date-picker
v-model="memberLevelForm.memberExpireTime"
type="date"
placeholder="选择到期日期"
value-format="YYYY-MM-DD"
style="width: 100%;"
/>
</el-form-item>
<el-form-item v-if="memberLevelForm.memberLevel === 1">
<el-text type="info">
不限时会员无需设置到期时间
</el-text>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="memberLevelDialogVisible = false">

View File

@ -28,10 +28,9 @@
v-if="imageUrl"
class="popup-image"
:src="imageUrl"
mode="aspectFit"
mode="widthFix"
@click="handleImageClick"
/>
<view v-if="title" class="popup-title">{{ title }}</view>
<button
v-if="buttonText"
class="popup-btn"
@ -265,7 +264,6 @@ export default {
.popup-image {
width: 100%;
height: 300rpx;
margin-bottom: 20rpx;
border-radius: 12rpx;
}
@ -305,6 +303,35 @@ export default {
}
}
// /广 -
.popup-daily,
.popup-member {
background: transparent;
padding: 0;
width: auto;
max-width: 85%;
.popup-image {
width: 600rpx;
border-radius: 24rpx;
margin-bottom: 0;
}
.close-btn {
top: -60rpx;
right: 0;
text {
color: #fff;
font-size: 50rpx;
}
}
.popup-btn {
margin-top: 30rpx;
}
}
//
.popup-gender {
.gender-options {

View File

@ -300,11 +300,11 @@ export default {
.tag {
font-size: 22rpx;
padding: 6rpx 16rpx;
border-radius: 20rpx;
border-radius: 8rpx;
&.tag-realname {
background: #e8f5e9;
color: #4caf50;
background: #3d4a4a;
color: #fff;
}
&.tag-member {

View File

@ -23,7 +23,7 @@ const ENV = {
}
// 当前环境 - 开发时使用 development打包时改为 production
const CURRENT_ENV = 'production'
const CURRENT_ENV = 'development'
// 导出配置
export const config = {

View File

@ -585,6 +585,12 @@
onShow() {
const configStore = useConfigStore()
const userStore = useUserStore()
//
if (userStore.isLoggedIn) {
userStore.refreshFromServer()
}
configStore.checkPopupDisplay({
genderPreference: userStore.genderPreference,
isProfileCompleted: userStore.isProfileCompleted,

View File

@ -27,6 +27,7 @@
<view class="user-detail">
<view class="user-name-row">
<text class="user-nickname">{{ userInfo.nickname || '用户名' }}</text>
<image v-if="userInfo.isMember && memberIconUrl" class="member-icon" :src="memberIconUrl" mode="aspectFit" />
<text class="edit-icon"></text>
</view>
<text class="user-xiangqin-no">相亲编号{{ userInfo.xiangQinNo || '未设置' }}</text>
@ -87,12 +88,15 @@
</view>
<!-- 会员公告横幅 -->
<view class="vip-banner" @click="handleMember">
<view class="banner-content">
<text class="banner-title">会员权益升级公告</text>
<text class="banner-desc">最新会员体系重磅上线</text>
</view>
<image src="/static/logo.png" mode="aspectFit" class="banner-icon" />
<view class="vip-banner" :class="{ 'has-image': memberEntryImageUrl }" @click="handleMember">
<image v-if="memberEntryImageUrl" :src="memberEntryImageUrl" mode="widthFix" class="banner-full-img" />
<template v-else>
<view class="banner-content">
<text class="banner-title">会员权益升级公告</text>
<text class="banner-desc">最新会员体系重磅上线</text>
</view>
<image src="/static/logo.png" mode="aspectFit" class="banner-icon" />
</template>
</view>
<!-- 常用功能 -->
@ -195,6 +199,18 @@ export default {
isRealName: userStore.isRealName
}))
// URL
const memberIconUrl = computed(() => {
if (!userStore.isMember || !userStore.memberLevel) return ''
const iconUrl = configStore.getMemberIcon(userStore.memberLevel)
return iconUrl ? getFullImageUrl(iconUrl) : ''
})
// URL
const memberEntryImageUrl = computed(() => {
return configStore.memberEntryImage ? getFullImageUrl(configStore.memberEntryImage) : ''
})
//
const loadInteractCounts = async () => {
if (!userStore.isLoggedIn) return
@ -366,6 +382,8 @@ export default {
userInfo,
interactCounts,
defaultAvatar,
memberIconUrl,
memberEntryImageUrl,
avatarLoadError,
onAvatarError,
handleLogin,
@ -488,6 +506,12 @@ export default {
margin-right: 12rpx;
}
.member-icon {
width: 100rpx;
height: 36rpx;
margin-right: 8rpx;
}
.edit-icon {
font-size: 28rpx;
color: #999;
@ -668,12 +692,27 @@ export default {
position: relative;
z-index: 1;
margin: 0 32rpx 32rpx;
padding: 32rpx;
background: linear-gradient(135deg, #4a3728 0%, #2d1f15 100%);
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
overflow: hidden;
&.has-image {
padding: 0;
}
&:not(.has-image) {
padding: 32rpx;
background: linear-gradient(135deg, #4a3728 0%, #2d1f15 100%);
display: flex;
align-items: center;
justify-content: space-between;
}
.banner-full-img {
width: 100%;
height: auto;
display: block;
border-radius: 24rpx;
}
.banner-content {
.banner-title {

View File

@ -346,8 +346,8 @@
</view>
</view>
<!-- 步骤4: 择偶要求 -->
<view v-show="currentStep === 3" class="form-section requirement-section">
<!-- 步骤5: 择偶要求 -->
<view v-show="currentStep === 4" class="form-section requirement-section">
<view class="section-title">择偶要求</view>
<view class="section-tip">以下条件均为可选帮助您更精准匹配</view>
@ -520,8 +520,8 @@
</view>
</view>
<!-- 步骤5: 父母情况 -->
<view v-show="currentStep === 4" class="form-section">
<!-- 步骤4: 父母情况 -->
<view v-show="currentStep === 3" class="form-section">
<view class="section-title">父母情况</view>
<!-- 是否独居 -->
@ -729,8 +729,8 @@ const steps = [
{ label: '基础信息' },
{ label: '详细信息' },
{ label: '孩子介绍' },
{ label: '择偶要求' },
{ label: '父母情况' },
{ label: '择偶要求' },
{ label: '联系方式' }
]
@ -1358,17 +1358,17 @@ const validateStep = (step) => {
}
return true
case 3: //
// 1
if (!formData.requirement.city1Province || !formData.requirement.city1City) {
uni.showToast({ title: '请至少选择一个意向城市', icon: 'none' })
case 3: //
if (!formData.parentStatus) {
uni.showToast({ title: '请选择父母情况', icon: 'none' })
return false
}
return true
case 4: //
if (!formData.parentStatus) {
uni.showToast({ title: '请选择父母情况', icon: 'none' })
case 4: //
// 1
if (!formData.requirement.city1Province || !formData.requirement.city1City) {
uni.showToast({ title: '请至少选择一个意向城市', icon: 'none' })
return false
}
return true

View File

@ -34,6 +34,7 @@ export const useConfigStore = defineStore('config', {
defaultAvatar: getDefaultAvatar() || '/static/logo.png',
searchBanner: '',
butlerQrcode: '', // 管家指导二维码
memberEntryImage: '', // 会员入口图
// 会员图标配置
memberIcons: {
@ -104,6 +105,7 @@ export const useConfigStore = defineStore('config', {
}
this.searchBanner = config.searchBanner || ''
this.butlerQrcode = config.butlerQrcode || ''
this.memberEntryImage = config.memberEntryImage || ''
// 会员图标配置
if (config.memberIcons) {
@ -151,8 +153,8 @@ export const useConfigStore = defineStore('config', {
}
// 会员广告
if (!isMember && this.memberAdConfig && this.memberAdConfig.status === 1) {
const displayMode = this.memberAdConfig.displayMode || 2
if (!isMember && this.memberAdConfig && (this.memberAdConfig.status === 1 || this.memberAdConfig.Status === 1)) {
const displayMode = this.memberAdConfig.displayMode || this.memberAdConfig.DisplayMode || 2
if (displayMode === 1) {
this.showMemberAd = true
@ -183,7 +185,7 @@ export const useConfigStore = defineStore('config', {
const today = getTodayDateString()
this.showMemberAd = false
const displayMode = this.memberAdConfig?.displayMode || 2
const displayMode = this.memberAdConfig?.displayMode || this.memberAdConfig?.DisplayMode || 2
if (displayMode === 2) {
this.memberAdClosedDate = today
@ -192,6 +194,7 @@ export const useConfigStore = defineStore('config', {
this.memberAdClosedForever = true
setMemberAdClosedForever(true)
}
// displayMode === 1 时不保存任何状态,下次进入页面会重新显示
},
reset() {

View File

@ -9,6 +9,7 @@ import {
getUserInfo, setUserInfo, removeUserInfo,
getGenderPreference, setGenderPreference
} from '../utils/storage.js'
import { getMyProfile } from '../api/profile.js'
/**
* 用户状态定义
@ -191,6 +192,33 @@ export const useUserStore = defineStore('user', {
setRealNameStatus(isRealName) {
this.isRealName = isRealName
this.updateUserInfo({ isRealName })
},
/**
* 从服务器刷新用户信息
* 用于同步后台修改的用户状态如会员等级变更
*/
async refreshFromServer() {
if (!this.token) return
try {
const res = await getMyProfile()
if (res && res.code === 0 && res.data) {
const data = res.data
this.updateUserInfo({
userId: data.userId,
nickname: data.nickname,
avatar: data.avatar,
xiangQinNo: data.xiangQinNo,
isProfileCompleted: data.auditStatus === 1,
isMember: data.isMember,
memberLevel: data.memberLevel,
isRealName: data.isRealName
})
}
} catch (error) {
console.error('刷新用户信息失败:', error)
}
}
}
})

View File

@ -250,6 +250,34 @@ public class AdminConfigController : ControllerBase
var result = await _configService.SetMemberIconsAsync(request);
return result ? ApiResponse.Success("设置成功") : ApiResponse.Error(40001, "设置失败");
}
/// <summary>
/// 获取会员入口图
/// </summary>
[HttpGet("memberEntryImage")]
public async Task<ApiResponse<MemberEntryImageResponse>> GetMemberEntryImage()
{
var imageUrl = await _configService.GetMemberEntryImageAsync();
return ApiResponse<MemberEntryImageResponse>.Success(new MemberEntryImageResponse
{
ImageUrl = imageUrl
});
}
/// <summary>
/// 设置会员入口图
/// </summary>
[HttpPost("memberEntryImage")]
public async Task<ApiResponse> SetMemberEntryImage([FromBody] SetMemberEntryImageRequest request)
{
if (string.IsNullOrWhiteSpace(request.ImageUrl))
{
return ApiResponse.Error(40001, "图片URL不能为空");
}
var result = await _configService.SetMemberEntryImageAsync(request.ImageUrl);
return result ? ApiResponse.Success("设置成功") : ApiResponse.Error(40001, "设置失败");
}
}
/// <summary>
@ -383,3 +411,25 @@ public class SetMemberIconRequest
/// </summary>
public string ImageUrl { get; set; } = string.Empty;
}
/// <summary>
/// 会员入口图响应
/// </summary>
public class MemberEntryImageResponse
{
/// <summary>
/// 图片URL
/// </summary>
public string? ImageUrl { get; set; }
}
/// <summary>
/// 设置会员入口图请求
/// </summary>
public class SetMemberEntryImageRequest
{
/// <summary>
/// 图片URL
/// </summary>
public string ImageUrl { get; set; } = string.Empty;
}

View File

@ -110,6 +110,11 @@ public class AppConfigResponse
/// 会员广告弹窗配置
/// </summary>
public PopupConfigResponse? MemberAdPopup { get; set; }
/// <summary>
/// 会员入口图片URL我的页面
/// </summary>
public string? MemberEntryImage { get; set; }
}
/// <summary>

View File

@ -101,4 +101,14 @@ public interface ISystemConfigService
/// 设置所有会员图标
/// </summary>
Task<bool> SetMemberIconsAsync(MemberIconsDto icons);
/// <summary>
/// 获取会员入口图URL
/// </summary>
Task<string?> GetMemberEntryImageAsync();
/// <summary>
/// 设置会员入口图URL
/// </summary>
Task<bool> SetMemberEntryImageAsync(string imageUrl);
}

View File

@ -323,11 +323,7 @@ public class AdminAccountService : IAdminAccountService
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
#endregion

View File

@ -244,11 +244,7 @@ public class AdminMemberService : IAdminMemberService
/// </summary>
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
/// <summary>

View File

@ -602,11 +602,7 @@ public class AdminOrderService : IAdminOrderService
/// </summary>
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
/// <summary>

View File

@ -346,11 +346,7 @@ public class AdminProfileAuditService : IAdminProfileAuditService
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
private static string GetGenderText(int gender)

View File

@ -507,11 +507,7 @@ public class AdminReportService : IAdminReportService
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
private static string GetReportTypeText(int reportType)

View File

@ -671,15 +671,11 @@ public class AdminUserService : IAdminUserService
/// <summary>
/// 手机号脱敏
/// 手机号(管理后台不脱敏
/// </summary>
private static string? MaskPhone(string? phone)
{
if (string.IsNullOrEmpty(phone) || phone.Length < 7)
{
return phone;
}
return $"{phone[..3]}****{phone[^4..]}";
return phone;
}
/// <summary>

View File

@ -51,6 +51,7 @@ public class ConfigService : IConfigService
var memberIcons = await _systemConfigService.GetMemberIconsAsync();
var dailyPopup = await GetPopupConfigAsync(1); // 每日弹窗
var memberAdPopup = await GetPopupConfigAsync(3); // 会员广告弹窗
var memberEntryImage = await _systemConfigService.GetMemberEntryImageAsync();
return new AppConfigResponse
{
@ -61,7 +62,8 @@ public class ConfigService : IConfigService
ButlerQrcode = butlerQrcode,
MemberIcons = memberIcons,
DailyPopup = dailyPopup,
MemberAdPopup = memberAdPopup
MemberAdPopup = memberAdPopup,
MemberEntryImage = memberEntryImage
};
}

View File

@ -19,29 +19,10 @@ public class OrderService : IOrderService
private readonly IRepository<Order> _orderRepository;
private readonly IRepository<User> _userRepository;
private readonly IRepository<Member> _memberRepository;
private readonly IRepository<MemberTierConfig> _tierConfigRepository;
private readonly IWeChatService _weChatService;
private readonly ILogger<OrderService> _logger;
/// <summary>
/// 会员等级价格配置(单位:元)
/// </summary>
private static readonly Dictionary<int, decimal> MemberPrices = new()
{
{ 1, 1299m }, // 不限时会员
{ 2, 1999m }, // 诚意会员
{ 3, 2999m } // 家庭版会员
};
/// <summary>
/// 会员等级名称
/// </summary>
private static readonly Dictionary<int, string> MemberLevelNames = new()
{
{ 1, "不限时会员" },
{ 2, "诚意会员" },
{ 3, "家庭版会员" }
};
/// <summary>
/// 订单类型名称
/// </summary>
@ -71,12 +52,14 @@ public class OrderService : IOrderService
IRepository<Order> orderRepository,
IRepository<User> userRepository,
IRepository<Member> memberRepository,
IRepository<MemberTierConfig> tierConfigRepository,
IWeChatService weChatService,
ILogger<OrderService> logger)
{
_orderRepository = orderRepository;
_userRepository = userRepository;
_memberRepository = memberRepository;
_tierConfigRepository = tierConfigRepository;
_weChatService = weChatService;
_logger = logger;
}
@ -103,20 +86,28 @@ public class OrderService : IOrderService
if (request.OrderType == (int)OrderType.Membership)
{
// 会员订单
if (!request.MemberLevel.HasValue || !MemberPrices.ContainsKey(request.MemberLevel.Value))
// 会员订单 - 从数据库读取价格配置
if (!request.MemberLevel.HasValue || request.MemberLevel < 1 || request.MemberLevel > 3)
{
throw new BusinessException(ErrorCodes.InvalidParameter, "无效的会员等级");
}
// 获取会员等级配置
var tierConfigs = await _tierConfigRepository.GetListAsync(t => t.Level == request.MemberLevel.Value && t.Status == 1);
var tierConfig = tierConfigs.FirstOrDefault();
if (tierConfig == null)
{
throw new BusinessException(ErrorCodes.InvalidParameter, "会员等级配置不存在");
}
// 检查是否已是会员
if (user.IsMember && user.MemberLevel >= request.MemberLevel.Value)
{
throw new BusinessException(ErrorCodes.MembershipRequired, "您已是该等级或更高等级会员");
}
amount = MemberPrices[request.MemberLevel.Value];
productName = MemberLevelNames[request.MemberLevel.Value];
amount = tierConfig.Price;
productName = tierConfig.Name;
}
else
{

View File

@ -63,6 +63,11 @@ public class SystemConfigService : ISystemConfigService
/// </summary>
public const string FamilyMemberIconKey = "family_member_icon";
/// <summary>
/// 会员入口图配置键
/// </summary>
public const string MemberEntryImageKey = "member_entry_image";
public SystemConfigService(
IRepository<SystemConfig> configRepository,
ILogger<SystemConfigService> logger)
@ -250,6 +255,18 @@ public class SystemConfigService : ISystemConfigService
return false;
}
}
/// <inheritdoc />
public async Task<string?> GetMemberEntryImageAsync()
{
return await GetConfigValueAsync(MemberEntryImageKey);
}
/// <inheritdoc />
public async Task<bool> SetMemberEntryImageAsync(string imageUrl)
{
return await SetConfigValueAsync(MemberEntryImageKey, imageUrl, "会员入口图URL");
}
}
/// <summary>