From 74de21b28f40d35f67a87a7952a4fd0513beced2 Mon Sep 17 00:00:00 2001 From: 18631081161 <2088094923@qq.com> Date: Tue, 6 Jan 2026 19:00:44 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=86=E8=8A=82=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/.env.development | 6 +- admin/src/api/config.ts | 28 ++ admin/src/components/ImageUpload/index.vue | 4 +- admin/src/utils/image.ts | 4 +- admin/src/views/system/config.vue | 206 +++++++++-- docs/用户协议.txt | 56 +++ docs/隐私协议.txt | 68 ++++ miniapp/api/agreement.js | 15 + miniapp/api/profile.js | 8 +- miniapp/api/request.js | 2 +- miniapp/pages.json | 7 + miniapp/pages/agreement/index.vue | 327 ++++++++++++++++++ miniapp/pages/chat/index.vue | 2 +- miniapp/pages/mine/index.vue | 4 +- miniapp/pages/profile/detail.vue | 2 +- miniapp/pages/profile/edit.vue | 4 +- miniapp/pages/profile/personal.vue | 4 +- miniapp/utils/image.js | 2 +- .../Controllers/AdminConfigController.cs | 78 +++++ .../Properties/launchSettings.json | 13 + server/src/XiangYi.AdminApi/appsettings.json | 2 +- .../Controllers/ConfigController.cs | 48 ++- .../Properties/launchSettings.json | 4 +- .../Interfaces/ISystemConfigService.cs | 20 ++ .../Services/SystemConfigService.cs | 34 ++ 25 files changed, 891 insertions(+), 57 deletions(-) create mode 100644 docs/用户协议.txt create mode 100644 docs/隐私协议.txt create mode 100644 miniapp/api/agreement.js create mode 100644 miniapp/pages/agreement/index.vue create mode 100644 server/src/XiangYi.AdminApi/Properties/launchSettings.json diff --git a/admin/.env.development b/admin/.env.development index a7c01e5..05c3e77 100644 --- a/admin/.env.development +++ b/admin/.env.development @@ -4,7 +4,7 @@ VITE_APP_TITLE=相宜相亲后台管理系统(开发) # API基础地址 -VITE_API_BASE_URL=http://localhost:5000/api +VITE_API_BASE_URL=http://localhost:5001/api -# 静态资源服务器地址(AppApi,用于图片等静态资源) -VITE_STATIC_BASE_URL=http://localhost:5001 +# 静态资源服务器地址(所有图片统一从AppApi访问) +VITE_STATIC_BASE_URL=http://localhost:5000 diff --git a/admin/src/api/config.ts b/admin/src/api/config.ts index 8b9eea4..7dac945 100644 --- a/admin/src/api/config.ts +++ b/admin/src/api/config.ts @@ -20,3 +20,31 @@ export function setDefaultAvatar(avatarUrl: string) { export function getAllConfigs() { return request.get('/admin/config/all') } + +/** + * 获取用户协议 + */ +export function getUserAgreement() { + return request.get('/admin/config/userAgreement') +} + +/** + * 设置用户协议 + */ +export function setUserAgreement(content: string) { + return request.post('/admin/config/userAgreement', { content }) +} + +/** + * 获取隐私协议 + */ +export function getPrivacyPolicy() { + return request.get('/admin/config/privacyPolicy') +} + +/** + * 设置隐私协议 + */ +export function setPrivacyPolicy(content: string) { + return request.post('/admin/config/privacyPolicy', { content }) +} diff --git a/admin/src/components/ImageUpload/index.vue b/admin/src/components/ImageUpload/index.vue index 7c08334..218c7be 100644 --- a/admin/src/components/ImageUpload/index.vue +++ b/admin/src/components/ImageUpload/index.vue @@ -60,8 +60,8 @@ import { ElMessage } from 'element-plus' import type { UploadFile, UploadFiles, UploadRawFile, UploadUserFile } from 'element-plus' import { getToken } from '@/utils/auth' -// 获取静态资源服务器地址(AppApi,用于图片等静态资源) -const STATIC_BASE = import.meta.env.VITE_STATIC_BASE_URL || 'http://localhost:5001' +// 获取静态资源服务器地址(所有图片统一从AppApi访问) +const STATIC_BASE = import.meta.env.VITE_STATIC_BASE_URL || 'http://localhost:5000' // 处理图片URL,将相对路径转换为完整URL function getFullImageUrl(url: string): string { diff --git a/admin/src/utils/image.ts b/admin/src/utils/image.ts index 5c689d8..cc6261f 100644 --- a/admin/src/utils/image.ts +++ b/admin/src/utils/image.ts @@ -2,8 +2,8 @@ * 图片URL处理工具 */ -// 获取静态资源服务器地址(AppApi,用于图片等静态资源) -const STATIC_BASE = import.meta.env.VITE_STATIC_BASE_URL || 'http://localhost:5001' +// 静态资源服务器地址(所有图片统一从AppApi访问) +const STATIC_BASE = import.meta.env.VITE_STATIC_BASE_URL || 'http://localhost:5000' /** * 处理图片URL,将相对路径转换为完整URL diff --git a/admin/src/views/system/config.vue b/admin/src/views/system/config.vue index 72ea414..9aa23d1 100644 --- a/admin/src/views/system/config.vue +++ b/admin/src/views/system/config.vue @@ -7,36 +7,79 @@ - - - -
- - - - -
-

