u
This commit is contained in:
1 parent
9e00adf2fe
commit
ae0d245605
34 files changed
+1425
-127
No files matched your search
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoImports">
|
||||
<option name="excludedPackages">
|
||||
<array>
|
||||
<option value="github.com/pkg/errors" />
|
||||
<option value="golang.org/x/net/context" />
|
||||
</array>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
FROM golang:1.25.3 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
go build -o app ./cmd/main.go
|
||||
|
||||
FROM alpine:3.19
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/app .
|
||||
|
||||
CMD ["./app"]
|
||||
@@ -3,17 +3,18 @@ package main
|
||||
import (
|
||||
"allapp-go-v2/internal/bootstrap"
|
||||
"allapp-go-v2/internal/server"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app, err := bootstrap.NewApp()
|
||||
app, err := bootstrap.Start()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := server.Start(app); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = server.Run(app.Config)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
server:
|
||||
port: 8086
|
||||
@@ -0,0 +1,17 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
container_name: allapp
|
||||
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
environment:
|
||||
- APP_ENV=prod
|
||||
|
||||
volumes:
|
||||
- .:/app
|
||||
|
||||
restart: always
|
||||
@@ -12,7 +12,7 @@ type App struct {
|
||||
Db *pgxpool.Pool
|
||||
}
|
||||
|
||||
func NewApp() (*App, error) {
|
||||
func Start() (*App, error) {
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"allapp-go-v2/internal/bootstrap"
|
||||
"fmt"
|
||||
"allapp-go-v2/internal/config"
|
||||
"log"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/requestid"
|
||||
)
|
||||
|
||||
func Start(appCtx *bootstrap.App) error {
|
||||
// 1️⃣ 创建 fiber 实例
|
||||
func Run(cfg *config.Config) error {
|
||||
app := fiber.New()
|
||||
|
||||
app.Use(requestid.New())
|
||||
// 注册路由
|
||||
//registerRoutes(app)
|
||||
|
||||
// 2️⃣ 注册路由
|
||||
//registerRoutes(app, appCtx)
|
||||
port := cfg.Server.Port
|
||||
|
||||
// 3️⃣ 启动服务
|
||||
addr := fmt.Sprintf(":%s", appCtx.Config.Server.Port)
|
||||
log.Println("🚀 server start on :" + port)
|
||||
|
||||
fmt.Println("🚀 server running at", addr)
|
||||
|
||||
return app.Listen(addr)
|
||||
return app.Listen(":" + port)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{"level":"INFO","time":"2026-04-02 15:02:57","caller":"bootstrap/app.go:28","msg":"√ 数据库连接成功"}
|
||||
{"level":"INFO","time":"2026-04-02 15:03:21","caller":"bootstrap/app.go:28","msg":"√ 数据库连接成功"}
|
||||
{"level":"INFO","time":"2026-04-02 15:03:31","caller":"bootstrap/app.go:28","msg":"√ 数据库连接成功"}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoImports">
|
||||
<option name="excludedPackages">
|
||||
<array>
|
||||
<option value="github.com/pkg/errors" />
|
||||
<option value="golang.org/x/net/context" />
|
||||
</array>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/allapp-go-v3.iml" filepath="$PROJECT_DIR$/.idea/allapp-go-v3.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"allapp-go/internal/bootstrap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_ = bootstrap.BootService()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
app:
|
||||
port: 8087
|
||||
Whitespace-only changes.
@@ -0,0 +1,3 @@
|
||||
app:
|
||||
name: allapp
|
||||
port: 8080
|
||||
@@ -0,0 +1,36 @@
|
||||
module allapp-go
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gofiber/fiber/v3 v3.1.0 // indirect
|
||||
github.com/gofiber/schema v1.7.0 // indirect
|
||||
github.com/gofiber/utils/v2 v2.0.2 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.9.1 // indirect
|
||||
github.com/klauspost/compress v1.18.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/philhofer/fwd v1.2.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tinylib/msgp v1.6.3 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.69.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gofiber/fiber/v3 v3.1.0 h1:1p4I820pIa+FGxfwWuQZ5rAyX0WlGZbGT6Hnuxt6hKY=
|
||||
github.com/gofiber/fiber/v3 v3.1.0/go.mod h1:n2nYQovvL9z3Too/FGOfgtERjW3GQcAUqgfoezGBZdU=
|
||||
github.com/gofiber/schema v1.7.0 h1:yNM+FNRZjyYEli9Ey0AXRBrAY9jTnb+kmGs3lJGPvKg=
|
||||
github.com/gofiber/schema v1.7.0/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk=
|
||||
github.com/gofiber/utils/v2 v2.0.2 h1:ShRRssz0F3AhTlAQcuEj54OEDtWF7+HJDwEi/aa6QLI=
|
||||
github.com/gofiber/utils/v2 v2.0.2/go.mod h1:+9Ub4NqQ+IaJoTliq5LfdmOJAA/Hzwf4pXOxOa3RrJ0=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=
|
||||
github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
|
||||
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s=
|
||||
github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.69.0 h1:fNLLESD2SooWeh2cidsuFtOcrEi4uB4m1mPrkJMZyVI=
|
||||
github.com/valyala/fasthttp v1.69.0/go.mod h1:4wA4PfAraPlAsJ5jMSqCE2ug5tqUPwKXxVj8oNECGcw=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -0,0 +1,24 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"allapp-go/internal/config"
|
||||
"log"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
func BootService() *App {
|
||||
// 1️⃣ 加载配置
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
log.Fatalf("❌ load config failed: %v", err)
|
||||
}
|
||||
|
||||
RunServer(cfg)
|
||||
|
||||
return &App{
|
||||
Config: cfg,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"allapp-go/internal/config"
|
||||
"allapp-go/internal/router"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func RunServer(cfg *config.Config) {
|
||||
app := fiber.New()
|
||||
|
||||
router.Setup(app)
|
||||
|
||||
addr := fmt.Sprintf(":%d", cfg.App.Port)
|
||||
|
||||
log.Printf("🚀 Server running on %s", addr)
|
||||
|
||||
if err := app.Listen(addr); err != nil {
|
||||
log.Fatalf("❌ start server failed: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package config
|
||||
|
||||
type Config struct {
|
||||
App AppConfig `mapstructure:"app"`
|
||||
Postgres PostgresConfig `mapstructure:"postgres"`
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
|
||||
type PostgresConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
User string `mapstructure:"user"`
|
||||
Password string `mapstructure:"password"`
|
||||
Dbname string `mapstructure:"dbname"`
|
||||
SslMode bool `mapstructure:"ssl_mode"`
|
||||
TimeZone string `mapstructure:"timezone"`
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func Load() (*Config, error) {
|
||||
env := getEnv("APP_ENV", "dev")
|
||||
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
|
||||
// 基础配置
|
||||
v.AddConfigPath("configs")
|
||||
v.SetConfigName("config")
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("read base config failed: %w", err)
|
||||
}
|
||||
|
||||
// 环境配置(覆盖)
|
||||
envConfigName := fmt.Sprintf("config.%s", env)
|
||||
v.SetConfigName(envConfigName)
|
||||
|
||||
if err := v.MergeInConfig(); err != nil {
|
||||
// dev 允许没有文件,prod 建议必须存在
|
||||
if env == "prod" {
|
||||
return nil, fmt.Errorf("read env config failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal config failed: %w", err)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
func getEnv(key, defaultVal string) string {
|
||||
val := os.Getenv(key)
|
||||
if val == "" {
|
||||
return defaultVal
|
||||
}
|
||||
return strings.ToLower(val)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func Setup(app *fiber.App) {
|
||||
// 健康检查
|
||||
app.Get("/ping", func(c fiber.Ctx) error {
|
||||
return c.SendString("pong")
|
||||
})
|
||||
|
||||
// 你后面可以这样分组:
|
||||
// setupUserRoutes(app)
|
||||
// setupOrderRoutes(app)
|
||||
}
|
||||
@@ -1,11 +1,486 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { toast } from 'sard-uniapp'
|
||||
import { ref } from 'vue'
|
||||
import ShDialog from '@/components/sh-dialog/index.vue'
|
||||
import { useDeviceInfo } from '@/hooks/useDeviceInfo'
|
||||
import { loaddataApi, searchdatapageindexApi } from '@/request/api'
|
||||
import { useUserStore } from '@/store'
|
||||
import { useCountsStore } from '@/store/counts'
|
||||
import { groupFieldsBySpan } from '@/utils/common'
|
||||
|
||||
const countsStore = useCountsStore()
|
||||
const userStore = useUserStore()
|
||||
const { isMobile } = useDeviceInfo()
|
||||
|
||||
const auditComponentData = ref({
|
||||
moduleId: 'car_daily',
|
||||
saveTable: 'car_daily',
|
||||
state: '',
|
||||
row: null,
|
||||
})
|
||||
|
||||
const pagingRef = ref<any>(null)
|
||||
const dataList = ref<any[]>([])
|
||||
const modLevelList = ref<any[]>([])
|
||||
|
||||
const showShDialog = ref(false)
|
||||
|
||||
// 自定义 tabs
|
||||
const tabList = computed(() => [
|
||||
{ name: '待审', count: countsStore.baoxiao.v_dsh || 0 },
|
||||
{ name: '已处理', count: countsStore.baoxiao.v_ash || 0 },
|
||||
{ name: '全部', count: countsStore.baoxiao.all_cnt || 0 },
|
||||
])
|
||||
|
||||
const activeTab = ref(tabList.value[0])
|
||||
|
||||
const itemFields = [
|
||||
{ label: '账单日期', value: item => item.b_date, span: 12 },
|
||||
{ label: '结算单位', value: item => item.v_dw_name, span: 12 },
|
||||
{ label: '报销金额', value: item => item.b_amount_root, span: 6 },
|
||||
{ label: '币种', value: item => item.b_money_id, span: 6 },
|
||||
{ label: '汇率', value: item => item.b_exrate, span: 6 },
|
||||
{ label: '折后金额', value: item => item.b_amount, span: 6 },
|
||||
]
|
||||
const groupedFields = groupFieldsBySpan(itemFields)
|
||||
|
||||
// 搜索关键字
|
||||
const searchValue = ref('')
|
||||
|
||||
onShow(async () => {
|
||||
await loadModLevelList()
|
||||
|
||||
// await pagingRef.value?.reload()
|
||||
|
||||
countsStore.loadTaskCounts(['baoxiao'])
|
||||
})
|
||||
|
||||
async function loadModLevelList() {
|
||||
await loaddataApi({
|
||||
viewname: 'v_sh_b_set',
|
||||
searchcondition: `b_user_id='${userStore.userInfo.userid}' and b_module_id = 'car_daily'`,
|
||||
orderfield: 'b_level',
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
modLevelList.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
// 切换 tab
|
||||
function switchTab(tab: any) {
|
||||
activeTab.value = tab
|
||||
|
||||
pagingRef.value.reload()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch() {
|
||||
pagingRef.value.reload()
|
||||
}
|
||||
|
||||
function getTagType(state) {
|
||||
switch (state) {
|
||||
case '审核通过':
|
||||
return 'success'
|
||||
case '草拟':
|
||||
return 'info'
|
||||
case '审核驳回':
|
||||
return 'danger'
|
||||
default:
|
||||
return 'primary'
|
||||
}
|
||||
}
|
||||
|
||||
// 分页请求
|
||||
async function queryList(pageNo: number, pageSize: number) {
|
||||
toast.loading('正在加载中')
|
||||
|
||||
const userid = userStore.userInfo.userid
|
||||
|
||||
let sql = '2 > 1 '
|
||||
let mlvSearch = ''
|
||||
let slevel = ''
|
||||
|
||||
for (let i in modLevelList.value) {
|
||||
let item = modLevelList.value[i]
|
||||
|
||||
slevel = item.b_level
|
||||
let viewname = item.b_ViewTable
|
||||
let condition = item.b_condition
|
||||
let j = Number.parseInt(slevel) - 1
|
||||
|
||||
if (mlvSearch !== '') {
|
||||
mlvSearch = `${mlvSearch} or `
|
||||
}
|
||||
mlvSearch = `${mlvSearch}(b_module_id = '${item.b_module_id}'`
|
||||
if (viewname !== '' && condition !== '') {
|
||||
mlvSearch = `${mlvSearch} and b_id in (select b_id from ${viewname} where ${condition})`
|
||||
}
|
||||
|
||||
let canlevel = ` and b_level in('${j}','${slevel}')`
|
||||
if (activeTab.value.name === '待审') {
|
||||
canlevel = ` and b_level = '${j}'`
|
||||
}
|
||||
if (activeTab.value.name === '已处理') {
|
||||
canlevel = ` and b_level = '${slevel}'`
|
||||
}
|
||||
if (canlevel !== '') {
|
||||
mlvSearch = mlvSearch + canlevel
|
||||
}
|
||||
mlvSearch = `${mlvSearch})`
|
||||
}
|
||||
|
||||
if (mlvSearch) {
|
||||
sql = `${sql} and (${mlvSearch})`
|
||||
}
|
||||
if (searchValue.value) {
|
||||
sql = `${sql} and b_id like '%${searchValue.value}%'`
|
||||
}
|
||||
|
||||
searchdatapageindexApi({
|
||||
viewname: 'v_sh_recorddata',
|
||||
searchcondition: sql,
|
||||
userid,
|
||||
page: pageNo,
|
||||
rows: pageSize,
|
||||
orderfield: 'b_ss_date desc',
|
||||
})
|
||||
.then((res) => {
|
||||
const { rows, _total } = res.data
|
||||
|
||||
let idList = []
|
||||
rows.forEach((row) => {
|
||||
idList.push(row.b_id)
|
||||
})
|
||||
let sql2 = '2 > 1'
|
||||
if (idList.length > 0) {
|
||||
let idString = idList.map(id => `'${id}'`).join(',')
|
||||
sql2 = `b_id IN (${idString})`
|
||||
}
|
||||
else {
|
||||
sql2 = `b_id IN (NULL)`
|
||||
}
|
||||
|
||||
loaddataApi({
|
||||
viewname: 'v_car_daily',
|
||||
searchcondition: sql2,
|
||||
orderfield: 'b_date desc',
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
let rows2 = res.data
|
||||
|
||||
rows2.forEach((row) => {
|
||||
if (row.b_id) {
|
||||
let slevel: string | number = ''
|
||||
let cansh = false
|
||||
let canbh = false
|
||||
let bModuleId = ''
|
||||
let bLevel: string | number = ''
|
||||
|
||||
const foundItem = rows.find(item => item.b_id === row.b_id)
|
||||
if (foundItem) {
|
||||
bModuleId = foundItem.b_module_id
|
||||
bLevel = foundItem.b_level
|
||||
|
||||
row.b_module_id = bModuleId
|
||||
}
|
||||
for (const modLevel of modLevelList.value) {
|
||||
if (modLevel.b_module_id === bModuleId) {
|
||||
slevel = modLevel.b_level
|
||||
slevel = Number.parseInt(slevel as string)
|
||||
if (Number.isNaN(slevel)) {
|
||||
slevel = 0
|
||||
}
|
||||
let j = slevel - 1
|
||||
if (bLevel === j) {
|
||||
cansh = true
|
||||
}
|
||||
if (bLevel === slevel) {
|
||||
canbh = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canbh || cansh) {
|
||||
if (cansh) {
|
||||
row.tongGuoButton = true
|
||||
row.boHuiButton = true
|
||||
}
|
||||
else if (canbh) {
|
||||
row.tongGuoButton = false
|
||||
row.boHuiButton = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
row.tongGuoButton = false
|
||||
row.boHuiButton = false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (rows2) {
|
||||
console.log(rows2)
|
||||
|
||||
pagingRef.value.complete(rows2)
|
||||
}
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
toast.hide()
|
||||
})
|
||||
}
|
||||
|
||||
async function handleApproval(item: any, state: string) {
|
||||
auditComponentData.value.row = item
|
||||
auditComponentData.value.state = state
|
||||
showShDialog.value = true
|
||||
}
|
||||
|
||||
function handleShSuccess() {
|
||||
pagingRef.value.reload()
|
||||
countsStore.loadTaskCounts(['baoxiao'])
|
||||
}
|
||||
|
||||
function handleToProcess(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages-sub/process/index?b_id=${item.b_id}&b_module_id=${item.b_module_id}&v_modulename=费用报销`,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="" />
|
||||
<view>
|
||||
<z-paging ref="pagingRef" v-model="dataList" auto-show-back-to-top @query="queryList">
|
||||
<template #top>
|
||||
<sar-search
|
||||
v-model="searchValue"
|
||||
placeholder="业务单号"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<view class="tabs">
|
||||
<view
|
||||
v-for="tab in tabList"
|
||||
:key="tab.name"
|
||||
class="tabs__item"
|
||||
:class="{ 'tabs__item--active': activeTab.name === tab.name }"
|
||||
@click="switchTab(tab)"
|
||||
>
|
||||
<sar-badge v-if="tab.count > 0" :value="tab.count">
|
||||
{{ tab.name }}
|
||||
</sar-badge>
|
||||
|
||||
<text v-else>
|
||||
{{ tab.name }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<!-- 列表内容 -->
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="index"
|
||||
class="list-item"
|
||||
:class="[!isMobile ? 'list-item--desktop' : '']"
|
||||
@click="handleToProcess(item)"
|
||||
>
|
||||
<view class="list-item__header">
|
||||
<view class="list-item__main">
|
||||
<!-- <sar-checkbox size="36rpx" /> -->
|
||||
<text>
|
||||
{{ item.b_id }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="list-item__extra">
|
||||
<sar-tag :theme="getTagType(item.b_state)">
|
||||
{{ item.b_state }}
|
||||
</sar-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list-item__body">
|
||||
<sar-row v-for="(row, rowIndex) in groupedFields" :key="rowIndex">
|
||||
<sar-col
|
||||
v-for="(col, colIndex) in row"
|
||||
:key="colIndex"
|
||||
:span="col.span || 6"
|
||||
>
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
{{ col.label }}:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ col.value(item) }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
</sar-row>
|
||||
</view>
|
||||
|
||||
<view class="list-item__footer">
|
||||
<sar-button v-if="item.boHuiButton" theme="danger" size="mini" icon="close" inline @click.stop="handleApproval(item, '审核驳回')">
|
||||
驳回
|
||||
</sar-button>
|
||||
<sar-button v-if="item.tongGuoButton" size="mini" icon="success" inline @click.stop="handleApproval(item, '审核通过')">
|
||||
通过
|
||||
</sar-button>
|
||||
</view>
|
||||
<view class="list-item__line" />
|
||||
</view>
|
||||
|
||||
<!-- <template #bottom>
|
||||
<view class="bottom-bar">
|
||||
<sar-checkbox>
|
||||
全选
|
||||
</sar-checkbox>
|
||||
|
||||
<sar-button block size="small" icon="success">
|
||||
批量通过
|
||||
</sar-button>
|
||||
</view>
|
||||
</template> -->
|
||||
</z-paging>
|
||||
|
||||
<ShDialog v-model="showShDialog" :component-data="auditComponentData" @success="handleShSuccess" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/style/mixins.scss';
|
||||
|
||||
.dialog-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 36rpx;
|
||||
background: #fff;
|
||||
border-top: 2rpx solid #ddd;
|
||||
@include flexGap(32rpx, '');
|
||||
}
|
||||
|
||||
/* tab 栏 */
|
||||
.tabs {
|
||||
display: flex;
|
||||
border-bottom: 2rpx solid #eee;
|
||||
background-color: #fff;
|
||||
|
||||
.tabs__item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
font-size: 30rpx;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.tabs__item--active {
|
||||
color: var(--sar-primary);
|
||||
font-weight: bold;
|
||||
border-bottom: 4rpx solid var(--sar-primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* 列表项 */
|
||||
.list-item {
|
||||
position: relative;
|
||||
padding: 24rpx 16rpx;
|
||||
background-color: #fff;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
&.list-item--desktop {
|
||||
.list-item__header {
|
||||
max-width: 1000rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.list-item__body {
|
||||
max-width: 1000rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.list-item__footer {
|
||||
max-width: 1000rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.list-item__main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include flexGap(16rpx, '');
|
||||
font-weight: bold;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
.list-item__extra {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include flexGap(16rpx, '');
|
||||
.list-item__finishdate {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__body {
|
||||
padding: 24rpx 0rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include flexGap(16rpx, 'column');
|
||||
.list-item__info {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
width: 100%;
|
||||
font-size: 32rpx;
|
||||
line-height: 1;
|
||||
|
||||
.list-item__label {
|
||||
display: block;
|
||||
min-width: 192rpx;
|
||||
color: #4b5563;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-item__value {
|
||||
flex: 1;
|
||||
color: #111827;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@include flexGap(36rpx, '');
|
||||
|
||||
:deep(.sar-button) {
|
||||
padding: 0rpx 48rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__line {
|
||||
position: absolute;
|
||||
bottom: 0rpx;
|
||||
left: 0rpx;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: #dcdcdc;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -44,8 +44,6 @@ async function loadFileData() {
|
||||
url: item.mx_mapfilename,
|
||||
}
|
||||
})
|
||||
|
||||
console.log(fileList.value)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -59,13 +59,11 @@ onShow(async () => {
|
||||
async function loadModLevelList() {
|
||||
await loaddataApi({
|
||||
viewname: 'v_sh_b_set',
|
||||
searchcondition: `b_user_id='${userStore.userInfo.userid}'`,
|
||||
searchcondition: `b_user_id='${userStore.userInfo.userid}' AND b_module_id = 'cw_zdorder_f'`,
|
||||
orderfield: 'b_level',
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
modLevelList.value = res.data.filter(item => item.b_module_id === 'cw_zdorder_f')
|
||||
|
||||
console.log(modLevelList.value)
|
||||
modLevelList.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -149,12 +147,13 @@ async function queryList(pageNo: number, pageSize: number) {
|
||||
orderfield: 'b_ss_date desc',
|
||||
})
|
||||
.then((res) => {
|
||||
const { rows, _total } = res.data
|
||||
const { rows, total } = res.data
|
||||
|
||||
let idList = []
|
||||
rows.forEach((row) => {
|
||||
idList.push(row.b_id)
|
||||
})
|
||||
|
||||
let sql2 = '2 > 1'
|
||||
if (idList.length > 0) {
|
||||
let idString = idList.map(id => `'${id}'`).join(',')
|
||||
@@ -319,10 +318,10 @@ function handleToProcess(item) {
|
||||
</view>
|
||||
|
||||
<view class="list-item__footer">
|
||||
<sar-button v-if="item.boHuiButton" theme="danger" size="mini" icon="close" inline @click="handleApproval(item, '审核驳回')">
|
||||
<sar-button v-if="item.boHuiButton" theme="danger" size="mini" icon="close" inline @click.stop="handleApproval(item, '审核驳回')">
|
||||
驳回
|
||||
</sar-button>
|
||||
<sar-button v-if="item.tongGuoButton" size="mini" icon="success" inline @click="handleApproval(item, '审核通过')">
|
||||
<sar-button v-if="item.tongGuoButton" size="mini" icon="success" inline @click.stop="handleApproval(item, '审核通过')">
|
||||
通过
|
||||
</sar-button>
|
||||
</view>
|
||||
@@ -421,9 +420,9 @@ function handleToProcess(item) {
|
||||
.list-item__main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include flexGap(16rpx, '');
|
||||
font-weight: bold;
|
||||
font-size: 36rpx;
|
||||
@include flexGap(16rpx, '');
|
||||
}
|
||||
.list-item__extra {
|
||||
display: flex;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<script setup lang="ts">
|
||||
import type { UploadFile, UploadFileItem } from 'sard-uniapp'
|
||||
import { loaddataAttachApi } from '@/request/api'
|
||||
|
||||
const props = defineProps({
|
||||
componentData: {
|
||||
type: Object,
|
||||
},
|
||||
})
|
||||
|
||||
const fileList = ref<UploadFileItem[]>([])
|
||||
|
||||
const father = ref('')
|
||||
const moduleid = ref('')
|
||||
const cateid = ref('')
|
||||
|
||||
onLoad(() => {
|
||||
father.value = props.componentData.b_id
|
||||
moduleid.value = props.componentData.b_module_id
|
||||
|
||||
nextTick(() => {
|
||||
loadFileData()
|
||||
})
|
||||
})
|
||||
|
||||
async function loadFileData() {
|
||||
let searchcondition = ` father = '${father.value}' and mx_moduleid = '${moduleid.value}'`
|
||||
if (cateid.value !== '') {
|
||||
searchcondition += ` and mx_cate_id = '${cateid.value}'`
|
||||
}
|
||||
loaddataAttachApi({
|
||||
viewname: 'bf_files',
|
||||
searchcondition,
|
||||
orderfield: 'mx_xh',
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
fileList.value = res.data.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
name: item.mx_filename,
|
||||
url: item.mx_mapfilename,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="file">
|
||||
<sar-result v-if="fileList.length === 0" status="info" title="提示" description="暂无附件" />
|
||||
<sar-upload v-model="fileList" :readonly="true" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file {
|
||||
padding: 36rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import File from './file.vue'
|
||||
import Information from './information.vue'
|
||||
import Step from './step.vue'
|
||||
|
||||
@@ -69,6 +70,7 @@ onLoad((options) => {
|
||||
|
||||
<Step v-if="segmentedValue === '流程'" :component-data="data" />
|
||||
<Information v-else-if="segmentedValue === '详细'" :component-data="data" />
|
||||
<File v-else-if="segmentedValue === '附件'" :component-data="data" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import LoadingPage from '@/components/loading-page/index.vue'
|
||||
import { loaddataApi } from '@/request/api'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -7,33 +6,124 @@ const props = defineProps({
|
||||
type: Object,
|
||||
},
|
||||
})
|
||||
const data = ref<any[]>([])
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
const loading = ref(true)
|
||||
const stepsData = ref<Array<any>>([])
|
||||
|
||||
const progress = ref({
|
||||
finish: 0,
|
||||
all: 0,
|
||||
})
|
||||
|
||||
const computedProgress = computed(() => {
|
||||
if (progress.value.all === 0) {
|
||||
return 0
|
||||
}
|
||||
return Math.round((progress.value.finish / progress.value.all) * 100)
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
async function initData() {
|
||||
loading.value = true
|
||||
await loaddataApi({
|
||||
viewname: 'v_sh_record',
|
||||
orderfield: 'b_id desc',
|
||||
// 定义两个请求
|
||||
const request1 = loaddataApi({
|
||||
viewname: 'v_sh_setjd',
|
||||
orderfield: 'b_level',
|
||||
searchcondition: `b_module_id = '${props.componentData.b_module_id}'`,
|
||||
soption: '',
|
||||
})
|
||||
|
||||
const request2 = loaddataApi({
|
||||
viewname: 'v_sh_modshrecord',
|
||||
orderfield: 'b_level',
|
||||
searchcondition: `b_module_id = '${props.componentData.b_module_id}' and b_dj_id = '${props.componentData.b_id}'`,
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
data.value = res.data
|
||||
})
|
||||
|
||||
// 使用 Promise.all 等待两个请求都完成
|
||||
Promise.all([request1, request2])
|
||||
.then(([res1, res2]) => {
|
||||
const stepData = res1.data
|
||||
const stepItemData = res2.data
|
||||
|
||||
progress.value.finish = stepItemData.length
|
||||
progress.value.all = stepData.length
|
||||
let current = true
|
||||
stepData.forEach((item, index) => {
|
||||
const obj = {
|
||||
type: 0,
|
||||
current: false,
|
||||
b_name: '',
|
||||
v_user_name: '',
|
||||
b_sh_memo: '',
|
||||
b_sh_datetime: '',
|
||||
b_level: item.b_level,
|
||||
consume_time: '',
|
||||
}
|
||||
const stepItem = stepItemData[index]
|
||||
|
||||
if (stepItem !== undefined) {
|
||||
obj.type = 2
|
||||
obj.v_user_name = stepItem.v_user_name
|
||||
obj.b_sh_memo = stepItem.b_sh_memo
|
||||
obj.b_sh_datetime = stepItem.b_sh_datetime
|
||||
obj.b_name = stepItem.b_name
|
||||
// 计算审批耗时,需要计算与上一级的耗时
|
||||
if (obj.b_level !== 0) {
|
||||
// 计算与上一个的耗时
|
||||
const lastItem = stepItemData[index - 1]
|
||||
obj.consume_time = computedTimeDifference(lastItem.b_sh_datetime, obj.b_sh_datetime)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (current) {
|
||||
obj.current = true
|
||||
obj.type = 1
|
||||
current = false
|
||||
}
|
||||
if (item.b_level === 0) {
|
||||
obj.b_name = `送审`
|
||||
}
|
||||
else {
|
||||
obj.b_name = `${getCharNumber(item.b_level)}审通过`
|
||||
}
|
||||
obj.v_user_name = item.v_dshusername
|
||||
}
|
||||
stepsData.value.push(obj)
|
||||
})
|
||||
stepsData.value.reverse()
|
||||
|
||||
console.log(stepsData.value)
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function computedConsumeTime(index: number) {
|
||||
if (index === data.value.length - 1) {
|
||||
function getCharNumber(number: number): string {
|
||||
switch (number) {
|
||||
case 1:
|
||||
return '一'
|
||||
case 2:
|
||||
return '二'
|
||||
case 3:
|
||||
return '三'
|
||||
case 4:
|
||||
return '四'
|
||||
case 5:
|
||||
return '五'
|
||||
case 6:
|
||||
return '六'
|
||||
case 7:
|
||||
return '七'
|
||||
case 8:
|
||||
return '八'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
if (data.value.length === 1) {
|
||||
return ''
|
||||
}
|
||||
return computedTimeDifference(data.value[index].b_sh_date, data.value[index + 1].b_sh_date)
|
||||
}
|
||||
function computedTimeDifference(date1: string, date2: string): string {
|
||||
// 将日期字符串转换为 Date 对象
|
||||
@@ -63,46 +153,165 @@ function computedTimeDifference(date1: string, date2: string): string {
|
||||
// 如果没有任何值,说明两个日期相等,返回"0秒"
|
||||
return result.length > 0 ? result.join('') : '0秒'
|
||||
}
|
||||
// 计算步骤的颜色
|
||||
function getTimelineStyle(item: any) {
|
||||
const colorMap: Record<number, string> = {
|
||||
0: '#B0B0B0',
|
||||
1: '#6A9EF1',
|
||||
2: '#70C070',
|
||||
3: '#F17A7A',
|
||||
}
|
||||
|
||||
const color = colorMap[item.type] || '#B0B0B0'
|
||||
|
||||
return {
|
||||
'--dot-color': color,
|
||||
'--line-color': color,
|
||||
}
|
||||
}
|
||||
function computedStepText(item): string {
|
||||
switch (item.type) {
|
||||
case 0:
|
||||
return '未开始' // 未开始,灰色
|
||||
case 1:
|
||||
return '进行中'
|
||||
// 进行中,蓝色
|
||||
case 2:
|
||||
return '已完成' // 已完成,绿色
|
||||
case 3:
|
||||
return '驳回' // 已驳回,红色
|
||||
default:
|
||||
return '未开始' // 默认灰色
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateTime(dateTime: string): string {
|
||||
if (!dateTime) {
|
||||
return ''
|
||||
}
|
||||
return dateTime.replace(/\.\d+$/, '')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoadingPage v-if="loading" />
|
||||
<view v-else-if="data.length > 0" class="timeline">
|
||||
<view v-for="(item, index) in data" :key="index" class="timeline-item">
|
||||
|
||||
<view v-else-if="stepsData.length > 0" class="">
|
||||
<view style="display: flex;align-items: center;">
|
||||
<text style="font-size: 28rpx; margin-right: 8rpx;">
|
||||
当前进度 -
|
||||
</text>
|
||||
|
||||
<view style="flex:1">
|
||||
<sar-progress-bar
|
||||
:percent="computedProgress"
|
||||
inside
|
||||
striped
|
||||
animated
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="timeline">
|
||||
<view
|
||||
v-for="(item, index) in stepsData"
|
||||
:key="index"
|
||||
class="timeline-item"
|
||||
:style="getTimelineStyle(item)"
|
||||
>
|
||||
<view class="timeline-col left-col">
|
||||
<view class="timeline-content left">
|
||||
<text>
|
||||
{{ item.b_name }}
|
||||
</text>
|
||||
|
||||
<view style="margin-top: 8rpx">
|
||||
<sar-tag v-if="item.type === 1" theme="primary" size="small">
|
||||
{{ computedStepText(item) }}
|
||||
</sar-tag>
|
||||
<sar-tag v-else-if="item.type === 2" theme="success" size="small">
|
||||
{{ computedStepText(item) }}
|
||||
</sar-tag>
|
||||
<sar-tag v-else-if="item.type === 3" theme="danger" size="small">
|
||||
{{ computedStepText(item) }}
|
||||
</sar-tag>
|
||||
<sar-tag v-else theme="secondary" size="small">
|
||||
{{ computedStepText(item) }}
|
||||
</sar-tag>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="timeline-col right-col">
|
||||
<view class="timeline-content right">
|
||||
<view v-if="item.v_user_name" class="title">
|
||||
{{ item.v_user_name }}
|
||||
<text v-if="item.v_tosh_user_name">
|
||||
> {{ item.v_tosh_user_name }}
|
||||
</text>
|
||||
<view v-if="item.b_level === 0">
|
||||
<view>
|
||||
<text>操作人:</text>
|
||||
<text>{{ item.v_user_name }}</text>
|
||||
</view>
|
||||
<view>{{ item.b_sh_date }}</view>
|
||||
<view v-if="computedConsumeTime(index)">
|
||||
审批耗时:{{ computedConsumeTime(index) }}
|
||||
</view>
|
||||
<view>{{ item.b_sh_memo }}</view>
|
||||
<view>
|
||||
<text>操作时间:</text>
|
||||
<text>{{ formatDateTime(item.b_sh_datetime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else>
|
||||
<view v-if="item.type === 0 || item.type === 1">
|
||||
<view>
|
||||
<text>审核人:</text>
|
||||
<text>{{ item.v_user_name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else-if="item.type === 3">
|
||||
<view>
|
||||
<text>审核人:</text>
|
||||
<text>{{ item.v_user_name }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>审核时间:</text>
|
||||
<text>{{ formatDateTime(item.b_sh_datetime) }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>审核耗时:</text>
|
||||
<text>{{ item.consume_time }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else>
|
||||
<view>
|
||||
<text>审核人:</text>
|
||||
<text>{{ item.v_user_name }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>审核时间:</text>
|
||||
<text>{{ formatDateTime(item.b_sh_datetime) }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>审核意见:</text>
|
||||
<text>{{ item.b_sh_memo }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="timeline-center">
|
||||
<view class="timeline-dot" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<sar-result v-else status="info" title="空空如也" style="margin-top: 64rpx;" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 整个容器 */
|
||||
.timeline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 每个步骤项 */
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
@@ -110,6 +319,7 @@ function computedTimeDifference(date1: string, date2: string): string {
|
||||
align-items: center;
|
||||
padding: 32rpx 0;
|
||||
}
|
||||
|
||||
/* 左右列容器,用来固定左右比例,不受内容内 padding 影响 */
|
||||
.timeline-col {
|
||||
box-sizing: border-box;
|
||||
@@ -127,34 +337,30 @@ function computedTimeDifference(date1: string, date2: string): string {
|
||||
padding-left: 32rpx; /* 给中间圆点留出空间 */
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 左右内容,可以自由添加 padding */
|
||||
.timeline-content {
|
||||
font-size: 28rpx;
|
||||
word-break: break-all;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.timeline-content.left {
|
||||
&.left {
|
||||
padding: 8rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
background-color: #f0f2f5; /* 轻柔的灰色背景,避免视觉突兀 */
|
||||
border-radius: 12rpx; /* 让边角更柔和 */
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); /* 轻微阴影,增加层次感 */
|
||||
// background-color: #f0f2f5; /* 轻柔的灰色背景,避免视觉突兀 */
|
||||
// border-radius: 12rpx; /* 让边角更柔和 */
|
||||
// box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); /* 轻微阴影,增加层次感 */
|
||||
}
|
||||
|
||||
.timeline-content.right {
|
||||
&.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
color: #666;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
/* 中间圆点容器,绝对定位在左右列分界处 */
|
||||
.timeline-center {
|
||||
position: absolute;
|
||||
@@ -169,8 +375,9 @@ function computedTimeDifference(date1: string, date2: string): string {
|
||||
.timeline-dot {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background: #007aff;
|
||||
background: var(--dot-color, #007aff);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
/* 使用每个步骤项的伪元素绘制竖线 */
|
||||
.timeline-item::before {
|
||||
@@ -180,7 +387,7 @@ function computedTimeDifference(date1: string, date2: string): string {
|
||||
left: calc(30%);
|
||||
width: 4rpx; /* 可随意调整宽度 */
|
||||
content: '';
|
||||
background: #409eff; /* 竖线颜色 */
|
||||
background: #dddddd; /* 竖线颜色 */
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
/* 第一项:只显示圆点下方的线 */
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
<script lang="ts" setup>
|
||||
import LoadingPage from '@/components/loading-page/index.vue'
|
||||
import { loaddataApi } from '@/request/api'
|
||||
|
||||
const props = defineProps({
|
||||
componentData: {
|
||||
type: Object,
|
||||
},
|
||||
})
|
||||
const data = ref<any[]>([])
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
onLoad(() => {
|
||||
initData()
|
||||
})
|
||||
|
||||
async function initData() {
|
||||
loading.value = true
|
||||
await loaddataApi({
|
||||
viewname: 'v_sh_record',
|
||||
orderfield: 'b_id desc',
|
||||
searchcondition: `b_module_id = '${props.componentData.b_module_id}' and b_dj_id = '${props.componentData.b_id}'`,
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
data.value = res.data
|
||||
})
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
function computedConsumeTime(index: number) {
|
||||
if (index === data.value.length - 1) {
|
||||
return ''
|
||||
}
|
||||
if (data.value.length === 1) {
|
||||
return ''
|
||||
}
|
||||
return computedTimeDifference(data.value[index].b_sh_date, data.value[index + 1].b_sh_date)
|
||||
}
|
||||
function computedTimeDifference(date1: string, date2: string): string {
|
||||
// 将日期字符串转换为 Date 对象
|
||||
const d1 = new Date(date1)
|
||||
const d2 = new Date(date2)
|
||||
|
||||
// 计算两个日期之间的毫秒差值
|
||||
const diffInMilliseconds = Math.abs(d2.getTime() - d1.getTime())
|
||||
|
||||
// 将毫秒差值转换为对应的天、小时、分钟和秒
|
||||
const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24))
|
||||
const hours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||||
const minutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60))
|
||||
const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000)
|
||||
|
||||
// 根据条件组合输出结果
|
||||
const result: string[] = []
|
||||
if (days > 0)
|
||||
result.push(`${days}天`)
|
||||
if (hours > 0)
|
||||
result.push(`${hours}时`)
|
||||
if (minutes > 0)
|
||||
result.push(`${minutes}分`)
|
||||
if (seconds > 0)
|
||||
result.push(`${seconds}秒`)
|
||||
|
||||
// 如果没有任何值,说明两个日期相等,返回"0秒"
|
||||
return result.length > 0 ? result.join('') : '0秒'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoadingPage v-if="loading" />
|
||||
<view v-else-if="data.length > 0" class="timeline">
|
||||
<view v-for="(item, index) in data" :key="index" class="timeline-item">
|
||||
<view class="timeline-col left-col">
|
||||
<view class="timeline-content left">
|
||||
{{ item.b_name }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="timeline-col right-col">
|
||||
<view class="timeline-content right">
|
||||
<view v-if="item.v_user_name" class="title">
|
||||
{{ item.v_user_name }}
|
||||
<text v-if="item.v_tosh_user_name">
|
||||
> {{ item.v_tosh_user_name }}
|
||||
</text>
|
||||
</view>
|
||||
<view>{{ item.b_sh_date }}</view>
|
||||
<view v-if="computedConsumeTime(index)">
|
||||
审批耗时:{{ computedConsumeTime(index) }}
|
||||
</view>
|
||||
<view>{{ item.b_sh_memo }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="timeline-center">
|
||||
<view class="timeline-dot" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<sar-result v-else status="info" title="空空如也" style="margin-top: 64rpx;" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 整个容器 */
|
||||
.timeline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
/* 每个步骤项 */
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 32rpx 0;
|
||||
}
|
||||
|
||||
.timeline-item:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* 左右列容器,用来固定左右比例,不受内容内 padding 影响 */
|
||||
.timeline-col {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.left-col {
|
||||
width: 30%;
|
||||
padding-right: 32rpx; /* 给中间圆点留出空间 */
|
||||
font-size: 28rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.right-col {
|
||||
width: 70%;
|
||||
padding-left: 32rpx; /* 给中间圆点留出空间 */
|
||||
text-align: left;
|
||||
}
|
||||
/* 左右内容,可以自由添加 padding */
|
||||
.timeline-content {
|
||||
font-size: 28rpx;
|
||||
word-break: break-all;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.timeline-content.left {
|
||||
padding: 8rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
background-color: #f0f2f5; /* 轻柔的灰色背景,避免视觉突兀 */
|
||||
border-radius: 12rpx; /* 让边角更柔和 */
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); /* 轻微阴影,增加层次感 */
|
||||
}
|
||||
|
||||
.timeline-content.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
color: #666;
|
||||
background: #f5f5f5;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
/* 中间圆点容器,绝对定位在左右列分界处 */
|
||||
.timeline-center {
|
||||
position: absolute;
|
||||
left: calc(30%);
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
/* 圆点 */
|
||||
.timeline-dot {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background: #007aff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
/* 使用每个步骤项的伪元素绘制竖线 */
|
||||
.timeline-item::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: calc(30%);
|
||||
width: 4rpx; /* 可随意调整宽度 */
|
||||
content: '';
|
||||
background: #409eff; /* 竖线颜色 */
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
/* 第一项:只显示圆点下方的线 */
|
||||
.timeline-item:first-child::before {
|
||||
top: 50%;
|
||||
}
|
||||
/* 最后一项:只显示圆点上方的线 */
|
||||
.timeline-item:last-child::before {
|
||||
bottom: 50%;
|
||||
}
|
||||
</style>
|
||||
@@ -36,7 +36,7 @@ async function onSubmit() {
|
||||
const searchcondition = `b_id = '${userStore.userInfo.userid}' AND ISNULL(b_password, '') = ISNULL('${formModel.oldPassword}', '')`
|
||||
|
||||
const searchRes = await loaddataApi({
|
||||
viewname: 'v_mini_loginid',
|
||||
viewname: 'b_user',
|
||||
searchcondition: `${searchcondition}`,
|
||||
orderfield: 'b_id',
|
||||
soption: '',
|
||||
@@ -58,7 +58,7 @@ async function onSubmit() {
|
||||
const delValues = []
|
||||
const keys = []
|
||||
|
||||
tables.push('b_truck')
|
||||
tables.push('b_user')
|
||||
insertValues.push('[]')
|
||||
updateValues.push(JSON.stringify([updateObj]))
|
||||
delValues.push('[]')
|
||||
|
||||
@@ -26,50 +26,80 @@ export const useCountsStore = defineStore('taskCounts', () => {
|
||||
// 请求的 SQL 查询列表
|
||||
const sqlQueries = {
|
||||
fukuan: `
|
||||
SELECT COUNT(*) AS all_cnt,
|
||||
SUM(CASE WHEN rs.b_level >= st.b_level THEN 1 ELSE 0 END) AS v_ash,
|
||||
SUM(CASE WHEN rs.b_level = st.b_level - 1 THEN 1 ELSE 0 END) AS v_dsh
|
||||
FROM (
|
||||
SELECT
|
||||
COUNT(1) AS all_cnt,
|
||||
|
||||
SUM(CASE
|
||||
WHEN rs.b_level >= st.b_level THEN 1
|
||||
ELSE 0
|
||||
END) AS v_ash,
|
||||
|
||||
SUM(CASE
|
||||
WHEN rs.b_level = st.b_level - 1 THEN 1
|
||||
ELSE 0
|
||||
END) AS v_dsh
|
||||
|
||||
FROM
|
||||
(
|
||||
-- 只取每个单据的最新一条
|
||||
SELECT r.*
|
||||
FROM (
|
||||
FROM
|
||||
(
|
||||
SELECT b_dj_id, b_module_id, MAX(b_id) AS b_maxid
|
||||
FROM dbo.sh_record
|
||||
GROUP BY b_dj_id, b_module_id
|
||||
) AS a
|
||||
JOIN sh_record r ON a.b_maxid = r.b_id
|
||||
) a
|
||||
INNER JOIN sh_record r ON a.b_maxid = r.b_id
|
||||
WHERE r.b_sh = '1'
|
||||
) AS rs
|
||||
LEFT JOIN (
|
||||
SELECT b_module_id, b_level
|
||||
) rs
|
||||
|
||||
CROSS JOIN
|
||||
(
|
||||
SELECT TOP 1 b_level
|
||||
FROM sh_b_set
|
||||
WHERE b_user_id = '${userStore.userInfo.userid}'
|
||||
) AS st
|
||||
ON rs.b_module_id = st.b_module_id
|
||||
AND (rs.b_level = st.b_level - 1 OR rs.b_level = st.b_level)
|
||||
AND b_module_id = 'cw_zdorder_f'
|
||||
ORDER BY b_level DESC
|
||||
) st
|
||||
|
||||
WHERE rs.b_module_id = 'cw_zdorder_f';
|
||||
`,
|
||||
baoxiao: `
|
||||
SELECT COUNT(*) AS all_cnt,
|
||||
SUM(CASE WHEN rs.b_level >= st.b_level THEN 1 ELSE 0 END) AS v_ash,
|
||||
SUM(CASE WHEN rs.b_level = st.b_level - 1 THEN 1 ELSE 0 END) AS v_dsh
|
||||
FROM (
|
||||
SELECT
|
||||
COUNT(1) AS all_cnt,
|
||||
|
||||
SUM(CASE
|
||||
WHEN rs.b_level >= st.b_level THEN 1
|
||||
ELSE 0
|
||||
END) AS v_ash,
|
||||
|
||||
SUM(CASE
|
||||
WHEN rs.b_level = st.b_level - 1 THEN 1
|
||||
ELSE 0
|
||||
END) AS v_dsh
|
||||
|
||||
FROM
|
||||
(
|
||||
SELECT r.*
|
||||
FROM (
|
||||
FROM
|
||||
(
|
||||
SELECT b_dj_id, b_module_id, MAX(b_id) AS b_maxid
|
||||
FROM dbo.sh_record
|
||||
GROUP BY b_dj_id, b_module_id
|
||||
) AS a
|
||||
JOIN sh_record r ON a.b_maxid = r.b_id
|
||||
) a
|
||||
INNER JOIN sh_record r ON a.b_maxid = r.b_id
|
||||
WHERE r.b_sh = '1'
|
||||
) AS rs
|
||||
LEFT JOIN (
|
||||
SELECT b_module_id, b_level
|
||||
AND r.b_module_id = 'car_daily'
|
||||
) rs
|
||||
|
||||
CROSS JOIN
|
||||
(
|
||||
SELECT TOP 1 b_level
|
||||
FROM sh_b_set
|
||||
WHERE b_user_id = '${userStore.userInfo.userid}'
|
||||
) AS st
|
||||
ON rs.b_module_id = st.b_module_id
|
||||
AND (rs.b_level = st.b_level - 1 OR rs.b_level = st.b_level)
|
||||
WHERE rs.b_module_id = 'car_daily';
|
||||
AND b_module_id = 'car_daily'
|
||||
ORDER BY b_level DESC
|
||||
) st
|
||||
`,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,30 +5,14 @@ import { getModuleQxApi } from '@/request/api'
|
||||
import { useUserStore } from './user'
|
||||
|
||||
const PERMISSION_PATH_MAP = [
|
||||
// {
|
||||
// moduleId: 'xc_consite_checkcon',
|
||||
// path: '/pages-sub/jiaoyan',
|
||||
// },
|
||||
// {
|
||||
// moduleId: 'xc_consite_clearcon',
|
||||
// path: '/pages-sub/qingxi',
|
||||
// },
|
||||
// {
|
||||
// moduleId: 'xc_consite_jiarecon',
|
||||
// path: '/pages-sub/jiare',
|
||||
// },
|
||||
// {
|
||||
// moduleId: 'xc_consite_wxcon',
|
||||
// path: '/pages-sub/weixiu',
|
||||
// },
|
||||
// {
|
||||
// moduleId: 'xc_conyard_in',
|
||||
// path: '/pages-sub/jinchang',
|
||||
// },
|
||||
// {
|
||||
// moduleId: 'xc_conyard_out',
|
||||
// path: '/pages-sub/chuchang',
|
||||
// },
|
||||
{
|
||||
moduleId: 'cw_zdorder_f',
|
||||
path: '/pages-sub/fukuan',
|
||||
},
|
||||
{
|
||||
moduleId: 'car_daily',
|
||||
path: '/pages-sub/baoxiao',
|
||||
}
|
||||
]
|
||||
|
||||
export const usePermissionStore = defineStore(
|
||||
|
||||
Reference in new issue
Block a user