refactor: 优化多个视图组件并添加功能

本次提交对多个视图组件进行了重构和功能增强:

    PointGoodsView.vue:
    - 清理了未使用的导入(`useAccount`)和变量(`accountInfo`, `biliInfo` prop)。
    - 通过重组计算属性和方法提高了代码可读性。
    - 增强了商品列表的筛选和排序逻辑。
    - 为购买商品功能添加了错误处理和加载状态。

    PointUserHistoryView.vue:
    - 为获取积分历史记录实现了加载状态。
    - 改进了 PointHistoryCard 组件的渲染。

    QuestionBoxView.vue:
    - 优化了可读性和性能(整合状态变量,改进命名)。
    - 增强了文件上传处理和验证逻辑。
    - 改进了标签选择逻辑和数据获取方法。
    - 添加了代码注释以提高可理解性。

    UserIndexView.vue:
    - 简化了确定要显示的模板组件的逻辑。
    - 确保无论用户信息是否存在,都一致返回默认模板。
This commit is contained in:
2025-04-17 02:15:22 +08:00
parent 1ea4404307
commit 2e5e0afd30
23 changed files with 4747 additions and 3080 deletions

View File

@@ -8,6 +8,8 @@
goods: ResponsePointGoodModel | undefined;
contentStyle?: string | undefined;
}>();
// 默认封面图片
const emptyCover = IMGUR_URL + 'None.png';
</script>
@@ -20,7 +22,9 @@
v-else
embedded
:style="props.contentStyle"
class="goods-card"
>
<!-- 商品封面 -->
<template #cover>
<NImage
:src="goods.cover ? FILE_BASE_URL + goods.cover : emptyCover"
@@ -31,6 +35,8 @@
style="width: 100%"
/>
</template>
<!-- 商品信息头部 -->
<template #header-extra>
<NFlex justify="space-between">
<NFlex>
@@ -52,11 +58,14 @@
</NFlex>
</NFlex>
</template>
<!-- 商品标题 -->
<template #header>
<NFlex
align="center"
:size="5"
>
<!-- 售罄标签 -->
<NTag
v-if="goods.count == 0"
size="small"
@@ -65,17 +74,23 @@
>
已售完
</NTag>
<!-- 商品类型标签 -->
<NTag
size="small"
:bordered="goods.type != GoodsTypes.Physical"
>
{{ goods.type == GoodsTypes.Physical ? '实物' : '虚拟' }}
</NTag>
<!-- 商品名称 -->
<NEllipsis>
{{ goods.name }}
</NEllipsis>
</NFlex>
</template>
<!-- 商品描述和标签 -->
<NFlex vertical>
<NEllipsis :line-clamp="2">
<NText
@@ -85,7 +100,10 @@
{{ goods.description ? goods.description : '暂无描述' }}
</NText>
</NEllipsis>
<NFlex>
<!-- 标签展示 -->
<NFlex wrap>
<!-- 舰长限制标签 -->
<NTag
v-if="goods.allowGuardLevel > 0"
size="tiny"
@@ -96,6 +114,8 @@
</template>
仅限舰长
</NTag>
<!-- 商品标签 -->
<NTag
v-for="tag in goods.tags"
:key="tag"
@@ -106,8 +126,21 @@
</NTag>
</NFlex>
</NFlex>
<!-- 自定义页脚 -->
<template #footer>
<slot name="footer" />
</template>
</NCard>
</template>
<style scoped>
.goods-card {
transition: all 0.3s ease;
}
.goods-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
</style>

View File