建议尺寸:200x200像素

-

支持格式:JPG、PNG

-

新用户注册时将使用此头像作为默认头像

-
-
-
+ + + + + + +
+ + + + +
+

建议尺寸:200x200像素

+

支持格式:JPG、PNG

+

新用户注册时将使用此头像作为默认头像

+
+
+
- - - 保存配置 - - -
+ + + 保存配置 + + +
+ + + + +
+
+ 用户协议内容 + + 保存协议 + +
+ +
+
+ + + +
+
+ 隐私协议内容 + + 保存协议 + +
+ +
+
+ @@ -45,7 +88,14 @@ import { ref, onMounted, computed } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' -import { getDefaultAvatar, setDefaultAvatar } from '@/api/config' +import { + getDefaultAvatar, + setDefaultAvatar, + getUserAgreement, + setUserAgreement, + getPrivacyPolicy, + setPrivacyPolicy +} from '@/api/config' import { useUserStore } from '@/stores/user' const userStore = useUserStore() @@ -53,11 +103,20 @@ const apiBaseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000/a // 去掉 /api 后缀获取服务器根地址 const serverUrl = apiBaseUrl.replace(/\/api$/, '') +const activeTab = ref('basic') + const configForm = ref({ defaultAvatar: '' }) +const agreementForm = ref({ + userAgreement: '', + privacyPolicy: '' +}) + const saving = ref(false) +const savingAgreement = ref(false) +const savingPolicy = ref(false) const uploadUrl = computed(() => `${apiBaseUrl}/admin/upload`) @@ -83,6 +142,25 @@ const loadConfig = async () => { } } +const loadAgreements = async () => { + try { + const [userAgreementRes, privacyPolicyRes] = await Promise.all([ + getUserAgreement(), + getPrivacyPolicy() + ]) + + if (userAgreementRes) { + agreementForm.value.userAgreement = userAgreementRes.content || '' + } + + if (privacyPolicyRes) { + agreementForm.value.privacyPolicy = privacyPolicyRes.content || '' + } + } catch (error) { + console.error('加载协议失败:', error) + } +} + const handleAvatarSuccess = (response) => { if (response.code === 0 && response.data) { configForm.value.defaultAvatar = response.data.url @@ -107,7 +185,7 @@ const beforeAvatarUpload = (file) => { return true } -const saveConfig = async () => { +const saveBasicConfig = async () => { if (!configForm.value.defaultAvatar) { ElMessage.warning('请先上传默认头像') return @@ -126,8 +204,43 @@ const saveConfig = async () => { } } +const saveUserAgreement = async () => { + if (!agreementForm.value.userAgreement.trim()) { + ElMessage.warning('请输入用户协议内容') + return + } + + savingAgreement.value = true + try { + await setUserAgreement(agreementForm.value.userAgreement) + ElMessage.success('用户协议保存成功') + } catch (error) { + console.error('保存用户协议失败:', error) + } finally { + savingAgreement.value = false + } +} + +const savePrivacyPolicy = async () => { + if (!agreementForm.value.privacyPolicy.trim()) { + ElMessage.warning('请输入隐私协议内容') + return + } + + savingPolicy.value = true + try { + await setPrivacyPolicy(agreementForm.value.privacyPolicy) + ElMessage.success('隐私协议保存成功') + } catch (error) { + console.error('保存隐私协议失败:', error) + } finally { + savingPolicy.value = false + } +} + onMounted(() => { loadConfig() + loadAgreements() }) @@ -137,7 +250,7 @@ onMounted(() => { } .config-card { - max-width: 800px; + max-width: 1200px; } .card-header { @@ -145,6 +258,10 @@ onMounted(() => { font-weight: 600; } +.config-tabs { + margin-top: 20px; +} + .config-form { padding: 20px 0; } @@ -199,4 +316,29 @@ onMounted(() => { .avatar-tip p { margin: 0; } + +.agreement-editor { + padding: 20px 0; +} + +.editor-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--el-border-color-light); +} + +.toolbar-title { + font-size: 16px; + font-weight: 600; + color: var(--el-text-color-primary); +} + +.agreement-textarea :deep(.el-textarea__inner) { + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 14px; + line-height: 1.6; +} diff --git a/docs/用户协议.txt b/docs/用户协议.txt new file mode 100644 index 0000000..d1f3b42 --- /dev/null +++ b/docs/用户协议.txt @@ -0,0 +1,56 @@ +

