修改页面样式功能,首页样式功能导航栏样式功能等
@@ -532,7 +532,7 @@
|
|||||||
escapeHtml(item.name) +
|
escapeHtml(item.name) +
|
||||||
'" /></div><div class="lottery-nav__text"><strong>' +
|
'" /></div><div class="lottery-nav__text"><strong>' +
|
||||||
escapeHtml(item.name) +
|
escapeHtml(item.name) +
|
||||||
"</strong><span>进入预测文章</span></div><em>查看</em></a>",
|
"</strong><span>进入分析文章</span></div><em>查看</em></a>",
|
||||||
);
|
);
|
||||||
$trend.append(
|
$trend.append(
|
||||||
'<a href="' +
|
'<a href="' +
|
||||||
|
|||||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const commonUtil = fs.readFileSync("utils/CommonUtil.js", "utf8");
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
if (!condition) {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(
|
||||||
|
/installCaiSingleLotteryMode\(\)\s*\{[\s\S]*#lotteryFilter[\s\S]*closest\('\.cxz-filter-row'\)\.hide\(\);/.test(
|
||||||
|
commonUtil,
|
||||||
|
),
|
||||||
|
"CommonUtil should hide the inner lottery filter row on cai.html",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
/installCaiSingleLotteryMode\(\)\s*\{[\s\S]*ApiClient\.loadMenuCompat\(\)[\s\S]*topbar__nav-link/.test(
|
||||||
|
commonUtil,
|
||||||
|
),
|
||||||
|
"CommonUtil should render lottery switching into the top navigation",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
/activeClass\s*=\s*String\(code\)\s*===\s*currentCode[\s\S]*topbar__nav-link'\s*\+\s*activeClass/.test(
|
||||||
|
commonUtil,
|
||||||
|
),
|
||||||
|
"CommonUtil top navigation should mark current lottery active",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
/this\.installCaiSingleLotteryMode\(\);/.test(commonUtil),
|
||||||
|
"CommonUtil.loadPageConfig should install cai single-lottery mode",
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("cai single-lottery checks passed");
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
Add-Type -AssemblyName System.Drawing
|
||||||
|
|
||||||
|
$outDir = Join-Path (Get-Location) "images\trend-icons"
|
||||||
|
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
||||||
|
|
||||||
|
function New-IconBitmap {
|
||||||
|
$bitmap = New-Object System.Drawing.Bitmap 128, 128, ([System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
|
||||||
|
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
||||||
|
$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
||||||
|
$graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit
|
||||||
|
$graphics.Clear([System.Drawing.Color]::Transparent)
|
||||||
|
return @($bitmap, $graphics)
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-Pen($color, $width = 4) {
|
||||||
|
$pen = New-Object System.Drawing.Pen $color, $width
|
||||||
|
$pen.StartCap = [System.Drawing.Drawing2D.LineCap]::Round
|
||||||
|
$pen.EndCap = [System.Drawing.Drawing2D.LineCap]::Round
|
||||||
|
$pen.LineJoin = [System.Drawing.Drawing2D.LineJoin]::Round
|
||||||
|
return $pen
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-Brush($color) {
|
||||||
|
return New-Object System.Drawing.SolidBrush $color
|
||||||
|
}
|
||||||
|
|
||||||
|
function Draw-Ball($g, $x, $y, $size, $color1, $color2, $text = "") {
|
||||||
|
$rect = New-Object System.Drawing.RectangleF $x, $y, $size, $size
|
||||||
|
$path = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||||
|
$path.AddEllipse($rect)
|
||||||
|
$brush = New-Object System.Drawing.Drawing2D.LinearGradientBrush $rect, $color1, $color2, 135
|
||||||
|
$g.FillPath($brush, $path)
|
||||||
|
$g.DrawPath((New-Pen ([System.Drawing.Color]::FromArgb(160, 255, 255, 255)) 2), $path)
|
||||||
|
if ($text) {
|
||||||
|
$font = New-Object System.Drawing.Font "Arial", 13, ([System.Drawing.FontStyle]::Bold)
|
||||||
|
$format = New-Object System.Drawing.StringFormat
|
||||||
|
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$g.DrawString($text, $font, (New-Brush ([System.Drawing.Color]::White)), $rect, $format)
|
||||||
|
$font.Dispose()
|
||||||
|
$format.Dispose()
|
||||||
|
}
|
||||||
|
$brush.Dispose()
|
||||||
|
$path.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Draw-Grid($g) {
|
||||||
|
$gridPen = New-Pen ([System.Drawing.Color]::FromArgb(42, 16, 43, 106)) 2
|
||||||
|
foreach ($x in @(32, 56, 80, 104)) {
|
||||||
|
$g.DrawLine($gridPen, $x, 24, $x, 104)
|
||||||
|
}
|
||||||
|
foreach ($y in @(32, 56, 80, 104)) {
|
||||||
|
$g.DrawLine($gridPen, 24, $y, 112, $y)
|
||||||
|
}
|
||||||
|
$gridPen.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Draw-Axes($g) {
|
||||||
|
$axisPen = New-Pen ([System.Drawing.Color]::FromArgb(150, 16, 43, 106)) 3
|
||||||
|
$g.DrawLine($axisPen, 24, 102, 108, 102)
|
||||||
|
$g.DrawLine($axisPen, 24, 102, 24, 24)
|
||||||
|
$axisPen.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Save-Icon($name, [scriptblock]$draw) {
|
||||||
|
$parts = New-IconBitmap
|
||||||
|
$bitmap = $parts[0]
|
||||||
|
$graphics = $parts[1]
|
||||||
|
& $draw $graphics
|
||||||
|
$path = Join-Path $outDir $name
|
||||||
|
$bitmap.Save($path, [System.Drawing.Imaging.ImageFormat]::Png)
|
||||||
|
$graphics.Dispose()
|
||||||
|
$bitmap.Dispose()
|
||||||
|
Write-Host $path
|
||||||
|
}
|
||||||
|
|
||||||
|
$redA = [System.Drawing.Color]::FromArgb(246, 91, 80)
|
||||||
|
$redB = [System.Drawing.Color]::FromArgb(218, 28, 49)
|
||||||
|
$blueA = [System.Drawing.Color]::FromArgb(74, 158, 255)
|
||||||
|
$blueB = [System.Drawing.Color]::FromArgb(18, 79, 190)
|
||||||
|
$gold = [System.Drawing.Color]::FromArgb(253, 185, 51)
|
||||||
|
$navy = [System.Drawing.Color]::FromArgb(16, 43, 106)
|
||||||
|
$green = [System.Drawing.Color]::FromArgb(36, 196, 132)
|
||||||
|
$purple = [System.Drawing.Color]::FromArgb(138, 92, 246)
|
||||||
|
|
||||||
|
Save-Icon "ssq-trend.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
Draw-Axes $g
|
||||||
|
$linePen = New-Pen $redA 5
|
||||||
|
$g.DrawLines($linePen, @(
|
||||||
|
[System.Drawing.PointF]::new(28, 82),
|
||||||
|
[System.Drawing.PointF]::new(46, 58),
|
||||||
|
[System.Drawing.PointF]::new(66, 72),
|
||||||
|
[System.Drawing.PointF]::new(88, 42),
|
||||||
|
[System.Drawing.PointF]::new(108, 56)
|
||||||
|
))
|
||||||
|
$linePen.Dispose()
|
||||||
|
Draw-Ball $g 22 72 25 $redA $redB "06"
|
||||||
|
Draw-Ball $g 56 62 25 $redA $redB "12"
|
||||||
|
Draw-Ball $g 88 46 25 $blueA $blueB "16"
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "basic-trend.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
Draw-Axes $g
|
||||||
|
$pen1 = New-Pen $navy 5
|
||||||
|
$pen2 = New-Pen $gold 4
|
||||||
|
$g.DrawLines($pen1, @(
|
||||||
|
[System.Drawing.PointF]::new(28, 86),
|
||||||
|
[System.Drawing.PointF]::new(46, 76),
|
||||||
|
[System.Drawing.PointF]::new(64, 62),
|
||||||
|
[System.Drawing.PointF]::new(82, 46),
|
||||||
|
[System.Drawing.PointF]::new(106, 36)
|
||||||
|
))
|
||||||
|
$g.DrawLines($pen2, @(
|
||||||
|
[System.Drawing.PointF]::new(30, 96),
|
||||||
|
[System.Drawing.PointF]::new(54, 90),
|
||||||
|
[System.Drawing.PointF]::new(78, 70),
|
||||||
|
[System.Drawing.PointF]::new(104, 68)
|
||||||
|
))
|
||||||
|
$pen1.Dispose()
|
||||||
|
$pen2.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "number-distribution.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
foreach ($row in 0..3) {
|
||||||
|
foreach ($col in 0..4) {
|
||||||
|
$x = 24 + $col * 20
|
||||||
|
$y = 28 + $row * 18
|
||||||
|
$color = if (($row + $col) % 3 -eq 0) { $redA } elseif (($row + $col) % 3 -eq 1) { $blueA } else { $gold }
|
||||||
|
Draw-Ball $g $x $y 13 $color ([System.Drawing.Color]::FromArgb($color.A, [Math]::Max(0, $color.R - 32), [Math]::Max(0, $color.G - 32), [Math]::Max(0, $color.B - 32))) ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$barBrush = New-Brush ([System.Drawing.Color]::FromArgb(170, 16, 43, 106))
|
||||||
|
$g.FillRectangle($barBrush, 28, 102, 18, 10)
|
||||||
|
$g.FillRectangle($barBrush, 54, 92, 18, 20)
|
||||||
|
$g.FillRectangle($barBrush, 80, 84, 18, 28)
|
||||||
|
$barBrush.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "red-blue-trend.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
$redPen = New-Pen $redA 5
|
||||||
|
$bluePen = New-Pen $blueA 5
|
||||||
|
$g.DrawLines($redPen, @(
|
||||||
|
[System.Drawing.PointF]::new(22, 82),
|
||||||
|
[System.Drawing.PointF]::new(44, 48),
|
||||||
|
[System.Drawing.PointF]::new(68, 64),
|
||||||
|
[System.Drawing.PointF]::new(92, 34),
|
||||||
|
[System.Drawing.PointF]::new(112, 52)
|
||||||
|
))
|
||||||
|
$g.DrawLines($bluePen, @(
|
||||||
|
[System.Drawing.PointF]::new(22, 56),
|
||||||
|
[System.Drawing.PointF]::new(44, 76),
|
||||||
|
[System.Drawing.PointF]::new(68, 46),
|
||||||
|
[System.Drawing.PointF]::new(92, 72),
|
||||||
|
[System.Drawing.PointF]::new(112, 36)
|
||||||
|
))
|
||||||
|
Draw-Ball $g 24 78 19 $redA $redB ""
|
||||||
|
Draw-Ball $g 86 68 19 $blueA $blueB ""
|
||||||
|
$redPen.Dispose()
|
||||||
|
$bluePen.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "combined-trend.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
$area = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||||
|
$area.AddPolygon(@(
|
||||||
|
[System.Drawing.PointF]::new(26, 96),
|
||||||
|
[System.Drawing.PointF]::new(26, 74),
|
||||||
|
[System.Drawing.PointF]::new(48, 52),
|
||||||
|
[System.Drawing.PointF]::new(72, 66),
|
||||||
|
[System.Drawing.PointF]::new(102, 38),
|
||||||
|
[System.Drawing.PointF]::new(102, 96)
|
||||||
|
))
|
||||||
|
$g.FillPath((New-Brush ([System.Drawing.Color]::FromArgb(52, 74, 158, 255))), $area)
|
||||||
|
$pen = New-Pen $purple 5
|
||||||
|
$g.DrawLines($pen, @(
|
||||||
|
[System.Drawing.PointF]::new(26, 74),
|
||||||
|
[System.Drawing.PointF]::new(48, 52),
|
||||||
|
[System.Drawing.PointF]::new(72, 66),
|
||||||
|
[System.Drawing.PointF]::new(102, 38)
|
||||||
|
))
|
||||||
|
Draw-Ball $g 72 70 20 $redA $redB ""
|
||||||
|
Draw-Ball $g 92 34 20 $blueA $blueB ""
|
||||||
|
$pieBrush = New-Brush ([System.Drawing.Color]::FromArgb(230, 253, 185, 51))
|
||||||
|
$g.FillPie($pieBrush, 28, 28, 24, 24, 270, 230)
|
||||||
|
$g.DrawEllipse((New-Pen $navy 3), 28, 28, 24, 24)
|
||||||
|
$area.Dispose()
|
||||||
|
$pen.Dispose()
|
||||||
|
$pieBrush.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "blue-trend.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Grid $g
|
||||||
|
Draw-Axes $g
|
||||||
|
$pen = New-Pen $blueA 5
|
||||||
|
$g.DrawLines($pen, @(
|
||||||
|
[System.Drawing.PointF]::new(28, 84),
|
||||||
|
[System.Drawing.PointF]::new(46, 66),
|
||||||
|
[System.Drawing.PointF]::new(64, 76),
|
||||||
|
[System.Drawing.PointF]::new(86, 44),
|
||||||
|
[System.Drawing.PointF]::new(108, 58)
|
||||||
|
))
|
||||||
|
Draw-Ball $g 32 76 21 $blueA $blueB "03"
|
||||||
|
Draw-Ball $g 80 38 21 $blueA $blueB "12"
|
||||||
|
$pen.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "blue-amplitude.png" {
|
||||||
|
param($g)
|
||||||
|
$axisPen = New-Pen ([System.Drawing.Color]::FromArgb(150, 16, 43, 106)) 3
|
||||||
|
$g.DrawLine($axisPen, 24, 64, 108, 64)
|
||||||
|
$g.DrawLine($axisPen, 32, 24, 32, 104)
|
||||||
|
$wavePen = New-Pen $blueA 6
|
||||||
|
$g.DrawBezier($wavePen, 24, 76, 44, 18, 66, 110, 88, 52)
|
||||||
|
$g.DrawBezier($wavePen, 88, 52, 96, 34, 106, 28, 114, 38)
|
||||||
|
$arrowPen = New-Pen $gold 4
|
||||||
|
$g.DrawLine($arrowPen, 98, 92, 98, 34)
|
||||||
|
$g.DrawLine($arrowPen, 98, 34, 90, 44)
|
||||||
|
$g.DrawLine($arrowPen, 98, 34, 106, 44)
|
||||||
|
$g.DrawLine($arrowPen, 98, 92, 90, 82)
|
||||||
|
$g.DrawLine($arrowPen, 98, 92, 106, 82)
|
||||||
|
Draw-Ball $g 50 70 22 $blueA $blueB ""
|
||||||
|
$axisPen.Dispose()
|
||||||
|
$wavePen.Dispose()
|
||||||
|
$arrowPen.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "blue-tail.png" {
|
||||||
|
param($g)
|
||||||
|
$ringPen = New-Pen $blueA 5
|
||||||
|
$g.DrawEllipse($ringPen, 26, 22, 76, 76)
|
||||||
|
$font = New-Object System.Drawing.Font "Arial", 24, ([System.Drawing.FontStyle]::Bold)
|
||||||
|
$small = New-Object System.Drawing.Font "Arial", 13, ([System.Drawing.FontStyle]::Bold)
|
||||||
|
$format = New-Object System.Drawing.StringFormat
|
||||||
|
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$g.DrawString("0-9", $font, (New-Brush $navy), ([System.Drawing.RectangleF]::new(20, 30, 88, 40)), $format)
|
||||||
|
$g.DrawString("TAIL", $small, (New-Brush $blueB), ([System.Drawing.RectangleF]::new(20, 68, 88, 24)), $format)
|
||||||
|
Draw-Ball $g 78 82 24 $blueA $blueB "7"
|
||||||
|
$ringPen.Dispose()
|
||||||
|
$font.Dispose()
|
||||||
|
$small.Dispose()
|
||||||
|
$format.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "blue-two-sum.png" {
|
||||||
|
param($g)
|
||||||
|
Draw-Ball $g 18 42 34 $blueA $blueB "08"
|
||||||
|
Draw-Ball $g 76 42 34 $blueA $blueB "11"
|
||||||
|
$font = New-Object System.Drawing.Font "Arial", 22, ([System.Drawing.FontStyle]::Bold)
|
||||||
|
$format = New-Object System.Drawing.StringFormat
|
||||||
|
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$g.DrawString("+", $font, (New-Brush $gold), ([System.Drawing.RectangleF]::new(51, 42, 28, 34)), $format)
|
||||||
|
$sumBrush = New-Brush ([System.Drawing.Color]::FromArgb(230, 16, 43, 106))
|
||||||
|
$g.FillRectangle($sumBrush, 34, 88, 60, 18)
|
||||||
|
$g.DrawString("=19", (New-Object System.Drawing.Font "Arial", 13, ([System.Drawing.FontStyle]::Bold)), (New-Brush ([System.Drawing.Color]::White)), ([System.Drawing.RectangleF]::new(34, 87, 60, 20)), $format)
|
||||||
|
$font.Dispose()
|
||||||
|
$format.Dispose()
|
||||||
|
$sumBrush.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
Save-Icon "dev-coming.png" {
|
||||||
|
param($g)
|
||||||
|
$plate = New-Object System.Drawing.RectangleF 18, 28, 92, 64
|
||||||
|
$plateBrush = New-Object System.Drawing.Drawing2D.LinearGradientBrush $plate, ([System.Drawing.Color]::FromArgb(245, 255, 255, 255)), ([System.Drawing.Color]::FromArgb(235, 232, 239, 250)), 90
|
||||||
|
$path = New-Object System.Drawing.Drawing2D.GraphicsPath
|
||||||
|
$path.AddArc(18, 28, 16, 16, 180, 90)
|
||||||
|
$path.AddArc(94, 28, 16, 16, 270, 90)
|
||||||
|
$path.AddArc(94, 76, 16, 16, 0, 90)
|
||||||
|
$path.AddArc(18, 76, 16, 16, 90, 90)
|
||||||
|
$path.CloseFigure()
|
||||||
|
$g.FillPath($plateBrush, $path)
|
||||||
|
$g.DrawPath((New-Pen ([System.Drawing.Color]::FromArgb(105, 16, 43, 106)) 2), $path)
|
||||||
|
|
||||||
|
$pen = New-Pen $blueA 5
|
||||||
|
$g.DrawLines($pen, @(
|
||||||
|
[System.Drawing.PointF]::new(32, 72),
|
||||||
|
[System.Drawing.PointF]::new(46, 56),
|
||||||
|
[System.Drawing.PointF]::new(62, 64),
|
||||||
|
[System.Drawing.PointF]::new(80, 42),
|
||||||
|
[System.Drawing.PointF]::new(98, 54)
|
||||||
|
))
|
||||||
|
Draw-Ball $g 28 78 22 $redA $redB ""
|
||||||
|
Draw-Ball $g 74 34 24 $blueA $blueB ""
|
||||||
|
Draw-Ball $g 50 58 20 $gold ([System.Drawing.Color]::FromArgb(232, 140, 20)) ""
|
||||||
|
|
||||||
|
$font = New-Object System.Drawing.Font "Arial", 15, ([System.Drawing.FontStyle]::Bold)
|
||||||
|
$format = New-Object System.Drawing.StringFormat
|
||||||
|
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
||||||
|
$g.DrawString("DEV", $font, (New-Brush $navy), ([System.Drawing.RectangleF]::new(30, 94, 68, 24)), $format)
|
||||||
|
|
||||||
|
$plateBrush.Dispose()
|
||||||
|
$path.Dispose()
|
||||||
|
$pen.Dispose()
|
||||||
|
$font.Dispose()
|
||||||
|
$format.Dispose()
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const commonUtil = fs.readFileSync("utils/CommonUtil.js", "utf8");
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
if (!condition) throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
"cai.html",
|
||||||
|
"caiinfo.html",
|
||||||
|
].forEach((page) => {
|
||||||
|
assert(commonUtil.includes(`'${page}'`), `cai navigation page missing: ${page}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
"usercenter.html",
|
||||||
|
"mianfeishoucang.html",
|
||||||
|
"tuiguang.html",
|
||||||
|
"jine.html",
|
||||||
|
"chongzhi.html",
|
||||||
|
"tixian.html",
|
||||||
|
"tixianlist.html",
|
||||||
|
"fabumianfeiwenzhang.html",
|
||||||
|
"fufei.html",
|
||||||
|
"appdown.html",
|
||||||
|
"apply.html",
|
||||||
|
"open-browser.html",
|
||||||
|
"reg.html",
|
||||||
|
"repwd.html",
|
||||||
|
"social-callback.html",
|
||||||
|
"upgrade.html",
|
||||||
|
"wodefenxiao.html",
|
||||||
|
"yinsixieyi.html",
|
||||||
|
"yonghuxieyi.html",
|
||||||
|
].forEach((page) => {
|
||||||
|
assert(commonUtil.includes(`'${page}'`), `empty navigation page missing: ${page}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
"双色球走势图",
|
||||||
|
"基本走势",
|
||||||
|
"出号分布",
|
||||||
|
"红蓝走势",
|
||||||
|
"综合走势",
|
||||||
|
"蓝球走势",
|
||||||
|
"蓝球振幅",
|
||||||
|
"蓝球尾数",
|
||||||
|
"蓝球两数和",
|
||||||
|
].forEach((label) => {
|
||||||
|
assert(commonUtil.includes(`label: '${label}'`), `feature nav item missing: ${label}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(commonUtil.includes("开发中敬请期待"), "coming-soon popup text missing");
|
||||||
|
assert(commonUtil.includes("trend-icons/dev-coming.png"), "coming-soon popup image missing");
|
||||||
|
assert(commonUtil.includes("this.installTopbarNavigationMode();"), "loadPageConfig should install topbar navigation mode");
|
||||||
|
assert(commonUtil.includes("DOMContentLoaded', installTopbarNavigationMode"), "DOMContentLoaded should install topbar navigation mode");
|
||||||
|
|
||||||
|
console.log("topbar navigation mode checks passed");
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const source = fs.readFileSync(path.join(__dirname, '..', 'utils', 'CommonUtil.js'), 'utf8');
|
||||||
|
|
||||||
|
function assertContains(pattern, message) {
|
||||||
|
if (!pattern.test(source)) {
|
||||||
|
console.error(message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertContains(/topbar__btn--signin/, 'Expected public topbar to inject a sign-in button.');
|
||||||
|
assertContains(/CommonUtil\.signIn\(/, 'Expected sign-in button to call CommonUtil.signIn().');
|
||||||
|
assertContains(/text:\s*['"]\u7b7e\u5230['"]/, 'Expected sign-in button text to be sign in.');
|
||||||
|
assertContains(/ensureTopbarSignInStyle/, 'Expected public topbar to install a dedicated sign-in button style.');
|
||||||
|
assertContains(/\.topbar__btn--signin\s*\{/, 'Expected dedicated sign-in button CSS to be injected.');
|
||||||
|
assertContains(/setTopbarSignInSigned/, 'Expected a shared helper to lock the topbar sign-in button.');
|
||||||
|
assertContains(/\u5df2\u7b7e\u5230/, 'Expected signed state text to be already signed.');
|
||||||
|
assertContains(/mineSignInStatus|\/api\/web\/mine\/sign-in\/status/, 'Expected topbar to load the current sign-in status.');
|
||||||
|
assertContains(/\u5df2\u7b7e\u5230\|\u5df2\u7b7e\|\u5df2\u7ecf\u7b7e\u5230\|\u7b7e\u5230\u8fc7/, 'Expected already-signed API messages to lock the button.');
|
||||||
|
|
||||||
|
if (/class:\s*['"][^'"]*topbar__btn--signin[^'"]*topbar__btn--primary/.test(source)) {
|
||||||
|
console.error('Expected sign-in button to use a quieter dedicated style, not the primary button style.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('topbar sign-in checks passed');
|
||||||
|
After Width: | Height: | Size: 36 KiB |
@@ -229,8 +229,125 @@ const CommonUtil = {
|
|||||||
$('.topbar__ubadge, .uc-role').text(text);
|
$('.topbar__ubadge, .uc-role').text(text);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ensureTopbarSignInStyle() {
|
||||||
|
if (typeof document === 'undefined' || document.getElementById('topbar-signin-style')) return;
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'topbar-signin-style';
|
||||||
|
style.textContent = `
|
||||||
|
.topbar__btn--signin {
|
||||||
|
min-width: 58px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 14px;
|
||||||
|
color: #ffd66e;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 34px;
|
||||||
|
background: rgba(255, 255, 255, .08);
|
||||||
|
border: 1px solid rgba(253, 185, 51, .42);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12);
|
||||||
|
}
|
||||||
|
.topbar__btn--signin:hover {
|
||||||
|
color: #fff3c4;
|
||||||
|
background: rgba(253, 185, 51, .16);
|
||||||
|
border-color: rgba(253, 185, 51, .62);
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
.topbar__btn--signin:disabled {
|
||||||
|
cursor: default;
|
||||||
|
opacity: .72;
|
||||||
|
}
|
||||||
|
.topbar__btn--signin.is-signed {
|
||||||
|
color: rgba(255, 255, 255, .72);
|
||||||
|
background: rgba(255, 255, 255, .06);
|
||||||
|
border-color: rgba(255, 255, 255, .16);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
},
|
||||||
|
|
||||||
|
setTopbarSignInSigned(signed) {
|
||||||
|
if (typeof document === 'undefined') return;
|
||||||
|
const $ = this.$;
|
||||||
|
$('.topbar__btn--signin').each((index, button) => {
|
||||||
|
const $button = $(button);
|
||||||
|
$button
|
||||||
|
.prop('disabled', !!signed)
|
||||||
|
.toggleClass('is-signed', !!signed)
|
||||||
|
.text(signed ? '已签到' : '签到');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
hasTopbarSignInStatusValue(data) {
|
||||||
|
if (typeof data === 'boolean') return true;
|
||||||
|
if (!data || typeof data !== 'object') return false;
|
||||||
|
const source = data.data && typeof data.data === 'object' ? data.data : data;
|
||||||
|
return [
|
||||||
|
'signedToday',
|
||||||
|
'todaySigned',
|
||||||
|
'isSignedToday',
|
||||||
|
'signed',
|
||||||
|
'isSigned',
|
||||||
|
'hasSigned',
|
||||||
|
'signIn',
|
||||||
|
'signInStatus',
|
||||||
|
].some((key) => source[key] !== undefined);
|
||||||
|
},
|
||||||
|
|
||||||
|
readTopbarSignInSigned(data) {
|
||||||
|
if (typeof data === 'boolean') return data;
|
||||||
|
if (!data || typeof data !== 'object') return false;
|
||||||
|
const source = data.data && typeof data.data === 'object' ? data.data : data;
|
||||||
|
const keys = [
|
||||||
|
'signedToday',
|
||||||
|
'todaySigned',
|
||||||
|
'isSignedToday',
|
||||||
|
'signed',
|
||||||
|
'isSigned',
|
||||||
|
'hasSigned',
|
||||||
|
'signIn',
|
||||||
|
'signInStatus',
|
||||||
|
];
|
||||||
|
const value = keys.map((key) => source[key]).find((item) => item !== undefined && item !== null && item !== '');
|
||||||
|
return value === true || value === 1 || value === '1' || String(value).toLowerCase() === 'true';
|
||||||
|
},
|
||||||
|
|
||||||
|
isAlreadySignedResponse(res) {
|
||||||
|
if (this.hasTopbarSignInStatusValue(res) && this.readTopbarSignInSigned(res)) return true;
|
||||||
|
const data = res && typeof res.data === 'object' ? res.data : {};
|
||||||
|
const text = [
|
||||||
|
res && res.msg,
|
||||||
|
res && res.message,
|
||||||
|
data.msg,
|
||||||
|
data.message,
|
||||||
|
].filter(Boolean).join(' ');
|
||||||
|
return /已签到|已签|已经签到|签到过/.test(text);
|
||||||
|
},
|
||||||
|
|
||||||
|
isSignInSuccessResponse(res) {
|
||||||
|
if (typeof ApiClient !== 'undefined' && ApiClient.isSuccess) return ApiClient.isSuccess(res);
|
||||||
|
return !!res && res.code === 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
loadTopbarSignInStatus() {
|
||||||
|
if (typeof ApiClient === 'undefined' || !this.getToken()) return;
|
||||||
|
const url = ApiClient.API && ApiClient.API.mineSignInStatus
|
||||||
|
? ApiClient.API.mineSignInStatus
|
||||||
|
: '/api/web/mine/sign-in/status';
|
||||||
|
ApiClient.get(url, null, { headers: this.authHeaders() })
|
||||||
|
.then((res) => {
|
||||||
|
if (this.isAlreadySignedResponse(res)) {
|
||||||
|
this.setTopbarSignInSigned(true);
|
||||||
|
} else if (this.hasTopbarSignInStatusValue(res)) {
|
||||||
|
this.setTopbarSignInSigned(this.readTopbarSignInSigned(res));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
},
|
||||||
|
|
||||||
installTopbarUserCenterEntry() {
|
installTopbarUserCenterEntry() {
|
||||||
if (typeof document === 'undefined') return;
|
if (typeof document === 'undefined') return;
|
||||||
|
this.ensureTopbarSignInStyle();
|
||||||
const $ = this.$;
|
const $ = this.$;
|
||||||
$('#loggedInBox').each((index, box) => {
|
$('#loggedInBox').each((index, box) => {
|
||||||
const $box = $(box);
|
const $box = $(box);
|
||||||
@@ -244,14 +361,348 @@ const CommonUtil = {
|
|||||||
if ($logout.length && !$logout.parent().is($actions)) {
|
if ($logout.length && !$logout.parent().is($actions)) {
|
||||||
$logout.appendTo($actions);
|
$logout.appendTo($actions);
|
||||||
}
|
}
|
||||||
if ($actions.find('.topbar__btn--center').length) return;
|
if (!$box.find('.topbar__btn--signin').length) {
|
||||||
const $entry = $('<a>', {
|
const $signIn = $('<button>', {
|
||||||
href: 'usercenter.html',
|
type: 'button',
|
||||||
class: 'topbar__btn topbar__btn--center',
|
class: 'topbar__btn topbar__btn--signin',
|
||||||
text: '个人中心',
|
text: '签到',
|
||||||
});
|
});
|
||||||
$actions.prepend($entry);
|
$signIn.on('click', function () {
|
||||||
|
const $button = $(this);
|
||||||
|
if ($button.prop('disabled')) return;
|
||||||
|
$button.prop('disabled', true).text('签到中');
|
||||||
|
CommonUtil.signIn((res) => {
|
||||||
|
if (CommonUtil.isSignInSuccessResponse(res) || CommonUtil.isAlreadySignedResponse(res)) {
|
||||||
|
CommonUtil.setTopbarSignInSigned(true);
|
||||||
|
} else {
|
||||||
|
CommonUtil.setTopbarSignInSigned(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const $profile = $box.find('.topbar__profile').first();
|
||||||
|
if ($profile.length) $signIn.insertBefore($profile);
|
||||||
|
else $box.prepend($signIn);
|
||||||
|
}
|
||||||
|
if (!$actions.find('.topbar__btn--center').length) {
|
||||||
|
const $entry = $('<a>', {
|
||||||
|
href: 'usercenter.html',
|
||||||
|
class: 'topbar__btn topbar__btn--center',
|
||||||
|
text: '个人中心',
|
||||||
|
});
|
||||||
|
$actions.prepend($entry);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
this.loadTopbarSignInStatus();
|
||||||
|
},
|
||||||
|
|
||||||
|
getAssetRoot() {
|
||||||
|
if (typeof window === 'undefined' || !window.location) return '../images/';
|
||||||
|
return /\/html\/[^/]*$/i.test(window.location.pathname) ? '../images/' : 'images/';
|
||||||
|
},
|
||||||
|
|
||||||
|
getCurrentPageName() {
|
||||||
|
if (typeof window === 'undefined' || !window.location) return '';
|
||||||
|
return (window.location.pathname.split('/').pop() || 'index.html').toLowerCase() || 'index.html';
|
||||||
|
},
|
||||||
|
|
||||||
|
isTopbarCaiNavPage() {
|
||||||
|
return ['cai.html', 'caiinfo.html'].includes(this.getCurrentPageName());
|
||||||
|
},
|
||||||
|
|
||||||
|
isTopbarEmptyNavPage() {
|
||||||
|
return [
|
||||||
|
'usercenter.html',
|
||||||
|
'mianfeishoucang.html',
|
||||||
|
'tuiguang.html',
|
||||||
|
'jine.html',
|
||||||
|
'chongzhi.html',
|
||||||
|
'tixian.html',
|
||||||
|
'tixianlist.html',
|
||||||
|
'fabumianfeiwenzhang.html',
|
||||||
|
'fufei.html',
|
||||||
|
'appdown.html',
|
||||||
|
'apply.html',
|
||||||
|
'open-browser.html',
|
||||||
|
'reg.html',
|
||||||
|
'repwd.html',
|
||||||
|
'social-callback.html',
|
||||||
|
'upgrade.html',
|
||||||
|
'wodefenxiao.html',
|
||||||
|
'yinsixieyi.html',
|
||||||
|
'yonghuxieyi.html',
|
||||||
|
].includes(this.getCurrentPageName());
|
||||||
|
},
|
||||||
|
|
||||||
|
getTopbarFeatureNavItems() {
|
||||||
|
const root = this.getAssetRoot();
|
||||||
|
return [
|
||||||
|
{ label: '双色球走势图', icon: root + 'trend-icons/ssq-trend.png' },
|
||||||
|
{ label: '基本走势', icon: root + 'trend-icons/basic-trend.png' },
|
||||||
|
{ label: '出号分布', icon: root + 'trend-icons/number-distribution.png' },
|
||||||
|
{ label: '红蓝走势', icon: root + 'trend-icons/red-blue-trend.png' },
|
||||||
|
{ label: '综合走势', icon: root + 'trend-icons/combined-trend.png' },
|
||||||
|
{ label: '蓝球走势', icon: root + 'trend-icons/blue-trend.png' },
|
||||||
|
{ label: '蓝球振幅', icon: root + 'trend-icons/blue-amplitude.png' },
|
||||||
|
{ label: '蓝球尾数', icon: root + 'trend-icons/blue-tail.png' },
|
||||||
|
{ label: '蓝球两数和', icon: root + 'trend-icons/blue-two-sum.png' },
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
ensureTopbarNavigationModeStyle() {
|
||||||
|
if (typeof document === 'undefined' || document.getElementById('topbar-nav-mode-style')) return;
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'topbar-nav-mode-style';
|
||||||
|
style.textContent = `
|
||||||
|
.topbar__nav.is-empty {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.topbar__nav--feature {
|
||||||
|
gap: 6px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.topbar__nav-link--feature {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
min-width: 82px;
|
||||||
|
padding: 5px 9px;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
.topbar__nav-feature-icon {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
flex: 0 0 34px;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.topbar__nav-feature-text {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.topbar-dev-modal {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 24px 24px 22px;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 22% 16%, rgba(253, 185, 51, .22), transparent 28%),
|
||||||
|
linear-gradient(180deg, #f7fbff 0%, #ffffff 76%);
|
||||||
|
border: 1px solid rgba(16, 43, 106, .08);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
.topbar-dev-modal::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 5px;
|
||||||
|
background: linear-gradient(90deg, #102b6a, #2478d7 58%, #fdb933);
|
||||||
|
}
|
||||||
|
.topbar-dev-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 10px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
color: #102b6a;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: rgba(16, 43, 106, .08);
|
||||||
|
}
|
||||||
|
.topbar-dev-modal img {
|
||||||
|
display: block;
|
||||||
|
width: 118px;
|
||||||
|
height: 118px;
|
||||||
|
object-fit: contain;
|
||||||
|
margin: 0 auto 14px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 24px;
|
||||||
|
background: rgba(255, 255, 255, .82);
|
||||||
|
box-shadow: 0 12px 28px rgba(16, 43, 106, .12);
|
||||||
|
}
|
||||||
|
.topbar-dev-modal strong {
|
||||||
|
display: block;
|
||||||
|
color: #102b6a;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.topbar-dev-modal span {
|
||||||
|
display: block;
|
||||||
|
margin-top: 7px;
|
||||||
|
color: #7b8495;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.layui-layer.topbar-dev-layer {
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: 0 20px 54px rgba(11, 31, 73, .24);
|
||||||
|
}
|
||||||
|
.layui-layer.topbar-dev-layer .layui-layer-content {
|
||||||
|
overflow: visible;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.topbar-dev-confirm {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 34px;
|
||||||
|
min-width: 108px;
|
||||||
|
margin-top: 18px;
|
||||||
|
padding: 0 18px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: linear-gradient(135deg, #102b6a, #2478d7);
|
||||||
|
box-shadow: 0 8px 18px rgba(16, 43, 106, .2);
|
||||||
|
}
|
||||||
|
.topbar-dev-confirm:hover {
|
||||||
|
filter: brightness(1.05);
|
||||||
|
}
|
||||||
|
.topbar-dev-confirm:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.topbar__nav-link--feature {
|
||||||
|
min-width: 68px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
}
|
||||||
|
.topbar__nav-feature-icon {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
flex-basis: 28px;
|
||||||
|
}
|
||||||
|
.topbar__nav-feature-text {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
},
|
||||||
|
|
||||||
|
showTopbarFeatureComingSoon(item) {
|
||||||
|
const root = this.getAssetRoot();
|
||||||
|
const image = root + 'trend-icons/dev-coming.png';
|
||||||
|
const content =
|
||||||
|
'<div class="topbar-dev-modal">' +
|
||||||
|
'<div class="topbar-dev-badge">功能预告</div>' +
|
||||||
|
'<img src="' + this.escapeHtml(image) + '" alt="开发中" />' +
|
||||||
|
'<strong>开发中敬请期待</strong>' +
|
||||||
|
'<span>' + this.escapeHtml(item.label || '') + '</span>' +
|
||||||
|
'<button type="button" class="topbar-dev-confirm">我知道了</button>' +
|
||||||
|
'</div>';
|
||||||
|
if (typeof layui !== 'undefined' && layui.layer) {
|
||||||
|
const index = layui.layer.open({
|
||||||
|
type: 1,
|
||||||
|
title: false,
|
||||||
|
closeBtn: 0,
|
||||||
|
shadeClose: true,
|
||||||
|
area: ['348px', 'auto'],
|
||||||
|
skin: 'topbar-dev-layer',
|
||||||
|
content,
|
||||||
|
end: () => {
|
||||||
|
this.$('#navLotteryItems .topbar__nav-link--feature').removeClass('is-active');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$('.topbar-dev-confirm').off('click.topbarDev').on('click.topbarDev', () => layui.layer.close(index));
|
||||||
|
}, 0);
|
||||||
|
} else {
|
||||||
|
alert('开发中敬请期待');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderTopbarEmptyNav() {
|
||||||
|
const $ = this.$;
|
||||||
|
const $nav = $('#navLotteryItems');
|
||||||
|
if (!$nav.length) return;
|
||||||
|
this.ensureTopbarNavigationModeStyle();
|
||||||
|
if ($nav.attr('data-nav-mode') === 'empty' && !$nav.children().length) return;
|
||||||
|
$nav
|
||||||
|
.attr('data-nav-mode', 'empty')
|
||||||
|
.removeClass('topbar__nav--feature')
|
||||||
|
.addClass('is-empty')
|
||||||
|
.empty();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderTopbarFeatureNav() {
|
||||||
|
const $ = this.$;
|
||||||
|
const $nav = $('#navLotteryItems');
|
||||||
|
if (!$nav.length) return;
|
||||||
|
const items = this.getTopbarFeatureNavItems();
|
||||||
|
if (
|
||||||
|
$nav.attr('data-nav-mode') === 'feature' &&
|
||||||
|
$nav.find('.topbar__nav-link--feature').length === items.length
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ensureTopbarNavigationModeStyle();
|
||||||
|
$nav
|
||||||
|
.attr('data-nav-mode', 'feature')
|
||||||
|
.removeClass('is-empty')
|
||||||
|
.addClass('topbar__nav--feature')
|
||||||
|
.empty();
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
$('<a>', {
|
||||||
|
href: 'javascript:void(0)',
|
||||||
|
class: 'topbar__nav-link topbar__nav-link--feature',
|
||||||
|
'data-nav-label': item.label,
|
||||||
|
title: item.label,
|
||||||
|
})
|
||||||
|
.append($('<img>', {
|
||||||
|
src: item.icon,
|
||||||
|
alt: '',
|
||||||
|
class: 'topbar__nav-feature-icon',
|
||||||
|
'aria-hidden': 'true',
|
||||||
|
}))
|
||||||
|
.append($('<span>', {
|
||||||
|
class: 'topbar__nav-feature-text',
|
||||||
|
text: item.label,
|
||||||
|
}))
|
||||||
|
.on('click', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (event.stopImmediatePropagation) event.stopImmediatePropagation();
|
||||||
|
$('#navLotteryItems .topbar__nav-link--feature').removeClass('is-active');
|
||||||
|
this.showTopbarFeatureComingSoon(item);
|
||||||
|
})
|
||||||
|
.appendTo($nav);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
applyTopbarNavigationMode() {
|
||||||
|
if (typeof document === 'undefined' || this.isTopbarCaiNavPage()) return;
|
||||||
|
if (this.isTopbarEmptyNavPage()) {
|
||||||
|
this.renderTopbarEmptyNav();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.renderTopbarFeatureNav();
|
||||||
|
},
|
||||||
|
|
||||||
|
installTopbarNavigationMode() {
|
||||||
|
if (typeof document === 'undefined' || this.isTopbarCaiNavPage() || window.__TOPBAR_NAV_MODE_INSTALLED__) return;
|
||||||
|
window.__TOPBAR_NAV_MODE_INSTALLED__ = true;
|
||||||
|
const run = () => this.applyTopbarNavigationMode();
|
||||||
|
run();
|
||||||
|
const nav = document.getElementById('navLotteryItems');
|
||||||
|
if (!nav || typeof MutationObserver === 'undefined') return;
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
window.clearTimeout(window.__TOPBAR_NAV_MODE_TIMER__);
|
||||||
|
window.__TOPBAR_NAV_MODE_TIMER__ = window.setTimeout(run, 0);
|
||||||
|
});
|
||||||
|
observer.observe(nav, { childList: true, subtree: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
applyWebConfigs(configs) {
|
applyWebConfigs(configs) {
|
||||||
@@ -580,6 +1031,39 @@ const CommonUtil = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
installCaiSingleLotteryMode() {
|
||||||
|
if (typeof document === 'undefined' || typeof ApiClient === 'undefined') return;
|
||||||
|
const $ = this.$;
|
||||||
|
const $lotteryFilter = $('#lotteryFilter');
|
||||||
|
if (!$lotteryFilter.length) return;
|
||||||
|
|
||||||
|
$lotteryFilter.closest('.cxz-filter-row').hide();
|
||||||
|
|
||||||
|
const $nav = $('#navLotteryItems');
|
||||||
|
if (!$nav.length) return;
|
||||||
|
const currentCode = new URLSearchParams(window.location.search).get('id') || 'ssq';
|
||||||
|
ApiClient.loadMenuCompat()
|
||||||
|
.then((res) => {
|
||||||
|
if (!res || res.code !== 0 || !Array.isArray(res.data)) return;
|
||||||
|
$nav.find('.topbar__nav-link').remove();
|
||||||
|
res.data.forEach((item) => {
|
||||||
|
const code = item.suoxie || item.code || '';
|
||||||
|
if (!code) return;
|
||||||
|
const activeClass = String(code) === currentCode ? ' is-active' : '';
|
||||||
|
$nav.append(
|
||||||
|
'<a href="cai.html?id=' +
|
||||||
|
encodeURIComponent(code) +
|
||||||
|
'" class="topbar__nav-link' +
|
||||||
|
activeClass +
|
||||||
|
'">' +
|
||||||
|
this.escapeHtml(item.name || code) +
|
||||||
|
'</a>'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
},
|
||||||
|
|
||||||
asArray(value) {
|
asArray(value) {
|
||||||
if (typeof ApiClient !== 'undefined' && ApiClient.asArray) return ApiClient.asArray(value);
|
if (typeof ApiClient !== 'undefined' && ApiClient.asArray) return ApiClient.asArray(value);
|
||||||
if (Array.isArray(value)) return value;
|
if (Array.isArray(value)) return value;
|
||||||
@@ -601,6 +1085,8 @@ const CommonUtil = {
|
|||||||
this.ensureGlobalFooterLayout();
|
this.ensureGlobalFooterLayout();
|
||||||
this.installWechatLoginEntry();
|
this.installWechatLoginEntry();
|
||||||
this.installWechatAccountBindEntry();
|
this.installWechatAccountBindEntry();
|
||||||
|
this.installCaiSingleLotteryMode();
|
||||||
|
this.installTopbarNavigationMode();
|
||||||
const loadHomeData = options.home !== false && this.isHomePageDom();
|
const loadHomeData = options.home !== false && this.isHomePageDom();
|
||||||
const request = loadHomeData ? this.loadHomePageData() : this.loadBasePageData(options);
|
const request = loadHomeData ? this.loadHomePageData() : this.loadBasePageData(options);
|
||||||
this.applyCaiExpertListLabels();
|
this.applyCaiExpertListLabels();
|
||||||
@@ -1919,13 +2405,21 @@ const CommonUtil = {
|
|||||||
signIn(onComplete) {
|
signIn(onComplete) {
|
||||||
layui.use('layer', () => {
|
layui.use('layer', () => {
|
||||||
const layer = layui.layer;
|
const layer = layui.layer;
|
||||||
ApiClient.post('/api/web/mine/sign-in', null, { headers: this.authHeaders() }).then((res) => {
|
ApiClient.post('/api/web/mine/sign-in', null, { headers: this.authHeaders() })
|
||||||
layer.msg(res.code === 0 ? '签到成功' : res.msg || '签到失败', {
|
.then((res) => {
|
||||||
icon: res.code === 0 ? 1 : 2,
|
layer.msg(res.code === 0 ? '签到成功' : res.msg || '签到失败', {
|
||||||
time: 1500,
|
icon: res.code === 0 ? 1 : 2,
|
||||||
|
time: 1500,
|
||||||
|
});
|
||||||
|
if (typeof onComplete === 'function') onComplete(res);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
layer.msg(error?.message || '签到失败', {
|
||||||
|
icon: 2,
|
||||||
|
time: 1500,
|
||||||
|
});
|
||||||
|
if (typeof onComplete === 'function') onComplete({ code: -1, msg: '签到失败', error });
|
||||||
});
|
});
|
||||||
if (typeof onComplete === 'function') onComplete(res);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2019,12 +2513,15 @@ if (typeof module !== 'undefined' && module.exports) {
|
|||||||
window.CommonUtil = CommonUtil;
|
window.CommonUtil = CommonUtil;
|
||||||
CommonUtil.installUnifiedPagination();
|
CommonUtil.installUnifiedPagination();
|
||||||
const installTopbarUserCenterEntry = () => CommonUtil.installTopbarUserCenterEntry();
|
const installTopbarUserCenterEntry = () => CommonUtil.installTopbarUserCenterEntry();
|
||||||
|
const installTopbarNavigationMode = () => CommonUtil.installTopbarNavigationMode();
|
||||||
const ensureGlobalFooterLayout = () => CommonUtil.ensureGlobalFooterLayout();
|
const ensureGlobalFooterLayout = () => CommonUtil.ensureGlobalFooterLayout();
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', installTopbarUserCenterEntry);
|
document.addEventListener('DOMContentLoaded', installTopbarUserCenterEntry);
|
||||||
|
document.addEventListener('DOMContentLoaded', installTopbarNavigationMode);
|
||||||
document.addEventListener('DOMContentLoaded', ensureGlobalFooterLayout);
|
document.addEventListener('DOMContentLoaded', ensureGlobalFooterLayout);
|
||||||
} else {
|
} else {
|
||||||
installTopbarUserCenterEntry();
|
installTopbarUserCenterEntry();
|
||||||
|
installTopbarNavigationMode();
|
||||||
ensureGlobalFooterLayout();
|
ensureGlobalFooterLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||