@jx3box/jx3box-common-ui 6.1.2 → 6.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Author.vue CHANGED
@@ -1,225 +1,52 @@
1
1
  <template>
2
- <div class="c-author" v-if="data">
3
- <div class="u-author">
4
- <Avatar class="u-avatar" :uid="uid" :url="data.user_avatar" :size="68" :frame="data.user_avatar_frame" />
5
- <div class="u-info">
6
- <a class="u-name" :href="authorLink(uid)" target="_blank">
7
- <span>{{ data.display_name.slice(0, 8) }}</span>
8
- <el-tooltip class="item" effect="dark" content="签约作者" placement="top" v-if="isSuperAuthor">
9
- <a class="u-superauthor" href="/dashboard/#/cooperation" target="_blank">
10
- <img :src="super_author_icon" alt="superauthor" />
11
- </a>
12
- </el-tooltip>
13
- </a>
14
- <div class="u-extend">
15
- <el-tooltip class="item" effect="dark" placement="top">
16
- <div slot="content">
17
- <span class="u-tips">经验值:{{ data.experience }}</span>
18
- </div>
19
- <span class="u-level" :class="'lv-' + level" :style={backgroundColor:showLevelColor(level)}>Lv.{{ level }}</span>
20
- </el-tooltip>
21
- <el-tooltip class="item" effect="dark" :content="vipTypeTitle" placement="top" v-if="isVip">
22
- <a class="u-vip" href="/vip/premium?from=sidebar_author" target="_blank">
23
- <i class="i-icon-vip on">{{ vipType }}</i>
24
- </a>
25
- </el-tooltip>
26
- </div>
2
+ <div class="c-author">
3
+ <AuthorInfo :uid="uid" @ready="installModules" />
4
+ <template v-if="data">
5
+ <div class="u-fans">
6
+ <AuthorFollow style="margin-right: 8px;" :uid="uid" />
7
+ <AuthorGift :uid="uid" />
27
8
  </div>
28
- </div>
29
- <div class="u-bio">{{ data.user_bio }}</div>
30
- <AuthorFollow class="u-follow-box" :uid="uid" />
31
- <div class="u-link" v-if="hasLink">
32
- <a v-if="data.weibo_name" class="u-weibo" :href="weiboLink(data.weibo_id)" target="_blank">
33
- <img svg-inline src="../assets/img/author/weibo.svg" />
34
- {{ data.weibo_name }}
35
- </a>
36
- <a v-if="data.github_name" class="u-github" :href="githubLink(data.github_name)" target="_blank">
37
- <img svg-inline src="../assets/img/author/github.svg" />
38
- {{ data.github_name }}
39
- </a>
40
- <div v-if="data.tuilan_id" class="u-tuilan" title="推栏ID">
41
- <img src="../assets/img/author/tuilan.png" />
42
- {{ data.tuilan_id }}
43
- </div>
44
- <a v-if="data.tv_type && data.tv_id" class="u-tv" :href="tv_link" target="_blank">
45
- <img :src="tv_img" />
46
- {{ data.tv_id }}
47
- <span class="u-tv-living" v-if="tv_status">
48
- <div class="u-tv-living-icon">
49
- <div class="u-tv-living-icon-col first"></div>
50
- <div class="u-tv-living-icon-col"></div>
51
- <div class="u-tv-living-icon-col last"></div>
52
- </div>
53
- </span>
54
- </a>
55
- </div>
56
- <slot></slot>
57
- <div class="u-trophy" v-if="hasTrophy">
58
- <div class="u-label">
59
- <i class="el-icon-trophy"></i>
60
- <span>作者荣誉</span>
61
- </div>
62
- <div class="u-medals" v-if="medals && medals.length">
63
- <!-- <span class="u-medal" v-for="(item, i) in medals" :key="i">
64
- <img :src="showMedalIcon(item.medal)" :title="showMedalDesc(item)" />
65
- </span> -->
66
- <medal :medals="medals" :showIcon="showMedalIcon"></medal>
67
- </div>
68
- </div>
69
- <div class="u-teams" v-if="teams && teams.length">
70
- <div class="u-label">
71
- <i class="el-icon-school"></i>
72
- <span>所属团队</span>
73
- </div>
74
- <a class="u-team" v-for="(item, i) in teams" :key="i" :href="teamLink(item.team_id)" target="_blank">
75
- <img class="u-team-logo" :src="showTeamLogo(item.team_logo)" />
76
- <span class="u-team-name">{{ item.team_name }}@{{ item.team_server }}</span>
77
- </a>
78
- </div>
79
- <Authorposts :uid="uid" />
9
+ <!-- <AuthorMsg :uid="uid" /> -->
10
+ <AuthorLink class="u-links" :uid="uid" :data="data" />
11
+ <AuthorMedals class="u-trophy" :uid="uid" />
12
+ <AuthorTeams class="u-teams" :uid="uid" />
13
+ <slot></slot>
14
+ <AuthorPosts class="u-posts" :uid="uid" />
15
+ </template>
80
16
  </div>
