Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
wangxiaolu-sfa-ui
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
sfa
wangxiaolu-sfa-ui
Commits
6e3cf651
提交
6e3cf651
authored
3月 27, 2025
作者:
lidongxu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(mobile/promotion): 移动端_促销计划列表和搜索完成
同上
上级
56028c0f
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
165 行增加
和
50 行删除
+165
-50
.env.development
.env.development
+1
-0
login.js
src/api/common/login.js
+10
-2
date.js
src/hooks/date.js
+15
-12
index.vue
src/mobile_views/promotion/index.vue
+105
-32
index.js
src/router/index.js
+5
-0
user.js
src/store/modules/user.js
+8
-1
login.vue
src/views/login.vue
+16
-3
vite.config.js
vite.config.js
+5
-0
没有找到文件。
.env.development
浏览文件 @
6e3cf651
...
...
@@ -7,6 +7,7 @@ VITE_APP_PUBLIC_PATH = '/'
# 基地址
VITE_APP_BASE_API = '/dev-api' # 小卤
# VITE_APP_BASE_API = '/ql_local' # 小卤
VITE_APP_PROMOTION = '/promotion-api' # 促销
# 飞书服务回调地址(本地测试已经通过并上线,后台飞书登录接口重定向地址已经不是 localhost 了所以本地开发无需使用飞书登录,线上已经可用)
...
...
src/api/common/login.js
浏览文件 @
6e3cf651
...
...
@@ -39,6 +39,14 @@ export function fsLogin(data) {
})
}
// 勤策系统-静默登录(用勤测在 URL 上回传的参数调用自己后台登录接口)
export
function
qcLogin
(
params
)
{
return
request
({
url
:
`/auth/qc/login?
${
params
}
`
})
}
// 账号密码登录
export
function
login
(
data
)
{
return
request
({
...
...
@@ -61,4 +69,5 @@ export function logout() {
url
:
'/auth/logout'
,
method
:
'delete'
})
}
\ No newline at end of file
}
src/hooks/date.js
浏览文件 @
6e3cf651
/**
* 日期选项配置
* @param {*}
type 0:从今天开始往前,-1 则是 T - 1 开始日期往前
* @param {*}
* @returns {}
*/
export
const
useDatePickerOptions
=
(
type
=
-
1
)
=>
{
const
last30Date
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
-
(
30
-
1
))),
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
))]
const
last7Date
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
-
(
7
-
1
))),
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
))]
const
lastDate
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
)),
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
))]
export
const
useDatePickerOptions
=
()
=>
{
const
last30Date
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
-
(
30
-
1
))),
new
Date
().
setDate
((
new
Date
().
getDate
()))]
const
last7Date
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
-
(
7
-
1
))),
new
Date
().
setDate
((
new
Date
().
getDate
()))]
const
lastDate
=
[
new
Date
().
setDate
((
new
Date
().
getDate
()
)),
new
Date
().
setDate
((
new
Date
().
getDate
()
))]
// 今日 0 点到 24 点
const
today
=
new
Date
();
today
.
setHours
(
0
,
0
,
0
,
0
);
const
tomorrow
=
new
Date
();
tomorrow
.
setDate
(
tomorrow
.
getDate
());
tomorrow
.
setHours
(
23
,
59
,
59
,
59
);
const
todayDate
=
[
today
,
tomorrow
]
// 今年的 1.1 号到 12.31号
...
...
@@ -24,19 +23,23 @@ export const useDatePickerOptions = (type = -1) => {
}
},
{
text
:
'最近
一周
'
,
text
:
'最近
7 日
'
,
value
()
{
const
end
=
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
));
const
start
=
new
Date
();
start
.
setTime
(
start
.
getTime
()
-
3600
*
1000
*
24
*
(
7
-
1
));
start
.
setTime
(
start
.
getTime
()
-
3600
*
1000
*
24
*
7
);
start
.
setHours
(
0
,
0
,
0
,
0
);
const
end
=
new
Date
();
end
.
setHours
(
23
,
59
,
59
,
59
);
return
[
start
,
end
]
}
},
{
text
:
'最近
一个月
'
,
text
:
'最近
30 日
'
,
value
()
{
const
end
=
new
Date
().
setDate
((
new
Date
().
getDate
()
+
type
));
const
start
=
new
Date
();
start
.
setTime
(
start
.
getTime
()
-
3600
*
1000
*
24
*
(
30
-
1
));
start
.
setDate
((
new
Date
().
getDate
()
-
30
))
start
.
setHours
(
0
,
0
,
0
,
0
);
const
end
=
new
Date
();
end
.
setHours
(
23
,
59
,
59
,
59
);
return
[
start
,
end
]
}
}
...
...
src/mobile_views/promotion/index.vue
浏览文件 @
6e3cf651
...
...
@@ -4,20 +4,24 @@
right-text=
"搜索"
@
click-right=
"showSearch = true"
/>
<!-- 计划列表 -->
<van-list
v-model:loading=
"loading"
:finished=
"finished"
:immediate-check=
"false"
finished-text=
"没有更多了"
@
load=
"onLoad"
>
<van-cell-group
inset
>
<van-cell
v-for=
"item in planList"
:key=
"item.id"
:title=
"item.employeeName"
:value=
"item.pattern"
:label=
"item.storeName"
@
click=
"detailFn"
/>
</van-cell-group>
</van-list>
<van-pull-refresh
v-model=
"refreshLoading"
:pull-distance=
"100"
@
refresh=
"onRefresh"
>
<van-list
v-model:loading=
"loading"
:finished=
"finished"
:immediate-check=
"false"
finished-text=
"没有更多了"
@
load=
"onLoad"
>
<van-cell-group
inset
>
<van-cell
v-for=
"item in planList"
:key=
"item.id"
:title=
"item.employeeName"
:value=
"item.pattern"
:label=
"item.storeName"
@
click=
"detailFn"
/>
</van-cell-group>
</van-list>
</van-pull-refresh>
<van-popup
v-model:show=
"showSearch"
position=
"right"
...
...
@@ -30,7 +34,7 @@
<van-button
size=
"small"
type=
"primary"
v-for=
"item in pickerOptions"
@
click
.
stop
.
self
.
prevent
=
"pickerBtn(item)"
>
{{
item
.
text
}}
</van-button>
@
click=
"pickerBtn(item)"
>
{{
item
.
text
}}
</van-button>
</
template
>
</van-field>
<!-- 开始时间 -->
...
...
@@ -40,7 +44,8 @@
name=
"datePicker"
label=
"开始时间"
placeholder=
"点击选择时间"
@
click=
"startShowPicker = true"
/>
@
click=
"startShowPicker = true"
>
</van-field>
<van-popup
v-model:show=
"startShowPicker"
destroy-on-close
position=
"bottom"
...
...
@@ -102,7 +107,14 @@
<!-- 终端名 -->
<van-field
v-model=
"query.storeNameLike"
label=
"终端名"
placeholder=
"请输入终端名"
/>
placeholder=
"请输入终端名"
@
input=
"searchByStoreName"
/>
<!-- 重置按钮 -->
<van-button
icon=
"replay"
class=
"reset"
block
@
click=
"resetFn"
>
重置
</van-button>
</van-popup>
...
...
@@ -147,15 +159,8 @@ const query = reactive({
// 快捷时间
const
pickerBtn
=
(
item
)
=>
{
let
[
startTime
,
endTime
]
=
item
.
value
()
// 判断不是空并且不是日期对象则转换成日期对象
if
(
startTime
&&
!
(
startTime
instanceof
Date
))
{
startTime
=
new
Date
(
startTime
)
}
if
(
endTime
&&
!
(
endTime
instanceof
Date
))
{
endTime
=
new
Date
(
endTime
)
}
query
.
activityStartDate
=
parseTime
(
startTime
,
'{y}-{m}-{d}'
)
query
.
activityEndDate
=
parseTime
(
endTime
,
'{y}-{m}-{d}'
)
query
.
activityStartDate
=
parseTime
(
startTime
)
query
.
activityEndDate
=
parseTime
(
endTime
)
// 更新两个数组格式时间
activityStartDatePicker
[
0
]
=
startTime
.
getFullYear
()
activityStartDatePicker
[
1
]
=
startTime
.
getMonth
()
+
1
...
...
@@ -163,6 +168,10 @@ const pickerBtn = (item) => {
activityEndDatePicker
[
0
]
=
endTime
.
getFullYear
()
activityEndDatePicker
[
1
]
=
endTime
.
getMonth
()
+
1
activityEndDatePicker
[
2
]
=
endTime
.
getDate
()
planList
.
value
=
[]
planQueryParams
.
pageNum
=
1
getPlanList
()
}
// 开始时间
const
startShowPicker
=
ref
(
false
)
...
...
@@ -195,6 +204,10 @@ const onPlanConfirm = (val) => {
query
.
planStatus
=
val
.
selectedOptions
[
0
].
text
planStatusStr
.
value
=
val
.
selectedValues
planStatusShowPicker
.
value
=
false
planList
.
value
=
[]
planQueryParams
.
pageNum
=
1
getPlanList
()
}
// 归属人
const
employeeIdShowPicker
=
ref
(
false
)
...
...
@@ -220,6 +233,10 @@ const onEmployeeConfirm = (val) => {
query
.
employeeId
=
val
.
selectedOptions
[
0
].
text
employeeIdStr
.
value
=
val
.
selectedValues
employeeIdShowPicker
.
value
=
false
planList
.
value
=
[]
planQueryParams
.
pageNum
=
1
getPlanList
()
}
// 计划列表
...
...
@@ -231,37 +248,93 @@ const planList = ref([])
const
loading
=
ref
(
false
)
const
finished
=
ref
(
false
)
const
getPlanList
=
async
()
=>
{
loading
.
value
=
true
const
res
=
await
getPlanListAPI
(
planQueryParams
)
console
.
log
(
query
)
const
res
=
await
getPlanListAPI
({
...
planQueryParams
,
activityDate
:
[
query
.
activityStartDate
,
query
.
activityEndDate
],
planStatus
:
planColumns
.
find
(
item
=>
item
.
text
===
query
.
planStatus
)?.
value
,
employeeId
:
employeeIdColumns
.
value
.
find
(
item
=>
item
.
text
===
query
.
employeeId
)?.
value
,
storeName
:
query
.
storeNameLike
,
})
planList
.
value
=
[...
planList
.
value
,
...
res
.
data
.
records
]
finished
.
value
=
res
.
data
.
records
.
length
===
0
loading
.
value
=
false
}
getPlanList
()
const
searchByStoreName
=
(
val
)
=>
{
query
.
storeNameLike
=
val
.
data
planList
.
value
=
[]
planQueryParams
.
pageNum
=
1
getPlanList
()
}
const
onLoad
=
()
=>
{
loading
.
value
=
true
planQueryParams
.
pageNum
++
getPlanList
()
}
const
detailFn
=
()
=>
{
}
// 刷新
const
refreshLoading
=
ref
(
false
)
const
onRefresh
=
()
=>
{
refreshLoading
.
value
=
true
setTimeout
(()
=>
{
refreshLoading
.
value
=
false
planQueryParams
.
pageNum
=
1
query
.
activityStartDate
=
''
query
.
activityEndDate
=
''
query
.
planStatus
=
''
query
.
employeeId
=
''
query
.
storeNameLike
=
''
planList
.
value
=
[]
getPlanList
()
},
1000
)
}
// 重置
const
resetFn
=
()
=>
{
query
.
activityStartDate
=
''
query
.
activityEndDate
=
''
query
.
planStatus
=
''
query
.
employeeId
=
''
query
.
storeNameLike
=
''
planList
.
value
=
[]
planQueryParams
.
pageNum
=
1
getPlanList
()
}
</
script
>
<
style
scoped
lang=
"scss"
>
.mobile-container
{
.mobile-container
{
background
:
#f5f5f5
;
.van-cell-group
{
min-height
:
100vh
;
.van-cell-group
{
background
:
#f5f5f5
;
}
.van-cell
{
.van-cell
{
margin-top
:
10px
;
::v-deep
(
.van-cell__label
)
{
::v-deep
(
.van-cell__label
)
{
/* 强制一行显示 */
white-space
:
nowrap
;
}
}
}
.van-list
{
min-height
:
100vh
;
}
.reset
{
margin-top
:
20px
;
}
::v-deep
(
.van-field
)
:first-of-type
{
.van-button
{
margin
:
0
5px
;
...
...
src/router/index.js
浏览文件 @
6e3cf651
...
...
@@ -88,6 +88,11 @@ export const constantMobileRoutes = [
path
:
'/'
,
redirect
:
'/promotion'
},
{
path
:
'/login'
,
component
:
()
=>
import
(
'@/views/login'
),
hidden
:
true
},
{
path
:
'/promotion'
,
component
:
()
=>
import
(
'@/mobile_views/promotion/index'
),
...
...
src/store/modules/user.js
浏览文件 @
6e3cf651
import
{
login
,
fsLogin
,
getInfo
}
from
'@/api'
import
{
login
,
fsLogin
,
getInfo
,
qcLogin
}
from
'@/api'
import
{
getToken
,
setToken
,
removeToken
}
from
'@/utils/auth'
import
{
isHttp
,
isEmpty
}
from
"@/utils/validate"
import
defAva
from
'@/assets/images/profile.jpg'
...
...
@@ -41,6 +41,13 @@ export default defineStore(
}).
catch
(
error
=>
{
reject
(
error
)
})
}
else
if
(
type
===
'qc'
)
{
// 勤策登录
qcLogin
(
data
).
then
(
res
=>
{
setToken
(
res
.
data
.
access_token
)
this
.
token
=
res
.
data
.
access_token
resolve
()
})
}
})
},
...
...
src/views/login.vue
浏览文件 @
6e3cf651
...
...
@@ -136,8 +136,8 @@ const getOAuthState = () => {
}
getOAuthState
()
//
飞书
客户端登录
const
checkLoginAuth
=
async
()
=>
{
//
检查-是否飞书回跳,并
客户端登录
const
check
Fs
LoginAuth
=
async
()
=>
{
if
(
window
.
h5sdk
)
{
const
code
=
await
fsClientAuth
()
loginByType
(
'fs'
,
{
code
})
...
...
@@ -145,7 +145,20 @@ const checkLoginAuth = async () => {
isShowLogin
.
value
=
true
}
}
checkLoginAuth
()
checkFsLoginAuth
()
// 检查-是否勤策回跳,并客户端登录
const
checkQcLoginAuth
=
async
()
=>
{
const
params
=
new
URLSearchParams
(
window
.
location
.
href
.
split
(
'?'
)[
1
]);
const
state
=
params
.
get
(
'state'
);
console
.
log
(
state
,
'state'
)
if
(
state
===
'STATE'
)
{
loginByType
(
'qc'
,
window
.
location
.
href
.
split
(
'?'
)[
1
])
}
else
{
isShowLogin
.
value
=
true
}
}
checkQcLoginAuth
()
// 工号密码登录
function
handleLogin
()
{
...
...
vite.config.js
浏览文件 @
6e3cf651
...
...
@@ -30,6 +30,11 @@ export default defineConfig(({ mode, command }) => {
target
:
'http://192.168.100.39:8010'
,
changeOrigin
:
true
,
rewrite
:
(
p
)
=>
p
.
replace
(
/^
\/
promotion-api/
,
''
)
},
'/ql_local'
:
{
target
:
'http://192.168.131.48:8080'
,
changeOrigin
:
true
,
rewrite
:
(
p
)
=>
p
.
replace
(
/^
\/
ql_local/
,
''
)
}
}
},
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论