@@ -12,6 +12,7 @@ import {
NText,
NTime,
NTooltip,
NEmpty
} from 'naive-ui'
import { h, ref } from 'vue'
import PointGoodsItem from './PointGoodsItem.vue'
@@ -20,9 +21,11 @@ const props = defineProps<{
histories: ResponsePointHisrotyModel[]
}>()
// 礼物详情模态框
const showGoodsModal = ref(false)
const currentGoods = ref<ResponsePointGoodModel>()
// 数据表格列定义
const historyColumn: DataTableColumns<ResponsePointHisrotyModel> = [
{
title: '时间',
@@ -102,7 +105,6 @@ const historyColumn: DataTableColumns<ResponsePointHisrotyModel> = [
{
title: '详情',
key: 'action',
render: (row: ResponsePointHisrotyModel) => {
switch (row.from) {
case PointFrom.Danmaku:
@@ -128,6 +130,7 @@ const historyColumn: DataTableColumns<ResponsePointHisrotyModel> = [
row.extra?.danmaku.price,
])
}
break
case PointFrom.Manual:
return h(NFlex, { align: 'center' }, () => [
h(NTag, { type: 'info', size: 'small', style: { margin: '0' } }, () => '来自'),
@@ -162,23 +165,48 @@ const historyColumn: DataTableColumns<ResponsePointHisrotyModel> = [
),
])
}
return null
},
},
]
</script>
<template>
<!-- 无数据时显示提示 -->
<NEmpty
v-if="!histories || histories.length === 0"
description="暂无积分历史记录"
/>
<!-- 有数据时显示表格 -->
<NDataTable
v-else
:columns="historyColumn"
:data="histories"
:pagination="{ showSizePicker: true, pageSizes: [10, 25, 50, 100], defaultPageSize: 10, size: 'small' }"
:pagination="{
showSizePicker: true,
pageSizes: [10, 25, 50, 100],
defaultPageSize: 10,
size: 'small'
}"
/>
<!-- 商品详情模态框 -->
<NModal
v-model:show="showGoodsModal"
preset="card"
title="礼物详情 (快照)"
style="max-width: 400px; height: auto"
>
</NDataTable>
<NModal v-model:show="showGoodsModal" preset="card" title="礼物详情 (快照)" style="max-width: 400px; height: auto">
<PointGoodsItem :goods="currentGoods" />
<template v-if="currentGoods?.content">
<NDivider> 礼物内容 </NDivider>
<NInput :value="currentGoods?.content" type="textarea" readonly placeholder="无内容" />
<NDivider>礼物内容</NDivider>
<NInput
:value="currentGoods?.content"
type="textarea"
readonly
placeholder="无内容"
/>
</template>
</NModal>
</template>

View File