相宜相亲用户服务协议

+ +

更新日期:2026年1月6日

+

生效日期:2026年1月6日

+ +

欢迎您使用相宜相亲小程序(以下简称"本平台")!在使用本平台服务之前,请您仔细阅读并充分理解本协议的全部内容。

+ +

一、服务说明

+

1. 本平台是一个为用户提供相亲交友服务的社交平台,旨在帮助用户寻找合适的另一半。

+

2. 本平台提供的服务包括但不限于:资料填写、信息浏览、用户沟通、会员服务、消息推送等功能。

+

3. 用户需年满18周岁方可使用本平台服务。

+ +

二、用户注册与账号管理

+

1. 用户在注册时应提供真实、准确、完整的个人信息,并在信息发生变化时及时更新。

+

2. 用户应妥善保管账号和密码,因用户原因导致的账号安全问题由用户自行承担。

+

3. 用户不得将账号转让、出借给他人使用。

+ +

三、用户行为规范

+

1. 用户应遵守国家法律法规,不得利用本平台从事违法违规活动。

+

2. 用户不得发布虚假、欺诈、骚扰、侮辱、诽谤等不良信息。

+

3. 用户不得上传含有色情、暴力、恐怖等违法违规内容的图片或信息。

+

4. 用户应尊重其他用户的隐私和合法权益。

+ +

四、相亲资料管理

+

1. 用户填写的相亲资料应真实、准确,不得提供虚假信息。

+

2. 用户上传的照片应为本人或其子女的真实照片,不得使用他人照片。

+

3. 用户可选择是否公开照片,平台将根据用户选择进行展示。

+ +

五、会员服务

+

1. 本平台提供多种会员服务,包括限时会员(1299元)、诚意会员(1999元)、诚意会员家庭版(2999元)。

+

2. 会员服务的具体权益以平台公示为准。

+

3. 会员费用一经支付,除法律规定的情形外,不予退还。

+ +

六、实名认证

+

1. 用户可选择进行实名认证,认证通过后将获得"已实名"标识。

+

2. 实名认证需支付88元认证费用,并提供真实有效的身份证信息。

+

3. 平台将对用户提交的身份信息进行严格保密。

+ +

七、联系方式解锁

+

1. 用户解锁其他用户的联系方式需消耗联系次数。

+

2. 新用户注册时赠送2次免费联系次数。

+

3. 联系次数用完后,需开通会员获取更多次数。

+ +

八、免责声明

+

1. 本平台仅提供信息展示和沟通渠道,不对用户之间的交往结果承担责任。

+

2. 用户应自行判断其他用户信息的真实性,谨慎交往。

+

3. 因不可抗力导致的服务中断,本平台不承担责任。

+ +

九、协议修改

+

1. 本平台有权根据需要修改本协议内容。

+

2. 协议修改后,将在平台公示,用户继续使用即视为同意修改后的协议。

+ +

十、联系方式

+

如您对本协议有任何疑问,请通过平台内的"管家指导"功能联系我们。

+ +

相宜相亲运营团队

\ No newline at end of file diff --git a/docs/隐私协议.txt b/docs/隐私协议.txt new file mode 100644 index 0000000..8bc611c --- /dev/null +++ b/docs/隐私协议.txt @@ -0,0 +1,68 @@ +

