初始化

This commit is contained in:
2026-03-02 08:31:49 +08:00
commit d8ae21ced4
582 changed files with 66532 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
<template>
<view class="mb-16rpx overflow-hidden rounded-12rpx bg-white shadow-sm">
<view
class="flex items-center justify-between p-24rpx"
@click="handleToggle"
>
<view class="flex items-center">
<!-- 展开/收起图标 -->
<view class="mr-16rpx w-40rpx">
<wd-icon
v-if="hasChildren"
:name="expanded ? 'arrow-down' : 'arrow-right'"
size="16px"
color="#999"
/>
</view>
<!-- 地区信息 -->
<view class="text-28rpx text-[#333]">
{{ item.name }}
</view>
</view>
<!-- 编码 -->
<view class="text-24rpx text-[#999]">
编码{{ item.id }}
</view>
</view>
<!-- 子节点 -->
<view v-if="expanded && hasChildren" class="border-t border-[#f5f5f5] pl-56rpx">
<AreaTreeItem
v-for="child in item.children"
:key="child.id"
:item="child"
:level="level + 1"
/>
</view>
</view>
</template>
<script lang="ts" setup>
import type { Area } from '@/api/system/area'
import { computed, ref } from 'vue'
const props = withDefaults(defineProps<{
item: Area
level?: number
}>(), {
level: 0,
})
const expanded = ref(false)
const hasChildren = computed(() => props.item.children && props.item.children.length > 0)
/** 切换展开/收起 */
function handleToggle() {
if (hasChildren.value) {
expanded.value = !expanded.value
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,74 @@
<template>
<wd-popup v-model="visible" position="bottom" closable safe-area-inset-bottom>
<view class="p-32rpx">
<view class="mb-24rpx text-32rpx font-semibold">
IP 查询
</view>
<wd-input
v-model="ipAddress"
label="IP 地址"
label-width="160rpx"
placeholder="请输入 IP 地址"
clearable
/>
<wd-input
v-model="ipResult"
label="地址"
label-width="160rpx"
placeholder="展示查询 IP 结果"
readonly
class="mt-24rpx"
/>
<wd-button type="primary" block class="mt-32rpx" @click="handleQueryIp">
查询
</wd-button>
</view>
</wd-popup>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { getAreaByIp } from '@/api/system/area'
import { isIp } from '@/utils/validator'
const props = defineProps<{
modelValue: boolean
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
}>()
const visible = ref(false)
const ipAddress = ref('')
const ipResult = ref('')
watch(() => props.modelValue, (val) => {
visible.value = val
if (val) {
ipAddress.value = ''
ipResult.value = ''
}
})
watch(visible, (val) => {
emit('update:modelValue', val)
})
/** 查询 IP */
async function handleQueryIp() {
if (!ipAddress.value) {
uni.showToast({ title: '请输入 IP 地址', icon: 'none' })
return
}
if (!isIp(ipAddress.value)) {
uni.showToast({ title: '请输入正确的 IP 地址', icon: 'none' })
return
}
ipResult.value = await getAreaByIp(ipAddress.value)
uni.showToast({ title: '查询成功', icon: 'success' })
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,91 @@
<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="地区管理"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 地区树列表 -->
<view class="p-24rpx">
<!-- 加载中 -->
<view v-if="loading" class="py-100rpx text-center">
<wd-loading />
</view>
<!-- 地区树 -->
<view v-else-if="areaList.length > 0">
<AreaTreeItem
v-for="item in areaList"
:key="item.id"
:item="item"
/>
</view>
<!-- 空状态 -->
<view v-else class="py-100rpx text-center">
<wd-status-tip image="content" tip="暂无地区数据" />
</view>
</view>
<!-- 搜索按钮 -->
<wd-fab
position="right-bottom"
type="primary"
:expandable="false"
icon="search"
@click="handleOpenIpQuery"
/>
<!-- IP 查询弹窗 -->
<IpQueryForm v-model="showIpQuery" />
</view>
</template>
<script lang="ts" setup>
import type { Area } from '@/api/system/area'
import { ref } from 'vue'
import { getAreaTree } from '@/api/system/area'
import { navigateBackPlus } from '@/utils'
import AreaTreeItem from './components/area-tree-item.vue'
import IpQueryForm from './components/ip-query-form.vue'
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const loading = ref(false)
const areaList = ref<Area[]>([])
const showIpQuery = ref(false) // 是否显示 IP 查询弹窗
/** 获取地区树 */
async function getList() {
loading.value = true
try {
areaList.value = await getAreaTree()
} finally {
loading.value = false
}
}
/** 打开 IP 查询弹窗 */
function handleOpenIpQuery() {
showIpQuery.value = true
}
/** 返回上一页 */
function handleBack() {
navigateBackPlus()
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped>
</style>