feat: release
This commit is contained in:
@@ -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",
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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 || "",
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user