81
17
  </template>
82
18
 
83
19
  <script>
84
- // const liveStatusMap = ["等待开播", "直播中", "直播结束"];
85
- import { authorLink, tvLink, getLink, getThumbnail } from "@jx3box/jx3box-common/js/utils";
86
- import { __server, __imgPath,__userLevelColor } from "@jx3box/jx3box-common/data/jx3box.json";
87
- import { getUserInfo, getDouyu, getUserMedals, getUserPublicTeams } from "../service/author";
88
- import { user as medal_map } from "@jx3box/jx3box-common/data/medals.json";
89
- import User from "@jx3box/jx3box-common/js/user";
90
- import { __userLevel } from "@jx3box/jx3box-common/data/jx3box.json";
91
- // components
92
- import medal from './medal/medal.vue'
93
- import Avatar from "./author/Avatar.vue";
94
- import Authorposts from "./author/Authorposts.vue";
20
+ import AuthorInfo from "./author/AuthorInfo.vue";
21
+ import AuthorLink from "./author/AuthorLink.vue";
95
22
  import AuthorFollow from "./author/AuthorFollow.vue";
23
+ // import AuthorMsg from "./author/AuthorMsg.vue";
24
+ import AuthorGift from "./author/AuthorGift.vue";
25
+ import AuthorMedals from "./author/AuthorMedals.vue";
26
+ import AuthorTeams from "./author/AuthorTeams.vue";
27
+ import AuthorPosts from "./author/AuthorPosts.vue";
96
28
  export default {
97
29
  name: "Author",
98
30
  props: ["uid"],
99
- data: function() {
31
+ data: function () {
100
32
  return {
101
33
  data: "",
102
- tv: "",
103
- medals: [],
104
- medal_map,
105
- teams: [
106
- // {
107
- // team_name : '诗画印象',
108
- // team_logo : 'https://oss.jx3box.com/2019/09/logo.png',
109
- // team_server : "蝶恋花"
110
- // }
111
- ],
112
- isVIP: false,
113
34
  };
114
35
  },
115
- computed: {
116
- tv_type: function() {
117
- return this.data && this.data.tv_type;
118
- },
119
- tv_id: function() {
120
- return (this.data && this.data.tv_id) || 0;
121
- },
122
- tv_img: function() {
123
- return __imgPath + "image/tv/" + this.tv_type + ".png";
124
- },
125
- tv_link: function() {
126
- return tvLink(this.tv_type, this.tv_id) || "";
127
- },
128
- tv_status: function() {
129
- return (this.tv && this.tv.show_status == 1) || false;
130
- },
131
- super_author_icon: function() {
132
- return __imgPath + "image/user/" + "superauthor.svg";
133
- },
134
- hasLink: function() {
135
- return this.data.weibo_name || this.data.github_name || this.data.tuilan_id || this.data.tv_id;
136
- },
137
- hasTrophy: function() {
138
- return this.medals.length;
139
- },
140
- vipType: function() {
141
- return this.data?.is_pro ? "PRO" : "PRE";
142
- },
143
- vipTypeTitle: function() {
144
- return this.data?.is_pro ? "专业版会员" : "高级版会员";
145
- },
146
- isVip: function() {
147
- return this.data?.is_pro || this.data?.is_pre;
148
- },
149
- isSuperAuthor: function() {
150
- return this.data?.sign;
151
- },
152
- level: function() {
153
- return User.getLevel(this.data?.experience);
154
- },
155
- },
156
36
  methods: {
157
- loadData: function() {
158
- return getUserInfo(this.uid)
159
- .then((data) => {
160
- this.data = data;
161
- })
162
- .then(() => {
163
- this.loadMedals();
164
- this.loadTeams();
165
- });
166
- },
167
- loadTV: function() {
168
- if (this.tv_type == "douyu") {
169
- if (!this.tv_id || isNaN(this.tv_id)) return;
170
- getDouyu(this.tv_id).then((data) => {
171
- this.tv = data;
172
- });
173
- }
174
- },
175
- loadMedals: function() {
176
- getUserMedals(this.uid).then((data) => {
177
- this.medals = data;
178
- });
179
- },
180
- loadTeams: function() {
181
- getUserPublicTeams(this.uid).then((data) => {
182
- this.teams = data && data.slice(0, 5);
183
- });
184
- },
185
-
186
- // filters
187
- showMedalIcon: function(val) {
188
- return __imgPath + "image/medals/user/" + val + ".gif";
189
- },
190
- showMedalDesc: function(item) {
191
- return item.medal_desc || medal_map[item.medal];
37
+ installModules: function (data) {
38
+ this.data = data;
192
39
  },
193
- authorLink,
194
- weiboLink: function(val) {
195
- return "https://weibo.com/" + val;
196
- },
197
- githubLink: function(val) {
198
- return "https://github.com/" + val;
199
- },
200
- teamLink: function(team_id) {
201
- return getLink("org", team_id);
202
- },
203
- showTeamLogo: function(val) {
204
- return getThumbnail(val, 96);
205
- },
206
- showLevelColor:function (level){
207
- return __userLevelColor[level]
208
- }
209
- },
210
- watch: {
211
- uid: function() {
212
- this.loadData();
213
- },
214
- },
215
- mounted: function() {
216
- this.uid && this.loadData();
217
40
  },
218
41
  components: {
219
- Avatar,
220
- Authorposts,
221
- medal,
42
+ AuthorInfo,
43
+ AuthorLink,
222
44
  AuthorFollow,
45
+ // AuthorMsg,
46
+ AuthorGift,
47
+ AuthorMedals,
48
+ AuthorTeams,
49
+ AuthorPosts,
223
50
  },
224
51
  };
225
52
  </script>
@@ -0,0 +1,144 @@
1
+ <!--
2
+ * @Author: X3ZvaWQ
3
+ * @Date: 2022-08-20 20:23:57
4
+ * @LastEditors: X3ZvaWQ
5
+ * @LastEditTime: 2022-08-20 23:12:34
6
+ * @Description: 用于渲染游戏内Text标签的文本
7
+ -->
8
+ <template>
9
+ <span v-html="html"></span>
10
+ </template>
11
+
12
+ <script>
13
+ import { extractTextContent, getLink } from "@jx3box/jx3box-common/js/utils";
14
+ import { getResource } from "../service/resource";
15
+
16
+ export default {
17
+ name: "GameText",
18
+ props: {
19
+ text: {
20
+ type: String,
21
+ default: "",
22
+ },
23
+ client: {
24
+ type: String,
25
+ default: "std",
26
+ },
27
+ },
28
+ data: function () {
29
+ return {
30
+ html: "",
31
+ };
32
+ },
33
+ methods: {
34
+ /**
35
+ * 渲染某一个单独的Text标签成Span或链接
36
+ * @param {*} school_id
37
+ * @returns
38
+ */
39
+ renderItemHtml: function (item) {
40
+ let content = item.text;
41
+ let style = ``;
42
+ let link = null;
43
+ content = content.replace(/\n/g, "<br />").replace(/\\/g, "");
44
+ if ([item.r, item.g, item.b].every((v) => v != undefined && v > 0)) {
45
+ style = `color: rgb(${item.r}, ${item.g}, ${item.b});`;
46
+ } else if (item.font != undefined) {
47
+ const fonts = require("../assets/data/game_font.json");
48
+ for (let color in fonts) {
49
+ if (fonts[color].includes(item.font)) {
50
+ style = `color: ${color};`;
51
+ break;
52
+ }
53
+ }
54
+ }
55
+ if (item.name == "iteminfolink" && item.script) {
56
+ let item_type = item.script?.match(/this\.dwTabType=(\d+)/i)?.[1];
57
+ let item_index = item.script?.match(/this\.dwIndex=(\d+)/i)?.[1];
58
+ if (item_type && item_index) {
59
+ let item_id = `${item_type}_${item_index}`;
60
+ link = getLink("item", item_id);
61
+ }
62
+ }
63
+ if (link) {
64
+ return `<a style="${style} text-decoration: none;" target="_blank" href="${link}">${content}</a>`;
65
+ } else {
66
+ return `<span style="${style}">${content}</span>`;
67
+ }
68
+ },
69
+ /**
70
+ * 将一段游戏内文本转换为Html
71
+ * @param {Object[]} texts 标签对象
72
+ */
73
+ renderTextHtml: function (Text) {
74
+ let result = Text;
75
+ const matches = Text.match(/<Text>(.*?)<\/text>/gimsy);
76
+ if (!matches) return Text;
77
+ for (let match of matches) {
78
+ let text = extractTextContent(match);
79
+ let html = this.renderItemHtml(text[0]);
80
+ result = result.replace(match, html);
81
+ }
82
+ return result;
83
+ },
84
+ /**
85
+ * 获取形如<BUFF 110 1 desc>的资源字段并转换
86
+ */
87
+ renderResource: function () {
88
+ const matches = this.html.match(/<BUFF (\d+) (\d+) (.*?)>/gim);
89
+ if (!matches) return;
90
+ for (let match of matches) {
91
+ let [, id, level, type] = match.match(/<BUFF (\d+) (\d+) (.*?)>/i);
92
+ type = type.toLowerCase();
93
+ let type_map = {
94
+ desc: "Desc",
95
+ time: "Interval",
96
+ };
97
+ getResource(`buff.${id}_${level}`, this.client)
98
+ .then((res) => {
99
+ let data = res.data;
100
+ let attr = type_map[type] || type;
101
+ let value = data[attr];
102
+ if (typeof value == "number" && type == "time") {
103
+ let time = value / 16;
104
+ if (time > 60) {
105
+ time = `${Math.floor(time / 60)}分钟`;
106
+ } else {
107
+ time = `${time}秒`;
108
+ }
109
+ this.html = this.html.replace(match, time);
110
+ return;
111
+ }
112
+ if (!value) return;
113
+ let _matches = value.match(/<BUFF ([0-9a-zA-Z]+)>/gi);
114
+ if (!_matches) this.html = this.html.replace(match, value);
115
+ for (let _match of _matches) {
116
+ let [, _attr] = _match.match(/<BUFF ([0-9a-zA-Z]+)>/i);
117
+ for (let i = 1; i < 15; i++) {
118
+ if (data[`BeginAttrib${i}`] == _attr) {
119
+ value = value.replace(_match, data[`BeginValue${i}A`]);
120
+ }
121
+ }
122
+ }
123
+ this.html = this.html.replace(match, value);
124
+ })
125
+ .catch((err) => {
126
+ console.log(err);
127
+ });
128
+ }
129
+ },
130
+ },
131
+ watch: {
132
+ text: {
133
+ immediate: true,
134
+ handler: function (val) {
135
+ this.html = this.renderTextHtml(val);
136
+ this.renderResource();
137
+ },
138
+ },
139
+ },
140
+ };
141
+ </script>
142
+
143
+ <style>
144
+ </style>
@@ -1,45 +1,31 @@
1
1
  <template>
2
- <div class="u-follow">
3
- <!-- <template v-if="isLogin">
4
- <template v-if="isSelf">
5
- <div class="u-fans-box">
6
- <span class="u-fans-label">关注</span>
7
- <span class="u-fans">{{ formatFansNum(fansNum) }}</span>
8
- </div>
9
- </template>
10
- <template v-else>
11
-
12
- </template>
13
- </template>
14
- <el-button class="u-fans-box" @click="follow" size="mini" v-else>
15
- <span class="u-fans-label">关注</span>
16
- <span class="u-fans">{{ formatFansNum(fansNum) }}</span>
17
- </el-button> -->
2
+ <div class="c-author-follow">
18
3
  <el-button
19
4
  v-if="!isFollow"
5
+ class="u-btn"
20
6
  :class="{ 'is-follow': isFollow, 'u-fans-box': isSelf }"
21
7
  size="mini"
22
- :icon="!isSelf && btnIcon"
8
+ plain
9
+ :icon="btnIcon"
23
10
  @click="follow"
24
- :type="isSelf ? '' : btnType"
25
11
  :loading="loading"
26
12
  :disabled="isSelf"
27
13
  >
28
- {{ btnText }}<span class="u-follow-count">{{ formatFansNum(fansNum) }}</span>
14
+ {{ btnText }}
15
+ <!-- <span class="u-follow-count">{{ formatFansNum(fansNum) }} </span> -->
29
16
  </el-button>
30
- <el-popover
31
- v-else
32
- placement="bottom"
33
- trigger="hover"
34
- popper-class="u-follow-popover"
35
- :visible-arrow="false"
36
- >
17
+ <el-popover v-else placement="bottom" trigger="hover" popper-class="u-follow-popover" :visible-arrow="false">
37
18
  <div class="u-action-list">
38
- <div class="u-action-item" v-for="item in actions" :key="item.label" @click.stop="item.action">{{ item.label }}</div>
19
+ <div class="u-action-item" v-for="item in actions" :key="item.label" @click.stop="item.action">
20
+ {{ item.label }}
21
+ </div>
39
22
  </div>
40
- <el-button class="u-unfollow-btn" size="mini" :type="btnType" slot="reference">{{ btnText }}<span class="u-follow-count">{{ formatFansNum(fansNum) }}</span></el-button>
23
+ <el-button class="u-unfollow-btn" size="mini" :type="btnType" slot="reference"
24
+ >{{ btnText }}
25
+ <!-- TODO:后续在粉丝榜中展示粉丝数 -->
26
+ <!-- <span class="u-follow-count">{{ formatFansNum(fansNum) }}</span> -->
27
+ </el-button>
41
28
  </el-popover>
42
- <el-button size="mini" icon="el-icon-message" disabled title="Lv4+可用">私信</el-button>
43
29
  </div>
44
30
  </template>
45
31
 
@@ -58,7 +44,7 @@ export default {
58
44
  return {
59
45
  isFollow: false,
60
46
  fansNum: 0,
61
- loading: false
47
+ loading: false,
62
48
  };
63
49
  },
64
50
  computed: {
@@ -66,10 +52,10 @@ export default {
66
52
  return this.isFollow ? "已关注" : "关注";
67
53
  },
68
54
  btnIcon() {
69
- return this.isSelf ? "" : (this.isFollow ? "" : "el-icon-plus");
55
+ return this.isSelf ? "" : this.isFollow ? "" : "el-icon-plus";
70
56
  },
71
57
  btnType() {
72
- return this.isFollow ? "info" : "warning"
58
+ return this.isFollow ? "info" : "warning";
73
59
  },
74
60
  actions() {
75
61
  return [
@@ -87,7 +73,7 @@ export default {
87
73
  user() {
88
74
  return User.getInfo();
89
75
  },
90
- isLogin: function() {
76
+ isLogin: function () {
91
77
  return User.isLogin();
92
78
  },
93
79
  },
@@ -97,7 +83,7 @@ export default {
97
83
  handler(val) {
98
84
  val && this.loadFans();
99
85
  },
100
- }
86
+ },
101
87
  },
102
88
  methods: {
103
89
  // 格式化粉丝数
@@ -126,10 +112,10 @@ export default {
126
112
  },
127
113
  // 取消关注
128
114
  unfollow() {
129
- this.$confirm('确定不再关注此人?', '提示', {
130
- confirmButtonText: '确定',
131
- cancelButtonText: '取消',
132
- type: 'warning'
115
+ this.$confirm("确定不再关注此人?", "提示", {
116
+ confirmButtonText: "确定",
117
+ cancelButtonText: "取消",
118
+ type: "warning",
133
119
  }).then(() => {
134
120
  unfollow(this.uid)
135
121
  .then((res) => {
@@ -151,15 +137,24 @@ export default {
151
137
  })
152
138
  .catch((err) => {
153
139
  console.log(err);
154
- }).finally(() => {
140
+ })
141
+ .finally(() => {
155
142
  this.loading = false;
156
143
  });
157
- }
144
+ },
158
145
  },
159
146
  };
160
147
  </script>
161
148
 
162
- <style lang="less">
149
+ <style scoped lang="less">
150
+ .c-author-follow{
151
+ // .u-btn{
152
+ // background-color: #31dee6;
153
+ // border-color:lighten(#31dee6,5%);
154
+ // color: #fff;
155
+ // }
156
+ }
157
+
163
158
  .u-unfollow-btn {
164
159
  &.el-button {
165
160
  margin-right: 10px;
@@ -176,24 +171,14 @@ export default {
176
171
  cursor: pointer;
177
172
  padding: 8px 10px;
178
173
  &:hover {
179
- background: rgb(248,248,251);
174
+ background: rgb(248, 248, 251);
180
175
  }
181
176
  }
182
177
  }
183
178
  }
184
179
  }
185
- .u-follow-count{
186
- margin-left:5px;
180
+ .u-follow-count {
181
+ margin-left: 5px;
187
182
  }
188
183
 
189
- .u-fans-box {
190
- cursor: default !important;
191
- .u-fans-label {
192
- color: #999;
193
- margin-right: 5px;
194
- }
195
- .u-fans {
196
- color: #333;
197
- }
198
- }
199
184
  </style>