@@ -289,7 +321,7 @@ import { ref, reactive, computed, onMounted, onActivated, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowLeft, ArrowDown, Refresh, Edit, Delete } from '@element-plus/icons-vue'
-import { getUserGoodsDetail, updateUserGoods, deleteUserGoods } from '@/api/admin/userVm'
+import { getUserGoodsDetail, updateUserGoods, deleteUserGoods, renewUserGoods } from '@/api/admin/userVm'
import { extractApiError } from '@/utils/kvmErrorUtil'
import VmSelectorPopup from '@/components/admin/VmSelectorPopup.vue'
import KvmServiceSelector from '@/components/admin/KvmServiceSelector.vue'
@@ -417,6 +449,41 @@ const goToOrder = () => {
router.push({ path: '/order/list', query: { order_id: oid } })
}
+// ---- 续费 ----
+const renewVisible = ref(false)
+const renewLoading = ref(false)
+const renewForm = reactive({ purchase_duration: 1, renew_price: 0, complete_pay: false, deduct_balance: false })
+const renewTotalPrice = computed(() => {
+ const price = renewForm.renew_price || (detail.value?.renewPrice || detail.value?.renew_price || 0) / 100
+ return (price * renewForm.purchase_duration).toFixed(2)
+})
+const openRenew = () => {
+ const rawRenew = detail.value?.renewPrice || detail.value?.renew_price || 0
+ Object.assign(renewForm, { purchase_duration: 1, renew_price: rawRenew / 100, complete_pay: false, deduct_balance: false })
+ renewVisible.value = true
+}
+const handleRenew = async () => {
+ renewLoading.value = true
+ try {
+ const data = { id: goodsId.value, purchase_duration: renewForm.purchase_duration }
+ if (renewForm.renew_price) data.renew_price = Math.round(renewForm.renew_price * 100)
+ if (renewForm.complete_pay) data.complete_pay = true
+ if (renewForm.complete_pay && renewForm.deduct_balance) data.deduct_balance = true
+ const res = await renewUserGoods(data)
+ if (res?.data?.code === 200) {
+ ElMessage.success('续费成功')
+ renewVisible.value = false
+ loadDetail()
+ } else {
+ ElMessage.error(extractApiError(res?.data, '续费失败'))
+ }
+ } catch (e) {
+ ElMessage.error(extractApiError(e?.response?.data, '续费失败'))
+ } finally {
+ renewLoading.value = false
+ }
+}
+
const editVisible = ref(false)
const editForm = reactive({ note: '', renew_price: 0, base_price: 0, expire_time: '', item_id: 0, _serviceId: 0, _serviceName: '', _itemName: '' })
const showVmSelector = ref(false)
diff --git a/src/views/user/UserDetail.vue b/src/views/user/UserDetail.vue
index efdd312..73fc0e0 100644
--- a/src/views/user/UserDetail.vue
+++ b/src/views/user/UserDetail.vue
@@ -116,6 +116,20 @@
{{ getRealNameTypeText(userInfo.RealName?.Type) }}
+
+
+
+
+
+
+ {{ userInfo.idc_agent.Uid || '-' }}
+ {{ userInfo.idc_agent.AgentLevelName || '-' }}
+ {{ userInfo.idc_agent.AgentLevent ?? '-' }}
+ {{ formatDate(userInfo.idc_agent.CreatedAt) }}
+
+
diff --git a/src/views/user/UserList.vue b/src/views/user/UserList.vue
index 0ce702f..5d9a616 100644
--- a/src/views/user/UserList.vue
+++ b/src/views/user/UserList.vue
@@ -32,10 +32,23 @@
@keyup.enter="handleJumpToUser"
/>
+
+ 代理商ID
+
+