freindship: add frontend implement

pull/192/head
Michael Li 2 years ago
parent 09949295e8
commit e34af9a202

@ -13,6 +13,7 @@ import (
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/rocboss/paopao-ce/pkg/types"
"github.com/sirupsen/logrus"
)
@ -28,6 +29,7 @@ type postsEntry struct {
type bigCacheIndexServant struct {
ips core.IndexPostsService
ams core.AuthorizationManageService
indexActionCh chan *core.IndexAction
cachePostsCh chan *postsEntry
@ -133,7 +135,7 @@ func (s *bigCacheIndexServant) handleIndexAction(action *core.IndexAction) {
switch act {
case core.IdxActCreatePost, core.IdxActDeletePost:
if post.Visibility == model.PostVisitPrivate {
s.deleteCacheByUserId(post.UserID)
s.deleteCacheByUserId(post.UserID, true)
return
}
}
@ -141,29 +143,34 @@ func (s *bigCacheIndexServant) handleIndexAction(action *core.IndexAction) {
// 如果在s.preventDuration时间内就清除所有缓存否则只清除自个儿的缓存
// TODO: 需要优化只清除受影响的缓存,后续完善
if time.Since(s.lastCacheResetTime) > s.preventDuration {
s.cache.Reset()
s.lastCacheResetTime = time.Now()
logrus.Debugf("bigCacheIndexServant.handleIndexAction reset cache by %s", action.Act)
s.deleteCacheByUserId(post.UserID, false)
} else {
s.deleteCacheByUserId(post.UserID)
s.deleteCacheByUserId(post.UserID, true)
}
}
func (s *bigCacheIndexServant) deleteCacheByUserId(id int64) {
func (s *bigCacheIndexServant) deleteCacheByUserId(id int64, oneself bool) {
var keys []string
userId := strconv.FormatInt(id, 10)
friendSet := core.FriendSet{}
if !oneself {
friendSet = s.ams.MyFriendSet(id)
}
friendSet[userId] = types.Empty{}
// 获取需要删除缓存的key目前是仅删除自个儿的缓存
for it := s.cache.Iterator(); it.SetNext(); {
entry, err := it.Value()
if err != nil {
logrus.Debugf("bigCacheIndexServant.deleteCacheByUserId usrId: %s err:%s", userId, err)
logrus.Debugf("bigCacheIndexServant.deleteCacheByUserId userId: %s err:%s", userId, err)
return
}
key := entry.Key()
keyParts := strings.Split(key, ":")
if len(keyParts) > 2 && keyParts[0] == "index" && keyParts[1] == userId {
keys = append(keys, key)
if len(keyParts) > 2 && keyParts[0] == "index" {
if _, ok := friendSet[keyParts[1]]; ok {
keys = append(keys, key)
}
}
}
@ -172,7 +179,7 @@ func (s *bigCacheIndexServant) deleteCacheByUserId(id int64) {
s.cache.Delete(k)
}
s.lastCacheResetTime = time.Now()
logrus.Debugf("bigCacheIndexServant.deleteCacheByUserId userId:%d", id)
logrus.Debugf("bigCacheIndexServant.deleteCacheByUserId userId:%s oneself:%t keys:%d", userId, oneself, len(keys))
}
func (s *bigCacheIndexServant) Name() string {

@ -9,7 +9,7 @@ import (
"github.com/sirupsen/logrus"
)
func NewBigCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndexService, core.VersionInfo) {
func NewBigCacheIndexService(ips core.IndexPostsService, ams core.AuthorizationManageService) (core.CacheIndexService, core.VersionInfo) {
s := conf.BigCacheIndexSetting
config := bigcache.DefaultConfig(s.ExpireInSecond)
@ -23,7 +23,8 @@ func NewBigCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndex
}
cacheIndex := &bigCacheIndexServant{
ips: indexPosts,
ips: ips,
ams: ams,
cache: cache,
preventDuration: 10 * time.Second,
}

@ -47,7 +47,8 @@ func NewDataService() (core.DataService, core.VersionInfo) {
i = newSimpleIndexPostsService(db)
c, v = cache.NewSimpleCacheIndexService(i)
} else if conf.CfgIf("BigCacheIndex") {
c, v = cache.NewBigCacheIndexService(i)
a := newAuthorizationManageService(db)
c, v = cache.NewBigCacheIndexService(i, a)
} else {
c, v = cache.NewNoneCacheIndexService(i)
}
@ -72,9 +73,7 @@ func NewDataService() (core.DataService, core.VersionInfo) {
}
func NewAuthorizationManageService() core.AuthorizationManageService {
return &authorizationManageServant{
db: conf.MustGormDB(),
}
return newAuthorizationManageService(conf.MustGormDB())
}
func (s *dataServant) Name() string {

@ -88,8 +88,3 @@ func (s *userManageServant) CreateUser(user *model.User) (*model.User, error) {
func (s *userManageServant) UpdateUser(user *model.User) error {
return user.Update(s.db)
}
func (s *userManageServant) IsFriend(userId int64, friendId int64) bool {
// just true now
return true
}

@ -60,9 +60,6 @@ func NewRouter() *gin.Engine {
// 获取话题列表
noAuthApi.GET("/tags", api.GetPostTags)
// 获取用户基本信息
noAuthApi.GET("/user/profile", api.GetUserProfile)
}
// 宽松鉴权路由组
@ -73,6 +70,9 @@ func NewRouter() *gin.Engine {
// 获取用户动态列表
looseApi.GET("/user/posts", api.GetUserPosts)
// 获取用户基本信息
looseApi.GET("/user/profile", api.GetUserProfile)
}
// 鉴权路由组
@ -248,7 +248,6 @@ func routeRelationship(authApi gin.IRoutes) {
// TODO: 后期提供一种无关系模式(既不是好友模式也不是关注者模式)作为默认的关系模式
routeFriendship(authApi)
}
}
// routeFriendship register Friendship feature releated routes

@ -1,3 +1,4 @@
components.d.ts
*Dockerfile*
node_modules
src-tauri/target

@ -1,19 +1,26 @@
VITE_HOST="https://api.paopao.info"
VITE_HOST=""
# 模块开启
VITE_ENABLE_WALLET=true
VITE_ENABLE_ANOUNCEMENT=false
VITE_ENABLE_WALLET=false
# 功能开启
VITE_ALLOW_TWEET_ATTACHMENT=true
VITE_ALLOW_TWEET_ATTACHMENT_PRICE=true
VITE_ALLOW_TWEET_VIDEO=true
VITE_ALLOW_TWEET_ATTACHMENT=false
VITE_ALLOW_TWEET_ATTACHMENT_PRICE=false
VITE_ALLOW_TWEET_VIDEO=false
VITE_ALLOW_TWEET_VISIBILITY=true
VITE_ALLOW_ACTIVATION=false
VITE_ALLOW_PHONE_BIND=true
# 局部参数
VITE_DEFAULT_TWEET_VISIBILITY=public
VITE_DEFAULT_TWEET_VISIBILITY=friend
VITE_COPYRIGHT_TOP="2022 paopao.info"
VITE_COPYRIGHT_LEFT="Roc's Me"
VITE_COPYRIGHT_LEFT_LINK=""
VITE_COPYRIGHT_RIGHT="泡泡(PaoPao)开源社区"
VITE_COPYRIGHT_RIGHT_LINK="https://paopao.info"
# 图片推文404参数
# 图片推文参数
VITE_DEFAULT_TWEET_IMAGE_404="https://paopao-assets.oss-cn-shanghai.aliyuncs.com/public/404.png"
# AliOSS 图片thumbnail参数
VITE_TWEET_IMAGE_THUMBNAIL="?x-oss-process=image/resize,m_fill,w_300,h_300,limit_0/auto-orient,1/format,png"

3
web/.gitignore vendored

@ -11,7 +11,6 @@ node_modules
dist
dist-ssr
*.local
.env
# Editor directories and files
.vscode/*
@ -25,4 +24,4 @@ dist-ssr
*.sw?
package-lock.json
components.d.ts
components.d.ts

@ -0,0 +1 @@
paopao-ce's web frontend.

@ -1,4 +0,0 @@
{
"version": "8",
"buildTime": "2022-06-13 17:16:22"
}

@ -1,46 +0,0 @@
import type { Plugin } from "vite"
import { resolve } from "path"
import { readFileSync, writeFileSync } from "fs"
function getFormatTime() {
let date = new Date();
let year: string | number = date.getFullYear();
let month: string | number = date.getMonth() + 1;
let day: string | number = date.getDate();
let h: string | number = date.getHours();
let m: string | number = date.getMinutes();
let s: string | number = date.getSeconds();
if (month < 10) month = "0"+month;
if (day < 10) day = "0"+day;
if (h < 10) h = "0"+h;
if (m < 10) m = "0"+m;
if (s < 10) s = "0"+s;
return [year, month, day].join("-") + " " + [h, m, s].join(":");
}
/**
*
* @returns
*/
export function changePackageVersion(): Plugin {
if (process.env.NODE_ENV === "production") {
let packagePath = resolve(__dirname, "./info.json");
let packageStr = readFileSync(packagePath, {
encoding: "utf-8"
});
let packageJson = JSON.parse(packageStr);
let version = packageJson.version;
let versionArr: (string | number)[] = version.split(".");
let lastVersionNum = +versionArr[versionArr.length - 1];
lastVersionNum++;
versionArr.splice(versionArr.length - 1, 1, lastVersionNum);
packageJson.version = versionArr.join(".");
packageJson.buildTime = getFormatTime();
writeFileSync(packagePath, JSON.stringify(packageJson, null, "\t"), {
encoding: "utf-8"
})
}
return {
name: "changePackageVersion"
}
}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.wrap404[data-v-4c5da4ba]{min-height:500px;display:flex;align-items:center;justify-content:center}

@ -0,0 +1,34 @@
import{c as j,ce as k,cf as u,b as f,l as y,m as c,bz as B,o as F,n as M,d as O,u as N,q as E,x as V,s as S,ba as K,v as g,y as q,r as D,h as s,b2 as G,cg as J,K as Q,N as U,bt as X,bu as Y,bv as Z,bs as ee,z as oe,bx as re}from"./index.f480f018.js";const ne=r=>{const{lineHeight:o,borderRadius:i,fontWeightStrong:m,baseColor:n,dividerColor:v,actionColor:z,textColor1:t,textColor2:a,closeColor:h,closeColorHover:C,closeColorPressed:b,infoColor:l,successColor:e,warningColor:p,errorColor:x,fontSize:T}=r;return Object.assign(Object.assign({},k),{fontSize:T,lineHeight:o,titleFontWeight:m,borderRadius:i,border:`1px solid ${v}`,color:z,titleTextColor:t,iconColor:a,contentTextColor:a,closeColor:h,closeColorHover:C,closeColorPressed:b,borderInfo:`1px solid ${u(n,f(l,{alpha:.25}))}`,colorInfo:u(n,f(l,{alpha:.08})),titleTextColorInfo:t,iconColorInfo:l,contentTextColorInfo:a,closeColorInfo:h,closeColorHoverInfo:C,closeColorPressedInfo:b,borderSuccess:`1px solid ${u(n,f(e,{alpha:.25}))}`,colorSuccess:u(n,f(e,{alpha:.08})),titleTextColorSuccess:t,iconColorSuccess:e,contentTextColorSuccess:a,closeColorSuccess:h,closeColorHoverSuccess:C,closeColorPressedSuccess:b,borderWarning:`1px solid ${u(n,f(p,{alpha:.33}))}`,colorWarning:u(n,f(p,{alpha:.08})),titleTextColorWarning:t,iconColorWarning:p,contentTextColorWarning:a,closeColorWarning:h,closeColorHoverWarning:C,closeColorPressedWarning:b,borderError:`1px solid ${u(n,f(x,{alpha:.25}))}`,colorError:u(n,f(x,{alpha:.08})),titleTextColorError:t,iconColorError:x,contentTextColorError:a,closeColorError:h,closeColorHoverError:C,closeColorPressedError:b})},te={name:"Alert",common:j,self:ne};var le=te,se=y("alert",`
line-height: var(--n-line-height);
border-radius: var(--n-border-radius);
position: relative;
transition: background-color .3s var(--n-bezier);
background-color: var(--n-color);
text-align: start;
`,[c("icon",{color:"var(--n-icon-color)"}),y("alert-body",{border:"var(--n-border)",padding:"var(--n-padding)"},[c("title",{color:"var(--n-title-text-color)"}),c("content",{color:"var(--n-content-text-color)"})]),B({originalTransition:"transform .3s var(--n-bezier)",enterToProps:{transform:"scale(1)"},leaveToProps:{transform:"scale(0.9)"}}),c("icon",`
position: absolute;
left: 0;
top: 0;
align-items: center;
justify-content: center;
display: flex;
width: var(--n-icon-size);
height: var(--n-icon-size);
font-size: var(--n-icon-size);
margin: var(--n-icon-margin);
`),c("close",`
transition: color .3s var(--n-bezier);
position: absolute;
right: 0;
top: 0;
margin: var(--n-close-margin);
font-size: var(--n-close-size);
`),F("show-icon",[y("alert-body",{paddingLeft:"calc(var(--n-icon-margin-left) + var(--n-icon-size) + var(--n-icon-margin-right))"})]),y("alert-body",`
border-radius: var(--n-border-radius);
transition: border-color .3s var(--n-bezier);
`,[c("title",`
transition: color .3s var(--n-bezier);
font-size: 16px;
line-height: 19px;
font-weight: var(--n-title-font-weight);
`,[M("& +",[c("content",{marginTop:"9px"})])]),c("content",{transition:"color .3s var(--n-bezier)",fontSize:"var(--n-font-size)"})]),c("icon",{transition:"color .3s var(--n-bezier)"})]);const ie=Object.assign(Object.assign({},E.props),{title:{type:String,default:void 0},showIcon:{type:Boolean,default:!0},type:{type:String,default:"default"},closable:{type:Boolean,default:!1},onClose:Function,onAfterLeave:{type:Function,default:void 0},onAfterHide:{type:Function,validator:()=>!0,default:void 0}});var ce=O({name:"Alert",inheritAttrs:!1,props:ie,setup(r){const{mergedClsPrefixRef:o,inlineThemeDisabled:i,mergedRtlRef:m}=N(r),n=E("Alert","-alert",se,le,r,o),v=V("Alert",m,o),z=S(()=>{const{common:{cubicBezierEaseInOut:l},self:e}=n.value,{fontSize:p,borderRadius:x,titleFontWeight:T,lineHeight:P,iconSize:$,iconMargin:I,iconMarginRtl:R,closeSize:_,closeMargin:A,closeMarginRtl:W,padding:w}=e,{type:d}=r,{left:H,right:L}=K(I);return{"--n-bezier":l,"--n-color":e[g("color",d)],"--n-close-color":e[g("closeColor",d)],"--n-close-color-hover":e[g("closeColorHover",d)],"--n-close-color-pressed":e[g("closeColorPressed",d)],"--n-icon-color":e[g("iconColor",d)],"--n-border":e[g("border",d)],"--n-title-text-color":e[g("titleTextColor",d)],"--n-content-text-color":e[g("contentTextColor",d)],"--n-line-height":P,"--n-border-radius":x,"--n-font-size":p,"--n-title-font-weight":T,"--n-icon-size":$,"--n-icon-margin":I,"--n-icon-margin-rtl":R,"--n-close-size":_,"--n-close-margin":A,"--n-close-margin-rtl":W,"--n-padding":w,"--n-icon-margin-left":H,"--n-icon-margin-right":L}}),t=i?q("alert",S(()=>r.type[0]),z,r):void 0,a=D(!0),h=()=>{const{onAfterLeave:l,onAfterHide:e}=r;l&&l(),e&&e()};return{rtlEnabled:v,mergedClsPrefix:o,visible:a,handleCloseClick:()=>{var l;Promise.resolve((l=r.onClose)===null||l===void 0?void 0:l.call(r)).then(e=>{e!==!1&&(a.value=!1)})},handleAfterLeave:()=>{h()},mergedTheme:n,cssVars:i?void 0:z,themeClass:t==null?void 0:t.themeClass,onRender:t==null?void 0:t.onRender}},render(){var r;return(r=this.onRender)===null||r===void 0||r.call(this),s(re,{onAfterLeave:this.handleAfterLeave},{default:()=>{const{mergedClsPrefix:o,$slots:i}=this,m={class:[`${o}-alert`,this.themeClass,this.showIcon&&`${o}-alert--show-icon`,this.rtlEnabled&&`${o}-alert--rtl`],style:this.cssVars,role:"alert"};return this.visible?s("div",Object.assign({},G(this.$attrs,m)),this.closable&&s(J,{clsPrefix:o,class:`${o}-alert__close`,onClick:this.handleCloseClick}),this.showIcon&&s("div",{class:`${o}-alert__icon`,"aria-hidden":"true"},Q(i.icon,()=>[s(U,{clsPrefix:o},{default:()=>{switch(this.type){case"success":return s(ee,null);case"info":return s(Z,null);case"warning":return s(Y,null);case"error":return s(X,null);default:return null}}})])),s("div",{class:`${o}-alert-body`},oe(i.header,n=>{const v=n||this.title;return v?s("div",{class:`${o}-alert-body__title`},v):null}),i.default&&s("div",{class:`${o}-alert-body__content`},i))):null}})}});export{ce as _};

@ -0,0 +1 @@
.balance-wrap[data-v-543914f4]{padding:16px}.balance-wrap .balance-line[data-v-543914f4]{display:flex;justify-content:space-between}.balance-wrap .balance-line .balance-opts[data-v-543914f4]{display:flex;flex-direction:column}.bill-line[data-v-543914f4]{padding:16px;display:flex;justify-content:space-between}.bill-line .income[data-v-543914f4],.bill-line .out[data-v-543914f4]{font-weight:700}.bill-line .income[data-v-543914f4]{color:#18a058}.pagination-wrap[data-v-543914f4]{padding:10px;display:flex;justify-content:center;overflow:hidden}.qrcode-wrap[data-v-543914f4]{display:flex;flex-direction:column;align-items:center;justify-content:center}.qrcode-wrap .pay-tips[data-v-543914f4]{margin-top:16px}.qrcode-wrap .pay-sub-tips[data-v-543914f4]{margin-top:4px;font-size:12px;opacity:.75;display:flex;align-items:center}.dark .income[data-v-543914f4]{color:#63e2b7}

@ -0,0 +1 @@
import{_ as N}from"./post-skeleton.39a35f5b.js";import{_ as V}from"./main-nav.9110259b.js";import{ah as z,d as A,Z as E,ai as R,r as a,a1 as S,V as n,W as t,a3 as o,a4 as c,a2 as l,a6 as m,aa as F,ab as P,a5 as q,Y as s,a9 as _,c3 as D}from"./index.f480f018.js";import{f as I}from"./formatTime.02109bf5.js";import{_ as L}from"./List.49bcdf81.js";import{_ as M}from"./Pagination.1263479e.js";import{a as O,_ as T}from"./Skeleton.57e98fe3.js";const U={key:0,class:"pagination-wrap"},W={key:0,class:"skeleton-wrap"},Y={key:1},Z={key:0,class:"empty-wrap"},$={class:"bill-line"},j=A({setup(G){const d=E(),g=R(),v=a(!1),u=a([]),r=a(+g.query.p||1),f=a(20),p=a(0),h=i=>{r.value=i};return S(()=>{}),(i,H)=>{const y=V,k=M,x=N,w=O,C=T,B=L;return n(),t("div",null,[o(y,{title:"\u516C\u544A"}),o(B,{class:"main-content-wrap",bordered:""},{footer:c(()=>[p.value>1?(n(),t("div",U,[o(k,{page:r.value,"onUpdate:page":h,"page-slot":l(d).state.collapsedRight?5:8,"page-count":p.value},null,8,["page","page-slot","page-count"])])):m("",!0)]),default:c(()=>[v.value?(n(),t("div",W,[o(x,{num:f.value},null,8,["num"])])):(n(),t("div",Y,[u.value.length===0?(n(),t("div",Z,[o(w,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):m("",!0),(n(!0),t(F,null,P(u.value,e=>(n(),q(C,{key:e.id},{default:c(()=>[s("div",$,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:D({income:e.change_amount>=0,out:e.change_amount<0})},_((e.change_amount>0?"+":"")+(e.change_amount/100).toFixed(2)),3),s("div",null,_(l(I)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});var te=z(j,[["__scopeId","data-v-543914f4"]]);export{te as default};

@ -0,0 +1 @@
import{_ as z}from"./post-item.03452002.js";import{_ as B}from"./post-skeleton.39a35f5b.js";import{_ as E}from"./main-nav.9110259b.js";import{ah as P,d as R,Z as V,ai as b,aj as F,r as n,a1 as M,V as e,W as o,a3 as a,a4 as p,cm as N,a2 as S,a6 as m,aa as $,ab as j,a5 as q}from"./index.f480f018.js";import{_ as I}from"./List.49bcdf81.js";import{_ as L}from"./Pagination.1263479e.js";import{a as T,_ as U}from"./Skeleton.57e98fe3.js";import"./content.ef1e095a.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";const W={key:0,class:"pagination-wrap"},Z={key:0,class:"skeleton-wrap"},A={key:1},D={key:0,class:"empty-wrap"},G=R({setup(H){const d=V(),g=b();F();const s=n(!1),_=n([]),l=n(+g.query.p||1),c=n(20),u=n(0),r=()=>{s.value=!0,N({page:l.value,page_size:c.value}).then(t=>{s.value=!1,_.value=t.list,u.value=Math.ceil(t.pager.total_rows/c.value),window.scrollTo(0,0)}).catch(t=>{s.value=!1})},v=t=>{l.value=t,r()};return M(()=>{r()}),(t,J)=>{const f=E,h=L,k=B,y=T,w=z,C=U,x=I;return e(),o("div",null,[a(f,{title:"\u6536\u85CF"}),a(x,{class:"main-content-wrap",bordered:""},{footer:p(()=>[u.value>1?(e(),o("div",W,[a(h,{page:l.value,"onUpdate:page":v,"page-slot":S(d).state.collapsedRight?5:8,"page-count":u.value},null,8,["page","page-slot","page-count"])])):m("",!0)]),default:p(()=>[s.value?(e(),o("div",Z,[a(k,{num:c.value},null,8,["num"])])):(e(),o("div",A,[_.value.length===0?(e(),o("div",D,[a(y,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):m("",!0),(e(!0),o($,null,j(_.value,i=>(e(),q(C,{key:i.id},{default:p(()=>[a(w,{post:i},null,8,["post"])]),_:2},1024))),128))]))]),_:1})])}}});var se=P(G,[["__scopeId","data-v-2f4c0166"]]);export{se as default};

@ -0,0 +1 @@
.pagination-wrap[data-v-2f4c0166]{padding:10px;display:flex;justify-content:center;overflow:hidden}

@ -0,0 +1 @@
import{ah as k,d as C,aj as D,V as e,W as n,Y as c,a3 as o,a9 as v,ad as E,Z as N,ai as P,r as l,a1 as R,cn as S,a4 as g,a2 as U,a6 as y,aa as q,ab as M,a5 as T}from"./index.f480f018.js";import{_ as j}from"./post-skeleton.39a35f5b.js";import{_ as F}from"./main-nav.9110259b.js";import{_ as L}from"./List.49bcdf81.js";import{_ as W}from"./Pagination.1263479e.js";import{a as Y,_ as Z}from"./Skeleton.57e98fe3.js";const A={class:"avatar"},G={class:"base-info"},H={class:"username"},J={class:"uid"},K=C({props:{contact:null},setup(s){const p=D(),m=t=>{p.push({name:"user",query:{username:t}})};return(t,a)=>{const _=E;return e(),n("div",{class:"contact-item",onClick:a[0]||(a[0]=u=>m(s.contact.username))},[c("div",A,[o(_,{size:"large",src:s.contact.avatar},null,8,["src"])]),c("div",G,[c("div",H,[c("strong",null,v(s.contact.nickname),1),c("span",null," @"+v(s.contact.username),1)]),c("div",J,"UID. "+v(s.contact.user_id),1)])])}}});var O=k(K,[["__scopeId","data-v-23bc18c8"]]);const Q={key:0,class:"pagination-wrap"},X={key:0,class:"skeleton-wrap"},ee={key:1},te={key:0,class:"empty-wrap"},ae=C({setup(s){const p=N(),m=P(),t=l(!1),a=l([]),_=l(+m.query.p||1),u=l(20),d=l(0),w=r=>{_.value=r,f()};R(()=>{f()});const f=(r=!1)=>{a.value.length===0&&(t.value=!0),S({page:_.value,page_size:u.value}).then(i=>{t.value=!1,a.value=i.list,d.value=Math.ceil(i.pager.total_rows/u.value),r&&setTimeout(()=>{window.scrollTo(0,99999)},50)}).catch(i=>{t.value=!1})};return(r,i)=>{const x=F,$=W,B=j,b=Y,z=O,I=Z,V=L;return e(),n("div",null,[o(x,{title:"\u597D\u53CB"}),o(V,{class:"main-content-wrap",bordered:""},{footer:g(()=>[d.value>1?(e(),n("div",Q,[o($,{page:_.value,"onUpdate:page":w,"page-slot":U(p).state.collapsedRight?5:8,"page-count":d.value},null,8,["page","page-slot","page-count"])])):y("",!0)]),default:g(()=>[t.value?(e(),n("div",X,[o(B,{num:u.value},null,8,["num"])])):(e(),n("div",ee,[a.value.length===0?(e(),n("div",te,[o(b,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):y("",!0),(e(!0),n(q,null,M(a.value,h=>(e(),T(I,{key:h.user_id},{default:g(()=>[o(z,{contact:h},null,8,["contact"])]),_:2},1024))),128))]))]),_:1})])}}});var ue=k(ae,[["__scopeId","data-v-e9de9e50"]]);export{ue as default};

@ -0,0 +1 @@
.contact-item[data-v-23bc18c8]{display:flex;width:100%;padding:12px 16px}.contact-item[data-v-23bc18c8]:hover{background:#f7f9f9;cursor:pointer}.contact-item .avatar[data-v-23bc18c8]{width:55px}.contact-item .base-info[data-v-23bc18c8]{position:relative;width:calc(100% - 55px)}.contact-item .base-info .username[data-v-23bc18c8]{line-height:16px;font-size:16px}.contact-item .base-info .uid[data-v-23bc18c8]{font-size:14px;line-height:14px;margin-top:10px;opacity:.75}.dark .contact-item[data-v-23bc18c8]:hover{background:#18181c}.pagination-wrap[data-v-e9de9e50]{padding:10px;display:flex;justify-content:center;overflow:hidden}

Binary file not shown.

@ -0,0 +1 @@
.compose-wrap{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .text-statistic{margin-right:8px;width:20px;height:20px;transform:rotate(180deg)}.compose-wrap .link-wrap{margin-left:42px;margin-right:42px}.compose-wrap .eye-wrap{margin-left:64px}.compose-wrap .login-wrap{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button{margin:0 4px}.attachment-list-wrap{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail{overflow:hidden}.pagination-wrap[data-v-7e0dfc66]{padding:10px;display:flex;justify-content:center;overflow:hidden}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,56 @@
import{l as t,n as r,m as o,d as a,u as d,b$ as s,h as n}from"./index.f480f018.js";var p=t("input-group",`
display: inline-flex;
width: 100%;
flex-wrap: nowrap;
vertical-align: bottom;
`,[r(">",[t("input",[r("&:not(:last-child)",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`),r("&:not(:first-child)",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
margin-left: -1px!important;
`)]),t("button",[r("&:not(:last-child)",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`,[o("state-border, border",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`)]),r("&:not(:first-child)",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`,[o("state-border, border",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`)])]),r("*",[r("&:not(:last-child)",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`,[r(">",[t("input",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`),t("base-selection",[t("base-selection-label",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`),t("base-selection-tags",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`),o("box-shadow, border, state-border",`
border-top-right-radius: 0!important;
border-bottom-right-radius: 0!important;
`)])])]),r("&:not(:first-child)",`
margin-left: -1px!important;
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`,[r(">",[t("input",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`),t("base-selection",[t("base-selection-label",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`),t("base-selection-tags",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`),o("box-shadow, border, state-border",`
border-top-left-radius: 0!important;
border-bottom-left-radius: 0!important;
`)])])])])])]);const b={};var u=a({name:"InputGroup",props:b,setup(i){const{mergedClsPrefixRef:e}=d(i);return s("-input-group",p,e),{mergedClsPrefix:e}},render(){const{mergedClsPrefix:i}=this;return n("div",{class:`${i}-input-group`},this.$slots)}});export{u as _};

@ -0,0 +1,53 @@
import{n as d,l as n,o as z,m as i,aA as y,aB as _,d as P,u as R,q as c,A as $,s as j,y as B,h as a,e as M,aC as I}from"./index.f480f018.js";var L=d([n("list",`
--n-merged-border-color: var(--n-border-color);
--n-merged-color: var(--n-color)
font-size: var(--n-font-size);
transition:
background-color .3s var(--n-bezier),
color .3s var(--n-bezier),
border-color .3s var(--n-bezier);
padding: 0;
list-style-type: none;
color: var(--n-text-color);
background-color: var(--n-merged-color);
`,[z("bordered",`
border-radius: var(--n-border-radius);
border: 1px solid var(--n-merged-border-color);
`,[n("list-item",`
padding: 12px 20px;
`,[d("&:not(:last-child)",`
border-bottom: 1px solid var(--n-merged-border-color);
`)]),i("header, footer",`
padding: 12px 20px;
`,[d("&:not(:last-child)",`
border-bottom: 1px solid var(--n-merged-border-color);
`)])]),i("header, footer",`
padding: 12px 0;
box-sizing: border-box;
transition: border-color .3s var(--n-bezier);
`,[d("&:not(:last-child)",`
border-bottom: 1px solid var(--n-merged-border-color);
`)]),n("list-item",`
padding: 12px 0;
box-sizing: border-box;
display: flex;
flex-wrap: nowrap;
align-items: center;
transition: border-color .3s var(--n-bezier);
`,[i("prefix",`
margin-right: 20px;
flex: 0;
`),i("suffix",`
margin-left: 20px;
flex: 0;
`),i("main",`
flex: 1;
`),d("&:not(:last-child)",`
border-bottom: 1px solid var(--n-merged-border-color);
`)])]),y(n("list",`
--merged-color: var(--n-color-modal);
--merged-border-color: var(--n-border-color-modal);
`)),_(n("list",`
--merged-color: var(--n-color-popover);
--merged-border-color: var(--n-border-color-popover);
`))]);const O=Object.assign(Object.assign({},c.props),{size:{type:String,default:"medium"},bordered:{type:Boolean,default:!1}}),T=M("n-list");var k=P({name:"List",props:O,setup(r){const{mergedClsPrefixRef:o,inlineThemeDisabled:e}=R(r),s=c("List","-list",L,I,r,o);$(T,{mergedClsPrefixRef:o});const t=j(()=>{const{common:{cubicBezierEaseInOut:b},self:{fontSize:m,textColor:p,color:v,colorModal:f,colorPopover:u,borderColor:g,borderColorModal:x,borderColorPopover:h,borderRadius:C}}=s.value;return{"--n-font-size":m,"--n-bezier":b,"--n-text-color":p,"--n-color":v,"--n-border-radius":C,"--n-border-color":g,"--n-border-color-modal":x,"--n-border-color-popover":h,"--n-color-modal":f,"--n-color-popover":u}}),l=e?B("list",void 0,t,r):void 0;return{mergedClsPrefix:o,cssVars:e?void 0:t,themeClass:l==null?void 0:l.themeClass,onRender:l==null?void 0:l.onRender}},render(){var r;const{$slots:o,mergedClsPrefix:e,onRender:s}=this;return s==null||s(),a("ul",{class:[`${e}-list`,this.bordered&&`${e}-list--bordered`,this.themeClass],style:this.cssVars},o.header?a("div",{class:`${e}-list__header`},o.header()):null,(r=o.default)===null||r===void 0?void 0:r.call(o),o.footer?a("div",{class:`${e}-list__footer`},o.footer()):null)}});export{k as _,T as l};

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.message-item[data-v-44920a13]{padding:16px}.message-item.unread[data-v-44920a13]{background:#fcfffc}.message-item .sender-wrap[data-v-44920a13]{display:flex;align-items:center}.message-item .sender-wrap .username[data-v-44920a13]{opacity:.75;font-size:14px}.message-item .timestamp[data-v-44920a13]{opacity:.75;font-size:12px;display:flex;align-items:center}.message-item .timestamp .timestamp-txt[data-v-44920a13]{margin-left:6px}.message-item .brief-wrap[data-v-44920a13]{margin-top:10px}.message-item .brief-wrap .brief-content[data-v-44920a13],.message-item .brief-wrap .whisper-content-wrap[data-v-44920a13],.message-item .brief-wrap .requesting-friend-wrap[data-v-44920a13]{display:flex;width:100%}.message-item .view-link[data-v-44920a13]{margin-left:8px;display:flex;align-items:center}.message-item .status-info[data-v-44920a13]{margin-left:8px;align-items:center}.dark .message-item.unread[data-v-44920a13]{background:#0f180b}.skeleton-item[data-v-d0b0628c]{padding:12px;display:flex}.skeleton-item .content[data-v-d0b0628c]{width:100%}.pagination-wrap[data-v-532e9e3c]{padding:10px;display:flex;justify-content:center;overflow:hidden}

@ -0,0 +1 @@
import{d as e,V as o,W as s,Y as r}from"./index.f480f018.js";const t={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},n=r("path",{d:"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2z",fill:"currentColor"},null,-1),l=[n];var m=e({name:"MoreHorizFilled",render:function(i,a){return o(),s("svg",t,l)}});export{m as M};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.reply-compose-wrap .reply-switch[data-v-3616e66c]{text-align:right;font-size:12px;margin:10px 0}.reply-compose-wrap .reply-switch .show[data-v-3616e66c]{color:#18a058;cursor:pointer}.reply-compose-wrap .reply-switch .hide[data-v-3616e66c]{opacity:.75;cursor:pointer}.reply-item[data-v-1e3df20d]{display:flex;flex-direction:column;font-size:12px;padding:8px;border-bottom:1px solid #f3f3f3}.reply-item .header-wrap[data-v-1e3df20d]{display:flex;align-items:center;justify-content:space-between}.reply-item .header-wrap .username[data-v-1e3df20d]{max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .header-wrap .username .reply-name[data-v-1e3df20d]{margin:0 3px;opacity:.75}.reply-item .header-wrap .timestamp[data-v-1e3df20d]{opacity:.75;text-align:right;display:flex;align-items:center;max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.reply-item .base-wrap[data-v-1e3df20d]{display:flex}.reply-item .base-wrap .content[data-v-1e3df20d]{width:calc(100% - 40px);margin-top:4px;font-size:12px;text-align:justify;line-height:2}.reply-item .base-wrap .reply-switch[data-v-1e3df20d]{width:40px;text-align:right;font-size:12px;margin:10px 0 0}.reply-item .base-wrap .reply-switch .show[data-v-1e3df20d]{color:#18a058;cursor:pointer}.reply-item .base-wrap .reply-switch .hide[data-v-1e3df20d]{opacity:.75;cursor:pointer}.dark .reply-item[data-v-1e3df20d]{border-bottom:1px solid #262628}.comment-item[data-v-6b2cb186]{width:100%;padding:16px;box-sizing:border-box}.comment-item .nickname-wrap[data-v-6b2cb186]{font-size:14px}.comment-item .username-wrap[data-v-6b2cb186]{font-size:14px;opacity:.75}.comment-item .opt-wrap[data-v-6b2cb186]{display:flex;align-items:center}.comment-item .opt-wrap .timestamp[data-v-6b2cb186]{opacity:.75;font-size:12px}.comment-item .opt-wrap .del-btn[data-v-6b2cb186]{margin-left:4px}.comment-item .comment-text[data-v-6b2cb186]{display:block;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.comment-item .opt-item[data-v-6b2cb186]{display:flex;align-items:center;opacity:.7}.comment-item .opt-item .opt-item-icon[data-v-6b2cb186]{margin-right:10px}.reply-wrap[data-v-6b2cb186]{margin-top:10px;border-radius:5px;background:#fafafc}.reply-wrap .reply-item[data-v-6b2cb186]:last-child{border-bottom:none}.dark .reply-wrap[data-v-6b2cb186]{background:#18181c}.compose-wrap[data-v-0702a552]{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line[data-v-0702a552]{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user[data-v-0702a552]{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options[data-v-0702a552]{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap[data-v-0702a552]{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .cancel-btn[data-v-0702a552]{margin-right:8px}.compose-wrap .login-wrap[data-v-0702a552]{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner[data-v-0702a552]{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button[data-v-0702a552]{margin:0 4px}.attachment[data-v-0702a552]{display:flex;align-items:center}.attachment .text-statistic[data-v-0702a552]{margin-left:8px;width:18px;height:18px;transform:rotate(180deg)}.attachment-list-wrap[data-v-0702a552]{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail[data-v-0702a552]{overflow:hidden}.detail-item{width:100%;padding:16px;box-sizing:border-box;background:#f7f9f9}.detail-item .nickname-wrap{font-size:14px}.detail-item .username-wrap{font-size:14px;opacity:.75}.detail-item .top-tag{transform:scale(.75)}.detail-item .options{opacity:.75}.detail-item .post-text{font-size:16px;text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.detail-item .opts-wrap{margin-top:20px}.detail-item .opts-wrap .opt-item{display:flex;align-items:center;opacity:.7}.detail-item .opts-wrap .opt-item .opt-item-icon{margin-right:10px}.detail-item .opts-wrap .opt-item.hover{cursor:pointer}.detail-item .n-thing .n-thing-avatar-header-wrapper{align-items:center}.detail-item .timestamp{opacity:.75;font-size:12px;margin-top:10px}.dark .detail-item{background:#18181c}.detail-wrap[data-v-41747510]{min-height:100px}

@ -0,0 +1 @@
import{_ as N}from"./post-item.03452002.js";import{_ as S}from"./post-skeleton.39a35f5b.js";import{_ as U}from"./main-nav.9110259b.js";import{ah as D,d as M,Z as R,ai as $,r as c,a1 as q,V as e,W as o,a3 as t,a2 as _,a5 as h,a4 as r,a6 as d,c4 as F,Y as s,a9 as f,aa as L,ab as T,ad as W,c1 as Y,c2 as Z}from"./index.f480f018.js";import{_ as j}from"./List.49bcdf81.js";import{_ as A}from"./Pagination.1263479e.js";import{a as G,_ as H}from"./Skeleton.57e98fe3.js";import"./content.ef1e095a.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";const J={class:"profile-baseinfo"},K={class:"avatar"},O={class:"base-info"},Q={class:"username"},X={class:"uid"},ee={key:0,class:"pagination-wrap"},te={key:0,class:"skeleton-wrap"},ae={key:1},se={key:0,class:"empty-wrap"},ne=M({setup(oe){const a=R(),k=$(),l=c(!1),u=c([]),i=c(+k.query.p||1),p=c(20),m=c(0),v=()=>{l.value=!0,F({username:a.state.userInfo.username,page:i.value,page_size:p.value}).then(n=>{l.value=!1,u.value=n.list,m.value=Math.ceil(n.pager.total_rows/p.value),window.scrollTo(0,0)}).catch(n=>{l.value=!1})},y=n=>{i.value=n,v()};return q(()=>{v()}),(n,_e)=>{const w=U,b=W,I=A,E=Y,P=Z,x=S,B=G,C=N,z=H,V=j;return e(),o("div",null,[t(w,{title:"\u4E3B\u9875"}),_(a).state.userInfo.id>0?(e(),h(V,{key:0,class:"main-content-wrap profile-wrap",bordered:""},{footer:r(()=>[m.value>1?(e(),o("div",ee,[t(I,{page:i.value,"onUpdate:page":y,"page-slot":_(a).state.collapsedRight?5:8,"page-count":m.value},null,8,["page","page-slot","page-count"])])):d("",!0)]),default:r(()=>[s("div",J,[s("div",K,[t(b,{size:"large",src:_(a).state.userInfo.avatar},null,8,["src"])]),s("div",O,[s("div",Q,[s("strong",null,f(_(a).state.userInfo.nickname),1),s("span",null," @"+f(_(a).state.userInfo.username),1)]),s("div",X,"UID. "+f(_(a).state.userInfo.id),1)])]),t(P,{class:"profile-tabs-wrap",animated:""},{default:r(()=>[t(E,{name:"post",tab:"\u6CE1\u6CE1"})]),_:1}),l.value?(e(),o("div",te,[t(x,{num:p.value},null,8,["num"])])):(e(),o("div",ae,[u.value.length===0?(e(),o("div",se,[t(B,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):d("",!0),(e(!0),o(L,null,T(u.value,g=>(e(),h(z,{key:g.id},{default:r(()=>[t(C,{post:g},null,8,["post"])]),_:2},1024))),128))]))]),_:1})):d("",!0)])}}});var ge=D(ne,[["__scopeId","data-v-2fe5c266"]]);export{ge as default};

@ -0,0 +1 @@
.profile-baseinfo[data-v-2fe5c266]{display:flex;padding:16px}.profile-baseinfo .avatar[data-v-2fe5c266]{width:55px}.profile-baseinfo .base-info[data-v-2fe5c266]{position:relative;width:calc(100% - 55px)}.profile-baseinfo .base-info .username[data-v-2fe5c266]{line-height:16px;font-size:16px}.profile-baseinfo .base-info .uid[data-v-2fe5c266]{font-size:14px;line-height:14px;margin-top:10px;opacity:.75}.profile-tabs-wrap[data-v-2fe5c266]{padding:0 16px}.pagination-wrap[data-v-2fe5c266]{padding:10px;display:flex;justify-content:center;overflow:hidden}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.setting-card[data-v-6eb93a4d]{margin-top:-1px;border-radius:0}.setting-card .form-submit-wrap[data-v-6eb93a4d]{display:flex;justify-content:flex-end}.setting-card .base-line[data-v-6eb93a4d]{line-height:2;display:flex;align-items:center}.setting-card .base-line .base-label[data-v-6eb93a4d]{opacity:.75;margin-right:12px}.setting-card .base-line .nickname-input[data-v-6eb93a4d]{margin-right:10px;width:120px}.setting-card .avatar[data-v-6eb93a4d]{display:flex;flex-direction:column;align-items:flex-start;margin-bottom:20px}.setting-card .avatar .avatar-img[data-v-6eb93a4d]{margin-bottom:10px}.setting-card .hash-link[data-v-6eb93a4d]{margin-left:12px}.setting-card .phone-bind-wrap[data-v-6eb93a4d]{margin-top:20px}.setting-card .phone-bind-wrap .captcha-img-wrap[data-v-6eb93a4d]{width:100%;display:flex;align-items:center}.setting-card .phone-bind-wrap .captcha-img[data-v-6eb93a4d]{width:125px;height:34px;border-radius:3px;margin-left:10px;overflow:hidden;cursor:pointer}.setting-card .phone-bind-wrap .captcha-img img[data-v-6eb93a4d]{width:100%;height:100%}

File diff suppressed because one or more lines are too long

@ -0,0 +1,34 @@
import{l as r,m as l,n as c,d as _,u as s,q as v,bq as $,s as b,y as w,h as i,aa as E}from"./index.f480f018.js";var z=r("thing",`
display: flex;
transition: color .3s var(--n-bezier);
font-size: var(--n-font-size);
color: var(--n-text-color);
`,[r("thing-avatar",`
margin-right: 12px;
margin-top: 2px;
`),r("thing-avatar-header-wrapper",`
display: flex;
flex-wrap: nowrap;
`,[r("thing-header-wrapper",`
flex: 1;
`)]),r("thing-main",`
flex-grow: 1;
`,[r("thing-header",`
display: flex;
margin-bottom: 4px;
justify-content: space-between;
align-items: center;
`,[l("title",`
font-size: 16px;
font-weight: var(--n-title-font-weight);
transition: color .3s var(--n-bezier);
color: var(--n-title-text-color);
`)]),l("description",[c("&:not(:last-child)",`
margin-bottom: 4px;
`)]),l("content",[c("&:not(:first-child)",`
margin-top: 12px;
`)]),l("footer",[c("&:not(:first-child)",`
margin-top: 12px;
`)]),l("action",[c("&:not(:first-child)",`
margin-top: 12px;
`)])])]);const C=Object.assign(Object.assign({},v.props),{title:String,titleExtra:String,description:String,content:String,contentIndented:{type:Boolean,default:!1}});var T=_({name:"Thing",props:C,setup(t,{slots:e}){const{mergedClsPrefixRef:h,inlineThemeDisabled:g}=s(t),x=v("Thing","-thing",z,$,t,h),o=b(()=>{const{self:{titleTextColor:d,textColor:n,titleFontWeight:u,fontSize:f},common:{cubicBezierEaseInOut:m}}=x.value;return{"--n-bezier":m,"--n-font-size":f,"--n-text-color":n,"--n-title-font-weight":u,"--n-title-text-color":d}}),a=g?w("thing",void 0,o,t):void 0;return()=>{var d;const{value:n}=h;return(d=a==null?void 0:a.onRender)===null||d===void 0||d.call(a),i("div",{class:[`${n}-thing`,a==null?void 0:a.themeClass],style:g?void 0:o.value},e.avatar&&t.contentIndented?i("div",{class:`${n}-thing-avatar`},e.avatar()):null,i("div",{class:`${n}-thing-main`},!t.contentIndented&&(e.header||t.title||e["header-extra"]||t.titleExtra||e.avatar)?i("div",{class:`${n}-thing-avatar-header-wrapper`},e.avatar?i("div",{class:`${n}-thing-avatar`},e.avatar()):null,e.header||t.title||e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header-wrapper`},i("div",{class:`${n}-thing-header`},e.header||t.title?i("div",{class:`${n}-thing-header__title`},e.header?e.header():t.title):null,e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header__extra`},e["header-extra"]?e["header-extra"]():t.titleExtra):null),e.description||t.description?i("div",{class:`${n}-thing-main__description`},e.description?e.description():t.description):null):null):i(E,null,e.header||t.title||e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header`},e.header||t.title?i("div",{class:`${n}-thing-header__title`},e.header?e.header():t.title):null,e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header__extra`},e["header-extra"]?e["header-extra"]():t.titleExtra):null):null,e.description||t.description?i("div",{class:`${n}-thing-main__description`},e.description?e.description():t.description):null),e.default||t.content?i("div",{class:`${n}-thing-main__content`},e.default?e.default():t.content):null,e.footer?i("div",{class:`${n}-thing-main__footer`},e.footer()):null,e.action?i("div",{class:`${n}-thing-main__action`},e.action()):null))}}});export{T as _};

@ -0,0 +1 @@
.tags-wrap[data-v-ec1d2778]{padding:20px}.tags-wrap .tag-item .tag-hot[data-v-ec1d2778]{margin-left:12px;font-size:12px;opacity:.75}

@ -0,0 +1 @@
import{_ as T}from"./main-nav.9110259b.js";import{ah as w,d as x,r as s,a1 as B,al as D,V as _,W as r,a3 as a,a4 as n,c0 as V,aa as q,ab as C,c1 as E,c2 as N,ag as F,b_ as I,a5 as L,a8 as M,a9 as m,Y as S,ad as U,an as W}from"./index.f480f018.js";import{_ as Y}from"./List.49bcdf81.js";const $={class:"tag-hot"},j=x({setup(z){const c=s([]),u=s("hot"),o=s(!1),l=()=>{o.value=!0,V({type:u.value,num:50}).then(e=>{c.value=e,o.value=!1}).catch(e=>{o.value=!1})},i=e=>{u.value=e,l()};return B(()=>{l()}),(e,A)=>{const d=T,p=E,g=N,v=D("router-link"),f=U,h=W,y=F,b=I,k=Y;return _(),r("div",null,[a(d,{title:"\u8BDD\u9898"}),a(k,{class:"main-content-wrap tags-wrap",bordered:""},{default:n(()=>[a(g,{type:"line",animated:"","onUpdate:value":i},{default:n(()=>[a(p,{name:"hot",tab:"\u70ED\u95E8"}),a(p,{name:"new",tab:"\u6700\u65B0"})]),_:1}),a(b,{show:o.value},{default:n(()=>[a(y,null,{default:n(()=>[(_(!0),r(q,null,C(c.value,t=>(_(),L(h,{class:"tag-item",type:"success",round:"",key:t.id},{avatar:n(()=>[a(f,{src:t.user.avatar},null,8,["src"])]),default:n(()=>[a(v,{class:"hash-link",to:{name:"home",query:{q:t.tag,t:"tag"}}},{default:n(()=>[M(" #"+m(t.tag),1)]),_:2},1032,["to"]),S("span",$,"("+m(t.quote_num)+")",1)]),_:2},1024))),128))]),_:1})]),_:1},8,["show"])]),_:1})])}}});var K=w(j,[["__scopeId","data-v-ec1d2778"]]);export{K as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.whisper-wrap .whisper-line[data-v-3e021430]{margin-top:10px}.whisper-wrap .whisper-line.send-wrap .n-button[data-v-3e021430]{width:100%}.whisper-wrap .whisper-line[data-v-bf9bc04e]{margin-top:10px}.whisper-wrap .whisper-line.send-wrap .n-button[data-v-bf9bc04e]{width:100%}.profile-tabs-wrap[data-v-7a6aaa02]{padding:0 16px}.profile-baseinfo[data-v-7a6aaa02]{display:flex;padding:16px}.profile-baseinfo .avatar[data-v-7a6aaa02]{width:55px}.profile-baseinfo .base-info[data-v-7a6aaa02]{position:relative;width:calc(100% - 55px)}.profile-baseinfo .base-info .username[data-v-7a6aaa02]{line-height:16px;font-size:16px}.profile-baseinfo .base-info .uid[data-v-7a6aaa02]{font-size:14px;line-height:14px;margin-top:10px;opacity:.75}.profile-baseinfo .base-info .top-tag[data-v-7a6aaa02]{transform:scale(.75)}.profile-baseinfo .user-opts[data-v-7a6aaa02]{position:absolute;top:16px;right:16px;opacity:.75}.pagination-wrap[data-v-7a6aaa02]{padding:10px;display:flex;justify-content:center;overflow:hidden}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.balance-wrap[data-v-4ef16ff5]{padding:16px}.balance-wrap .balance-line[data-v-4ef16ff5]{display:flex;justify-content:space-between}.balance-wrap .balance-line .balance-opts[data-v-4ef16ff5]{display:flex;flex-direction:column}.bill-line[data-v-4ef16ff5]{padding:16px;display:flex;justify-content:space-between}.bill-line .income[data-v-4ef16ff5],.bill-line .out[data-v-4ef16ff5]{font-weight:700}.bill-line .income[data-v-4ef16ff5]{color:#18a058}.pagination-wrap[data-v-4ef16ff5]{padding:10px;display:flex;justify-content:center;overflow:hidden}.qrcode-wrap[data-v-4ef16ff5]{display:flex;flex-direction:column;align-items:center;justify-content:center}.qrcode-wrap .pay-tips[data-v-4ef16ff5]{margin-top:16px}.qrcode-wrap .pay-sub-tips[data-v-4ef16ff5]{margin-top:4px;font-size:12px;opacity:.75;display:flex;align-items:center}.dark .income[data-v-4ef16ff5]{color:#63e2b7}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.link-wrap[data-v-4c9a59cc]{margin-bottom:10px}.link-wrap .link-item[data-v-4c9a59cc]{display:flex;align-items:center}.link-wrap .link-item .hash-link .link-txt[data-v-4c9a59cc]{margin-left:4px;word-break:break-all}.images-wrap{margin-top:10px}.post-img{display:flex;margin:0;border-radius:3px;overflow:hidden;background:rgba(0,0,0,.1);border:1px solid #eee}.post-img img{width:100%;height:100%}.x1{height:140px}.x2{height:90px}.x3{height:80px}.dark .post-img{border:1px solid #333}@media screen and (max-width: 821px){.x1{height:100px}.x2{height:70px}.x3{height:50px}}.attach-item[data-v-ca4bb796]{margin:10px 0}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.auth-wrap[data-v-66895776]{margin-top:-30px}.rightbar-wrap[data-v-0dc4cb5d]{width:240px;position:fixed;left:calc(50% + var(--content-main) / 2 + 10px)}.rightbar-wrap .search-wrap[data-v-0dc4cb5d]{margin:12px 0}.rightbar-wrap .hot-tag-item[data-v-0dc4cb5d]{line-height:2;position:relative}.rightbar-wrap .hot-tag-item .hash-link[data-v-0dc4cb5d]{width:calc(100% - 60px);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block}.rightbar-wrap .hot-tag-item .post-num[data-v-0dc4cb5d]{position:absolute;right:0;top:0;width:60px;text-align:right;line-height:2;opacity:.5}.rightbar-wrap .copyright-wrap[data-v-0dc4cb5d]{margin-top:10px}.rightbar-wrap .copyright-wrap .copyright[data-v-0dc4cb5d]{font-size:12px;opacity:.75}.rightbar-wrap .copyright-wrap .hash-link[data-v-0dc4cb5d]{font-size:12px}.sidebar-wrap{z-index:99;width:200px;height:100vh;position:fixed;right:calc(50% + var(--content-main) / 2 + 10px);padding:12px 0;box-sizing:border-box}.sidebar-wrap .n-menu .n-menu-item-content:before{border-radius:21px}.logo-wrap{display:flex;justify-content:flex-start;margin-bottom:12px}.logo-wrap .logo-img{margin-left:24px}.logo-wrap .logo-img:hover{cursor:pointer}.user-wrap{display:flex;align-items:center;position:absolute;bottom:12px;left:12px;right:12px}.user-wrap .user-mini-wrap{display:none}.user-wrap .user-avatar{margin-right:8px}.user-wrap .user-info{display:flex;flex-direction:column}.user-wrap .user-info .nickname{font-size:16px;font-weight:700;line-height:16px;height:16px;margin-bottom:2px;display:flex;align-items:center}.user-wrap .user-info .nickname .nickname-txt{max-width:90px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.user-wrap .user-info .nickname .logout{margin-left:6px}.user-wrap .user-info .username{font-size:14px;line-height:16px;height:16px;width:120px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;opacity:.75}.user-wrap .login-wrap{display:flex;justify-content:center;width:100%}.user-wrap .login-wrap button{margin:0 4px}.auth-card .n-card-header{z-index:999}@media screen and (max-width: 821px){.sidebar-wrap{width:65px;right:calc(100% - 60px)}.logo-wrap .logo-img{margin-left:12px!important}.user-wrap .user-avatar,.user-wrap .user-info,.user-wrap .login-wrap{display:none}.user-wrap .user-mini-wrap{display:block!important}}:root{--content-main: 500px}.app-container{margin:0}.app-container .app-wrap{width:100%;margin:0 auto}.main-wrap{min-height:100vh;display:flex;flex-direction:row;justify-content:center}.main-wrap .content-wrap{width:100%;max-width:var(--content-main);position:relative}.main-wrap .main-content-wrap{margin:0;border-top:none;border-radius:0}.main-wrap .main-content-wrap .n-list-item{padding:0}.empty-wrap{min-height:300px;display:flex;align-items:center;justify-content:center}.hash-link,.user-link{color:#18a058;text-decoration:none;cursor:pointer}.hash-link:hover,.user-link:hover{opacity:.8}.beian-link{color:#333;text-decoration:none}.beian-link:hover{opacity:.75}.username-link{color:#000;color:none;text-decoration:none;cursor:pointer}.username-link:hover{text-decoration:underline}.dark .hash-link,.dark .user-link{color:#63e2b7}.dark .username-link{color:#eee}.dark .beian-link{color:#ddd}@media screen and (max-width: 821px){.content-wrap{top:0;left:60px;position:absolute!important;width:calc(100% - 60px)!important}}@font-face{font-family:v-sans;font-weight:400;src:url(/assets/LatoLatin-Regular.ddd4ef7f.woff2)}@font-face{font-family:v-sans;font-weight:600;src:url(/assets/LatoLatin-Semibold.267eef30.woff2)}@font-face{font-family:v-mono;font-weight:400;src:url(/assets/FiraCode-Regular.f13d1ece.woff2)}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.nav-title-card{z-index:99;width:100%;top:0;position:sticky;border-radius:0;border-bottom:0;background-color:#ffffffbf;backdrop-filter:blur(12px)}.nav-title-card .navbar{height:30px;position:relative;display:flex;align-items:center}.nav-title-card .navbar .back-btn{margin-right:8px}.nav-title-card .navbar .theme-switch-wrap{position:absolute;right:0;top:calc(50% - 9px)}.dark .nav-title-card{background-color:#101014bf}

@ -0,0 +1 @@
import{p as O,H as $,C as j,B as D,_ as E,a as F,b as L,c as M}from"./content.ef1e095a.js";import{d as R,ai as S,aj as I,Z as P,s as W,al as Y,V as o,W as f,a3 as i,am as Z,a2 as t,a4 as n,aa as A,ab as G,a7 as v,Y as u,a8 as p,a9 as c,a5 as r,a6 as _,ad as J,an as K,ae as Q,ag as U}from"./index.f480f018.js";import{f as X}from"./formatTime.02109bf5.js";import{_ as tt}from"./Thing.eef6b133.js";const et={class:"nickname-wrap"},st={class:"username-wrap"},at=p(" \u7F6E\u9876 "),nt=p(" \u79C1\u5BC6 "),ot=p(" \u597D\u53CB\u53EF\u89C1 "),it={class:"timestamp"},rt=["innerHTML"],_t={class:"opt-item"},ct={class:"opt-item"},pt={class:"opt-item"},ht=R({props:{post:null},setup(x){const C=x;S();const m=I(),B=P(),e=W(()=>{let a=Object.assign({texts:[],imgs:[],videos:[],links:[],attachments:[],charge_attachments:[]},C.post);return a.contents.map(s=>{(+s.type==1||+s.type==2)&&a.texts.push(s),+s.type==3&&a.imgs.push(s),+s.type==4&&a.videos.push(s),+s.type==6&&a.links.push(s),+s.type==7&&a.attachments.push(s),+s.type==8&&a.charge_attachments.push(s)}),a}),k=a=>{m.push({name:"post",query:{id:a}})},b=(a,s)=>{if(a.target.dataset.detail){const l=a.target.dataset.detail.split(":");if(l.length===2){B.commit("refresh"),l[0]==="tag"?m.push({name:"home",query:{q:l[1],t:"tag"}}):m.push({name:"user",query:{username:l[1]}});return}}k(s)};return(a,s)=>{const l=J,z=Y("router-link"),d=K,y=E,w=F,T=L,q=M,h=Q,N=U,V=tt;return o(),f("div",{class:"post-item",onClick:s[2]||(s[2]=g=>k(t(e).id))},[i(V,{"content-indented":""},Z({avatar:n(()=>[i(l,{round:"",size:30,src:t(e).user.avatar},null,8,["src"])]),header:n(()=>[u("span",et,[i(z,{onClick:s[0]||(s[0]=v(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{username:t(e).user.username}}},{default:n(()=>[p(c(t(e).user.nickname),1)]),_:1},8,["to"])]),u("span",st," @"+c(t(e).user.username),1),t(e).is_top?(o(),r(d,{key:0,class:"top-tag",type:"warning",size:"small",round:""},{default:n(()=>[at]),_:1})):_("",!0),t(e).visibility==1?(o(),r(d,{key:1,class:"top-tag",type:"error",size:"small",round:""},{default:n(()=>[nt]),_:1})):_("",!0),t(e).visibility==2?(o(),r(d,{key:2,class:"top-tag",type:"info",size:"small",round:""},{default:n(()=>[ot]),_:1})):_("",!0)]),"header-extra":n(()=>[u("span",it,c(t(e).ip_loc?t(e).ip_loc+" \xB7 ":t(e).ip_loc)+" "+c(t(X)(t(e).created_on)),1)]),footer:n(()=>[t(e).attachments.length>0?(o(),r(y,{key:0,attachments:t(e).attachments},null,8,["attachments"])):_("",!0),t(e).charge_attachments.length>0?(o(),r(y,{key:1,attachments:t(e).charge_attachments,price:t(e).attachment_price},null,8,["attachments","price"])):_("",!0),t(e).imgs.length>0?(o(),r(w,{key:2,imgs:t(e).imgs},null,8,["imgs"])):_("",!0),t(e).videos.length>0?(o(),r(T,{key:3,videos:t(e).videos},null,8,["videos"])):_("",!0),t(e).links.length>0?(o(),r(q,{key:4,links:t(e).links},null,8,["links"])):_("",!0)]),action:n(()=>[i(N,{justify:"space-between"},{default:n(()=>[u("div",_t,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t($))]),_:1}),p(" "+c(t(e).upvote_count),1)]),u("div",ct,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(j))]),_:1}),p(" "+c(t(e).comment_count),1)]),u("div",pt,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(D))]),_:1}),p(" "+c(t(e).collection_count),1)])]),_:1})]),_:2},[t(e).texts.length>0?{name:"description",fn:n(()=>[(o(!0),f(A,null,G(t(e).texts,g=>(o(),f("span",{key:g.id,class:"post-text",onClick:s[1]||(s[1]=v(H=>b(H,t(e).id),["stop"])),innerHTML:t(O)(g.content).content},null,8,rt))),128))])}:void 0]),1024)])}}});export{ht as _};

@ -0,0 +1 @@
.post-item{width:100%;padding:16px;box-sizing:border-box}.post-item .nickname-wrap{font-size:14px}.post-item .username-wrap{font-size:14px;opacity:.75}.post-item .top-tag{transform:scale(.75)}.post-item .timestamp{opacity:.75;font-size:12px}.post-item .post-text{text-align:justify;overflow:hidden;white-space:pre-wrap;word-break:break-all}.post-item .opt-item{display:flex;align-items:center;opacity:.7}.post-item .opt-item .opt-item-icon{margin-right:10px}.post-item:hover{background:#f7f9f9;cursor:pointer}.post-item .n-thing-avatar{margin-top:0}.post-item .n-thing-header{line-height:16px;margin-bottom:8px!important}.dark .post-item:hover{background:#18181c}

@ -0,0 +1 @@
.skeleton-item[data-v-a6d56894]{padding:12px;display:flex}.skeleton-item .user[data-v-a6d56894]{width:42px}.skeleton-item .content[data-v-a6d56894]{width:calc(100% - 42px)}

@ -0,0 +1 @@
import{ah as r,d as c,V as s,W as n,ab as l,Y as a,a3 as t,aa as p}from"./index.f480f018.js";import{b as d}from"./Skeleton.57e98fe3.js";const i={class:"user"},u={class:"content"},m=c({props:{num:{default:1}},setup(o){return(v,f)=>{const e=d;return s(!0),n(p,null,l(new Array(o.num),_=>(s(),n("div",{class:"skeleton-item",key:_},[a("div",i,[t(e,{circle:"",size:"small"})]),a("div",u,[t(e,{text:"",repeat:3}),t(e,{text:"",style:{width:"60%"}})])]))),128)}}});var h=r(m,[["__scopeId","data-v-a6d56894"]]);export{h as _};

BIN
web/dist/favicon.ico vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
<title></title>
<script type="module" crossorigin src="/assets/index.f480f018.js"></script>
<link rel="stylesheet" href="/assets/index.2a3b289f.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

@ -30,7 +30,7 @@
"vuex": "^4.0.2"
},
"devDependencies": {
"@tauri-apps/cli": "^1.0.0",
"@tauri-apps/cli": "^1.0.4",
"@types/node": "^17.0.35",
"@types/qrcode": "^1.4.2",
"@vitejs/plugin-vue": "^2.3.3",

@ -44,18 +44,9 @@
import { computed } from 'vue';
import { useStore } from 'vuex';
import { darkTheme } from 'naive-ui';
import { version, buildTime } from '../build/info.json';
const store = useStore();
const theme = computed(() => (store.state.theme === 'dark' ? darkTheme : null));
console.log(
`%c Release Build Info
%cVersion v${version}
BuildTime ${buildTime}`,
'background:#000;color:#FFF;font-weight:bold;',
'background:#FFF;color:#000;'
);
</script>
<style lang="less">

@ -72,6 +72,15 @@ export const getPostComments = (params: NetParams.PostGetPostComments): Promise<
});
};
/** 获取联系人列表 */
export const getContacts = (params: NetParams.GetContacts): Promise<NetReq.GetContacts> => {
return request({
method: 'get',
url: '/v1/user/contacts',
params
});
};
/** 发布动态 */
export const createPost = (data: NetParams.PostCreatePost): Promise<NetReq.PostCreatePost> => {
return request({

@ -35,6 +35,71 @@ export const sendUserWhisper = (data: NetParams.UserWhisper): Promise<NetParams.
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const requestingFriend = (data: NetParams.RequestingFriend): Promise<NetReq.RequestingFriend> => {
return request({
method: 'post',
url: '/v1/friend/requesting',
data
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const addFriend = (data: NetParams.AddFriend): Promise<NetReq.AddFriend> => {
return request({
method: 'post',
url: '/v1/friend/add',
data
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const rejectFriend = (data: NetParams.RejectFriend): Promise<NetReq.RejectFriend> => {
return request({
method: 'post',
url: '/v1/friend/reject',
data
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const deleteFriend = (data: NetParams.DeleteFriend): Promise<NetReq.DeleteFriend> => {
return request({
method: 'post',
url: '/v1/friend/delete',
data
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const getContacts = (data: NetParams.GetContacts): Promise<NetReq.GetContacts> => {
return request({
method: 'post',
url: '/v1/user/contacts',
data
});
};
/**
*
* @param {Object} data
@ -48,6 +113,19 @@ export const bindUserPhone = (data: NetParams.UserBindUserPhone): Promise<NetPar
});
};
/**
*
* @param {Object} data
* @returns Promise
*/
export const activateUser = (data: NetParams.UserActivation): Promise<NetParams.UserActivation> => {
return request({
method: 'post',
url: '/v1/user/activate',
data
});
};
/** 更改密码 */
export const changePassword = (data: NetParams.UserChangePassword): Promise<NetReq.UserChangePassword> => {
return request({
@ -119,15 +197,6 @@ export const getCollections = (params: NetParams.UserGetCollections): Promise<Ne
});
};
/** 获取点赞列表 */
export const getStars = (params: NetParams.UserGetStars): Promise<NetReq.UserGetStars> => {
return request({
method: 'get',
url: '/v1/user/stars',
params
});
};
/** 获取用户基础信息 */
export const getUserProfile = (params: NetParams.UserGetUserProfile): Promise<NetReq.UserGetUserProfile> => {
return request({

@ -71,7 +71,9 @@
</template>
<template #footer>
<post-image :imgs="comment.imgs" />
<post-image
v-if="comment.imgs.length > 0"
:imgs="comment.imgs" />
<!-- -->
<div class="reply-wrap">
<reply-item

@ -160,9 +160,6 @@ import { useStore } from 'vuex';
import { debounce } from 'lodash';
import {
ImageOutline,
VideocamOutline,
AttachOutline,
CompassOutline,
} from '@vicons/ionicons5';
import { createComment } from '@/api/post';
import { getSuggestUsers } from '@/api/user';

@ -74,8 +74,8 @@
</n-upload-trigger>
<n-upload-trigger
v-if="allowTweetVideo"
#="{ handleClick }" abstract>
v-if="allowTweetVideo"
#="{ handleClick }" abstract>
<n-button
:disabled="
(fileQueue.length > 0 &&
@ -104,8 +104,8 @@
</n-upload-trigger>
<n-upload-trigger
v-if="allowTweetAttachment"
#="{ handleClick }" abstract>
v-if="allowTweetAttachment"
#="{ handleClick }" abstract>
<n-button
:disabled="
(fileQueue.length > 0 &&
@ -209,18 +209,7 @@
</div>
</n-upload>
<div class="link-wrap" v-if="showLinkSet">
<n-dynamic-input
v-model:value="links"
placeholder="请输入以http(s)://开头的链接"
:min="0"
:max="3"
>
<template #create-button-default> </template>
</n-dynamic-input>
</div>
<div class="eye-wrap" v-if="showEyeSet">
<div class="eye-wrap" v-if="showEyeSet">
<n-radio-group v-model:value="visitType" name="radiogroup">
<n-space>
<n-radio
@ -232,6 +221,17 @@
</n-space>
</n-radio-group>
</div>
<div class="link-wrap" v-if="showLinkSet">
<n-dynamic-input
v-model:value="links"
placeholder="请输入以http(s)://开头的链接"
:min="0"
:max="3"
>
<template #create-button-default> </template>
</n-dynamic-input>
</div>
</div>
<div class="compose-wrap" v-else>
@ -304,7 +304,7 @@ const fileQueue = ref<UploadFileInfo[]>([]);
const imageContents = ref<Item.CommentItemProps[]>([]);
const videoContents = ref<Item.CommentItemProps[]>([]);
const attachmentContents = ref<Item.AttachmentProps[]>([]);
const visitType = ref<VisibilityEnum>(VisibilityEnum.PUBLIC);
const visitType = ref<VisibilityEnum>(VisibilityEnum.FRIEND);
const defaultVisitType = ref<VisibilityEnum>(VisibilityEnum.FRIEND)
const visibilities = [
{value: VisibilityEnum.PUBLIC, label: "公开"}
@ -586,7 +586,7 @@ const submitPost = () => {
imageContents.value = [];
videoContents.value = [];
attachmentContents.value = [];
visitType.value = defaultVisitType.value;;
visitType.value = defaultVisitType.value;
})
.catch((err) => {
submitting.value = false;

@ -0,0 +1,74 @@
<template>
<div class="contact-item" @click="goUserProfile(contact.username)">
<div class="avatar">
<n-avatar size="large" :src="contact.avatar" />
</div>
<div class="base-info">
<div class="username">
<strong>{{ contact.nickname }}</strong>
<span> @{{ contact.username }} </span>
</div>
<div class="uid">UID. {{ contact.user_id }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
const props = withDefaults(defineProps<{
contact: Item.ContactItemProps
}>(), {})
const goUserProfile = (username: string) => {
router.push({
name: 'user',
query: { username: username },
});
};
</script>
<style lang="less" scoped>
.contact-item {
display: flex;
width: 100%;
padding-left: 16px;
padding-right: 16px;
padding-top: 12px;
padding-bottom: 12px;
&:hover {
background: #f7f9f9;
cursor: pointer;
}
.avatar {
width: 55px;
}
.base-info {
position: relative;
width: calc(100% - 55px);
.username {
line-height: 16px;
font-size: 16px;
}
.uid {
font-size: 14px;
line-height: 14px;
margin-top: 10px;
opacity: 0.75;
}
}
}
.dark {
.contact-item {
&:hover {
background: #18181c;
}
}
}
</style>

@ -18,6 +18,7 @@
{{ props.title }}
<n-switch
v-if="props.theme"
:value="store.state.theme === 'dark'"
@update:value="switchTheme"
size="small"
@ -49,10 +50,12 @@ const props = withDefaults(
defineProps<{
title: string;
back?: boolean;
theme?: boolean;
}>(),
{
title: '',
back: false,
theme: true,
}
);
const switchTheme = (theme: boolean) => {

@ -1,31 +1,22 @@
<template>
<div
class="message-item"
:class="{ unread: message.is_read === 0 }"
@click="handleReadMessage(message)"
>
<div class="message-item" :class="{ unread: message.is_read === 0 }" @click="handleReadMessage(message)">
<n-thing content-indented>
<template #avatar>
<n-avatar round :size="30" :src="
message.sender_user.id > 0
? message.sender_user.avatar
: defaultavatar
" />
</template>
<template #header>
<div class="sender-wrap">
<n-avatar
:size="22"
:src="
message.sender_user.id > 0
? message.sender_user.avatar
: defaultavatar
"
/>
<span class="nickname" v-if="message.sender_user.id > 0">
<router-link
@click.stop
class="username-link"
:to="{
name: 'user',
query: {
username: message.sender_user.username,
},
}"
>
<router-link @click.stop class="username-link" :to="{
name: 'user',
query: {
username: message.sender_user.username,
},
}">
{{ message.sender_user.nickname }}
</router-link>
<span class="username">
@ -44,25 +35,46 @@
</span>
</template>
<template #description>
<n-alert
:show-icon="false"
class="brief-wrap"
:type="message.is_read > 0 ? 'default' : 'success'"
>
<div class="brief-content">
<n-alert :show-icon="false" class="brief-wrap" :type="message.is_read > 0 ? 'default' : 'success'">
<div v-if="message.type != 4" class="brief-content">
{{ message.brief }}
<span
v-if="message.type !== 4"
@click.stop="viewDetail(message)"
class="hash-link view-link"
>
<n-icon><share-outline /></n-icon>
<span v-if="message.type === 1 || message.type === 2 || message.type === 3"
@click.stop="viewDetail(message)" class="hash-link view-link">
<n-icon>
<share-outline />
</n-icon>
</span>
</div>
<div v-if="message.type === 4" class="whisper-content-wrap">
{{ message.content }}
</div>
<div v-if="message.type === 5" class="requesting-friend-wrap">
{{ message.content }}
<span v-if="message.reply_id === 1" @click.stop="agreeAddFriend(message)"
class="hash-link view-link">
<n-icon>
<checkmark-outline />
</n-icon>
</span>
<span v-if="message.reply_id === 1" @click.stop="rejectAddFriend(message)"
class="hash-link view-link">
<n-icon>
<close-outline />
</n-icon>
</span>
<span v-if="message.reply_id === 2" class="status-info">
<n-icon>
<checkmark-done-outline />
</n-icon>
</span>
<span v-if="message.reply_id === 3" class="status-info">
<n-icon>
<close-outline />
</n-icon>
</span>
</div>
</n-alert>
</template>
</n-thing>
@ -71,12 +83,11 @@
<script setup lang="ts">
import { useRouter } from 'vue-router';
import { ShareOutline } from '@vicons/ionicons5';
import { readMessage } from '@/api/user';
import { ShareOutline, CheckmarkOutline, CloseOutline, CheckmarkDoneOutline } from '@vicons/ionicons5';
import { readMessage, addFriend, rejectFriend } from '@/api/user';
import { formatRelativeTime } from '@/utils/formatTime';
const defaultavatar =
'https://assets.paopao.info/public/avatar/default/admin.png';
const defaultavatar = 'https://assets.paopao.info/public/avatar/default/admin.png';
const router = useRouter();
const props = withDefaults(
@ -85,6 +96,7 @@ const props = withDefaults(
}>(),
{}
);
const viewDetail = (message: Item.MessageProps) => {
handleReadMessage(message);
if (message.type === 1 || message.type === 2 || message.type === 3) {
@ -100,6 +112,35 @@ const viewDetail = (message: Item.MessageProps) => {
}
}
};
const agreeAddFriend = (message: Item.MessageProps) => {
handleReadMessage(message);
addFriend({
user_id: message.sender_user_id,
})
.then((res) => {
message.reply_id = 2;
window.$message.success('');
})
.catch((err) => {
console.log(err);
});
}
const rejectAddFriend = (message: Item.MessageProps) => {
handleReadMessage(message);
rejectFriend({
user_id: message.sender_user_id,
})
.then((res) => {
message.reply_id = 3;
window.$message.success('');
})
.catch((err) => {
console.log(err);
});
}
const handleReadMessage = (message: Item.MessageProps) => {
if (message.is_read === 0) {
readMessage({
@ -127,9 +168,6 @@ const handleReadMessage = (message: Item.MessageProps) => {
display: flex;
align-items: center;
.nickname {
margin-left: 10px;
}
.username {
opacity: 0.75;
font-size: 14px;
@ -141,6 +179,7 @@ const handleReadMessage = (message: Item.MessageProps) => {
font-size: 12px;
display: flex;
align-items: center;
.timestamp-txt {
margin-left: 6px;
}
@ -148,13 +187,20 @@ const handleReadMessage = (message: Item.MessageProps) => {
.brief-wrap {
margin-top: 10px;
.brief-content {
display: flex;
width: 100%;
}
.whisper-content-wrap {
margin-top: 12px;
text-decoration: underline;
display: flex;
width: 100%;
}
.requesting-friend-wrap {
display: flex;
width: 100%;
}
}
@ -163,7 +209,13 @@ const handleReadMessage = (message: Item.MessageProps) => {
display: flex;
align-items: center;
}
.status-info {
margin-left: 8px;
align-items: center;
}
}
.dark {
.message-item {
&.unread {

@ -64,14 +64,23 @@
</template>
<template #footer>
<post-attachment :attachments="post.attachments" />
<post-attachment
v-if="post.attachments.length > 0"
:attachments="post.attachments" />
<post-attachment
v-if="post.charge_attachments.length > 0"
:attachments="post.charge_attachments"
:price="post.attachment_price"
/>
<post-image :imgs="post.imgs" />
<post-video :videos="post.videos" />
<post-link :links="post.links" />
<post-image
v-if="post.imgs.length > 0"
:imgs="post.imgs" />
<post-video
v-if="post.videos.length > 0"
:videos="post.videos" />
<post-link
v-if="post.links.length > 0"
:links="post.links" />
</template>
<template #action>
<n-space justify="space-between">

@ -36,7 +36,25 @@
</n-spin>
</n-card>
<n-card class="copyright-wrap" embedded :bordered="false" size="small">
<div class="copyright">&copy; 2022 PaoPao.Info</div>
<div class="copyright">&copy; {{ copyrightTop }}</div>
<div>
<n-space>
<a
:href="copyrightLeftLink"
target="_blank"
class="hash-link"
>
{{ copyrightLeft }}
</a>
<a
:href="copyrightRightLink"
target="_blank"
class="hash-link"
>
{{ copyrightRight }}
</a>
</n-space>
</div>
</n-card>
</div>
</template>
@ -53,6 +71,11 @@ const loading = ref(false);
const keyword = ref('');
const store = useStore();
const router = useRouter();
const copyrightTop = import.meta.env.VITE_COPYRIGHT_TOP
const copyrightLeft = import.meta.env.VITE_COPYRIGHT_LEFT
const copyrightLeftLink = import.meta.env.VITE_COPYRIGHT_LEFT_LINK
const copyrightRight = import.meta.env.VITE_COPYRIGHT_RIGHT
const copyrightRightLink = import.meta.env.VITE_COPYRIGHT_RIGHT_LINK
const loadTags = () => {
loading.value = true;

@ -1,48 +1,25 @@
<template>
<div class="sidebar-wrap">
<div class="logo-wrap">
<n-image
class="logo-img"
width="36"
:src="LOGO"
:preview-disabled="true"
@click="goHome"
/>
<n-image class="logo-img" width="36" :src="LOGO" :preview-disabled="true" @click="goHome" />
</div>
<n-menu
:accordion="true"
:collapsed="store.state.collapsedLeft"
:collapsed-width="64"
:icon-size="24"
:options="menuOptions"
:render-label="renderMenuLabel"
:render-icon="renderMenuIcon"
:value="selectedPath"
@update:value="goRouter"
/>
<n-menu :accordion="true" :collapsed="store.state.collapsedLeft" :collapsed-width="64" :icon-size="24"
:options="menuOptions" :render-label="renderMenuLabel" :render-icon="renderMenuIcon" :value="selectedPath"
@update:value="goRouter" />
<div class="user-wrap" v-if="store.state.userInfo.id > 0">
<n-avatar
class="user-avatar"
round
:size="34"
:src="store.state.userInfo.avatar"
/>
<n-avatar class="user-avatar" round :size="34" :src="store.state.userInfo.avatar" />
<div class="user-info">
<div class="nickname">
<span class="nickname-txt">
{{ store.state.userInfo.nickname }}
</span>
<n-button
class="logout"
quaternary
circle
size="tiny"
@click="handleLogout"
>
<n-button class="logout" quaternary circle size="tiny" @click="handleLogout">
<template #icon>
<n-icon><log-out-outline /></n-icon>
<n-icon>
<log-out-outline />
</n-icon>
</template>
</n-button>
</div>
@ -50,36 +27,21 @@
</div>
<div class="user-mini-wrap">
<n-button
class="logout"
quaternary
circle
@click="handleLogout"
>
<n-button class="logout" quaternary circle @click="handleLogout">
<template #icon>
<n-icon :size="24"><log-out-outline /></n-icon>
<n-icon :size="24">
<log-out-outline />
</n-icon>
</template>
</n-button>
</div>
</div>
<div class="user-wrap" v-else>
<div class="login-wrap">
<n-button
strong
secondary
round
type="primary"
@click="triggerAuth('signin')"
>
<n-button strong secondary round type="primary" @click="triggerAuth('signin')">
</n-button>
<n-button
strong
secondary
round
type="info"
@click="triggerAuth('signup')"
>
<n-button strong secondary round type="info" @click="triggerAuth('signup')">
</n-button>
</div>
@ -95,10 +57,12 @@ import { NIcon, NBadge, useMessage } from 'naive-ui';
import type { RouteRecordName } from "vue-router";
import {
HomeOutline,
BookmarkOutline,
NotificationsOutline,
HeartOutline,
BookmarksOutline,
MegaphoneOutline,
SparklesOutline,
ChatbubblesOutline,
LeafOutline,
PeopleOutline,
WalletOutline,
SettingsOutline,
LogOutOutline,
@ -164,31 +128,39 @@ const menuOptions = computed(() => {
icon: () => h(Hash),
href: '/topic',
},
{
label: '',
key: 'profile',
icon: () => h(LeafOutline),
href: '/profile',
},
{
label: '',
key: 'notification',
icon: () => h(NotificationsOutline),
href: '/notification',
},
{
label: '',
key: 'collection',
icon: () => h(BookmarkOutline),
href: '/collection',
},
{
label: '',
key: 'star',
icon: () => h(HeartOutline),
href: '/star',
}
];
if (import.meta.env.VITE_ENABLE_ANOUNCEMENT.toLowerCase() === 'true') {
options.push( {
label: '',
key: 'anouncement',
icon: () => h(MegaphoneOutline),
href: '/anouncement',
});
}
options.push({
label: '',
key: 'profile',
icon: () => h(LeafOutline),
href: '/profile',
});
options.push({
label: '',
key: 'messages',
icon: () => h(ChatbubblesOutline),
href: '/messages',
})
options.push({
label: '',
key: 'collection',
icon: () => h(BookmarksOutline),
href: '/collection',
});
options.push({
label: '',
key: 'contacts',
icon: () => h(PeopleOutline),
href: '/contacts',
});
if (import.meta.env.VITE_ENABLE_WALLET.toLocaleLowerCase() === 'true') {
options.push({
label: '',
@ -203,22 +175,23 @@ const menuOptions = computed(() => {
icon: () => h(SettingsOutline),
href: '/setting',
});
return store.state.userInfo.id > 0
? options
: [
{
label: '广',
key: 'home',
icon: () => h(HomeOutline),
href: '/',
},
{
label: '',
key: 'topic',
icon: () => h(Hash),
href: '/topic',
},
];
{
label: '广',
key: 'home',
icon: () => h(HomeOutline),
href: '/',
},
{
label: '',
key: 'topic',
icon: () => h(Hash),
href: '/topic',
},
];
});
const renderMenuLabel = (option: AnyObject) => {
@ -228,7 +201,7 @@ const renderMenuLabel = (option: AnyObject) => {
return option.label;
};
const renderMenuIcon = (option: AnyObject) => {
if (option.key === 'notification') {
if (option.key === 'messages') {
return h(
NBadge,
{
@ -285,21 +258,26 @@ window.$message = useMessage();
right: calc(50% + var(--content-main) / 2 + 10px);
padding: 12px 0;
box-sizing: border-box;
.n-menu .n-menu-item-content::before {
border-radius: 21px;
}
}
.logo-wrap {
display: flex;
justify-content: flex-start;
margin-bottom: 12px;
.logo-img {
margin-left: 24px;
&:hover {
cursor: pointer;
}
}
}
.user-wrap {
display: flex;
align-items: center;
@ -307,9 +285,11 @@ window.$message = useMessage();
bottom: 12px;
left: 12px;
right: 12px;
.user-mini-wrap {
display: none;
}
.user-avatar {
margin-right: 8px;
}
@ -350,31 +330,38 @@ window.$message = useMessage();
opacity: 0.75;
}
}
.login-wrap {
display: flex;
justify-content: center;
width: 100%;
button {
margin: 0 4px;
}
}
}
.auth-card {
.n-card-header {
z-index: 999;
}
}
@media screen and (max-width: 821px) {
.sidebar-wrap {
width: 65px;
right: calc(100% - 60px);
}
.logo-wrap {
.logo-img {
margin-left: 12px !important;
}
}
.user-wrap {
.user-avatar,
.user-info,
.login-wrap {

@ -0,0 +1,105 @@
<template>
<n-modal
:show="show"
@update:show="closeModal"
class="whisper-card"
preset="card"
size="small"
title="申请添加朋友"
:mask-closable="false"
:bordered="false"
:style="{
width: '360px',
}"
>
<div class="whisper-wrap">
<n-alert :show-icon="false">
:
<n-ellipsis style="max-width: 100%">
<n-gradient-text type="success">
{{ user.nickname }}@{{ user.username }}
</n-gradient-text>
</n-ellipsis>
</n-alert>
<div class="whisper-line">
<n-input
type="textarea"
placeholder="请输入真挚的问候语"
:autosize="{
minRows: 5,
maxRows: 10,
}"
v-model:value="content"
maxlength="120"
show-count
/>
</div>
<div class="whisper-line send-wrap">
<n-button
strong
secondary
type="primary"
:loading="loading"
@click="sendWhisper"
>
</n-button>
</div>
</div>
</n-modal>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { requestingFriend } from '@/api/user';
const props = withDefaults(
defineProps<{
show: boolean;
user: Item.UserInfo;
}>(),
{
show: false,
}
);
const content = ref('');
const loading = ref(false);
const emit = defineEmits<{
(e: 'success'): void;
}>();
const closeModal = () => {
emit('success');
};
const sendWhisper = () => {
loading.value = true;
requestingFriend({
user_id: props.user.id,
greetings: content.value,
})
.then((res: any) => {
window.$message.success('');
loading.value = false;
content.value = '';
closeModal();
})
.catch((err: any) => {
loading.value = false;
});
};
</script>
<style lang="less" scoped>
.whisper-wrap {
.whisper-line {
margin-top: 10px;
&.send-wrap {
.n-button {
width: 100%;
}
}
}
}
</style>

@ -26,6 +26,14 @@ const routes = [
},
component: () => import('@/views/Topic.vue'),
},
{
path: '/anouncement',
name: 'anouncement',
meta: {
title: '公告',
},
component: () => import('@/views/Anouncement.vue'),
},
{
path: '/profile',
name: 'profile',
@ -43,12 +51,12 @@ const routes = [
component: () => import('@/views/User.vue'),
},
{
path: '/notification',
name: 'notification',
path: '/messages',
name: 'messages',
meta: {
title: '提醒',
title: '消息',
},
component: () => import('@/views/Notification.vue'),
component: () => import('@/views/Messages.vue'),
},
{
path: '/collection',
@ -59,12 +67,12 @@ const routes = [
component: () => import('@/views/Collection.vue'),
},
{
path: '/star',
name: 'star',
path: '/contacts',
name: 'contacts',
meta: {
title: '点赞',
title: '好友',
},
component: () => import('@/views/Star.vue'),
component: () => import('@/views/Contacts.vue'),
},
{
path: '/wallet',

@ -11,8 +11,12 @@ declare module Item {
avatar: string,
/** 用户手机号 */
phone?: string,
/** 激活码 */
activation?: string,
/** 是否为管理员 */
is_admin: boolean,
/** 是否好友 */
is_friend: boolean,
/** 用户余额(分) */
balance?: number,
/** 用户状态 */
@ -106,6 +110,15 @@ declare module Item {
is_del?: 0 | 1
}
/** 联系人数据 */
interface ContactItemProps {
user_id: number,
username: string,
nickname: string,
avatar: string,
phone?: string,
}
/** 帖子内容 */
interface PostItemProps {
/** 内容ID */
@ -191,7 +204,7 @@ declare module Item {
interface MessageProps {
id: number,
/** 类型1为动态2为评论3为回复4为私信99为系统通知 */
/** 类型1为动态2为评论3为回复4为私信5为好友申请 99为系统通知 */
type: import('@/utils/IEnum').MessageTypeEnum,
/** 摘要说明 */
brief: string,
@ -227,6 +240,13 @@ declare module Item {
is_del?: 0 | 1
}
interface ContactsItemProps {
user_id: number,
name: string,
nickname: string,
avatar: string
}
interface AttachmentProps {
id: number,
/** 类别1为图片2为视频3为其他附件 */

@ -52,11 +52,6 @@ declare module NetParams {
page_size: number
}
interface UserGetStars {
page: number,
page_size: number
}
interface UserGetUserProfile {
username: string
}
@ -84,6 +79,12 @@ declare module NetParams {
captcha: string
}
interface UserActivation {
activate_code: string,
captcha_id: string,
imgCaptcha: string
}
interface UserGetCaptcha {
}
@ -93,6 +94,28 @@ declare module NetParams {
content: string
}
interface RequestingFriend {
user_id: number,
greetings: string
}
interface AddFriend {
user_id: number
}
interface RejectFriend {
user_id: number
}
interface DeleteFriend {
user_id: number
}
interface GetContacts {
page: number,
page_size: number
}
interface UserChangePassword {
/** 新密码 */
password: string,
@ -155,6 +178,9 @@ declare module NetParams {
id: number
}
interface GetContacts {
}
interface PostCreatePost {
/** 帖子内容列表 */
contents: Partial<Item.PostItemProps>[],

@ -51,13 +51,6 @@ declare module NetReq {
pager: Item.PagerProps
}
interface UserGetStars {
/** 帖子列表 */
list: Item.PostProps[],
/** 页码信息 */
pager: Item.PagerProps
}
type UserGetUserProfile = Item.UserInfo
interface UserGetBills {
@ -97,6 +90,27 @@ declare module NetReq {
}
interface AddFriend {
}
interface DeleteFriend {
}
interface GetContacts {
contacts: Item.ContactsItemProps,
total: number
}
interface RejectFriend {
}
interface RequestingFriend {
}
type PostGetPost = Item.PostProps
interface PostGetPosts {
@ -164,4 +178,11 @@ declare module NetReq {
}
interface GetContacts {
/** 评论列表 */
list: Item.ContactItemProps[],
/** 页码信息 */
pager: Item.PagerProps
}
}

@ -54,10 +54,23 @@ export enum MessageTypeEnum {
REPLY = 3,
/** 私信 */
PRIVATELETTER = 4,
/** 添加好友申请 */
REQUESTINGFRIEND = 5,
/** 系统通知 */
SYSTEMNOTICE = 99
}
export enum RequestingFriendStatusEnum {
/** 请求好友 */
REQUESTING = 1,
/** 已同意好友 */
AGREE = 2,
/** 已拒绝 */
REJECT = 3,
/** 已删除 */
DELETED= 4
}
/** 动态可见度枚举 */
export enum VisibilityEnum {
/** 公开 */

@ -0,0 +1,131 @@
<template>
<div>
<main-nav title="公告" />
<n-list class="main-content-wrap" bordered>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination :page="page" @update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-count="totalPage" />
</div>
</template>
<div v-if="loading" class="skeleton-wrap">
<post-skeleton :num="pageSize" />
</div>
<div v-else>
<div class="empty-wrap" v-if="list.length === 0">
<n-empty size="large" description="暂无数据" />
</div>
<n-list-item v-for="bill in list" :key="bill.id">
<div class="bill-line">
<div>NO.{{ bill.id }}</div>
<div>{{ bill.reason }}</div>
<div :class="{
income: bill.change_amount >= 0,
out: bill.change_amount < 0,
}">
{{
(bill.change_amount > 0 ? '+' : '') +
(bill.change_amount / 100).toFixed(2)
}}
</div>
<div>
{{ formatRelativeTime(bill.created_on) }}
</div>
</div>
</n-list-item>
</div>
</n-list>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useStore } from 'vuex';
import { useRoute } from 'vue-router';
import { formatRelativeTime } from '@/utils/formatTime';
const store = useStore();
const route = useRoute();
const loading = ref(false);
const list = ref<Item.BillProps[]>([]);
const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20);
const totalPage = ref(0);
const updatePage = (p: number) => {
page.value = p;
// TODO
};
onMounted(() => {
// TODO
});
</script>
<style lang="less" scoped>
.balance-wrap {
padding: 16px;
.balance-line {
display: flex;
justify-content: space-between;
.balance-opts {
display: flex;
flex-direction: column;
}
}
}
.bill-line {
padding: 16px;
display: flex;
justify-content: space-between;
.income,
.out {
font-weight: bold;
}
.income {
color: #18a058;
}
}
.pagination-wrap {
padding: 10px;
display: flex;
justify-content: center;
overflow: hidden;
}
.qrcode-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.pay-tips {
margin-top: 16px;
}
.pay-sub-tips {
margin-top: 4px;
font-size: 12px;
opacity: 0.75;
display: flex;
align-items: center;
}
}
.dark {
.income {
color: #63e2b7;
}
}
</style>

@ -4,7 +4,7 @@
<n-list class="main-content-wrap" bordered>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination
:page="page"
@update:page="updatePage"

@ -1,16 +1,13 @@
<template>
<div>
<main-nav title="点赞" />
<main-nav title="好友" />
<n-list class="main-content-wrap" bordered>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<n-pagination
:page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage"
/>
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination :page="page" @update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-count="totalPage" />
</div>
</template>
@ -22,8 +19,10 @@
<n-empty size="large" description="暂无数据" />
</div>
<n-list-item v-for="post in list" :key="post.id">
<post-item :post="post" />
<n-list-item v-for="contact in list" :key="contact.user_id">
<contact-item
:contact="contact"
/>
</n-list-item>
</div>
</n-list>
@ -31,45 +30,52 @@
</template>
<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue';
import { ref, onMounted } from 'vue';
import { getContacts } from '@/api/post';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import { getStars } from '@/api/user';
import { useRoute } from 'vue-router';
const store = useStore();
const route = useRoute();
const router = useRouter();
const loading = ref(false);
const list = ref<Item.PostProps[]>([]);
const list = ref<Item.ContactItemProps[]>([]);
const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20);
const totalPage = ref(0);
const loadPosts = () => {
loading.value = true;
getStars({
const updatePage = (p: number) => {
page.value = p;
loadContacts();
};
onMounted(() => {
loadContacts()
});
const loadContacts = (scrollToBottom: boolean = false) => {
if (list.value.length === 0) {
loading.value = true;
}
getContacts({
page: page.value,
page_size: pageSize.value,
})
.then((rsp) => {
.then((res) => {
loading.value = false;
list.value = rsp.list;
totalPage.value = Math.ceil(rsp.pager.total_rows / pageSize.value);
list.value = res.list;
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
window.scrollTo(0, 0);
if (scrollToBottom) {
setTimeout(() => {
window.scrollTo(0, 99999);
}, 50);
}
})
.catch((err) => {
loading.value = false;
});
};
const updatePage = (p: number) => {
page.value = p;
loadPosts();
};
onMounted(() => {
loadPosts();
});
</script>
<style lang="less" scoped>

@ -4,7 +4,7 @@
<n-list class="main-content-wrap" bordered>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination
:page="page"
@update:page="updatePage"
@ -96,24 +96,24 @@ const onPostSuccess = (post: Item.PostProps) => {
}
// 如果实在第一页,就地插入新推文到文章列表中
let items = [];
let length = list.value.length;
if (length == pageSize.value) {
let items = [];
let length = list.value.length;
if (length == pageSize.value) {
length--;
}
var i = 0;
for (;i < length; i++) {
}
var i = 0;
for (;i < length; i++) {
let item: Item.PostProps = list.value[i];
if (!item.is_top) {
break;
}
items.push(item);
}
items.push(post);
for (;i < length; i++) {
}
items.push(post);
for (;i < length; i++) {
items.push(list.value[i]);
}
list.value = items;
}
list.value = items;
};
const updatePage = (p: number) => {
@ -145,7 +145,6 @@ watch(
}
if (from.path !== '/post' && to.path === '/') {
page.value = +(route.query.p as string) || 1;
setTimeout(() => {
loadPosts();
}, 0);

@ -1,6 +1,6 @@
<template>
<div>
<main-nav title="提醒" />
<main-nav title="消息" />
<n-list class="main-content-wrap messages-wrap" bordered>
<div v-if="loading" class="skeleton-wrap">
@ -18,7 +18,7 @@
</div>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination
:page="page"
@update:page="updatePage"

@ -5,7 +5,7 @@
<n-list class="main-content-wrap" bordered>
<n-list-item>
<n-spin :show="loading">
<div class="detail-wrap" v-if="post.id > 0">
<div class="detail-wrap" v-if="post.id > 1">
<post-detail :post="post" @reload="loadPost" />
</div>
<div class="empty-wrap" v-else>

@ -21,7 +21,7 @@
</div>
</div>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination
:page="page"
@update:page="updatePage"

@ -1,6 +1,6 @@
<template>
<div>
<main-nav title="设置" />
<main-nav title="设置" theme />
<n-card title="基本信息" size="small" class="setting-card">
<div class="base-line avatar">
<n-avatar
@ -72,9 +72,7 @@
</div>
</n-card>
<n-card
v-if="allowPhoneBind"
title="手机号" size="small" class="setting-card">
<n-card v-if="allowPhoneBind" title="手机号" size="small" class="setting-card">
<div
v-if="
store.state.userInfo.phone &&
@ -95,7 +93,7 @@
</div>
<div v-else>
<n-alert title="手机绑定提示" type="warning">
~<br />
~<br />
<a
class="hash-link"
@click="showPhoneBind = true"
@ -182,6 +180,93 @@
</div>
</n-card>
<n-card v-if="allowActivation" title="激活码" size="small" class="setting-card">
<div
v-if="
store.state.userInfo.activation &&
store.state.userInfo.activation.length > 0
"
>
{{ store.state.userInfo.activation }}
<n-button
quaternary
round
type="success"
v-if="!showActivation"
@click="showActivation = true"
>
</n-button>
</div>
<div v-else>
<n-alert title="激活码激活提示" type="warning">
/~<br />
<a
class="hash-link"
@click="showActivation = true"
v-if="!showActivation"
>
</a>
</n-alert>
</div>
<div class="phone-bind-wrap" v-if="showActivation">
<n-form
ref="activateFormRef"
:model="activateData"
:rules="activateRules"
>
<n-form-item path="activate_code" label="激活码">
<n-input
:value="activateData.activate_code"
@update:value="(v: string) => (activateData.activate_code = v.trim())"
placeholder="请输入激活码"
@keydown.enter.prevent
/>
</n-form-item>
<n-form-item path="img_captcha" label="图形验证码">
<div class="captcha-img-wrap">
<n-input
v-model:value="activateData.imgCaptcha"
placeholder="请输入图形验证码后获取验证码"
/>
<div class="captcha-img">
<img
v-if="activateData.b64s"
:src="activateData.b64s"
@click="loadCaptcha4Activate"
/>
</div>
</div>
</n-form-item>
<n-row :gutter="[0, 24]">
<n-col :span="24">
<div class="form-submit-wrap">
<n-button
quaternary
round
@click="showActivation = false"
>
</n-button>
<n-button
secondary
round
type="primary"
:loading="activating"
@click="handleActivation"
>
</n-button>
</div>
</n-col>
</n-row>
</n-form>
</div>
</n-card>
<n-card title="账户安全" size="small" class="setting-card">
<n-button
@ -262,6 +347,7 @@ import {
getCaptcha,
sendCaptcha,
bindUserPhone,
activateUser,
changePassword,
changeNickname,
changeAvatar,
@ -274,14 +360,17 @@ import type {
InputInst,
} from 'naive-ui';
const allowPhoneBind= (import.meta.env.VITE_ALLOW_PHONE_BIND.toLocaleLowerCase() === 'true')
const uploadGateway = import.meta.env.VITE_HOST + '/v1/attachment';
const uploadToken = 'Bearer ' + localStorage.getItem('PAOPAO_TOKEN');
const uploadType = ref('public/avatar');
const allowPhoneBind = (import.meta.env.VITE_ALLOW_PHONE_BIND.toLowerCase() === 'true')
const allowActivation = (import.meta.env.VITE_ALLOW_ACTIVATION.toLowerCase() === 'true')
const store = useStore();
const sending = ref(false);
const binding = ref(false);
const activating = ref(false)
const avatarRef = ref<UploadInst>();
const inputInstRef = ref<InputInst>();
const showNicknameEdit = ref(false);
@ -290,7 +379,9 @@ const showPasswordSetting = ref(false);
const smsDisabled = ref(false);
const smsCounter = ref(60);
const showPhoneBind = ref(false);
const showActivation = ref(false);
const phoneFormRef = ref<FormInst>();
const activateFormRef = ref<FormInst>();
const formRef = ref<FormInst>();
const rPasswordFormItemRef = ref<FormItemInst>();
const modelData = reactive({
@ -304,6 +395,13 @@ const modelData = reactive({
reenteredPassword: '',
});
const activateData = reactive({
id: '',
b64s: '',
imgCaptcha: '',
activate_code: '',
});
const beforeUpload = async (data: any) => {
// 图片类型校验
if (
@ -426,6 +524,46 @@ const handlePhoneBind = (e: MouseEvent) => {
});
};
const handleActivation = (e: MouseEvent) => {
e.preventDefault();
activateFormRef.value?.validate((errors) => {
if (activateData.imgCaptcha === '') {
window.$message.warning('');
return;
}
sending.value = true;
if (!errors) {
activating.value = true;
activateUser({
activate_code: activateData.activate_code,
captcha_id: activateData.id,
imgCaptcha: activateData.imgCaptcha
})
.then((res) => {
activating.value = false;
showActivation.value = false;
window.$message.success('');
store.commit('updateUserinfo', {
...store.state.userInfo,
activation: activateData.activate_code,
});
activateData.id = '';
activateData.b64s = '';
activateData.imgCaptcha = '';
activateData.activate_code = '';
})
.catch((err) => {
activating.value = false;
if (err.code === 20012) {
loadCaptcha4Activate();
}
});
}
});
};
const loadCaptcha = () => {
getCaptcha()
.then((res) => {
@ -437,6 +575,17 @@ const loadCaptcha = () => {
});
};
const loadCaptcha4Activate = () => {
getCaptcha()
.then((res) => {
activateData.id = res.id;
activateData.b64s = res.b64s;
})
.catch((err) => {
console.log(err);
});
};
const handleNicknameChange = () => {
changeNickname({
nickname: store.state.userInfo.nickname || '',
@ -505,6 +654,18 @@ const bindRules = {
},
],
};
const activateRules = {
activate_code: [
{
required: true,
message: '',
trigger: ['input'],
validator: (rule: FormItemRule, value: any) => {
return /\d{6}$/.test(value);
},
},
],
};
const passwordRules = {
password: [
{
@ -548,6 +709,7 @@ onMounted(() => {
store.commit('triggerAuthKey', 'signin');
}
loadCaptcha();
loadCaptcha4Activate();
});
</script>
@ -585,6 +747,10 @@ onMounted(() => {
}
}
.hash-link {
margin-left: 12px;
}
.phone-bind-wrap {
margin-top: 20px;
.captcha-img-wrap {

@ -13,48 +13,43 @@
<div class="username">
<strong>{{ user.nickname }}</strong>
<span> @{{ user.username }} </span>
<n-tag
v-if="store.state.userInfo.id > 0 && store.state.userInfo.username != user.username && user.is_friend"
class="top-tag" type="info" size="small" round>
</n-tag>
<n-tag v-if="user.is_admin" class="top-tag" type="error" size="small" round>
</n-tag>
</div>
<div class="uid">UID. {{ user.id }}</div>
</div>
<div class="user-opts" v-if="store.state.userInfo.id > 0">
<n-space>
<n-button
size="small"
secondary
type="primary"
@click="openWhisper"
>
<div class="user-opts"
v-if="store.state.userInfo.id > 0 && store.state.userInfo.username != user.username">
<n-dropdown placement="bottom-end" trigger="click" size="small" :options="userOptions"
@select="handleUserAction">
<n-button quaternary circle>
<template #icon>
<n-icon>
<more-horiz-filled />
</n-icon>
</template>
</n-button>
<n-button
v-if="store.state.userInfo.is_admin"
size="small"
secondary
:type="user.status === 1 ? 'error' : 'warning'"
@click="banUser"
>
{{ user.status === 1 ? '' : '' }}
</n-button>
</n-space>
</n-dropdown>
</div>
</div>
<!-- -->
<whisper
:show="showWhisper"
:user="user"
@success="whisperSuccess"
/>
<whisper :show="showWhisper" :user="user" @success="whisperSuccess" />
<!-- -->
<whisper-add-friend :show="showAddFriendWhisper" :user="user" @success="addFriendWhisperSuccess" />
</n-spin>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<n-pagination
:page="page"
@update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5"
:page-count="totalPage"
/>
<n-pagination :page="page" @update:page="updatePage"
:page-slot="!store.state.collapsedRight ? 8 : 5" :page-count="totalPage" />
</div>
</template>
<n-tabs class="profile-tabs-wrap" animated>
@ -78,11 +73,14 @@
</template>
<script setup lang="ts">
import { ref, reactive, watch, onMounted } from 'vue';
import { ref, reactive, watch, onMounted, computed } from 'vue';
import { useStore } from 'vuex';
import { useRoute } from 'vue-router';
import { getUserProfile, getUserPosts, changeUserStatus } from '@/api/user';
import { useDialog, useMessage } from 'naive-ui';
import { getUserProfile, getUserPosts, changeUserStatus, deleteFriend } from '@/api/user';
import { useDialog, useMessage, DropdownOption } from 'naive-ui';
import WhisperAddFriend from '../components/whisper-add-friend.vue';
import { MoreHorizFilled } from '@vicons/material';
import { VisibilityEnum } from '@/utils/IEnum';
const message = useMessage();
const dialog = useDialog();
@ -96,10 +94,12 @@ const user = reactive<Item.UserInfo>({
username: '',
nickname: '',
is_admin: false,
is_friend: true,
status: 1,
});
const userLoading = ref(false);
const showWhisper = ref(false);
const showAddFriendWhisper = ref(false);
const list = ref<Item.PostProps[]>([]);
const username = ref(route.query.username || '');
const page = ref(+(route.query.p as string) || 1);
@ -136,6 +136,7 @@ const loadUser = () => {
user.username = res.username;
user.nickname = res.nickname;
user.is_admin = res.is_admin;
user.is_friend = res.is_friend;
user.status = res.status;
loadPosts();
})
@ -153,9 +154,90 @@ const updatePage = (p: number) => {
const openWhisper = () => {
showWhisper.value = true;
};
const openAddFriendWhisper = () => {
showAddFriendWhisper.value = true;
};
const whisperSuccess = () => {
showWhisper.value = false;
};
const addFriendWhisperSuccess = () => {
showAddFriendWhisper.value = false;
};
const userOptions = computed(() => {
let options: DropdownOption[] = [{
label: '',
key: 'whisper',
}];
if (store.state.userInfo.is_admin) {
if (user.status === 1) {
options.push({
label: '',
key: 'banned',
});
} else {
options.push({
label: '',
key: 'deblocking',
});
}
}
if (user.is_friend) {
options.push({
label: '',
key: 'delete',
});
} else {
options.push({
label: '',
key: 'requesting',
});
}
return options;
});
const handleUserAction = (
item: 'whisper' | 'delete' | 'requesting' | 'banned' | 'deblocking'
) => {
switch (item) {
case 'whisper':
openWhisper();
break;
case 'delete':
openDeleteFriend();
break;
case 'requesting':
openAddFriendWhisper();
break;
case 'banned':
case 'deblocking':
banUser();
break;
default:
break;
}
};
const openDeleteFriend = () => {
dialog.warning({
title: '',
content: ' ' + user.nickname + ' / ',
positiveText: '',
negativeText: '',
onPositiveClick: () => {
userLoading.value = true;
deleteFriend({
user_id: user.id,
})
.then((res) => {
userLoading.value = false;
user.is_friend = false
loadPosts();
})
.catch((err) => {
userLoading.value = false;
console.log(err);
});
},
});
};
const banUser = () => {
dialog.warning({
title: '',
@ -203,6 +285,7 @@ onMounted(() => {
.profile-tabs-wrap {
padding: 0 16px;
}
.profile-baseinfo {
display: flex;
padding: 16px;
@ -226,12 +309,17 @@ onMounted(() => {
margin-top: 10px;
opacity: 0.75;
}
.top-tag {
transform: scale(0.75);
}
}
.user-opts {
position: absolute;
top: 16px;
right: 16px;
opacity: 0.75;
}
}

@ -37,7 +37,7 @@
</div>
<template #footer>
<div class="pagination-wrap" v-if="totalPage > 0">
<div class="pagination-wrap" v-if="totalPage > 1">
<n-pagination
:page="page"
@update:page="updatePage"

@ -5,15 +5,23 @@
interface ImportMetaEnv {
readonly VITE_HOST: string
readonly VITE_ENABLE_ANOUNCEMENT: string
readonly VITE_ENABLE_WALLET: string
readonly VITE_ALLOW_PHONE_BIND: string
readonly VITE_ALLOW_ACTIVATION: string
readonly VITE_ALLOW_TWEET_ATTACHMENT: string
readonly VITE_ALLOW_TWEET_ATTACHMENT_PRICE: string
readonly VITE_ALLOW_TWEET_VIDEO: string
readonly VITE_ALLOW_TWEET_LABEL: string
readonly VITE_ALLOW_TWEET_VISIBILITY: string
readonly VITE_ALLOW_PHONE_BIND: string
readonly VITE_DEFAULT_TWEET_VISIBILITY: string
readonly VITE_DEFAULT_TWEET_IMAGE_404: string
readonly VITE_TWEET_IMAGE_THUMBNAIL: string
readonly VITE_COPYRIGHT_TOP: string
readonly VITE_COPYRIGHT_LEFT: string
readonly VITE_COPYRIGHT_LEFT_LINK: string
readonly VITE_COPYRIGHT_RIGHT: string
readonly VITE_COPYRIGHT_RIGHT_LINK: string
}
interface ImportMeta {

@ -4,14 +4,12 @@ import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
import { changePackageVersion } from './build/plugins';
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: '0.0.0.0'
},
plugins: [
changePackageVersion(),
vue({
reactivityTransform: [/src/]
}),

@ -84,65 +84,65 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@tauri-apps/cli-darwin-arm64@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0.tgz#9ab439898b4d05a6e43df4451a42fa21e9d5eaa1"
integrity sha512-0ryomgLjdpylXypMPVXLU3PZCde3Sw5nwN4coUhBcHPBLFRb8QPet+nweVK/HiZ3mxg8WeIazvpx2s8hS0l2GQ==
"@tauri-apps/cli-darwin-arm64@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.1.1.tgz#c6f4553cfb338f24131910a1ebbe9fe74d89b8ae"
integrity sha512-qBG11ig525/qf0f5OQxn0ON3hT8YdpTfpa4Y4kVqBJhdW50R5fadPv6tv5Dpl2TS2X7nWh/zg5mEXYoCK3HZ9w==
"@tauri-apps/cli-darwin-x64@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0.tgz#5ffc8d444c7dc1cab14c8c743a929e448f1b1e93"
integrity sha512-oejvYUT4dEfzBi+FWMj+CMz4cZ6C2gEFHrUtKVLdTXr8Flj5UTwdB1YPGQjiOqk73LOI7cB/vXxb9DZT+Lrxgg==
"@tauri-apps/cli-darwin-x64@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.1.1.tgz#11beb8b3dfc43725f0acd3736cd9d181f93526a2"
integrity sha512-M3dMsp78OdxisbTwAWGvy3jIb3uqThtQcUYVvqOu9LeEOHyldOBFDSht+6PTBpaJLAHFMQK2rmNxiWgigklJaA==
"@tauri-apps/cli-linux-arm-gnueabihf@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0.tgz#c24d63b4637a0c20b9671f0284968b164482f6ee"
integrity sha512-yAu78v8TeXNx/ETS5F2G2Uw/HX+LQvZkX94zNiqFsAj7snfWI/IqSUM52OBrdh/D0EC9NCdjUJ7Vuo32uxf7tg==
"@tauri-apps/cli-linux-arm-gnueabihf@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.1.1.tgz#f4bd3f5839cfcd69132d213efee09ce5da5c6d90"
integrity sha512-LYlvdAd73cq+yTi6rw7j/DWIvDpeApwgQkIn+HYsNNeFhyFmABU7tmw+pekK3W3nHAkYAJ69Rl4ZdoxdNGKmHg==
"@tauri-apps/cli-linux-arm64-gnu@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0.tgz#dfb107a3d5f56dc0356126135f941261ffad10a3"
integrity sha512-YFUN/S58AN317njAynzcQ+EHhRsCDXqmp5g9Oiqmcdg1vU7fPWZivVLc1WHz+0037C7JnsX5PtKpNYewP/+Oqw==
"@tauri-apps/cli-linux-arm64-gnu@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.1.1.tgz#2631b2a68e7901ea7281af022d8826c0d82b9edd"
integrity sha512-o/hbMQIKuFI7cTNpeQBHD/OCNJOBIci78faKms/t6AstLXx0QJuRHDk477Rg6VVy/I3BBKbyATALbmcTq+ti0A==
"@tauri-apps/cli-linux-arm64-musl@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0.tgz#72ebfc5066c6fac82b513c20fbec6ab841b3ee05"
integrity sha512-al+TxMGoNVikEvRQfMyYE/mdjUcUNMo5brkCIAb+fL4rWQlAhAnYVzmg/rM8N4nhdXm1MOaYAagQmxr8898dNA==
"@tauri-apps/cli-linux-arm64-musl@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.1.1.tgz#11a4bdc52696583152fc70ea373cf31717cb0f4c"
integrity sha512-8Ci4qlDnXIp93XqUrtzFCBDatUzPHpZq7L3bociUbWpvy/bnlzxp1C/C+vwdc4uS1MiAp9v3BFgrU4i0f0Z3QQ==
"@tauri-apps/cli-linux-x64-gnu@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0.tgz#76f791378468a9ca2678885f0d14e05f4fd0d0c8"
integrity sha512-KQmYlYyGpn6/2kSl9QivWG6EIepm6PJd57e6IKmYwAyNhLr2XfGl1CLuocUQQgO+jprjT70HXp+MXD0tcB0+Sw==
"@tauri-apps/cli-linux-x64-gnu@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.1.1.tgz#11acbcc4743562cc8166c92ffc3bc12f68e0987f"
integrity sha512-ES4Bkx2JAI8+dDNDJswhLS3yqt+yT/4C6UfGOPIHFxcXUh6fe36eUllrTt+HLRS9xTZbYnteJy7ebq2TqMkaxw==
"@tauri-apps/cli-linux-x64-musl@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0.tgz#12ccc0747c88e9c2cbdf21834b94718c8da689ca"
integrity sha512-Qpaq5lZz569Aea6jfrRchgfEJaOrfLpCRBATcF8CJFFwVKmfCUcoV+MxbCIW30Zqw5Y06njC/ffa3261AV/ZIQ==
"@tauri-apps/cli-linux-x64-musl@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.1.1.tgz#7dd81b8380d7e7183fb43a2ccbbc26931718204a"
integrity sha512-qrN1WOMAaDl+LE8P8iO0+DYlrWNTc9jIu/CsnVY/LImTn79ZPxEkcVBo0UGeKRI7f10TfvkVmLCBLxTz8QhEyA==
"@tauri-apps/cli-win32-ia32-msvc@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0.tgz#5d56df6dbb62c11cae28b826619fbbad9a158399"
integrity sha512-e2DzFqEMI+s+gv14UupdI91gPxTbUJTbbfQlTHdQlOsTk4HEZTsh+ibAYBcCLAaMRW38NEsFlAUe1lQA0iRu/w==
"@tauri-apps/cli-win32-ia32-msvc@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.1.1.tgz#1d106ae1c3766f95d7f49bac51eba0d2cd2daf33"
integrity sha512-vw7VOmrQlywHhFV3pf54udf2FRNj9dg9WP1gL0My55FnB+w+PWS9Ipm871kX5qepmChdnZHKq9fsqE2uTjX//Q==
"@tauri-apps/cli-win32-x64-msvc@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0.tgz#6227331d177118323cff13bc6bfb04894130c83f"
integrity sha512-lWSs90pJeQX+L31IqIzmRhwLayEeyTh7mga0AxX8G868hvdLtcXCQA/rKoFtGdVLuHAx4+M+CBF5SMYb76xGYA==
"@tauri-apps/cli-win32-x64-msvc@1.1.1":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.1.1.tgz#ce931d299fcc8c60aceec3f9e18b0987f9951c25"
integrity sha512-OukxlLLi3AoCN4ABnqCDTiiC7xJGWukAjrKCIx7wFISrLjNfsrnH7/UOzuopfGpZChSe2c+AamVmcpBfVsEmJA==
"@tauri-apps/cli@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.0.0.tgz#28f021a2db4c2087b569845d42b4fe7978ccee19"
integrity sha512-4eHnk3p0xnCXd9Zel3kLvdiiSURnN98GMFvWUAdirm5AjyOjcx8TIET/jqRYmYKE5yd+LMQqYMUfHRwA6JJUkg==
"@tauri-apps/cli@^1.0.4":
version "1.1.1"
resolved "https://registry.npmmirror.com/@tauri-apps/cli/-/cli-1.1.1.tgz#480d5e1ab758aa1d7efcbf97d801bf9812b15cd4"
integrity sha512-80kjMEMPBwLYCp0tTKSquy90PHHGGBvZsneNr3B/mWxNsvjzA1C0vOyGJGFrJuT2OmkvrdvuJZ5mch5hL8O1Xg==
optionalDependencies:
"@tauri-apps/cli-darwin-arm64" "1.0.0"
"@tauri-apps/cli-darwin-x64" "1.0.0"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.0.0"
"@tauri-apps/cli-linux-arm64-gnu" "1.0.0"
"@tauri-apps/cli-linux-arm64-musl" "1.0.0"
"@tauri-apps/cli-linux-x64-gnu" "1.0.0"
"@tauri-apps/cli-linux-x64-musl" "1.0.0"
"@tauri-apps/cli-win32-ia32-msvc" "1.0.0"
"@tauri-apps/cli-win32-x64-msvc" "1.0.0"
"@tauri-apps/cli-darwin-arm64" "1.1.1"
"@tauri-apps/cli-darwin-x64" "1.1.1"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.1.1"
"@tauri-apps/cli-linux-arm64-gnu" "1.1.1"
"@tauri-apps/cli-linux-arm64-musl" "1.1.1"
"@tauri-apps/cli-linux-x64-gnu" "1.1.1"
"@tauri-apps/cli-linux-x64-musl" "1.1.1"
"@tauri-apps/cli-win32-ia32-msvc" "1.1.1"
"@tauri-apps/cli-win32-x64-msvc" "1.1.1"
"@types/jest@^27.0.1":
version "27.4.1"

Loading…
Cancel
Save