Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
basic-uniapp-v3
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-uniapp-v3
Commits
69e1168c
提交
69e1168c
authored
3月 31, 2026
作者:
廖在望
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 登录页面、供应需求、采购需求、地区组件、相关详情页面重构&问题修复。
上级
b5983f10
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
217 行增加
和
75 行删除
+217
-75
index.vue
src/components/AreaPicker/index.vue
+1
-1
chanxiao.vue
src/pages/chanxiao/chanxiao.vue
+110
-26
purchaseXuQiu.vue
src/pages/chanxiao/purchaseXuQiu.vue
+0
-0
supplyXuQiu.vue
src/pages/chanxiao/supplyXuQiu.vue
+0
-0
login.vue
src/pages/login/login.vue
+6
-3
register.vue
src/pages/login/register.vue
+5
-3
nongchang.vue
src/pages/nongchang/nongchang.vue
+64
-12
farm-form.vue
src/pages/nongjifuwu/farm-form.vue
+0
-0
machine-form.vue
src/pages/nongjifuwu/machine-form.vue
+0
-0
area.ts
src/utils/dict/area.ts
+31
-30
没有找到文件。
src/components/AreaPicker/index.vue
浏览文件 @
69e1168c
...
@@ -93,7 +93,7 @@
...
@@ -93,7 +93,7 @@
border-radius
:
32
rpx
32
rpx
0
0
;
border-radius
:
32
rpx
32
rpx
0
0
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
height
:
8
0vh
;
height
:
6
0vh
;
font-family
:
'DingTalk Sans'
,
sans-serif
;
font-family
:
'DingTalk Sans'
,
sans-serif
;
}
}
...
...
src/pages/chanxiao/chanxiao.vue
浏览文件 @
69e1168c
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
reactive
}
from
'vue'
import
{
reactive
,
onMounted
}
from
'vue'
import
{
onPullDownRefresh
,
onReachBottom
,
onShow
}
from
'@dcloudio/uni-app'
import
{
onPullDownRefresh
,
onReachBottom
,
onShow
}
from
'@dcloudio/uni-app'
import
PriceDialog
from
'./components/price-dialog.vue'
import
PriceDialog
from
'./components/price-dialog.vue'
import
Navigate
from
'@/utils/page/navigate'
import
Navigate
from
'@/utils/page/navigate'
import
*
as
ChanxiaoAPI
from
'@/api/model/chanxiao'
import
*
as
ChanxiaoAPI
from
'@/api/model/chanxiao'
import
{
getText
}
from
'@/utils/dict/area'
import
{
getDictData
,
getText
}
from
'@/utils/dict/area'
onMounted
(()
=>
{
getDictData
()
})
// 下拉刷新
// 下拉刷新
onPullDownRefresh
(()
=>
{
onPullDownRefresh
(()
=>
{
...
@@ -26,13 +30,13 @@
...
@@ -26,13 +30,13 @@
},
1000
)
},
1000
)
})
})
onShow
(()
=>
{
onShow
(()
=>
{
pageData
.
search
.
pageNo
=
1
// 只有当列表为空时才重新获取数据,避免每次返回页面都全量刷新
if
(
pageData
.
currentTransactionTab
===
1
)
{
if
(
pageData
.
currentTransactionTab
===
1
&&
pageData
.
supplyInfos
.
length
===
0
)
{
pageData
.
s
upplyInfos
=
[]
pageData
.
s
earch
.
pageNo
=
1
fetchSupplyInfos
()
fetchSupplyInfos
()
}
}
if
(
pageData
.
currentTransactionTab
===
2
)
{
if
(
pageData
.
currentTransactionTab
===
2
&&
pageData
.
purchaseDemands
.
length
===
0
)
{
pageData
.
purchaseDemands
=
[]
pageData
.
search
.
pageNo
=
1
fetchPurchaseDemands
()
fetchPurchaseDemands
()
}
}
})
})
...
@@ -151,11 +155,16 @@
...
@@ -151,11 +155,16 @@
ChanxiaoAPI
.
purchaseList
(
pageData
.
search
)
ChanxiaoAPI
.
purchaseList
(
pageData
.
search
)
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
const
{
records
,
total
}
=
res
const
{
records
,
total
}
=
res
pageData
.
purchaseDemands
=
[...
pageData
.
purchaseDemands
,
...
records
]
const
mappedRecords
=
records
.
map
((
item
)
=>
{
pageData
.
purchaseDemands
=
pageData
.
purchaseDemands
.
map
((
item
)
=>
({
const
nameParts
=
[
item
.
cityName
,
item
.
countryName
].
filter
(
Boolean
)
...
item
,
return
{
location
:
getText
(
`
${
item
.
province
}
,
${
item
.
city
}
,
${
item
.
country
}
`
,
' / '
),
...
item
,
}))
location
:
nameParts
.
length
>
0
?
nameParts
.
join
(
''
)
:
getText
(
`
${
item
.
city
}
,
${
item
.
country
}
`
,
''
),
}
})
pageData
.
purchaseDemands
=
[...
pageData
.
purchaseDemands
,
...
mappedRecords
]
pageData
.
total
=
total
pageData
.
total
=
total
})
})
.
finally
(()
=>
{
.
finally
(()
=>
{
...
@@ -171,11 +180,16 @@
...
@@ -171,11 +180,16 @@
ChanxiaoAPI
.
supplyList
(
params
)
ChanxiaoAPI
.
supplyList
(
params
)
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
const
{
records
,
total
}
=
res
const
{
records
,
total
}
=
res
pageData
.
supplyInfos
=
[...
pageData
.
supplyInfos
,
...
records
]
const
mappedRecords
=
records
.
map
((
item
)
=>
{
pageData
.
supplyInfos
=
pageData
.
supplyInfos
.
map
((
item
)
=>
({
const
nameParts
=
[
item
.
cityName
,
item
.
districtName
].
filter
(
Boolean
)
...
item
,
return
{
location
:
getText
(
`
${
item
.
province
}
,
${
item
.
city
}
,
${
item
.
country
}
`
,
' / '
),
...
item
,
}))
location
:
nameParts
.
length
>
0
?
nameParts
.
join
(
''
)
:
getText
(
`
${
item
.
city
}
,
${
item
.
district
}
`
,
''
),
}
})
pageData
.
supplyInfos
=
[...
pageData
.
supplyInfos
,
...
mappedRecords
]
pageData
.
total
=
total
pageData
.
total
=
total
})
})
.
finally
(()
=>
{
.
finally
(()
=>
{
...
@@ -388,6 +402,12 @@
...
@@ -388,6 +402,12 @@
<!-- 采购需求列表 -->
<!-- 采购需求列表 -->
<view
v-if=
"pageData.currentTransactionTab === 2"
>
<view
v-if=
"pageData.currentTransactionTab === 2"
>
<view
<view
v-if=
"pageData.purchaseDemands.length === 0"
style=
"height: 528rpx"
>
<fui-empty
src=
"/static/images/no-data.png"
title=
"暂无数据"
/>
</view>
<view
v-for=
"(demand, index) in pageData.purchaseDemands"
v-for=
"(demand, index) in pageData.purchaseDemands"
:key=
"demand.id"
:key=
"demand.id"
class=
"product-card purchase"
class=
"product-card purchase"
...
@@ -424,22 +444,86 @@
...
@@ -424,22 +444,86 @@
</view>
</view>
</view>
</view>
</view>
</view>
<fui-fab
position=
"right"
distance=
"30"
bottom=
"150"
width=
"96"
@
click=
"handlePublish"
>
<!-- 发布悬浮按钮 -->
<view
v-show=
"pageData.currentTransactionTab === 1"
class=
"text-white text-center"
>
<view
class=
"fab-container"
@
click=
"handlePublish"
>
<view
class=
"fab-icon"
/>
<view
class=
"ripple"
:class=
"
{ 'ripple-purchase': pageData.currentTransactionTab === 2 }">
</view>
<view
style=
"font-size: 24rpx"
>
发布
</view>
<view
class=
"ripple ripple-2"
:class=
"
{ 'ripple-purchase': pageData.currentTransactionTab === 2 }">
</view>
</view>
<view
class=
"fab-entry"
:class=
"
{ 'fab-purchase': pageData.currentTransactionTab === 2 }">
<view
v-show=
"pageData.currentTransactionTab === 2"
class=
"text-white text-center"
>
<fui-icon
name=
"plus"
:size=
"48"
color=
"#fff"
bold
></fui-icon>
<view
class=
"fab-icon"
/>
<text>
发布
</text>
<view
style=
"font-size: 24rpx"
>
发布
</view>
</view>
</view>
</
fui-fab
>
</
view
>
<PriceDialog
ref=
"priceDialogRef"
/>
<PriceDialog
ref=
"priceDialogRef"
/>
<fui-loading
isFixed
v-if=
"pageData.loading"
backgroundColor=
"rgba(0, 0, 0, 0.4)"
/>
<fui-loading
isFixed
v-if=
"pageData.loading"
backgroundColor=
"rgba(0, 0, 0, 0.4)"
/>
</
template
>
</
template
>
<
style
scoped
lang=
"scss"
>
<
style
scoped
lang=
"scss"
>
.fab-container
{
position
:
fixed
;
right
:
30
rpx
;
bottom
:
150
rpx
;
width
:
110
rpx
;
height
:
110
rpx
;
z-index
:
100
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
.ripple
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
background-color
:
#5db66f
;
border-radius
:
50%
;
opacity
:
0.4
;
animation
:
ripple
2s
infinite
ease-out
;
&.ripple-purchase
{
background-color
:
#fa8c16
;
}
}
.ripple-2
{
animation-delay
:
1s
;
}
.fab-entry
{
position
:
relative
;
width
:
110
rpx
;
height
:
110
rpx
;
background
:
linear-gradient
(
135deg
,
#5db66f
0%
,
#4caf50
100%
);
border-radius
:
50%
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
box-shadow
:
0
4
rpx
16
rpx
rgba
(
93
,
182
,
111
,
0.3
);
&.fab-purchase
{
background
:
linear-gradient
(
135deg
,
#ffbb96
0%
,
#fa8c16
100%
);
box-shadow
:
0
4
rpx
16
rpx
rgba
(
250
,
140
,
22
,
0.3
);
}
text
{
color
:
#fff
;
font-size
:
20
rpx
;
font-weight
:
bold
;
margin-top
:
-4
rpx
;
}
}
}
@keyframes
ripple
{
0
%
{
transform
:
scale
(
1
);
opacity
:
0.4
;
}
100
%
{
transform
:
scale
(
1.6
);
opacity
:
0
;
}
}
.ml-7
{
.ml-7
{
margin-left
:
14
rpx
;
margin-left
:
14
rpx
;
}
}
...
...
src/pages/chanxiao/purchaseXuQiu.vue
浏览文件 @
69e1168c
差异被折叠。
点击展开。
src/pages/chanxiao/supplyXuQiu.vue
浏览文件 @
69e1168c
差异被折叠。
点击展开。
src/pages/login/login.vue
浏览文件 @
69e1168c
...
@@ -141,6 +141,9 @@
...
@@ -141,6 +141,9 @@
function
onSlideSuccess
()
{
function
onSlideSuccess
()
{
if
(
slideType
.
value
===
'sms'
)
{
if
(
slideType
.
value
===
'sms'
)
{
// 立即开启倒计时(乐观更新),接口报错也不停止,防止恶意连点
startCountdown
()
// 发送验证码
// 发送验证码
const
params
=
{
const
params
=
{
mobile
:
model
.
form
.
data
.
username
,
mobile
:
model
.
form
.
data
.
username
,
...
@@ -149,10 +152,10 @@
...
@@ -149,10 +152,10 @@
API
.
sysSms
(
params
)
API
.
sysSms
(
params
)
.
then
(
async
()
=>
{
.
then
(
async
()
=>
{
Message
.
toast
(
'验证码已发送'
)
Message
.
toast
(
'验证码已发送'
)
startCountdown
()
})
})
.
catch
(()
=>
{
.
catch
((
err
)
=>
{
Message
.
toast
(
'验证码发送失败'
)
// 即使接口返回 code: 130 等错误,也不干扰已启动的倒计时
console
.
error
(
'短信发送业务异常:'
,
err
)
})
})
}
else
{
}
else
{
// 执行登录
// 执行登录
...
...
src/pages/login/register.vue
浏览文件 @
69e1168c
...
@@ -93,6 +93,9 @@
...
@@ -93,6 +93,9 @@
function
onSlideSuccess
()
{
function
onSlideSuccess
()
{
if
(
slideType
.
value
===
'sms'
)
{
if
(
slideType
.
value
===
'sms'
)
{
// 开启乐观倒计时,不论接口成败,60s内不准重发
startCountdown
()
const
params
=
{
const
params
=
{
mobile
:
model
.
form
.
data
.
phone
,
mobile
:
model
.
form
.
data
.
phone
,
smsmode
:
2
,
// 2-注册
smsmode
:
2
,
// 2-注册
...
@@ -100,10 +103,9 @@
...
@@ -100,10 +103,9 @@
API
.
sysSms
(
params
)
API
.
sysSms
(
params
)
.
then
(
async
()
=>
{
.
then
(
async
()
=>
{
Message
.
toast
(
'验证码已发送'
)
Message
.
toast
(
'验证码已发送'
)
startCountdown
()
})
})
.
catch
(()
=>
{
.
catch
((
err
)
=>
{
Message
.
toast
(
'验证码发送失败'
)
console
.
error
(
'注册短信发送失败:'
,
err
)
})
})
}
else
{
}
else
{
doRegister
()
doRegister
()
...
...
src/pages/nongchang/nongchang.vue
浏览文件 @
69e1168c
...
@@ -747,22 +747,74 @@
...
@@ -747,22 +747,74 @@
</view>
</view>
</view>
</view>
<fui-fab
<!-- 找人干活悬浮按钮 -->
v-if=
"!userStore.isAuditMode"
<view
class=
"fab-container"
v-if=
"!userStore.isAuditMode"
@
click=
"handlePublish"
>
position=
"right"
<view
class=
"ripple"
></view>
distance=
"10"
<view
class=
"ripple ripple-2"
></view>
bottom=
"240"
<view
class=
"fab-entry"
>
width=
"96"
<image
style=
"width: 48rpx; height: 48rpx"
src=
"/static/images/nongchang/work_icon.png"
/>
@
click=
"handlePublish"
<text>
找人干活
</text>
>
<view
class=
"text-white text-center"
>
<image
style=
"width: 52rpx; height: 52rpx"
src=
"/static/images/nongchang/work_icon.png"
/>
<view
style=
"font-size: 18rpx; margin-top: -16rpx"
>
找人干活
</view>
</view>
</view>
</
fui-fab
>
</
view
>
</
template
>
</
template
>
<
style
scoped
lang=
"scss"
>
<
style
scoped
lang=
"scss"
>
.fab-container
{
position
:
fixed
;
right
:
30
rpx
;
bottom
:
240
rpx
;
width
:
110
rpx
;
height
:
110
rpx
;
z-index
:
100
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
.ripple
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
background-color
:
#5db66f
;
border-radius
:
50%
;
opacity
:
0.4
;
animation
:
ripple
2s
infinite
ease-out
;
}
.ripple-2
{
animation-delay
:
1s
;
}
.fab-entry
{
position
:
relative
;
width
:
110
rpx
;
height
:
110
rpx
;
background
:
linear-gradient
(
135deg
,
#a5d63f
0%
,
#2e8b57
100%
);
border-radius
:
50%
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
box-shadow
:
0
4
rpx
16
rpx
rgba
(
46
,
139
,
87
,
0.3
);
text
{
color
:
#fff
;
font-size
:
18
rpx
;
font-weight
:
bold
;
margin-top
:
-4
rpx
;
}
}
}
@keyframes
ripple
{
0
%
{
transform
:
scale
(
1
);
opacity
:
0.4
;
}
100
%
{
transform
:
scale
(
1.6
);
opacity
:
0
;
}
}
.mt-19
{
.mt-19
{
margin-top
:
38
rpx
;
margin-top
:
38
rpx
;
}
}
...
...
src/pages/nongjifuwu/farm-form.vue
浏览文件 @
69e1168c
差异被折叠。
点击展开。
src/pages/nongjifuwu/machine-form.vue
浏览文件 @
69e1168c
差异被折叠。
点击展开。
src/utils/dict/area.ts
浏览文件 @
69e1168c
...
@@ -3,6 +3,21 @@ import { cascaderHn } from '/@/api/model/dict'
...
@@ -3,6 +3,21 @@ import { cascaderHn } from '/@/api/model/dict'
const
storageKey
=
'app_dict_data_area_cascaderHn'
const
storageKey
=
'app_dict_data_area_cascaderHn'
let
areaOptions
=
[]
let
areaOptions
=
[]
let
areaMap
=
new
Map
()
/**
* 构建扁平化字典Map,用于高效查询
*/
function
buildAreaMap
(
nodes
)
{
if
(
!
nodes
)
return
for
(
const
node
of
nodes
)
{
areaMap
.
set
(
node
.
value
,
node
.
text
)
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
buildAreaMap
(
node
.
children
)
}
}
}
export
async
function
getDictData
()
{
export
async
function
getDictData
()
{
// 先从本地加载数据
// 先从本地加载数据
let
dictData
=
getLocalDict
()
let
dictData
=
getLocalDict
()
...
@@ -15,6 +30,9 @@ export async function getDictData() {
...
@@ -15,6 +30,9 @@ export async function getDictData() {
}
}
areaOptions
=
dictData
areaOptions
=
dictData
// 构建查询Map
areaMap
.
clear
()
buildAreaMap
(
areaOptions
)
return
dictData
return
dictData
}
}
...
@@ -24,7 +42,11 @@ export async function getDictData() {
...
@@ -24,7 +42,11 @@ export async function getDictData() {
export
function
getLocalDict
()
{
export
function
getLocalDict
()
{
const
data
=
uni
.
getStorageSync
(
storageKey
)
const
data
=
uni
.
getStorageSync
(
storageKey
)
if
(
data
)
{
if
(
data
)
{
return
data
?
JSON
.
parse
(
data
)
:
null
const
dict
=
data
?
JSON
.
parse
(
data
)
:
null
if
(
dict
&&
areaMap
.
size
===
0
)
{
buildAreaMap
(
dict
)
}
return
dict
}
}
return
null
return
null
}
}
...
@@ -40,37 +62,16 @@ export function refreshDictData() {
...
@@ -40,37 +62,16 @@ export function refreshDictData() {
}
}
export
function
getText
(
scope
:
string
,
spliced
:
string
)
{
export
function
getText
(
scope
:
string
,
spliced
:
string
)
{
if
(
!
scope
||
!
areaOptions
||
areaOptions
.
length
===
0
)
{
if
(
!
scope
)
return
''
return
''
// 如果Map尚未初始化,则回退到原始递归方法或返回空
if
(
areaMap
.
size
===
0
)
{
const
dict
=
getLocalDict
()
if
(
!
dict
)
return
''
}
}
const
values
=
scope
.
split
(
','
)
const
values
=
scope
.
split
(
','
)
const
labels
=
[]
const
labels
=
values
.
map
(
val
=>
areaMap
.
get
(
val
.
trim
())
||
val
.
trim
())
// 递归查找label
const
findLabel
=
(
nodes
,
value
)
=>
{
for
(
const
node
of
nodes
)
{
if
(
node
.
value
===
value
)
{
return
node
.
text
}
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
const
found
=
findLabel
(
node
.
children
,
value
)
if
(
found
)
{
return
found
}
}
}
return
null
// 如果没找到,返回原始value
}
for
(
const
value
of
values
)
{
return
labels
.
join
(
spliced
||
''
)
const
text
=
findLabel
(
areaOptions
,
value
.
trim
())
labels
.
push
(
text
)
}
if
(
spliced
)
{
return
labels
?
labels
.
join
(
spliced
)
:
''
}
else
{
return
labels
?
labels
.
join
(
''
)
:
''
}
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论