相宜相亲隐私政策

+ +

更新日期:2026年1月6日

+

生效日期:2026年1月6日

+ +

相宜相亲(以下简称"我们")深知个人信息对您的重要性,我们将按照法律法规的规定,保护您的个人信息及隐私安全。

+ +

一、我们收集的信息

+

为了向您提供相亲交友服务,我们可能会收集以下信息:

+ +

1. 基本信息

+

• 微信授权信息(昵称、头像)

+

• 手机号码(用于账号验证和联系)

+

• 微信号(用于用户间交换联系方式)

+ +

2. 相亲资料信息

+

• 个人基本信息:姓名、性别、出生年份、身高、体重、学历、职业、月收入等

+

• 家庭信息:与孩子的关系、家乡城市、现居城市等

+

• 婚姻状况:婚姻状态、房产情况、车辆情况等

+

• 照片:用户上传的个人或子女照片

+

• 相亲要求:期望的另一半条件

+ +

3. 实名认证信息

+

• 身份证照片(正反面)

+

• 身份证号码

+

• 真实姓名

+ +

4. 使用信息

+

• 浏览记录、收藏记录、解锁记录

+

• 聊天记录

+

• 设备信息、IP地址、位置信息

+ +

二、信息的使用

+

我们收集的信息将用于以下目的:

+

1. 提供相亲交友服务,包括资料展示、用户匹配、消息通知等

+

2. 验证用户身份,保障账号安全

+

3. 进行实名认证,提升平台可信度

+

4. 改进和优化我们的服务

+

5. 向您推送相关通知和消息

+ +

三、信息的保护

+

1. 我们采用业界标准的安全技术措施保护您的个人信息。

+

2. 您的身份证信息仅用于实名认证,认证完成后将进行加密存储。

+

3. 您的照片可选择是否公开,未公开的照片将进行模糊处理展示。

+

4. 我们不会将您的个人信息出售给第三方。

+ +

四、信息的共享

+

1. 在您同意的情况下,您的部分信息将展示给其他用户(如相亲资料)。

+

2. 当您与其他用户交换联系方式时,相关信息将被共享。

+

3. 为完成实名认证,我们可能会将您的身份信息提交给第三方认证服务商。

+

4. 根据法律法规要求,我们可能需要向有关部门提供您的信息。

+ +

五、您的权利

+

1. 您可以随时查看和修改您的个人资料。

+

2. 您可以选择是否公开您的照片。

+

3. 您可以申请删除您的账号和相关数据。

+

4. 您可以拒绝接收推送消息。

+ +

六、未成年人保护

+

本平台仅面向18周岁及以上用户,我们不会故意收集未成年人的个人信息。

+ +

七、隐私政策的更新

+

我们可能会不时更新本隐私政策,更新后的政策将在平台公示。

+ +

八、联系我们

+

如您对本隐私政策有任何疑问,请通过平台内的"管家指导"功能联系我们。

+ +

相宜相亲运营团队

