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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ‹
+
+ {{ pageTitle }}
+
+
+
+
+
+
+
+
+
+
+
+ 暂无{{ agreementType === 'user' ? '用户协议' : '隐私协议' }}内容
+
+
+
+
+
+
+
+
+
+
\ 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, "隐私协议内容");
+ }
}