diff --git a/backend/app/services/creator.go b/backend/app/services/creator.go
index 9ef6ba6..bc494f4 100644
--- a/backend/app/services/creator.go
+++ b/backend/app/services/creator.go
@@ -545,15 +545,38 @@ func (s *creator) GetSettings(ctx context.Context, userID int64) (*creator_dto.S
if err != nil {
return nil, errorx.ErrRecordNotFound
}
- // Extract from t.Config
+ cfg := t.Config.Data()
return &creator_dto.Settings{
- Name: t.Name,
- // Bio/Avatar from Config
+ Name: t.Name,
+ Bio: cfg.Bio,
+ Avatar: cfg.Avatar,
+ Cover: cfg.Cover,
+ Description: cfg.Description,
}, nil
}
func (s *creator) UpdateSettings(ctx context.Context, userID int64, form *creator_dto.Settings) error {
- return nil
+ tid, err := s.getTenantID(ctx, userID)
+ if err != nil {
+ return err
+ }
+
+ t, err := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.ID.Eq(tid)).First()
+ if err != nil {
+ return errorx.ErrRecordNotFound
+ }
+
+ cfg := t.Config.Data()
+ cfg.Bio = form.Bio
+ cfg.Avatar = form.Avatar
+ cfg.Cover = form.Cover
+ cfg.Description = form.Description
+
+ _, err = models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.ID.Eq(tid)).Updates(&models.Tenant{
+ Name: form.Name,
+ Config: types.NewJSONType(cfg),
+ })
+ return err
}
func (s *creator) ListPayoutAccounts(ctx context.Context, userID int64) ([]creator_dto.PayoutAccount, error) {
diff --git a/backend/database/fields/tenants.go b/backend/database/fields/tenants.go
index 8d5cde7..78b24ee 100644
--- a/backend/database/fields/tenants.go
+++ b/backend/database/fields/tenants.go
@@ -2,6 +2,10 @@ package fields
// TenantConfig 租户配置
type TenantConfig struct {
- Theme string `json:"theme,omitempty"`
- Features []string `json:"features,omitempty"`
+ Theme string `json:"theme,omitempty"`
+ Features []string `json:"features,omitempty"`
+ Bio string `json:"bio,omitempty"`
+ Avatar string `json:"avatar,omitempty"`
+ Cover string `json:"cover,omitempty"`
+ Description string `json:"description,omitempty"`
}
diff --git a/frontend/portal/src/views/creator/SettingsView.vue b/frontend/portal/src/views/creator/SettingsView.vue
index 7940b7e..3fd0759 100644
--- a/frontend/portal/src/views/creator/SettingsView.vue
+++ b/frontend/portal/src/views/creator/SettingsView.vue
@@ -98,19 +98,26 @@
-
-
-
-
-
招商银行
-
储蓄卡 (8888)
+
+
-
+
+
+
+
@@ -175,12 +182,15 @@ import Dialog from 'primevue/dialog';
import RadioButton from 'primevue/radiobutton';
import Toast from 'primevue/toast';
import { useToast } from 'primevue/usetoast';
-import { reactive, ref } from 'vue';
+import { reactive, ref, onMounted } from 'vue';
+import { creatorApi } from '../../api/creator';
+import { commonApi } from '../../api/common';
const toast = useToast();
const fileInput = ref(null);
const currentUploadType = ref('');
const showAddAccount = ref(false);
+const payoutAccounts = ref([]);
const newAccount = reactive({
type: 'bank',
@@ -190,43 +200,106 @@ const newAccount = reactive({
});
const form = reactive({
- name: '梅派传人小林',
- bio: '专注京剧程派艺术传承与推广',
+ name: '',
+ bio: '',
description: '',
- avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Master1',
- cover: 'https://images.unsplash.com/photo-1514306191717-452ec28c7f31?ixlib=rb-1.2.1&auto=format&fit=crop&w=1200&q=80'
+ avatar: '',
+ cover: ''
});
+const fetchData = async () => {
+ try {
+ const [settings, accounts] = await Promise.all([
+ creatorApi.getSettings(),
+ creatorApi.listPayoutAccounts()
+ ]);
+ if (settings) {
+ Object.assign(form, settings);
+ // Set defaults if empty
+ if (!form.avatar) form.avatar = 'https://api.dicebear.com/7.x/avataaars/svg?seed=Master1';
+ }
+ if (accounts) payoutAccounts.value = accounts;
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+onMounted(fetchData);
+
const triggerUpload = (type) => {
currentUploadType.value = type;
- fileInput.value.click();
-};
-
-const handleFileChange = (event) => {
- const file = event.target.files[0];
- if (file) {
- const reader = new FileReader();
- reader.onload = (e) => {
- if (currentUploadType.value === 'avatar') {
- form.avatar = e.target.result;
- } else {
- form.cover = e.target.result;
- }
- };
- reader.readAsDataURL(file);
+ if (fileInput.value) {
+ fileInput.value.accept = 'image/*';
+ fileInput.value.click();
}
};
-const handleAddAccount = () => {
- showAddAccount.value = false;
- toast.add({ severity: 'success', summary: '添加成功', detail: '收款账户已添加', life: 3000 });
+const handleFileChange = async (event) => {
+ const file = event.target.files[0];
+ if (!file) return;
+
+ try {
+ toast.add({ severity: 'info', summary: '正在上传...', life: 2000 });
+ const task = commonApi.uploadWithProgress(file, 'image');
+ const res = await task.promise;
+ console.log('Upload response:', res);
+
+ if (res && res.url) {
+ if (currentUploadType.value === 'avatar') {
+ form.avatar = res.url;
+ } else {
+ form.cover = res.url;
+ }
+ toast.add({ severity: 'success', summary: '上传成功', life: 2000 });
+ } else {
+ console.error('Invalid upload response:', res);
+ toast.add({ severity: 'error', summary: '上传失败', detail: '服务器返回无效数据', life: 3000 });
+ }
+ } catch (e) {
+ console.error(e);
+ toast.add({ severity: 'error', summary: '上传失败', detail: e.message, life: 3000 });
+ }
+ event.target.value = '';
};
-const saveSettings = () => {
+const handleAddAccount = async () => {
+ if (!newAccount.name || !newAccount.account || !newAccount.realname) {
+ toast.add({ severity: 'warn', summary: '提示', detail: '请填写完整信息', life: 3000 });
+ return;
+ }
+ try {
+ await creatorApi.addPayoutAccount(newAccount);
+ showAddAccount.value = false;
+ toast.add({ severity: 'success', summary: '添加成功', detail: '收款账户已添加', life: 3000 });
+ fetchData();
+ // Reset
+ newAccount.name = ''; newAccount.account = ''; newAccount.realname = '';
+ } catch (e) {
+ toast.add({ severity: 'error', summary: '添加失败', detail: e.message, life: 3000 });
+ }
+};
+
+const removeAccount = async (id) => {
+ if (!confirm('确定要删除此账户吗?')) return;
+ try {
+ await creatorApi.removePayoutAccount(id);
+ toast.add({ severity: 'success', summary: '删除成功', life: 3000 });
+ fetchData();
+ } catch (e) {
+ toast.add({ severity: 'error', summary: '删除失败', detail: e.message, life: 3000 });
+ }
+};
+
+const saveSettings = async () => {
if (!form.name) {
toast.add({ severity: 'error', summary: '错误', detail: '频道名称不能为空', life: 3000 });
return;
}
- toast.add({ severity: 'success', summary: '保存成功', detail: '部分信息正在审核中', life: 3000 });
+ try {
+ await creatorApi.updateSettings(form);
+ toast.add({ severity: 'success', summary: '保存成功', detail: '设置已更新', life: 3000 });
+ } catch (e) {
+ toast.add({ severity: 'error', summary: '保存失败', detail: e.message, life: 3000 });
+ }
};
\ No newline at end of file