feat: add community post category selection
This commit is contained in:
@@ -48,9 +48,36 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="publish-category">
|
||||
<view class="publish-section__head">
|
||||
<view class="publish-section__title-wrap">
|
||||
<text class="publish-section__title">选择分类</text>
|
||||
<text class="publish-section__required">必选</text>
|
||||
</view>
|
||||
<text class="publish-section__hint">{{ selectedCategory ? '已选择 1 个分类' : '请选择帖子所属分类' }}</text>
|
||||
</view>
|
||||
<view v-if="categoryList.length" class="publish-category__list">
|
||||
<view v-for="category in categoryList" :key="category.id" class="publish-category__item"
|
||||
:class="{ 'publish-category__item--active': selectedCategory === category.id }"
|
||||
@tap="selectCategory(category.id)">
|
||||
<image v-if="category.icon" :src="category.icon" class="publish-category__icon" mode="aspectFit" />
|
||||
<view v-else class="publish-category__icon publish-category__icon--fallback">
|
||||
<text>{{ category.name.slice(0, 1) }}</text>
|
||||
</view>
|
||||
<text class="publish-category__name">{{ category.name }}</text>
|
||||
<u-icon v-if="selectedCategory === category.id" name="checkmark" size="22" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<text v-else class="publish-section__empty">暂无可选分类</text>
|
||||
</view>
|
||||
|
||||
<view class="publish-tags">
|
||||
<view class="publish-tags__label">
|
||||
<text>选择标签</text>
|
||||
<view class="publish-section__head">
|
||||
<view class="publish-section__title-wrap">
|
||||
<text class="publish-section__title">选择标签</text>
|
||||
<text class="publish-section__optional">可多选</text>
|
||||
</view>
|
||||
<text class="publish-section__hint">已选 {{ selectedTags.length }}/3</text>
|
||||
</view>
|
||||
<view class="publish-tags__list">
|
||||
<view v-for="tag in tagList" :key="tag.id" class="publish-tags__item"
|
||||
@@ -66,7 +93,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, computed, onMounted } from 'vue'
|
||||
import { publishPost, getTagLists } from '@/api/community'
|
||||
import { publishPost, getTagLists, getCommunityCategoryLists } from '@/api/community'
|
||||
import { uploadImage } from '@/api/app'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
@@ -75,6 +102,8 @@ const scrollHeight = ref(500)
|
||||
const publishing = ref(false)
|
||||
const tagList = ref<any[]>([])
|
||||
const selectedTags = ref<number[]>([])
|
||||
const categoryList = ref<any[]>([])
|
||||
const selectedCategory = ref(0)
|
||||
|
||||
const isPaid = ref(false)
|
||||
const pricePoints = ref('')
|
||||
@@ -85,7 +114,7 @@ const form = reactive({
|
||||
})
|
||||
|
||||
const canPublish = computed(() => {
|
||||
return form.content.trim().length > 0 || form.images.length > 0
|
||||
return selectedCategory.value > 0 && (form.content.trim().length > 0 || form.images.length > 0)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -97,13 +126,14 @@ onMounted(() => {
|
||||
statusBarHeight.value = 20
|
||||
// #endif
|
||||
scrollHeight.value = sysInfo.windowHeight - statusBarHeight.value - 88
|
||||
fetchTags()
|
||||
fetchPublishOptions()
|
||||
})
|
||||
|
||||
const fetchTags = async () => {
|
||||
const fetchPublishOptions = async () => {
|
||||
try {
|
||||
const res = await getTagLists()
|
||||
tagList.value = res || []
|
||||
const [categories, tags] = await Promise.all([getCommunityCategoryLists(), getTagLists()])
|
||||
categoryList.value = categories || []
|
||||
tagList.value = tags || []
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
@@ -121,6 +151,10 @@ const handlePublish = async () => {
|
||||
uni.navigateTo({ url: '/pages/login/login' })
|
||||
return
|
||||
}
|
||||
if (!selectedCategory.value) {
|
||||
uni.showToast({ title: '请选择帖子分类', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!canPublish.value || publishing.value) return
|
||||
publishing.value = true
|
||||
try {
|
||||
@@ -148,6 +182,7 @@ const handlePublish = async () => {
|
||||
await publishPost({
|
||||
content: form.content,
|
||||
images: uploadedImages,
|
||||
category_id: selectedCategory.value,
|
||||
tag_ids: selectedTags.value,
|
||||
post_type: 0,
|
||||
is_paid: isPaid.value ? 1 : 0,
|
||||
@@ -186,6 +221,10 @@ const removeImage = (idx: number) => {
|
||||
form.images.splice(idx, 1)
|
||||
}
|
||||
|
||||
const selectCategory = (id: number) => {
|
||||
selectedCategory.value = id
|
||||
}
|
||||
|
||||
const toggleTag = (id: number) => {
|
||||
const idx = selectedTags.value.indexOf(id)
|
||||
if (idx >= 0) {
|
||||
@@ -377,17 +416,134 @@ const toggleTag = (id: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
.publish-tags {
|
||||
.publish-section__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.publish-section__title-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.publish-section__title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.publish-section__required,
|
||||
.publish-section__optional {
|
||||
padding: 3rpx 10rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.publish-section__required {
|
||||
color: #ef4444;
|
||||
background: #fff1f2;
|
||||
}
|
||||
|
||||
.publish-section__optional {
|
||||
color: #185dff;
|
||||
background: #edf4ff;
|
||||
}
|
||||
|
||||
.publish-section__hint,
|
||||
.publish-section__empty {
|
||||
color: #9aa3b2;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.publish-category {
|
||||
padding: 24rpx 30rpx;
|
||||
border-top: 16rpx solid #f5f5f5;
|
||||
|
||||
&__label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
&__list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
&__item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: calc((100% - 16rpx) / 2);
|
||||
max-width: 100%;
|
||||
height: 76rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20rpx;
|
||||
gap: 12rpx;
|
||||
border: 2rpx solid #edf0f5;
|
||||
border-radius: 14rpx;
|
||||
background: #fafbfc;
|
||||
|
||||
&--active {
|
||||
border-color: #185dff;
|
||||
background: #eef4ff;
|
||||
|
||||
.publish-category__name {
|
||||
color: #185dff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 0 10rpx 0 12rpx;
|
||||
background: #185dff;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.u-icon {
|
||||
position: absolute;
|
||||
top: 2rpx;
|
||||
right: 3rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--fallback {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #dbe8ff;
|
||||
|
||||
text {
|
||||
color: #185dff;
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__name {
|
||||
overflow: hidden;
|
||||
color: #4b5563;
|
||||
font-size: 25rpx;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.publish-tags {
|
||||
padding: 24rpx 30rpx;
|
||||
border-top: 16rpx solid #f5f5f5;
|
||||
|
||||
&__list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
Reference in New Issue
Block a user