@@ -177,16 +177,28 @@ const orderColumn: DataTableColumns<ResponsePointOrder2UserModel | ResponsePoint
},
],
render: (row: ResponsePointOrder2UserModel | ResponsePointOrder2OwnerModel) => {
switch (row.status) {
case PointOrderStatus.Pending:
return h(NTag, { size: 'small' }, () => '等待发货')
case PointOrderStatus.Shipped:
return h(NTag, { size: 'small', type: row.expressCompany ? 'info' : 'warning', bordered: false }, () =>
row.expressCompany ? '已发货 | 已填写单号' : '已发货 | 未填写单号',
)
case PointOrderStatus.Completed:
return h(NTag, { size: 'small', type: 'success' }, () => '已完成')
const statusMap = {
[PointOrderStatus.Pending]: {
text: '等待发货',
type: 'default'
},
[PointOrderStatus.Shipped]: {
text: row.expressCompany ? '已发货 | 已填写单号' : '已发货 | 未填写单号',
type: row.expressCompany ? 'info' : 'warning'
},
[PointOrderStatus.Completed]: {
text: '已完成',
type: 'success'
}
}
const status = statusMap[row.status] || { text: '未知状态', type: 'error' }
return h(NTag, {
size: 'small',
type: status.type as any,
bordered: false
}, () => status.text)
},
},
{
@@ -294,6 +306,7 @@ function onChangeStatus(id: number, status: PointOrderStatus) {
}
async function updateStatus(id: number[], status: PointOrderStatus) {
try {
isLoading.value = true
const data = await QueryPostAPI(POINT_API_URL + 'update-orders-status', {
ids: id,
status,
@@ -311,6 +324,8 @@ async function updateStatus(id: number[], status: PointOrderStatus) {
} catch (err) {
message.error('操作失败: ' + err)
console.log(err)
} finally {
isLoading.value = false
}
}
async function updateExpress(item: ResponsePointOrder2OwnerModel) {
@@ -358,7 +373,6 @@ onMounted(() => {
<template #empty>
<NEmpty description="暂无订单" />
</template>
>
</NDataTable>
<NModal
v-if="orderDetail"
@@ -380,25 +394,38 @@ onMounted(() => {
</NTooltip>
</NDivider>
<NFlex justify="center">
<PointGoodsItem style="max-width: 300px" :goods="currentGoods" />
<PointGoodsItem
style="max-width: 300px"
:goods="currentGoods"
/>
</NFlex>
<template v-if="orderDetail.type == GoodsTypes.Virtual">
<NDivider> 虚拟礼物内容 </NDivider>
<NInput :value="currentGoods?.content" type="textarea" readonly placeholder="无内容" />
<NInput
:value="currentGoods?.content"
type="textarea"
readonly
placeholder="无内容"
/>
</template>
<template
v-if="
orderDetail.type == GoodsTypes.Physical &&
orderDetail.status == PointOrderStatus.Pending &&
orderDetail.goods.embedCollectUrl &&
orderDetail.goods.collectUrl
orderDetail.status == PointOrderStatus.Pending &&
orderDetail.goods.embedCollectUrl &&
orderDetail.goods.collectUrl
"
>
<NDivider> 填写收货地址 </NDivider>
<NButton tag="a" :href="orderDetail.goods.collectUrl" target="_blank" type="info">
<NButton
tag="a"
:href="orderDetail.goods.collectUrl"
target="_blank"
type="info"
>
在新窗口中打开地址填写表格
</NButton>
<br />
<br>
<iframe
height="1200"
width="800"
@@ -406,23 +433,41 @@ onMounted(() => {
frameborder="0"
allowfullscreen
sandbox="allow-same-origin allow-scripts allow-modals allow-downloads allow-forms allow-popups"
></iframe>
/>
</template>
</template>
<template v-else-if="orderDetail.instanceOf == 'owner'"
><NFlex justify="center">
<PointGoodsItem style="max-width: 300px" :goods="currentGoods" />
<template v-else-if="orderDetail.instanceOf == 'owner'">
<NFlex justify="center">
<PointGoodsItem
style="max-width: 300px"
:goods="currentGoods"
/>
</NFlex>
<NDivider> 设置订单状态 </NDivider>
<NFlex justify="center" style="width: 100%">
<NFlex
justify="center"
style="width: 100%"
>
<NSteps
:current="orderDetail.status + 1"
size="small"
@update:current="(c) => onChangeStatus(orderDetail?.id ?? -1, c - 1)"
>
<NStep title="等待中" description="等待主播发货" :disabled="orderDetail.status >= 0" />
<NStep title="已发货" description="已经发货了" :disabled="orderDetail.status >= 1" />
<NStep title="已完成" description="就是已完成" :disabled="orderDetail.status >= 2" />
<NStep
title="等待中"
description="等待主播发货"
:disabled="orderDetail.status >= 0"
/>
<NStep
title="已发货"
description="已经发货了"
:disabled="orderDetail.status >= 1"
/>
<NStep
title="已完成"
description="就是已完成"
:disabled="orderDetail.status >= 2"
/>
</NSteps>
</NFlex>
<template v-if="orderDetail.status == PointOrderStatus.Shipped && orderDetail.instanceOf == 'owner'">
@@ -442,7 +487,12 @@ onMounted(() => {
style="max-width: 200px"
/>
</NInputGroup>
<NButton type="primary" @click="updateExpress(orderDetail)" style="width: 120px" :loading="isLoading">
<NButton
type="primary"
style="width: 120px"
:loading="isLoading"
@click="updateExpress(orderDetail)"
>
更新快递信息
</NButton>
</NFlex>
@@ -452,3 +502,9 @@ onMounted(() => {
</NScrollbar>
</NModal>
</template>
<style scoped>
:deep(.n-data-table .n-data-table-tr:hover) {
background-color: rgba(0, 0, 0, 0.03);
}
</style>