功能基本完成
This commit is contained in:
@@ -13,5 +13,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"lastUpdated": 1776157357538
|
||||
"lastUpdated": 1776158712744
|
||||
}
|
||||
@@ -709,4 +709,42 @@ func ApiPurchase(r *gin.RouterGroup) {
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
})
|
||||
|
||||
// 获取订单数量统计
|
||||
r.POST("/getordercount", func(ctx *gin.Context) {
|
||||
isAuth, _, _ := AuthenticationAuthority(ctx)
|
||||
if !isAuth {
|
||||
ReturnJson(ctx, "userCookieError", nil)
|
||||
return
|
||||
}
|
||||
|
||||
type OrderCount struct {
|
||||
Pending int64 `json:"pending"` // 待处理
|
||||
Ordered int64 `json:"ordered"` // 已下单
|
||||
Arrived int64 `json:"arrived"` // 已到达
|
||||
Received int64 `json:"received"` // 已收件
|
||||
Lost int64 `json:"lost"` // 丢件
|
||||
Returned int64 `json:"returned"` // 退件
|
||||
Total int64 `json:"total"` // 总数
|
||||
}
|
||||
|
||||
var count OrderCount
|
||||
models.DB.Model(&TabPurchaseOrder{}).Count(&count.Total)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "pending").Count(&count.Pending)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "ordered").Count(&count.Ordered)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "arrived").Count(&count.Arrived)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "received").Count(&count.Received)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "lost").Count(&count.Lost)
|
||||
models.DB.Model(&TabPurchaseOrder{}).Where("order_status = ?", "returned").Count(&count.Returned)
|
||||
|
||||
ReturnJson(ctx, "apiOK", map[string]interface{}{
|
||||
"pending": count.Pending,
|
||||
"ordered": count.Ordered,
|
||||
"arrived": count.Arrived,
|
||||
"received": count.Received,
|
||||
"lost": count.Lost,
|
||||
"returned": count.Returned,
|
||||
"total": count.Total,
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ export const purchaseApi = {
|
||||
return api.post('/purchase/getorders', params)
|
||||
},
|
||||
|
||||
/** 获取订单数量统计 */
|
||||
getOrderCount() {
|
||||
return api.post('/purchase/getordercount', {})
|
||||
},
|
||||
|
||||
/** 新增采购订单 */
|
||||
addOrder(data) {
|
||||
return api.post('/purchase/addorder', data)
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"link": "Link",
|
||||
"no_photos": "No photos",
|
||||
"open_link": "Open Link",
|
||||
"copy_link": "Copy Link",
|
||||
"no_costs": "No cost records",
|
||||
"cost_total": "Total",
|
||||
"change_status": "Change Status",
|
||||
@@ -191,7 +192,8 @@
|
||||
"today_schedule_count": "Today: {count} schedule(s)",
|
||||
"today_no_schedule": "No schedules today",
|
||||
"loading": "Loading...",
|
||||
"today": "Today: {date}"
|
||||
"today": "Today: {date}",
|
||||
"pending_orders": "Pending orders"
|
||||
},
|
||||
"message": {
|
||||
"functionality_not_yet_developed": "Functionality not yet developed",
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"link": "链接",
|
||||
"no_photos": "暂无图片",
|
||||
"open_link": "打开链接",
|
||||
"copy_link": "复制链接",
|
||||
"no_costs": "暂无费用记录",
|
||||
"cost_total": "合计",
|
||||
"change_status": "变更状态",
|
||||
@@ -191,7 +192,8 @@
|
||||
"today_schedule_count": "今日共 {count} 个日程",
|
||||
"today_no_schedule": "今日暂无日程",
|
||||
"loading": "加载中...",
|
||||
"today": "今日:{date}"
|
||||
"today": "今日:{date}",
|
||||
"pending_orders": "待处理订单"
|
||||
},
|
||||
"message": {
|
||||
"functionality_not_yet_developed": "功能未开发",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useUserStore } from '@/stores/user'
|
||||
import { useUsersStore } from '@/stores/users'
|
||||
import { usePageTitle } from '@/composables/usePageTitle'
|
||||
import { scheduleApi } from '@/api/schedule'
|
||||
import { purchaseApi } from '@/api/purchase'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
usePageTitle('appname.home')
|
||||
@@ -15,6 +16,10 @@ const usersStore = useUsersStore()
|
||||
const todaySchedules = ref([])
|
||||
const loadingSchedules = ref(false)
|
||||
|
||||
// 采购订单数据
|
||||
const pendingOrderCount = ref(0)
|
||||
const loadingOrders = ref(false)
|
||||
|
||||
// 获取今日日期字符串
|
||||
const todayStr = computed(() => {
|
||||
const today = new Date()
|
||||
@@ -57,6 +62,21 @@ async function fetchTodaySchedules() {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取待处理订单数量
|
||||
async function fetchPendingOrders() {
|
||||
loadingOrders.value = true
|
||||
try {
|
||||
const { errCode, data } = await purchaseApi.getOrderCount()
|
||||
if (errCode === 0 && data) {
|
||||
pendingOrderCount.value = data.pending || 0
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取订单数量失败', e)
|
||||
} finally {
|
||||
loadingOrders.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户名
|
||||
function getUsername(userId) {
|
||||
if (!userId) return ''
|
||||
@@ -100,6 +120,9 @@ function getWeekday(dateStr) {
|
||||
|
||||
onMounted(() => {
|
||||
fetchTodaySchedules()
|
||||
if (userStore.isLoggedIn) {
|
||||
fetchPendingOrders()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -161,12 +184,19 @@ onMounted(() => {
|
||||
<!-- 功能入口卡片 -->
|
||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
|
||||
<div
|
||||
<RouterLink
|
||||
to="/purchase"
|
||||
class="rounded-xl border border-gray-200 bg-white px-5 py-4 transition-shadow hover:shadow-md dark:border-dk-muted dark:bg-dk-card"
|
||||
>
|
||||
<p class="mb-1 text-sm text-gray-500">{{ t('appname.purchase') }}</p>
|
||||
<p class="text-lg font-bold text-gray-900 dark:text-white">—</p>
|
||||
</div>
|
||||
<p class="text-lg font-bold text-gray-900 dark:text-white">
|
||||
<span v-if="loadingOrders">...</span>
|
||||
<span v-else :class="{ 'text-yellow-600 dark:text-yellow-400': pendingOrderCount > 0 }">
|
||||
{{ pendingOrderCount || '—' }}
|
||||
</span>
|
||||
</p>
|
||||
<p class="text-xs text-gray-400">{{ t('home.pending_orders') }}</p>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -160,7 +160,7 @@ onMounted(fetchOrders)
|
||||
@click="jumpToOrder(order.ID)"
|
||||
>
|
||||
<td class="px-6 py-3 text-gray-400">{{ order.ID }}</td>
|
||||
<td class="px-6 py-3 font-medium text-gray-900 dark:text-white">{{ order.Title }}</td>
|
||||
<td class="px-6 py-3 max-w-[200px] truncate font-medium text-gray-900 dark:text-white">{{ order.Title }}</td>
|
||||
<td class="px-6 py-3 max-w-[200px] truncate text-gray-600 dark:text-gray-300">{{ order.Remark || '-' }}</td>
|
||||
<td class="px-6 py-3 whitespace-nowrap text-gray-500 dark:text-gray-400">{{ formatDate(order.CreatedAt) }}</td>
|
||||
<td class="px-6 py-3">
|
||||
|
||||
@@ -137,6 +137,14 @@ function openLink() {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
|
||||
function copyLink() {
|
||||
if (!order.value?.Link) return;
|
||||
navigator.clipboard.writeText(order.value.Link.trim()).then(() => {
|
||||
const toast = useToastStore()
|
||||
toast.success('链接已复制')
|
||||
})
|
||||
}
|
||||
|
||||
function getStatusLabel(status) {
|
||||
if (!status) return "";
|
||||
const opt = statusOptions.find((o) => o.value === status);
|
||||
@@ -450,12 +458,26 @@ onMounted(fetchOrder);
|
||||
<label class="mb-1 block text-xs font-medium text-gray-400">{{
|
||||
t("purchase.link")
|
||||
}}</label>
|
||||
<div v-if="order?.Link" class="flex items-center gap-2">
|
||||
<p class="max-w-xs truncate text-blue-600 dark:text-blue-400">
|
||||
<div v-if="order?.Link" class="flex flex-wrap items-center gap-2">
|
||||
<a
|
||||
:href="order.Link.trim().startsWith('http') ? order.Link.trim() : 'https://' + order.Link.trim()"
|
||||
target="_blank"
|
||||
class="max-w-[400px] truncate rounded bg-gray-100 px-3 py-1.5 text-xs text-blue-600 hover:bg-gray-200 dark:bg-dk-base dark:text-blue-400 dark:hover:bg-gray-800"
|
||||
:title="order.Link"
|
||||
>
|
||||
{{ order.Link }}
|
||||
</p>
|
||||
</a>
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs text-blue-600 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-blue-900/20"
|
||||
class="inline-flex items-center gap-1 rounded bg-blue-100 px-3 py-1.5 text-xs font-medium text-blue-700 hover:bg-blue-200 dark:bg-blue-900/40 dark:text-blue-300 dark:hover:bg-blue-900/60"
|
||||
@click="copyLink"
|
||||
>
|
||||
<svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
|
||||
</svg>
|
||||
{{ t('purchase.copy_link') }}
|
||||
</button>
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded px-2 py-1 text-xs text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800"
|
||||
@click="openLink"
|
||||
>
|
||||
<IconExternalLink :size="14" />
|
||||
|
||||
Reference in New Issue
Block a user