Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
shouzhouServer
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chenjinjing
shouzhouServer
Commits
d562e619
Commit
d562e619
authored
Jul 22, 2024
by
Leo Zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
实现全部接口
parent
0cadb29f
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
295 additions
and
12 deletions
+295
-12
monthlyRevenueStrategy.ts
src/biz/map2/strategies/left/monthlyRevenueStrategy.ts
+4
-2
ticketRevenueAnalysisStrategy.ts
...biz/map2/strategies/left/ticketRevenueAnalysisStrategy.ts
+6
-6
abstractMerchantProfileStrategy.ts
.../map2/strategies/right/abstractMerchantProfileStrategy.ts
+18
-0
businessStatusStrategy.ts
src/biz/map2/strategies/right/businessStatusStrategy.ts
+23
-0
merchantBusinessStatisticsStrategy.ts
...p2/strategies/right/merchantBusinessStatisticsStrategy.ts
+30
-0
monthlyOpeningTrendStrategy.ts
src/biz/map2/strategies/right/monthlyOpeningTrendStrategy.ts
+22
-0
storeTypeDistributionStrategy.ts
...iz/map2/strategies/right/storeTypeDistributionStrategy.ts
+32
-0
visitorAgeProfileStrategy.ts
src/biz/map2/strategies/right/visitorAgeProfileStrategy.ts
+52
-0
visitorGenderProfileStrategy.ts
...biz/map2/strategies/right/visitorGenderProfileStrategy.ts
+26
-2
visitorHomeProfileStrategy.ts
src/biz/map2/strategies/right/visitorHomeProfileStrategy.ts
+47
-0
strategyFactory.ts
src/biz/strategyFactory.ts
+23
-1
httpErrorHandler.ts
src/middleware/httpErrorHandler.ts
+4
-0
routerRight.ts
src/routers/map2/routerRight.ts
+8
-1
No files found.
src/biz/map2/strategies/left/monthlyRevenueStrategy.ts
View file @
d562e619
...
...
@@ -53,8 +53,10 @@ export default class revenueAnalysisStrategy extends abstractDataStrategyLeft {
}
result
.
push
({
key
,
ticket
:
value
.
ticket
,
ecommerce
:
value
.
ecommerce
value
:
{
ticket
:
value
.
ticket
,
ecommerce
:
value
.
ecommerce
}
});
}
...
...
src/biz/map2/strategies/left/ticketRevenueAnalysisStrategy.ts
View file @
d562e619
...
...
@@ -39,20 +39,20 @@ export default class ticketSalesAnalysisStrategy extends abstractDataStrategyLef
conversionRate
=
(
totalCheckedIn
/
totalSales
)
*
100
;
}
if
(
metric
===
'amount'
)
{
return
{
const
result
=
metric
===
'amount'
?
{
totalSales
:
parseFloat
(
totalSales
.
toFixed
(
2
)),
totalCheckedIn
:
parseFloat
(
totalCheckedIn
.
toFixed
(
2
)),
totalCancellations
:
parseFloat
(
totalCancellations
.
toFixed
(
2
)),
conversionRate
:
parseFloat
(
conversionRate
.
toFixed
(
2
))
};
}
else
{
return
{
}
:
{
totalSales
:
totalTickets
,
totalCheckedIn
:
totalTickets
,
totalCancellations
:
cancellationCount
,
conversionRate
:
parseFloat
(
conversionRate
.
toFixed
(
2
))
};
}
return
Object
.
entries
(
result
).
map
(([
key
,
value
])
=>
({
key
,
value
}));
}
}
src/biz/map2/strategies/right/abstractMerchantProfileStrategy.ts
0 → 100644
View file @
d562e619
import
{
dataStrategy
}
from
"../../../dataStrategy"
;
import
{
DataExtractor
}
from
"../../../../util/dataExtractor"
;
export
abstract
class
abstractMerchantProfileStrategy
implements
dataStrategy
{
// 实例化数据提取器
extractor
=
DataExtractor
.
getInstance
();
static
readonly
FILENAME
=
'票务系统.xlsx'
;
static
readonly
SHEETNAME
=
'票务系统-游客门票表'
;
/**
* 执行策略的方法,具体实现由子类提供。
* @param params - 可选参数。
*/
abstract
execute
(
params
?:
any
):
any
;
abstract
processData
(...
param
):
any
;
}
\ No newline at end of file
src/biz/map2/strategies/right/businessStatusStrategy.ts
0 → 100644
View file @
d562e619
import
{
dataStrategy
}
from
"../../../dataStrategy"
;
export
default
class
businessStatusStrategy
implements
dataStrategy
{
execute
():
any
{
return
this
.
processData
();
}
processData
():
any
{
const
totalStores
=
Math
.
floor
(
Math
.
random
()
*
2000
)
+
1000
;
const
openStores
=
Math
.
floor
(
Math
.
random
()
*
totalStores
*
0.8
)
+
1
;
const
closedStores
=
totalStores
-
openStores
;
const
result
=
[
{
key
:
'门店数'
,
value
:
totalStores
},
{
key
:
'开店数'
,
value
:
openStores
},
{
key
:
'关店数'
,
value
:
closedStores
}
];
result
.
sort
((
a
,
b
)
=>
b
.
value
-
a
.
value
);
return
result
;
}
}
src/biz/map2/strategies/right/merchantBusinessStatisticsStrategy.ts
0 → 100644
View file @
d562e619
import
{
abstractMerchantProfileStrategy
}
from
"./abstractMerchantProfileStrategy"
;
export
default
class
merchantBusinessStatisticsStrategy
extends
abstractMerchantProfileStrategy
{
execute
():
any
{
return
this
.
processData
();
}
processData
():
any
{
const
totalBusinesses
=
Math
.
floor
(
Math
.
random
()
*
2000
)
+
1000
;
const
totalShops
=
Math
.
floor
(
Math
.
random
()
*
2500
)
+
1500
;
const
businessActivityRate
=
Math
.
floor
(
Math
.
random
()
*
50
)
+
50
;
// Random percentage between 50% and 100%
const
result
=
[
{
key
:
'totalBusinesses'
,
value
:
totalBusinesses
},
{
key
:
'totalShops'
,
value
:
totalShops
},
{
key
:
'businessActivityRate'
,
value
:
businessActivityRate
}
];
return
result
;
}
}
src/biz/map2/strategies/right/monthlyOpeningTrendStrategy.ts
0 → 100644
View file @
d562e619
export
default
class
monthlyOpeningTrendStrategy
{
execute
():
any
{
return
this
.
generateMonthlyOpeningTrendData
();
}
private
generateMonthlyOpeningTrendData
():
any
{
const
currentDate
=
new
Date
();
const
trendData
=
[];
for
(
let
i
=
11
;
i
>=
0
;
i
--
)
{
const
date
=
new
Date
(
currentDate
.
getFullYear
(),
currentDate
.
getMonth
()
-
i
,
1
);
const
month
=
`
${
date
.
getFullYear
().
toString
().
slice
(
2
)}
/
${(
date
.
getMonth
()
+
1
).
toString
().
padStart
(
2
,
'0'
)}
`
;
const
count
=
Math
.
floor
(
Math
.
random
()
*
300
)
+
100
;
trendData
.
push
({
key
:
month
,
value
:
count
});
}
return
trendData
;
}
}
src/biz/map2/strategies/right/storeTypeDistributionStrategy.ts
0 → 100644
View file @
d562e619
export
default
class
storeTypeDistributionStrategy
{
execute
():
any
{
return
this
.
generateStoreTypeData
();
}
private
generateStoreTypeData
():
any
{
const
totalStores
=
1000
;
// Total number of stores to be randomly distributed
const
storeTypes
=
[
'文化创意'
,
'特色餐饮'
,
'茶馆饮品'
,
'民宿客栈'
,
'特色工艺品'
,
'摄影照相'
,
'体验式商铺'
];
const
randomValues
=
Array
.
from
({
length
:
storeTypes
.
length
-
1
},
()
=>
Math
.
floor
(
Math
.
random
()
*
totalStores
*
0.3
));
const
remainingValue
=
totalStores
-
randomValues
.
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
randomValues
.
push
(
remainingValue
);
const
result
=
randomValues
.
map
((
value
,
index
)
=>
({
key
:
storeTypes
[
index
],
value
:
value
}));
result
.
sort
((
a
,
b
)
=>
b
.
value
-
a
.
value
);
return
result
;
}
}
src/biz/map2/strategies/right/visitorAgeProfileStrategy.ts
0 → 100644
View file @
d562e619
import
paramChecker
from
"../../../../util/paramChecker"
;
import
{
abstractCustomerProfileStrategy
}
from
"./abstractCustomerProfileStrategy"
;
export
default
class
visitorAgeProfileStrategy
extends
abstractCustomerProfileStrategy
{
execute
(
params
?:
any
):
any
{
paramChecker
.
checkDiscreteParam
(
params
,
'metric'
,
'ticket'
,
'ecommerce'
);
return
this
.
processData
(
params
.
query
[
'metric'
]);
}
processData
(
type
:
string
):
any
{
const
total
=
type
===
'ticket'
?
1000
:
3429
;
// Generate random values for each age group ensuring they sum up to total
const
children
=
Math
.
floor
(
Math
.
random
()
*
(
total
*
0.2
));
const
teenagers
=
Math
.
floor
(
Math
.
random
()
*
(
total
*
0.2
));
const
youngAdults
=
Math
.
floor
(
Math
.
random
()
*
(
total
*
0.5
));
const
adults
=
total
-
(
children
+
teenagers
+
youngAdults
);
const
ageGroups
=
[
{
key
:
'儿童'
,
value
:
{
count
:
children
,
percent
:
((
children
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
}
},
{
key
:
'少年'
,
value
:
{
count
:
teenagers
,
percent
:
((
teenagers
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
}
},
{
key
:
'青年'
,
value
:
{
count
:
youngAdults
,
percent
:
((
youngAdults
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
}
},
{
key
:
'老年'
,
value
:
{
count
:
adults
,
percent
:
((
adults
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
}
}
];
return
ageGroups
;
}
}
src/biz/map2/strategies/right/visitorGenderProfileStrategy.ts
View file @
d562e619
...
...
@@ -3,12 +3,36 @@ import paramChecker from "../../../../util/paramChecker";
export
default
class
visitorGenderProfileStrategy
extends
abstractCustomerProfileStrategy
{
execute
(
params
?:
any
):
any
{
paramChecker
.
checkDiscreteParam
(
params
,
'
type
'
,
'ecommerce'
,
'ticket'
);
paramChecker
.
checkDiscreteParam
(
params
,
'
metric
'
,
'ecommerce'
,
'ticket'
);
const
data
=
this
.
extractor
.
getData
(
visitorGenderProfileStrategy
.
FILENAME
,
visitorGenderProfileStrategy
.
SHEETNAME
);
return
this
.
processData
(
data
,
params
.
query
[
'
type
'
]);
return
this
.
processData
(
data
,
params
.
query
[
'
metric
'
]);
}
processData
(
data
:
any
,
type
:
string
):
any
{
let
total
=
0
,
maleCount
=
0
,
femaleCount
=
0
;
if
(
type
==
'ticket'
)
{
data
.
forEach
((
row
)
=>
{
total
++
;
if
(
row
[
'性别'
]
===
'男'
)
{
maleCount
++
;
}
else
{
femaleCount
++
;
}
});
}
else
if
(
type
==
'ecommerce'
)
{
total
=
3429
;
maleCount
=
Math
.
floor
(
Math
.
random
()
*
1700
)
+
100
;
femaleCount
=
total
-
maleCount
;
}
const
result
=
{
total
:
total
,
maleCount
:
maleCount
,
femaleCount
:
femaleCount
}
return
Object
.
entries
(
result
).
map
(([
key
,
value
])
=>
({
key
,
value
}));
}
...
...
src/biz/map2/strategies/right/visitorHomeProfileStrategy.ts
0 → 100644
View file @
d562e619
import
paramChecker
from
"../../../../util/paramChecker"
;
import
{
abstractCustomerProfileStrategy
}
from
"./abstractCustomerProfileStrategy"
;
export
default
class
visitorHomeProfileStrategy
extends
abstractCustomerProfileStrategy
{
execute
(
params
?:
any
):
any
{
paramChecker
.
checkDiscreteParam
(
params
,
'metric'
,
'ticket'
,
'ecommerce'
);
const
data
=
this
.
extractor
.
getData
(
visitorHomeProfileStrategy
.
FILENAME
,
visitorHomeProfileStrategy
.
SHEETNAME
);
return
this
.
processData
(
params
.
query
[
'metric'
],
data
);
}
processData
(
type
:
string
,
data
:
any
):
any
{
const
total
=
type
===
'ticket'
?
1000
:
3429
;
const
cityCounts
:
{
[
key
:
string
]:
number
}
=
{};
data
.
forEach
((
row
:
any
)
=>
{
const
city
=
row
[
'城市'
];
if
(
!
cityCounts
[
city
])
{
cityCounts
[
city
]
=
0
;
}
cityCounts
[
city
]
+=
1
;
});
const
totalVisitors
=
Object
.
values
(
cityCounts
).
reduce
((
a
,
b
)
=>
a
+
b
,
0
);
const
scaleFactor
=
total
/
totalVisitors
;
const
result
=
Object
.
entries
(
cityCounts
).
map
(([
key
,
count
])
=>
{
const
scaledCount
=
Math
.
floor
(
count
*
scaleFactor
);
return
{
key
,
value
:
{
count
:
scaledCount
,
percent
:
((
scaledCount
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
}
};
});
const
currentTotal
=
result
.
reduce
((
sum
,
city
)
=>
sum
+
city
.
value
.
count
,
0
);
if
(
currentTotal
!==
total
)
{
const
difference
=
total
-
currentTotal
;
result
[
0
].
value
.
count
+=
difference
;
result
[
0
].
value
.
percent
=
((
result
[
0
].
value
.
count
/
total
)
*
100
).
toFixed
(
2
)
+
'%'
;
}
return
result
;
}
}
src/biz/strategyFactory.ts
View file @
d562e619
...
...
@@ -34,6 +34,13 @@ import ecommerceRankingStrategy from "./map2/strategies/left/ecommerceRankingStr
import
mapDataStrategy
from
"./map2/strategies/middle/leftSideMapDataStrategy"
;
import
leftSideMapDataStrategy
from
"./map2/strategies/middle/leftSideMapDataStrategy"
;
import
rightSideMapDataStrategy
from
"./map2/strategies/middle/rightSideMapDataStrategy"
;
import
visitorGenderProfileStrategy
from
"./map2/strategies/right/visitorGenderProfileStrategy"
;
import
visitorAgeProfileStrategy
from
"./map2/strategies/right/visitorAgeProfileStrategy"
;
import
visitorHomeProfileStrategy
from
"./map2/strategies/right/visitorHomeProfileStrategy"
;
import
merchantBusinessStatisticsStrategy
from
"./map2/strategies/right/merchantBusinessStatisticsStrategy"
;
import
businessStatusStrategy
from
"./map2/strategies/right/businessStatusStrategy"
;
import
storeTypeDistributionStrategy
from
"./map2/strategies/right/storeTypeDistributionStrategy"
;
import
monthlyOpeningTrendStrategy
from
"./map2/strategies/right/monthlyOpeningTrendStrategy"
;
/**
* 策略工厂类,用于创建和管理各种数据策略。
...
...
@@ -44,15 +51,21 @@ export class strategyFactory {
*/
private
static
strategies
:
{
[
key
:
string
]:
new
()
=>
dataStrategy
}
=
{
// map 1
'allEvents'
:
allEventDataStrategy
,
//left
'sightVisitorFlowByDay'
:
sightVisitorFlowByDayStrategy
,
'gateStatus'
:
gateStatusStrategy
,
'sightVisitorFlowPerHour'
:
sightVisitorFlowByHourStrategy
,
'guchengLoad'
:
guchengLoadStrategy
,
'totalVisitorFlow'
:
totalVisitorFlowStrategy
,
'totalVisitorFlowByHour'
:
totalVisitorFlowByHourStrategy
,
// mid
'getCurrentEventCount'
:
currentEventStrategy
,
'totalEventCount'
:
totalEventCountStrategy
,
'allEvents'
:
allEventDataStrategy
,
// right
'getEventCountByYear'
:
getEventCountByYearStrategy
,
'getEventTimeDistribution'
:
eventTimeDistributionStrategy
,
'getEventMonthDistribution'
:
eventMonthDistributionStrategy
,
...
...
@@ -75,6 +88,15 @@ export class strategyFactory {
// mid
'leftSideMapData'
:
leftSideMapDataStrategy
,
'rightSideMapData'
:
rightSideMapDataStrategy
,
// right
'visitorGenderProfile'
:
visitorGenderProfileStrategy
,
'visitorAgeProfile'
:
visitorAgeProfileStrategy
,
'visitorSourceDistribution'
:
visitorHomeProfileStrategy
,
'merchantBusinessStatistics'
:
merchantBusinessStatisticsStrategy
,
'businessStatus'
:
businessStatusStrategy
,
'storeTypeDistribution'
:
storeTypeDistributionStrategy
,
'monthlyOpeningTrend'
:
monthlyOpeningTrendStrategy
};
/**
...
...
src/middleware/httpErrorHandler.ts
View file @
d562e619
...
...
@@ -50,6 +50,10 @@ export function httpErrorHandler(err, req, res, next) {
res
.
success
({
success
:
false
,
msg
:
err
.
message
,
code
:
512
});
next
();
}
else
if
(
err
.
message
==
'metric parameter must be one of ticket, ecommerce.'
)
{
res
.
success
({
success
:
false
,
msg
:
err
.
message
,
code
:
515
});
next
();
}
else
{
res
.
success
({
success
:
false
,
msg
:
err
.
message
,
code
:
500
});
next
();
...
...
src/routers/map2/routerRight.ts
View file @
d562e619
import
*
as
asyncHandler
from
'express-async-handler'
;
import
*
as
szgcBiz
from
'../../biz/getData'
;
import
storeTypeDistributionStrategy
from
"../../biz/map2/strategies/right/storeTypeDistributionStrategy"
;
export
function
setMap2RightRoutes
(
httpServer
)
{
httpServer
.
get
(
'/szgc/getdata/getEventCountByYear'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'getEventCountByYear'
)));
httpServer
.
get
(
'/szgc/getdata/visitorGenderProfile'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'visitorGenderProfile'
)));
httpServer
.
get
(
'/szgc/getdata/visitorAgeProfile'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'visitorAgeProfile'
)));
httpServer
.
get
(
'/szgc/getdata/visitorSourceDistribution'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'visitorSourceDistribution'
)));
httpServer
.
get
(
'/szgc/getdata/merchantBusinessStatistics'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'merchantBusinessStatistics'
)));
httpServer
.
get
(
'/szgc/getdata/businessStatus'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'businessStatus'
)));
httpServer
.
get
(
'/szgc/getdata/storeTypeDistribution'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'storeTypeDistribution'
)));
httpServer
.
get
(
'/szgc/getdata/monthlyOpeningTrend'
,
asyncHandler
((
req
,
res
)
=>
szgcBiz
.
getData
(
req
,
res
,
'monthlyOpeningTrend'
)));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment