feat: release

This commit is contained in:
zzc
2026-05-20 23:16:53 +08:00
parent 0143a08af7
commit 48c7cebac1
4 changed files with 142 additions and 26 deletions

View File

@@ -7,3 +7,10 @@ export const releaseTopic = async (data) => {
data, data,
}); });
}; };
export const fetchTopicCategories = async (data) => {
return request({
url: "/api/rating/topic/category/list",
method: "GET",
});
};

View File

@@ -17,7 +17,7 @@
<view class="content-wrap"> <view class="content-wrap">
<view class="topic-editor card-block"> <view class="topic-editor card-block">
<textarea <textarea
v-model="formData.topic" v-model="formData.title"
class="topic-input" class="topic-input"
maxlength="40" maxlength="40"
placeholder="输入一个有争议的话题..." placeholder="输入一个有争议的话题..."
@@ -34,10 +34,10 @@
/> />
</view> </view>
<view class="cover-card" :class="{ 'has-cover': formData.cover }" @tap="chooseCover"> <view class="cover-card" :class="{ 'has-cover': formData.coverUrl }" @tap="chooseCover">
<image <image
v-if="formData.cover" v-if="formData.coverUrl"
:src="formData.cover" :src="formData.coverUrl"
class="cover-image" class="cover-image"
mode="aspectFill" mode="aspectFill"
/> />
@@ -50,12 +50,12 @@
<view class="category-group"> <view class="category-group">
<view <view
v-for="category in categories" v-for="category in categories"
:key="category" :key="category.id"
class="category-chip" class="category-chip"
:class="{ active: formData.category === category }" :class="{ active: formData.categoryId === category.id }"
@tap="formData.category = category" @tap="formData.categoryId = category.id"
> >
{{ category }} {{ category.title }}
</view> </view>
</view> </view>
@@ -158,20 +158,45 @@
<script setup> <script setup>
import { reactive, ref } from "vue"; import { reactive, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { getStatusBarHeight } from "@/utils/system"; import { getStatusBarHeight } from "@/utils/system";
import { releaseTopic } from "@/api/release"; import { releaseTopic, fetchTopicCategories } from "@/api/release";
import { smartNavigateBack } from "@/utils/page"; import { smartNavigateBack } from "@/utils/page";
import {
uploadImage,
} from "@/utils/common.js";
const statusBarHeight = ref(getStatusBarHeight() || 0); const statusBarHeight = ref(getStatusBarHeight() || 0);
const categories = ["历史", "数码", "城市", "景点", "动漫", "影视"]; const categories = ref([]);
const loadCategories = async () => {
try {
const res = await fetchTopicCategories();
// 假设返回结构为 { data: { list: [{ id: 1, title: '历史' }, ...] } }
// 或者直接是一个数组 [{ id: 1, title: '历史' }, ...]
// 根据实际返回结构调整
const list = res?.data?.list || res?.list || res || [];
categories.value = list;
// 如果存在分类且未选择,则默认选中第一个
if (categories.value.length > 0 && !formData.categoryId) {
formData.categoryId = categories.value[0].id;
}
} catch (error) {
console.error("获取分类失败:", error);
}
};
onLoad(() => {
loadCategories();
});
const formData = reactive({ const formData = reactive({
topic: "", title: "",
description: "", description: "",
cover: "", coverUrl: "",
category: "历史", categoryId: "",
tags: ["历史", "皇帝"],
allowComment: true, allowComment: true,
allowPk: true, allowPk: true,
anonymous: false, anonymous: false,
@@ -186,12 +211,6 @@ const participants = ref([
desc: "一句话简介", desc: "一句话简介",
avatar: "", avatar: "",
}, },
{
id: 2,
name: "汉武帝",
desc: "开疆拓土,大汉盛世",
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=hanwudi",
},
]); ]);
const goBack = () => { const goBack = () => {
@@ -239,6 +258,22 @@ const chooseCover = () => {
}); });
}; };
const onAvatarSelect = async (url) => {
if (!url) return;
uni.showLoading({ title: "上传中...", mask: true });
try {
const imageUrl = await uploadImage(url);
formData.coverUrl = imageUrl;
uni.hideLoading();
} catch (e) {
uni.hideLoading();
uni.showToast({ title: e || "上传失败", icon: "none" });
console.error("Upload avatar error", e);
}
};
const chooseParticipantAvatar = (index) => { const chooseParticipantAvatar = (index) => {
uni.chooseImage({ uni.chooseImage({
count: 1, count: 1,
@@ -294,14 +329,18 @@ const removeParticipant = (id) => {
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
if (!formData.topic.trim()) { if (!formData.title.trim()) {
uni.showToast({ title: '请输入话题', icon: 'none' }); uni.showToast({ title: '请输入话题', icon: 'none' });
return; return;
} }
if (!formData.cover) { if (!formData.coverUrl) {
uni.showToast({ title: '请上传封面图', icon: 'none' }); uni.showToast({ title: '请上传封面图', icon: 'none' });
return; return;
} }
if (!formData.categoryId) {
uni.showToast({ title: '请选择话题分类', icon: 'none' });
return;
}
// 检查是否有空的对象名称 // 检查是否有空的对象名称
const hasEmptyName = participants.value.some(p => !p.name.trim()); const hasEmptyName = participants.value.some(p => !p.name.trim());
@@ -316,7 +355,7 @@ const handleSubmit = async () => {
...formData, ...formData,
participants: participants.value, participants: participants.value,
}; };
console.log(11111, payload)
await releaseTopic(payload); await releaseTopic(payload);
uni.hideLoading(); uni.hideLoading();

View File

@@ -39,3 +39,73 @@ export const smartNavigateBack = (options = {}) => {
executeBack(); executeBack();
} }
}; };
/**
* 对象转 URL 参数
* @param {Object} obj 要转换的对象
* @returns {string} 返回 a=1&b=2 格式的字符串
*/
export const objToUrlParams = (obj) => {
if (!obj || typeof obj !== 'object') return '';
const params = [];
for (let key in obj) {
if (obj.hasOwnProperty(key) && obj[key] !== undefined && obj[key] !== null) {
// 过滤掉 undefined 和 null 的参数
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`);
}
}
return params.join('&');
};
/**
* 封装带参数的跳转方法
* @param {string} url 跳转的页面路径
* @param {Object} params 要传递的参数对象
*/
export const navigateToWithParams = (url, params = {}) => {
const queryStr = objToUrlParams(params);
const finalUrl = queryStr ? `${url}${url.includes('?') ? '&' : '?'}${queryStr}` : url;
uni.navigateTo({
url: finalUrl
});
};
/**
* 获取当前页面的实例
* @returns {Object|null} 当前页面实例
*/
export const getCurrentPage = () => {
const pages = getCurrentPages();
return pages.length > 0 ? pages[pages.length - 1] : null;
};
/**
* 刷新当前页面(重新调用 onLoad 和 onShow
* 注意:部分复杂页面可能需要根据具体业务逻辑单独实现刷新机制
*/
export const refreshCurrentPage = () => {
const currentPage = getCurrentPage();
if (currentPage) {
if (typeof currentPage.onLoad === 'function') {
currentPage.onLoad(currentPage.options || {});
}
if (typeof currentPage.onShow === 'function') {
currentPage.onShow();
}
}
};
/**
* 检查当前是否是指定页面
* @param {string} route 页面路由,例如 'pages/index/index'
* @returns {boolean}
*/
export const isCurrentPage = (route) => {
const currentPage = getCurrentPage();
if (!currentPage) return false;
// 去除可能的首字符 '/'
const checkRoute = route.startsWith('/') ? route.substring(1) : route;
return currentPage.route === checkRoute;
};

View File

@@ -1,5 +1,5 @@
const BASE_URL = "https://api.ai-meng.com"; // const BASE_URL = "https://api.ai-meng.com";
// const BASE_URL = 'http://127.0.0.1:3999' const BASE_URL = 'http://127.0.0.1:3999'
// const BASE_URL = "http://192.168.1.2:3999"; // const BASE_URL = "http://192.168.1.2:3999";
// const BASE_URL = "http://192.168.31.253:3999"; // const BASE_URL = "http://192.168.31.253:3999";
import { useUserStore } from "@/stores/user"; import { useUserStore } from "@/stores/user";
@@ -35,7 +35,7 @@ function hideLoading() {
function getHeaders() { function getHeaders() {
const userStore = useUserStore(); const userStore = useUserStore();
const headers = { const headers = {
"x-app-id": "69665538a49b8ae3be50fe5d", "x-app-id": "6a0d7dbe4c5de50f2ba66475",
"x-platform": platform, "x-platform": platform,
"x-user-id": userStore?.userInfo?.id || "", "x-user-id": userStore?.userInfo?.id || "",
}; };