Compare commits
10 Commits
e3be1079b4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5961c12f7 | ||
|
|
2673c9fdde | ||
|
|
019297d261 | ||
|
|
9df2663b6e | ||
|
|
cee14cb3fd | ||
|
|
dae2941168 | ||
|
|
464937cf84 | ||
|
|
549b18daf0 | ||
|
|
9ef5707ca2 | ||
|
|
24553e9875 |
@@ -12,6 +12,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func (d *DiscoverMedias) getFileMD5(filePath string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractAudio extract audio from video
|
// extractAudio extract audio from video
|
||||||
func (d *DiscoverMedias) extractAudio(video string, output string) error {
|
func (d *DiscoverMedias) extractAudio(video, output string) error {
|
||||||
args := []string{
|
args := []string{
|
||||||
"-i", video,
|
"-i", video,
|
||||||
"-vn",
|
"-vn",
|
||||||
@@ -303,7 +303,7 @@ func (d *DiscoverMedias) runCleanup(to string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getSnapshot get the snapshot of target seconds of a video
|
// getSnapshot get the snapshot of target seconds of a video
|
||||||
func (d *DiscoverMedias) ffmpegVideoToPoster(video string, output string) error {
|
func (d *DiscoverMedias) ffmpegVideoToPoster(video, output string) error {
|
||||||
args := []string{
|
args := []string{
|
||||||
"-y", // 添加 -y 参数强制覆盖
|
"-y", // 添加 -y 参数强制覆盖
|
||||||
"-i", video,
|
"-i", video,
|
||||||
|
|||||||
@@ -21,6 +21,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
userSvc *users.Service,
|
userSvc *users.Service,
|
||||||
) (*Create, error) {
|
) (*Create, error) {
|
||||||
@@ -35,7 +34,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
userSvc *users.Service,
|
userSvc *users.Service,
|
||||||
) (*Expire, error) {
|
) (*Expire, error) {
|
||||||
@@ -49,6 +47,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
"github.com/speps/go-hashids/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @provider
|
// @provider
|
||||||
@@ -82,7 +82,8 @@ func (c *Controller) MediaIndex(ctx fiber.Ctx) error {
|
|||||||
if claim == nil {
|
if claim == nil {
|
||||||
return errorx.RequestUnAuthorized
|
return errorx.RequestUnAuthorized
|
||||||
}
|
}
|
||||||
|
// c.Locals(consts.CtxKeyJwt, token)
|
||||||
|
token := fiber.Locals[string](ctx, consts.CtxKeyJwt)
|
||||||
model, err := c.svc.GetMediaByHash(ctx.Context(), claim.TenantID, hash)
|
model, err := c.svc.GetMediaByHash(ctx.Context(), claim.TenantID, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaByHash")
|
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaByHash")
|
||||||
@@ -95,12 +96,13 @@ func (c *Controller) MediaIndex(ctx fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist, err := c.svc.GetM3U8(ctx.Context(), claim.TenantID, mediaType, model.Hash, bought)
|
playlist, err := c.svc.GetM3U8(ctx.Context(), claim.TenantID, mediaType, model.Hash, bought, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaPlaylist")
|
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaPlaylist")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Set("Content-Type", "application/vnd.apple.mpegurl")
|
||||||
return ctx.SendString(playlist.String())
|
return ctx.SendString(playlist.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +133,7 @@ func (c *Controller) MediaSegment(ctx fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filepath := c.svc.GetSegmentPath(ctx.Context(), mediaType, model.TenantID, model.Hash, segments[0])
|
filepath := c.svc.GetSegmentPath(ctx.Context(), mediaType, model.TenantID, model.Hash, segments[0])
|
||||||
|
ctx.Set("Content-Type", "video/mp2t")
|
||||||
return ctx.SendFile(filepath)
|
return ctx.SendFile(filepath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"git.ipao.vip/rogeecn/atom/container"
|
"git.ipao.vip/rogeecn/atom/container"
|
||||||
"git.ipao.vip/rogeecn/atom/contracts"
|
"git.ipao.vip/rogeecn/atom/contracts"
|
||||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
"git.ipao.vip/rogeecn/atom/utils/opt"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
"github.com/speps/go-hashids/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Provide(opts ...opt.Option) error {
|
func Provide(opts ...opt.Option) error {
|
||||||
@@ -24,7 +24,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
controller *Controller,
|
controller *Controller,
|
||||||
) (contracts.HttpRoute, error) {
|
) (contracts.HttpRoute, error) {
|
||||||
@@ -38,7 +37,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}, atom.GroupRoutes); err != nil {
|
}, atom.GroupRoutes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
db *sql.DB,
|
db *sql.DB,
|
||||||
hashIds *hashids.HashID,
|
hashIds *hashids.HashID,
|
||||||
@@ -56,6 +54,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"backend/providers/storage"
|
"backend/providers/storage"
|
||||||
|
|
||||||
. "github.com/go-jet/jet/v2/postgres"
|
. "github.com/go-jet/jet/v2/postgres"
|
||||||
|
"github.com/go-jet/jet/v2/qrm"
|
||||||
"github.com/grafov/m3u8"
|
"github.com/grafov/m3u8"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
@@ -163,7 +164,7 @@ func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *Li
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserBoughtMedias
|
// GetUserBoughtMedias
|
||||||
func (svc *Service) GetUserBoughtMedias(ctx context.Context, tenant int64, userID int64) ([]int64, error) {
|
func (svc *Service) GetUserBoughtMedias(ctx context.Context, tenant, userID int64) ([]int64, error) {
|
||||||
log := svc.log.WithField("method", "GetUserBoughtMedias")
|
log := svc.log.WithField("method", "GetUserBoughtMedias")
|
||||||
|
|
||||||
tbl := table.UserMedias
|
tbl := table.UserMedias
|
||||||
@@ -229,11 +230,21 @@ func (svc *Service) Upsert(ctx context.Context, tenantId int64, item media_store
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbl := table.Medias
|
tbl := table.Medias
|
||||||
stmt := tbl.
|
// if hash exists then update
|
||||||
INSERT(tbl.TenantID, tbl.Hash, tbl.Title, tbl.Price, tbl.Duration, tbl.Resources, tbl.Publish).
|
stmt := tbl.SELECT(tbl.ID.AS("id")).WHERE(tbl.Hash.EQ(String(item.Hash)))
|
||||||
VALUES(Int(tenantId), String(item.Hash), String(item.Name), Int(item.Price()), Int(item.Duration), Json(resources.MustValue()), Bool(true)).
|
log.Debug(stmt.DebugSql())
|
||||||
ON_CONFLICT(tbl.Hash).
|
|
||||||
DO_UPDATE(
|
var m struct {
|
||||||
|
ID int64
|
||||||
|
}
|
||||||
|
if err := stmt.QueryContext(ctx, svc.db, &m); err != nil && !errors.Is(err, qrm.ErrNoRows) {
|
||||||
|
return errors.Wrapf(err, "query media by hash %s", item.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.ID > 0 {
|
||||||
|
// update media
|
||||||
|
stmt2 := tbl.
|
||||||
|
UPDATE().
|
||||||
SET(
|
SET(
|
||||||
tbl.Title.SET(String(item.Name)),
|
tbl.Title.SET(String(item.Name)),
|
||||||
tbl.Price.SET(Int(item.Price())),
|
tbl.Price.SET(Int(item.Price())),
|
||||||
@@ -241,19 +252,34 @@ func (svc *Service) Upsert(ctx context.Context, tenantId int64, item media_store
|
|||||||
tbl.Duration.SET(Int(item.Duration)),
|
tbl.Duration.SET(Int(item.Duration)),
|
||||||
tbl.Publish.SET(Bool(true)),
|
tbl.Publish.SET(Bool(true)),
|
||||||
tbl.UpdatedAt.SET(TimestampT(time.Now())),
|
tbl.UpdatedAt.SET(TimestampT(time.Now())),
|
||||||
),
|
).
|
||||||
)
|
WHERE(tbl.ID.EQ(Int(m.ID)))
|
||||||
log.Debug(stmt.DebugSql())
|
log.Debug(stmt2.DebugSql())
|
||||||
|
|
||||||
if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
|
if _, err := stmt2.ExecContext(ctx, svc.db); err != nil {
|
||||||
return errors.Wrapf(err, "upsert media: %s %s", item.Hash, item.Name)
|
return errors.Wrapf(err, "update media: %s %s", item.Hash, item.Name)
|
||||||
|
}
|
||||||
|
svc.log.Infof("update media: %d %s %s", m.ID, item.Hash, item.Name)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stmt3 := tbl.
|
||||||
|
INSERT(tbl.TenantID, tbl.Hash, tbl.Title, tbl.Price, tbl.Duration, tbl.Resources, tbl.Publish).
|
||||||
|
VALUES(Int(tenantId), String(item.Hash), String(item.Name), Int(item.Price()), Int(item.Duration), Json(resources.MustValue()), Bool(true)).
|
||||||
|
ON_CONFLICT(tbl.Hash).
|
||||||
|
DO_NOTHING()
|
||||||
|
log.Debug(stmt3.DebugSql())
|
||||||
|
|
||||||
|
if _, err := stmt3.ExecContext(ctx, svc.db); err != nil {
|
||||||
|
return errors.Wrapf(err, "insert into media: %s %s", item.Hash, item.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
svc.log.Infof("insert media: %s %s", item.Hash, item.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get video m3u8
|
// get video m3u8
|
||||||
func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaType, hash string, bought bool) (m3u8.Playlist, error) {
|
func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaType, hash string, bought bool, token string) (m3u8.Playlist, error) {
|
||||||
log := svc.log.WithField("method", "GetM3U8")
|
log := svc.log.WithField("method", "GetM3U8")
|
||||||
indexPath := filepath.Join(svc.storageConfig.Path, fmt.Sprintf("%d", tenantId), hash, types.String(), "index.m3u8")
|
indexPath := filepath.Join(svc.storageConfig.Path, fmt.Sprintf("%d", tenantId), hash, types.String(), "index.m3u8")
|
||||||
log.Infof("m3u8 path: %s", indexPath)
|
log.Infof("m3u8 path: %s", indexPath)
|
||||||
@@ -309,6 +335,9 @@ func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaT
|
|||||||
return nil, errors.Wrap(err, "encode hash id")
|
return nil, errors.Wrap(err, "encode hash id")
|
||||||
}
|
}
|
||||||
seg.URI = fmt.Sprintf("%s/%s.%s", types, hashID, ext)
|
seg.URI = fmt.Sprintf("%s/%s.%s", types, hashID, ext)
|
||||||
|
if token != "" {
|
||||||
|
seg.URI += fmt.Sprintf("?token=%s", token)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return media, nil
|
return media, nil
|
||||||
|
|||||||
@@ -45,15 +45,15 @@ func Test_DiscoverMedias(t *testing.T) {
|
|||||||
func (t *ServiceTestSuite) Test_getM3U8() {
|
func (t *ServiceTestSuite) Test_getM3U8() {
|
||||||
FocusConvey("Test_ffmpegVideoToM3U8", t.T(), func() {
|
FocusConvey("Test_ffmpegVideoToM3U8", t.T(), func() {
|
||||||
Convey("Bought", func() {
|
Convey("Bought", func() {
|
||||||
hash := "f464a6641a60e2722e4042db8fad2813"
|
hash := "907f1c8fd92704233600ae54a1d75092"
|
||||||
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, true)
|
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, true, "hello")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
t.T().Logf("%+v", media)
|
t.T().Logf("%+v", media)
|
||||||
})
|
})
|
||||||
|
|
||||||
FocusConvey("Not Bought", func() {
|
FocusConvey("Not Bought", func() {
|
||||||
hash := "f464a6641a60e2722e4042db8fad2813"
|
hash := "907f1c8fd92704233600ae54a1d75092"
|
||||||
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, false)
|
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, false, "hello")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
t.T().Logf("%+v", media)
|
t.T().Logf("%+v", media)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"backend/pkg/consts"
|
"backend/pkg/consts"
|
||||||
"backend/pkg/errorx"
|
"backend/pkg/errorx"
|
||||||
|
|
||||||
@@ -11,13 +13,22 @@ import (
|
|||||||
func (f *Middlewares) ParseJWT(c fiber.Ctx) error {
|
func (f *Middlewares) ParseJWT(c fiber.Ctx) error {
|
||||||
tokens := c.GetReqHeaders()["Authorization"]
|
tokens := c.GetReqHeaders()["Authorization"]
|
||||||
if len(tokens) == 0 {
|
if len(tokens) == 0 {
|
||||||
return c.Next()
|
queryToken := c.Query("token")
|
||||||
|
tokens = []string{queryToken}
|
||||||
|
if len(tokens) == 0 {
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token := tokens[0]
|
token := tokens[0]
|
||||||
claim, err := f.jwt.Parse(token)
|
claim, err := f.jwt.Parse(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ClearCookie("token")
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "token",
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Now().Add(-1 * time.Hour),
|
||||||
|
HTTPOnly: true,
|
||||||
|
})
|
||||||
log.Errorf("failed to parse jwt from token: %s", token)
|
log.Errorf("failed to parse jwt from token: %s", token)
|
||||||
return errorx.RequestUnAuthorized
|
return errorx.RequestUnAuthorized
|
||||||
}
|
}
|
||||||
@@ -26,14 +37,24 @@ func (f *Middlewares) ParseJWT(c fiber.Ctx) error {
|
|||||||
_, err = f.userSvc.GetByOpenID(c.Context(), claim.OpenID)
|
_, err = f.userSvc.GetByOpenID(c.Context(), claim.OpenID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get user by open id(%s) from token: %s", claim.OpenID, token)
|
log.Errorf("failed to get user by open id(%s) from token: %s", claim.OpenID, token)
|
||||||
c.ClearCookie("token")
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "token",
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Now().Add(-1 * time.Hour),
|
||||||
|
HTTPOnly: true,
|
||||||
|
})
|
||||||
return errorx.RequestUnAuthorized
|
return errorx.RequestUnAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = f.userSvc.GetTenantBySlug(c.Context(), claim.Tenant)
|
_, err = f.userSvc.GetTenantBySlug(c.Context(), claim.Tenant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get tenant(%s) by from token: %s", claim.Tenant, token)
|
log.Errorf("failed to get tenant(%s) by from token: %s", claim.Tenant, token)
|
||||||
c.ClearCookie("token")
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "token",
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Now().Add(-1 * time.Hour),
|
||||||
|
HTTPOnly: true,
|
||||||
|
})
|
||||||
return errorx.RequestUnAuthorized
|
return errorx.RequestUnAuthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ func (f *Middlewares) WeChatAuth(c fiber.Ctx) error {
|
|||||||
if _, err := f.jwt.Parse(jwtToken); err != nil {
|
if _, err := f.jwt.Parse(jwtToken); err != nil {
|
||||||
log.WithError(err).Error("failed to parse jwt token")
|
log.WithError(err).Error("failed to parse jwt token")
|
||||||
|
|
||||||
c.ClearCookie("token")
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "token",
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Now().Add(-1 * time.Hour),
|
||||||
|
HTTPOnly: true,
|
||||||
|
})
|
||||||
return c.Redirect().To(c.Path())
|
return c.Redirect().To(c.Path())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
"github.com/speps/go-hashids/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @provider
|
// @provider
|
||||||
@@ -87,7 +87,7 @@ func (c *Controller) GetChargeCodes(ctx fiber.Ctx) error {
|
|||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
amount := []int64{1, 5, 10, 20, 50, 100}
|
amount := []int64{1, 2, 5, 10, 20, 50, 100, 200, 300, 500, 1000, 2000}
|
||||||
codes := []generateCode{}
|
codes := []generateCode{}
|
||||||
for _, a := range amount {
|
for _, a := range amount {
|
||||||
code, err := c.svc.GenerateChargeCode(ctx.Context(), claim.TenantID, a*100)
|
code, err := c.svc.GenerateChargeCode(ctx.Context(), claim.TenantID, a*100)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"git.ipao.vip/rogeecn/atom/container"
|
"git.ipao.vip/rogeecn/atom/container"
|
||||||
"git.ipao.vip/rogeecn/atom/contracts"
|
"git.ipao.vip/rogeecn/atom/contracts"
|
||||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
"git.ipao.vip/rogeecn/atom/utils/opt"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
"github.com/speps/go-hashids/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Provide(opts ...opt.Option) error {
|
func Provide(opts ...opt.Option) error {
|
||||||
@@ -23,7 +23,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
controller *Controller,
|
controller *Controller,
|
||||||
) (contracts.HttpRoute, error) {
|
) (contracts.HttpRoute, error) {
|
||||||
@@ -37,7 +36,6 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}, atom.GroupRoutes); err != nil {
|
}, atom.GroupRoutes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
db *sql.DB,
|
db *sql.DB,
|
||||||
hashIds *hashids.HashID,
|
hashIds *hashids.HashID,
|
||||||
@@ -53,6 +51,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"backend/modules/users"
|
"backend/modules/users"
|
||||||
"backend/pkg/pg"
|
"backend/pkg/pg"
|
||||||
@@ -78,6 +79,7 @@ func (c *Controller) Render(ctx fiber.Ctx) error {
|
|||||||
ctx.Cookie(&fiber.Cookie{
|
ctx.Cookie(&fiber.Cookie{
|
||||||
Name: "token",
|
Name: "token",
|
||||||
Value: jwtToken,
|
Value: jwtToken,
|
||||||
|
Expires: time.Now().Add(6 * time.Hour),
|
||||||
HTTPOnly: true,
|
HTTPOnly: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,5 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}, atom.GroupInitial); err != nil {
|
}, atom.GroupInitial); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (c *Controller) Prepare() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) store() {
|
func (c *Controller) store() {
|
||||||
ticker := time.NewTicker(time.Minute * 5)
|
ticker := time.NewTicker(time.Minute * 60)
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
c.log.WithField("action", "store").Info("start to run store")
|
c.log.WithField("action", "store").Info("start to run store")
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.ipao.vip/rogeecn/atom/container"
|
|
||||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
func DefaultProvider() container.ProviderContainer {
|
|
||||||
return container.ProviderContainer{
|
|
||||||
Provider: Provide,
|
|
||||||
Options: []opt.Option{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Generator struct {
|
|
||||||
generator uuid.Generator
|
|
||||||
}
|
|
||||||
|
|
||||||
func Provide(opts ...opt.Option) error {
|
|
||||||
o := opt.New(opts...)
|
|
||||||
return container.Container.Provide(func() (*Generator, error) {
|
|
||||||
return &Generator{
|
|
||||||
generator: uuid.DefaultGenerator,
|
|
||||||
}, nil
|
|
||||||
}, o.DiOptions()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Generator) MustGenerate() string {
|
|
||||||
uuid, _ := u.Generate()
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Generator) Generate() (string, error) {
|
|
||||||
uuid, err := u.generator.NewV4()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return uuid.String(), err
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
exec 1>>/var/log/cron.backupdb.log 2>&1
|
exec 1>>/var/log/cron.backupdb.log 2>&1
|
||||||
|
|
||||||
# Add timestamp to log entry
|
# Add timestamp to log entry
|
||||||
|
start_time=$(date "+%Y-%m-%d %H:%M:%S")
|
||||||
echo "=== Backup started at $(date '+%Y-%m-%d %H:%M:%S') ==="
|
echo "=== Backup started at $(date '+%Y-%m-%d %H:%M:%S') ==="
|
||||||
|
|
||||||
# Set variables
|
# Set variables
|
||||||
@@ -54,3 +55,12 @@ rclone sync --update /opt/services/postgres/data/backups/ alioss:/rogee-backups/
|
|||||||
|
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup completed: postgres_backup_${TIMESTAMP}.zip"
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup completed: postgres_backup_${TIMESTAMP}.zip"
|
||||||
echo "=== Backup finished at $(date '+%Y-%m-%d %H:%M:%S') ==="
|
echo "=== Backup finished at $(date '+%Y-%m-%d %H:%M:%S') ==="
|
||||||
|
end_time=$(date "+%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
/usr/bin/curl -X POST "https://gotify.jdwan.com/message?token=AknNrK_M.ZGqDz5" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"message\": \"Backup completed from $start_time to $end_time\",
|
||||||
|
\"title\": \"Backup Complete\",
|
||||||
|
\"priority\": 5
|
||||||
|
}"
|
||||||
|
|||||||
13
cron.sh
13
cron.sh
@@ -17,8 +17,17 @@ fi
|
|||||||
start_time=$(date "+%Y-%m-%d %H:%M:%S")
|
start_time=$(date "+%Y-%m-%d %H:%M:%S")
|
||||||
echo "Start sync at $start_time" >>"$LOG_FILE"
|
echo "Start sync at $start_time" >>"$LOG_FILE"
|
||||||
|
|
||||||
qvyun --config /usr/local/etc/qvyun.toml tasks discover --from /mnt/ypl/publish/ --to /mnt/ypl/publish/processed/1 2>&1 >>"$LOG_FILE"
|
/usr/local/bin/qvyun --config /usr/local/etc/qvyun.toml tasks discover --from /mnt/ypl/publish/ --to /mnt/ypl/publish/processed/1 2>&1 >>"$LOG_FILE"
|
||||||
rsync -avh --progress /mnt/ypl/publish/processed/ server.ali.bj.01:/data 2>&1 >>"$LOG_FILE"
|
/usr/bin/rsync -avh --progress /mnt/ypl/publish/processed/ server.ali.bj.01:/data 2>&1 >>"$LOG_FILE"
|
||||||
|
|
||||||
end_time=$(date "+%Y-%m-%d %H:%M:%S")
|
end_time=$(date "+%Y-%m-%d %H:%M:%S")
|
||||||
echo "End sync at $end_time" >>"$LOG_FILE"
|
echo "End sync at $end_time" >>"$LOG_FILE"
|
||||||
|
|
||||||
|
# Send notification via Gotify
|
||||||
|
/usr/bin/curl -X POST "https://gotify.jdwan.com/message?token=AknNrK_M.ZGqDz5" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"message\": \"Sync completed from $start_time to $end_time\",
|
||||||
|
\"title\": \"QVYun Sync Status\",
|
||||||
|
\"priority\": 5
|
||||||
|
}"
|
||||||
|
|||||||
35
frontend/package-lock.json
generated
35
frontend/package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
"dplayer": "^1.27.1",
|
||||||
"hls.js": "^0.8.5",
|
"hls.js": "^0.8.5",
|
||||||
"pinia": "^2.2.6",
|
"pinia": "^2.2.6",
|
||||||
"vant": "^4.9.9",
|
"vant": "^4.9.9",
|
||||||
@@ -871,6 +872,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/balloon-css": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://npm.hub.ipao.vip/repository/npm/balloon-css/-/balloon-css-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -1108,6 +1115,28 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dplayer": {
|
||||||
|
"version": "1.27.1",
|
||||||
|
"resolved": "https://npm.hub.ipao.vip/repository/npm/dplayer/-/dplayer-1.27.1.tgz",
|
||||||
|
"integrity": "sha512-2laBMXs5V1B9zPwJ7eAIw/OBo+Xjvy03i4GHTk3Cg+IWbrq8rKMFO0fFr6ClAYotYOCcFGOvaJDkOZcgKllsCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "1.2.3",
|
||||||
|
"balloon-css": "^1.0.3",
|
||||||
|
"promise-polyfill": "8.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dplayer/node_modules/axios": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://npm.hub.ipao.vip/repository/npm/axios/-/axios-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.66",
|
"version": "1.5.66",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -1997,6 +2026,12 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/promise-polyfill": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://npm.hub.ipao.vip/repository/npm/promise-polyfill/-/promise-polyfill-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://npm.hub.ipao.vip/repository/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://npm.hub.ipao.vip/repository/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite --host 0.0.0.0",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
"dplayer": "^1.27.1",
|
||||||
"hls.js": "^0.8.5",
|
"hls.js": "^0.8.5",
|
||||||
"pinia": "^2.2.6",
|
"pinia": "^2.2.6",
|
||||||
"vant": "^4.9.9",
|
"vant": "^4.9.9",
|
||||||
@@ -25,4 +26,4 @@
|
|||||||
"vite": "^5.4.10",
|
"vite": "^5.4.10",
|
||||||
"vite-plugin-vue-devtools": "^7.5.4"
|
"vite-plugin-vue-devtools": "^7.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<van-nav-bar :title="item.title" left-text="返回" left-arrow @click-left="onClickLeft" />
|
<van-nav-bar :title="item.title" left-text="返回" left-arrow @click-left="onClickLeft" />
|
||||||
<video controls id="video" :poster="item.poster" />
|
<!-- <video controls id="video" :poster="item.poster" /> -->
|
||||||
|
<div id="dplayer" :style="{ backgroundImage: `url(${item.poster})` }"></div>
|
||||||
|
|
||||||
<template v-if="false === item.bought">
|
<template v-if="false === item.bought">
|
||||||
<van-notice-bar left-icon="volume-o" text="未购买的视频、音频默认播放时长为1分钟左右。" />
|
<van-notice-bar left-icon="volume-o" text="未购买的视频、音频默认播放时长为1分钟左右。" />
|
||||||
@@ -26,32 +27,107 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
|
import DPlayer from "dplayer";
|
||||||
import Hls from "hls.js";
|
import Hls from "hls.js";
|
||||||
import { onBeforeUnmount, onMounted } from "vue";
|
import { onBeforeUnmount, onMounted } from "vue";
|
||||||
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const pageLoading = ref(true)
|
const pageLoading = ref(true)
|
||||||
|
|
||||||
|
let player = null;
|
||||||
|
|
||||||
const item = ref({
|
const item = ref({
|
||||||
title: "加载中...",
|
title: "加载中...",
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
const player = document.getElementById("video");
|
player?.destroy();
|
||||||
if (player) {
|
|
||||||
player.pause();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadMedia(route.params.hash);
|
loadMedia(route.params.hash);
|
||||||
const player = document.getElementById("video");
|
|
||||||
player.addEventListener("ended", function () {
|
|
||||||
console.log("Video ended");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onClickLeft = () => {
|
||||||
|
if (route.meta.from?.name) {
|
||||||
|
router.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.replace({
|
||||||
|
name: "tab.home",
|
||||||
|
params: {
|
||||||
|
tenant: route.params.tenant,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadMedia = (hash) => {
|
||||||
|
request
|
||||||
|
.get(`/medias/${hash}`)
|
||||||
|
.then((res) => {
|
||||||
|
console.log(res);
|
||||||
|
item.value = res.data;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("ERROR", err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
pageLoading.value = false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const play = (hash, type) => {
|
||||||
|
let source = `/v1/medias/${hash}/${type}`;
|
||||||
|
if (navigator.userAgent.indexOf("iPhone") > -1) {
|
||||||
|
source = `/v1/medias/${hash}/${type}?token=${__GA}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
player = new DPlayer({
|
||||||
|
container: document.getElementById('dplayer'),
|
||||||
|
playbackSpeed: [0.5, 0.75, 1, 1.25, 1.5, 2],
|
||||||
|
video: {
|
||||||
|
url: source,
|
||||||
|
pic: item.value.poster,
|
||||||
|
type: 'customHls',
|
||||||
|
customType: {
|
||||||
|
customHls: function (video, player) {
|
||||||
|
const hls = new Hls({
|
||||||
|
xhrSetup: function (xhr, url) {
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
xhr.setRequestHeader("Authorization", "Bearer " + __GA);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
hls.loadSource(source);
|
||||||
|
hls.attachMedia(video);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
player.play();
|
||||||
|
|
||||||
|
// if (Hls.isSupported()) {
|
||||||
|
// var hls = new Hls({
|
||||||
|
// xhrSetup: function (xhr, url) {
|
||||||
|
// xhr.withCredentials = true;
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// hls.loadSource(source);
|
||||||
|
// hls.attachMedia(player);
|
||||||
|
// hls.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||||
|
// player.play();
|
||||||
|
// });
|
||||||
|
// } else if (player.canPlayType("application/vnd.apple.mpegurl")) {
|
||||||
|
// player.src = source;
|
||||||
|
// player.addEventListener("loadedmetadata", function () {
|
||||||
|
// player.play();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const buy = () => {
|
const buy = () => {
|
||||||
// get use balance
|
// get use balance
|
||||||
request
|
request
|
||||||
@@ -99,55 +175,6 @@ const buy = () => {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickLeft = () => {
|
|
||||||
if (route.meta.from?.name) {
|
|
||||||
router.back();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
router.replace({
|
|
||||||
name: "tab.home",
|
|
||||||
params: {
|
|
||||||
tenant: route.params.tenant,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadMedia = (hash) => {
|
|
||||||
request
|
|
||||||
.get(`/medias/${hash}`)
|
|
||||||
.then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
item.value = res.data;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("ERROR", err);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
pageLoading.value = false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const play = (hash, type) => {
|
|
||||||
const player = document.getElementById("video");
|
|
||||||
const source = `/v1/medias/${hash}/${type}`;
|
|
||||||
if (Hls.isSupported()) {
|
|
||||||
var hls = new Hls({
|
|
||||||
xhrSetup: function (xhr, url) {
|
|
||||||
xhr.setRequestHeader("Authorization", "Bearer " + __GA);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
hls.loadSource(source);
|
|
||||||
hls.attachMedia(player);
|
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, function () {
|
|
||||||
player.play();
|
|
||||||
});
|
|
||||||
} else if (player.canPlayType("application/vnd.apple.mpegurl")) {
|
|
||||||
player.src = source;
|
|
||||||
player.addEventListener("loadedmetadata", function () {
|
|
||||||
player.play();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -155,10 +182,13 @@ const play = (hash, type) => {
|
|||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#video {
|
#video,
|
||||||
|
#dplayer {
|
||||||
background-color: #cccccc;
|
background-color: #cccccc;
|
||||||
aspect-ratio: 4 / 3;
|
aspect-ratio: 16 / 9;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
object-fit: fill;
|
object-fit: fill;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { defineConfig } from "vite";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'^/static': {
|
'^/poster': {
|
||||||
target: 'http://localhost:9600',
|
target: 'http://localhost:9600',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
|||||||
@@ -13,8 +13,9 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
|
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"dplayer",
|
||||||
"qvyun"
|
"qvyun"
|
||||||
],
|
],
|
||||||
"git.ignoreLimitWarning": true
|
"git.ignoreLimitWarning": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user