feat: 更新地址信息接口,优化地址选择逻辑和表单验证

This commit is contained in:
2025-04-17 04:21:00 +08:00
parent 2e5e0afd30
commit d53295bb0c
2 changed files with 97 additions and 73 deletions

View File

@@ -698,9 +698,9 @@ export interface PointGoodsModel {
export interface AddressInfo { export interface AddressInfo {
id?: string id?: string
province: string province: string
city: string city?: string
district: string district?: string
street: string street?: string
address: string address: string
phone: number phone: number
name: string name: string

View File

@@ -32,6 +32,7 @@ import { computed, ref } from 'vue'
//@ts-expect-error 导入有点问题 //@ts-expect-error 导入有点问题
import UserAgreement from '@/document/UserAgreement.md' import UserAgreement from '@/document/UserAgreement.md'
// 地区数据类型定义
type AreaData = { type AreaData = {
[province: string]: { [province: string]: {
[city: string]: { [city: string]: {
@@ -43,9 +44,13 @@ type AreaData = {
const useAuth = useAuthStore() const useAuth = useAuthStore()
const message = useMessage() const message = useMessage()
const isLoading = ref(false) const isLoading = ref(false)
const userAgree = ref(false) const userAgree = ref(false)
const showAddressModal = ref(false)
const showAgreementModal = ref(false)
const formRef = ref()
const currentAddress = ref<AddressInfo>()
// 本地存储区域数据
const areas = useStorage<{ const areas = useStorage<{
createAt: number createAt: number
data: AreaData data: AreaData
@@ -53,21 +58,34 @@ const areas = useStorage<{
createAt: 0, createAt: 0,
data: {}, data: {},
}) })
// 计算属性:获取省份选项
const provinceOptions = computed(() => { const provinceOptions = computed(() => {
return Object.keys(areas.value?.data ?? {}).map((p) => ({ label: p, value: p })) return Object.keys(areas.value?.data ?? {}).map((p) => ({ label: p, value: p }))
}) })
// 计算属性:当前用户授权信息
const biliAuth = computed(() => useAuth.biliAuth)
// 获取城市选项
const cityOptions = (province: string) => { const cityOptions = (province: string) => {
if (!areas.value?.data[province]) return [] if (!areas.value?.data[province]) return []
return Object.keys(areas.value?.data[province] ?? {}).map((c) => ({ label: c, value: c })) return Object.keys(areas.value?.data[province] ?? {}).map((c) => ({ label: c, value: c }))
} }
// 获取区/县选项
const districtOptions = (province: string, city: string) => { const districtOptions = (province: string, city: string) => {
if (!areas.value?.data[province]?.[city]) return [] if (!areas.value?.data[province]?.[city]) return []
return Object.keys(areas.value?.data[province][city] ?? {}).map((d) => ({ label: d, value: d })) return Object.keys(areas.value?.data[province][city] ?? {}).map((d) => ({ label: d, value: d }))
} }
// 获取街道选项
const streetOptions = (province: string, city: string, district: string) => { const streetOptions = (province: string, city: string, district: string) => {
if (!areas.value?.data[province]?.[city]?.[district]) return [] if (!areas.value?.data[province]?.[city]?.[district]) return []
return areas.value?.data[province][city][district]?.map((s) => ({ label: s, value: s })) ?? [] return areas.value?.data[province][city][district]?.map((s) => ({ label: s, value: s })) ?? []
} }
// 表单验证规则
const rules: FormRules = { const rules: FormRules = {
phone: { phone: {
required: true, required: true,
@@ -99,29 +117,30 @@ const rules: FormRules = {
}, },
}, },
} }
const formRef = ref()
const biliAuth = computed(() => useAuth.biliAuth) // 处理API错误的工具函数
const handleApiError = (action: string, err: any) => {
const currentAddress = ref<AddressInfo>() message.error(`${action}失败: ${err}`)
console.error(err)
const showAddressModal = ref(false) }
const showAgreementModal = ref(false)
// 地址管理相关函数
// 更新地址信息
async function updateAddress() { async function updateAddress() {
formRef.value
?.validate()
.then(async () => {
isLoading.value = true
try { try {
await formRef.value?.validate()
isLoading.value = true
const data = await useAuth.QueryBiliAuthPostAPI<AddressInfo>( const data = await useAuth.QueryBiliAuthPostAPI<AddressInfo>(
POINT_API_URL + 'user/update-address', POINT_API_URL + 'user/update-address',
currentAddress.value, currentAddress.value,
) )
if (data.code == 200) { if (data.code == 200) {
message.success('已保存') message.success('已保存')
showAddressModal.value = false showAddressModal.value = false
currentAddress.value = {} as AddressInfo
// 更新本地地址列表
if (biliAuth.value.address) { if (biliAuth.value.address) {
const index = biliAuth.value.address?.findIndex((a) => a.id == data.data.id) ?? -1 const index = biliAuth.value.address?.findIndex((a) => a.id == data.data.id) ?? -1
if (index >= 0) { if (index >= 0) {
@@ -130,22 +149,23 @@ async function updateAddress() {
biliAuth.value.address.push(data.data) biliAuth.value.address.push(data.data)
} }
} }
currentAddress.value = {} as AddressInfo
} else { } else {
message.error('更新地址失败: ' + data.message) handleApiError('更新地址', data.message)
console.error(data)
} }
} catch (err) { } catch (err) {
message.error('更新地址失败: ' + err) if (err instanceof Error) {
console.error(err) handleApiError('更新地址', err)
} } else {
})
.catch(() => {
message.error('信息未填写完成') message.error('信息未填写完成')
}) }
.finally(() => { } finally {
isLoading.value = false isLoading.value = false
}) }
} }
// 删除地址
async function deleteAddress(id: string) { async function deleteAddress(id: string) {
isLoading.value = true isLoading.value = true
try { try {
@@ -156,66 +176,69 @@ async function deleteAddress(id: string) {
biliAuth.value.address = biliAuth.value.address?.filter((a) => a.id != id) biliAuth.value.address = biliAuth.value.address?.filter((a) => a.id != id)
} }
} else { } else {
message.error('删除地址失败: ' + data.message) handleApiError('删除地址', data.message)
console.error(data)
} }
} catch (err) { } catch (err) {
message.error('删除地址失败: ' + err) handleApiError('删除地址', err)
console.error(err)
} finally { } finally {
isLoading.value = false isLoading.value = false
} }
} }
// 获取区域数据
async function getArea() { async function getArea() {
// 缓存一周内的数据,避免频繁请求
if (areas.value && Date.now() - areas.value?.createAt < 1000 * 60 * 60 * 24 * 7) { if (areas.value && Date.now() - areas.value?.createAt < 1000 * 60 * 60 * 24 * 7) {
return return
} }
try { try {
isLoading.value = true isLoading.value = true
const data = await fetch(THINGS_URL + 'area_data.json') const data = await fetch('https://oss.suki.club/vtsuru/area_data.json')
if (data.ok) { if (data.ok) {
const area = { const area = {
createAt: Date.now(), createAt: Date.now(),
data: await data.json(), data: await data.json(),
} }
console.log(area)
areas.value = area areas.value = area
} }
} catch (err) { } catch (err) {
console.error(err) handleApiError('获取区域数据', err)
message.error('获取区域数据失败') } finally {
}
isLoading.value = false isLoading.value = false
}
} }
// 打开地址编辑模态框
async function onOpenAddressModal() { async function onOpenAddressModal() {
showAddressModal.value = true showAddressModal.value = true
currentAddress.value = {} as AddressInfo currentAddress.value = {} as AddressInfo
await getArea() await getArea()
} }
// 处理地区选择变化,级联清除下级选项
function onAreaSelectChange(level: number) { function onAreaSelectChange(level: number) {
if (!currentAddress.value) return if (!currentAddress.value) return
const newValue = {} as AddressInfo
// 根据变化的级别清除下级数据
switch (level) { switch (level) {
case 0: { case 0: // 省份变化,清除市区街道
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.city = undefined currentAddress.value.city = undefined
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.district = undefined currentAddress.value.district = undefined
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.street = undefined currentAddress.value.street = undefined
} break
case 1: { case 1: // 城市变化,清除区县街道
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.district = undefined currentAddress.value.district = undefined
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.street = undefined currentAddress.value.street = undefined
} break
case 2: { case 2: // 区县变化,清除街道
// @ts-expect-error 不管这个,直接赋值
currentAddress.value.street = undefined currentAddress.value.street = undefined
} break
} }
} }
// 账号管理相关函数
// 切换当前使用的授权账号
function switchAuth(token: string) { function switchAuth(token: string) {
if (token == useAuth.biliToken) { if (token == useAuth.biliToken) {
message.info('当前正在使用该账号') message.info('当前正在使用该账号')
@@ -225,6 +248,7 @@ function switchAuth(token: string) {
message.success('已切换账号') message.success('已切换账号')
} }
// 登出当前账号
function logout() { function logout() {
useAuth.logout() useAuth.logout()
} }
@@ -392,7 +416,7 @@ function logout() {
<NSelect <NSelect
:key="currentAddress.city" :key="currentAddress.city"
v-model:value="currentAddress.district" v-model:value="currentAddress.district"
:options="districtOptions(currentAddress.province, currentAddress.city)" :options="currentAddress.city ? districtOptions(currentAddress.province, currentAddress.city) : []"
:disabled="!currentAddress?.city" :disabled="!currentAddress?.city"
placeholder="请选择区" placeholder="请选择区"
style="width: 100px" style="width: 100px"
@@ -402,7 +426,7 @@ function logout() {
<NSelect <NSelect
:key="currentAddress.district" :key="currentAddress.district"
v-model:value="currentAddress.street" v-model:value="currentAddress.street"
:options="streetOptions(currentAddress.province, currentAddress.city, currentAddress.district)" :options="currentAddress.city && currentAddress.district ? streetOptions(currentAddress.province, currentAddress.city, currentAddress.district) : []"
:disabled="!currentAddress?.district" :disabled="!currentAddress?.district"
placeholder="请选择街道" placeholder="请选择街道"
style="width: 150px" style="width: 150px"