\ No newline at end of file diff --git a/miniapp/api/agreement.js b/miniapp/api/agreement.js new file mode 100644 index 0000000..cd4bd52 --- /dev/null +++ b/miniapp/api/agreement.js @@ -0,0 +1,15 @@ +import { get } from './request.js' + +/** + * 获取用户协议 + */ +export const getUserAgreement = () => { + return get('/config/userAgreement') +} + +/** + * 获取隐私协议 + */ +export const getPrivacyPolicy = () => { + return get('/config/privacyPolicy') +} \ No newline at end of file diff --git a/miniapp/api/profile.js b/miniapp/api/profile.js index 8d8fdb6..e8878ce 100644 --- a/miniapp/api/profile.js +++ b/miniapp/api/profile.js @@ -6,10 +6,10 @@ import { get, post, del } from './request' import { getToken } from '../utils/storage' -// API 基础地址 -const BASE_URL = 'http://localhost:5001/api/app' -// 静态资源服务器地址 -const STATIC_URL = 'http://localhost:5001' +// API 基础地址(AppApi) +const BASE_URL = 'http://localhost:5000/api/app' +// 静态资源服务器地址(AppApi) +const STATIC_URL = 'http://localhost:5000' /** * 提交/更新用户资料 diff --git a/miniapp/api/request.js b/miniapp/api/request.js index 889dae5..5d092ab 100644 --- a/miniapp/api/request.js +++ b/miniapp/api/request.js @@ -9,7 +9,7 @@ import { getToken, removeToken, removeUserInfo } from '../utils/storage' // API 基础地址 -const BASE_URL = 'http://localhost:5001/api/app' +const BASE_URL = 'http://localhost:5000/api/app' // 请求状态 let isRefreshing = false diff --git a/miniapp/pages.json b/miniapp/pages.json index 1d0ee0d..a55390c 100644 --- a/miniapp/pages.json +++ b/miniapp/pages.json @@ -126,6 +126,13 @@ "navigationStyle": "custom", "navigationBarTitleText": "登录" } + }, + { + "path": "pages/agreement/index", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "协议" + } } ], "globalStyle": { diff --git a/miniapp/pages/agreement/index.vue b/miniapp/pages/agreement/index.vue new file mode 100644 index 0000000..99997e1 --- /dev/null +++ b/miniapp/pages/agreement/index.vue @@ -0,0 +1,327 @@ + + + + + \ No newline at end of file diff --git a/miniapp/pages/chat/index.vue b/miniapp/pages/chat/index.vue index 262792e..def1909 100644 --- a/miniapp/pages/chat/index.vue +++ b/miniapp/pages/chat/index.vue @@ -579,7 +579,7 @@ const handleCopyWeChat = (wechatNo) => { const previewPhotos = (photos, index) => { uni.previewImage({ urls: photos, - current: index + current: photos[index] || photos[0] }) } diff --git a/miniapp/pages/mine/index.vue b/miniapp/pages/mine/index.vue index 771a31b..52d7d7d 100644 --- a/miniapp/pages/mine/index.vue +++ b/miniapp/pages/mine/index.vue @@ -257,12 +257,12 @@ export default { // 用户协议 const handleUserAgreement = () => { - uni.showToast({ title: '功能开发中', icon: 'none' }) + uni.navigateTo({ url: '/pages/agreement/index?type=user' }) } // 隐私协议 const handlePrivacyPolicy = () => { - uni.showToast({ title: '功能开发中', icon: 'none' }) + uni.navigateTo({ url: '/pages/agreement/index?type=privacy' }) } // 退出登录 diff --git a/miniapp/pages/profile/detail.vue b/miniapp/pages/profile/detail.vue index 08d2b18..54ba45d 100644 --- a/miniapp/pages/profile/detail.vue +++ b/miniapp/pages/profile/detail.vue @@ -486,7 +486,7 @@ const previewPhoto = (index) => { const urls = displayPhotos.value.map(p => p.photoUrl) uni.previewImage({ urls, - current: index + current: urls[index] || urls[0] }) } diff --git a/miniapp/pages/profile/edit.vue b/miniapp/pages/profile/edit.vue index 627eb67..c76ac48 100644 --- a/miniapp/pages/profile/edit.vue +++ b/miniapp/pages/profile/edit.vue @@ -1276,8 +1276,8 @@ const loadProfile = async () => { formData.introduction = profile.introduction || '' formData.weChatNo = profile.weChatNo || '' - // 照片 - 需要拼接完整URL - const STATIC_URL = 'http://localhost:5001' + // 照片 - 需要拼接完整URL(使用AppApi地址) + const STATIC_URL = 'http://localhost:5000' if (profile.photos && profile.photos.length > 0) { formData.photos = profile.photos.map(p => ({ id: p.id, diff --git a/miniapp/pages/profile/personal.vue b/miniapp/pages/profile/personal.vue index b639b8b..8d852ba 100644 --- a/miniapp/pages/profile/personal.vue +++ b/miniapp/pages/profile/personal.vue @@ -114,10 +114,10 @@ export default { uni.showLoading({ title: '上传中...' }) try { - // 上传图片 + // 上传图片(使用AppApi地址) const uploadRes = await new Promise((resolve, reject) => { uni.uploadFile({ - url: `${import.meta.env.VITE_API_BASE_URL || 'http://localhost:5001/api'}/app/upload`, + url: `${import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000/api'}/app/upload`, filePath: tempFilePath, name: 'file', header: { diff --git a/miniapp/utils/image.js b/miniapp/utils/image.js index 0921a49..532bf21 100644 --- a/miniapp/utils/image.js +++ b/miniapp/utils/image.js @@ -4,7 +4,7 @@ */ // 后端服务器基础地址(图片资源 - 使用AppApi,因为图片存储在AppApi的wwwroot下) -const IMAGE_BASE_URL = 'http://localhost:5001' +const IMAGE_BASE_URL = 'http://localhost:5000' /** * 获取完整的图片URL diff --git a/server/src/XiangYi.AdminApi/Controllers/AdminConfigController.cs b/server/src/XiangYi.AdminApi/Controllers/AdminConfigController.cs index 59b064b..2b9c46b 100644 --- a/server/src/XiangYi.AdminApi/Controllers/AdminConfigController.cs +++ b/server/src/XiangYi.AdminApi/Controllers/AdminConfigController.cs @@ -61,6 +61,62 @@ public class AdminConfigController : ControllerBase var configs = await _configService.GetAllConfigsAsync(); return ApiResponse>.Success(configs); } + + /// + /// 获取用户协议 + /// + [HttpGet("userAgreement")] + public async Task> GetUserAgreement() + { + var content = await _configService.GetUserAgreementAsync(); + return ApiResponse.Success(new AgreementResponse + { + Content = content ?? "" + }); + } + + /// + /// 设置用户协议 + /// + [HttpPost("userAgreement")] + public async Task SetUserAgreement([FromBody] SetAgreementRequest request) + { + if (string.IsNullOrWhiteSpace(request.Content)) + { + return ApiResponse.Error(40001, "协议内容不能为空"); + } + + var result = await _configService.SetUserAgreementAsync(request.Content); + return result ? ApiResponse.Success("设置成功") : ApiResponse.Error(40001, "设置失败"); + } + + /// + /// 获取隐私协议 + /// + [HttpGet("privacyPolicy")] + public async Task> GetPrivacyPolicy() + { + var content = await _configService.GetPrivacyPolicyAsync(); + return ApiResponse.Success(new AgreementResponse + { + Content = content ?? "" + }); + } + + /// + /// 设置隐私协议 + /// + [HttpPost("privacyPolicy")] + public async Task SetPrivacyPolicy([FromBody] SetAgreementRequest request) + { + if (string.IsNullOrWhiteSpace(request.Content)) + { + return ApiResponse.Error(40001, "协议内容不能为空"); + } + + var result = await _configService.SetPrivacyPolicyAsync(request.Content); + return result ? ApiResponse.Success("设置成功") : ApiResponse.Error(40001, "设置失败"); + } } /// @@ -84,3 +140,25 @@ public class SetDefaultAvatarRequest /// public string AvatarUrl { get; set; } = string.Empty; } + +/// +/// 协议响应 +/// +public class AgreementResponse +{ + /// + /// 协议内容 + /// + public string Content { get; set; } = string.Empty; +} + +/// +/// 设置协议请求 +/// +public class SetAgreementRequest +{ + /// + /// 协议内容 + /// + public string Content { get; set; } = string.Empty; +} diff --git a/server/src/XiangYi.AdminApi/Properties/launchSettings.json b/server/src/XiangYi.AdminApi/Properties/launchSettings.json new file mode 100644 index 0000000..3b7d805 --- /dev/null +++ b/server/src/XiangYi.AdminApi/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "XiangYi.AdminApi": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/server/src/XiangYi.AdminApi/appsettings.json b/server/src/XiangYi.AdminApi/appsettings.json index 778c17f..7a24eb2 100644 --- a/server/src/XiangYi.AdminApi/appsettings.json +++ b/server/src/XiangYi.AdminApi/appsettings.json @@ -37,7 +37,7 @@ "Storage": { "Provider": "Local", "Local": { - "BasePath": "wwwroot/uploads", + "BasePath": "../XiangYi.AppApi/wwwroot/uploads", "BaseUrl": "/uploads" }, "TencentCos": { diff --git a/server/src/XiangYi.AppApi/Controllers/ConfigController.cs b/server/src/XiangYi.AppApi/Controllers/ConfigController.cs index 184a149..c36c9d6 100644 --- a/server/src/XiangYi.AppApi/Controllers/ConfigController.cs +++ b/server/src/XiangYi.AppApi/Controllers/ConfigController.cs @@ -14,11 +14,16 @@ namespace XiangYi.AppApi.Controllers; public class ConfigController : ControllerBase { private readonly IConfigService _configService; + private readonly ISystemConfigService _systemConfigService; private readonly ILogger _logger; - public ConfigController(IConfigService configService, ILogger logger) + public ConfigController( + IConfigService configService, + ISystemConfigService systemConfigService, + ILogger logger) { _configService = configService; + _systemConfigService = systemConfigService; _logger = logger; } @@ -57,4 +62,45 @@ public class ConfigController : ControllerBase var result = await _configService.GetAllPopupConfigsAsync(); return ApiResponse>.Success(result); } + + /// + /// 获取用户协议 + /// + /// 用户协议内容 + [HttpGet("userAgreement")] + [AllowAnonymous] + public async Task> GetUserAgreement() + { + var content = await _systemConfigService.GetUserAgreementAsync(); + return ApiResponse.Success(new AgreementContentResponse + { + Content = content ?? "暂无用户协议内容" + }); + } + + /// + /// 获取隐私协议 + /// + /// 隐私协议内容 + [HttpGet("privacyPolicy")] + [AllowAnonymous] + public async Task> GetPrivacyPolicy() + { + var content = await _systemConfigService.GetPrivacyPolicyAsync(); + return ApiResponse.Success(new AgreementContentResponse + { + Content = content ?? "暂无隐私协议内容" + }); + } +} + +/// +/// 协议内容响应 +/// +public class AgreementContentResponse +{ + /// + /// 协议内容 + /// + public string Content { get; set; } = string.Empty; } diff --git a/server/src/XiangYi.AppApi/Properties/launchSettings.json b/server/src/XiangYi.AppApi/Properties/launchSettings.json index 08e5dd6..1fe7740 100644 --- a/server/src/XiangYi.AppApi/Properties/launchSettings.json +++ b/server/src/XiangYi.AppApi/Properties/launchSettings.json @@ -5,7 +5,7 @@ "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "http://localhost:5001", + "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -15,7 +15,7 @@ "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:7001;http://localhost:5001", + "applicationUrl": "https://localhost:7000;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/server/src/XiangYi.Application/Interfaces/ISystemConfigService.cs b/server/src/XiangYi.Application/Interfaces/ISystemConfigService.cs index 71ed1ab..080d25f 100644 --- a/server/src/XiangYi.Application/Interfaces/ISystemConfigService.cs +++ b/server/src/XiangYi.Application/Interfaces/ISystemConfigService.cs @@ -29,4 +29,24 @@ public interface ISystemConfigService /// 获取所有配置 /// Task> GetAllConfigsAsync(); + + /// + /// 获取用户协议内容 + /// + Task GetUserAgreementAsync(); + + /// + /// 设置用户协议内容 + /// + Task SetUserAgreementAsync(string content); + + /// + /// 获取隐私协议内容 + /// + Task GetPrivacyPolicyAsync(); + + /// + /// 设置隐私协议内容 + /// + Task SetPrivacyPolicyAsync(string content); } diff --git a/server/src/XiangYi.Application/Services/SystemConfigService.cs b/server/src/XiangYi.Application/Services/SystemConfigService.cs index 5e0d512..d74cbd4 100644 --- a/server/src/XiangYi.Application/Services/SystemConfigService.cs +++ b/server/src/XiangYi.Application/Services/SystemConfigService.cs @@ -18,6 +18,16 @@ public class SystemConfigService : ISystemConfigService /// public const string DefaultAvatarKey = "default_avatar"; + /// + /// 用户协议配置键 + /// + public const string UserAgreementKey = "user_agreement"; + + /// + /// 隐私协议配置键 + /// + public const string PrivacyPolicyKey = "privacy_policy"; + public SystemConfigService( IRepository configRepository, ILogger logger) @@ -92,4 +102,28 @@ public class SystemConfigService : ISystemConfigService var configs = await _configRepository.GetListAsync(c => true); return configs.ToDictionary(c => c.ConfigKey, c => c.ConfigValue); } + + /// + public async Task GetUserAgreementAsync() + { + return await GetConfigValueAsync(UserAgreementKey); + } + + /// + public async Task SetUserAgreementAsync(string content) + { + return await SetConfigValueAsync(UserAgreementKey, content, "用户协议内容"); + } + + /// + public async Task GetPrivacyPolicyAsync() + { + return await GetConfigValueAsync(PrivacyPolicyKey); + } + + /// + public async Task SetPrivacyPolicyAsync(string content) + { + return await SetConfigValueAsync(PrivacyPolicyKey, content, "隐私协议内容"); + } }