@jx3box/jx3box-common-ui 6.1.4 → 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.
@@ -0,0 +1,277 @@
1
+ <template>
2
+ <div class="c-author-gift">
3
+ <el-button
4
+ class="u-btn"
5
+ size="mini"
6
+ icon="el-icon-present"
7
+ @click="openGiftDialog"
8
+ :disabled="isSelf || !status"
9
+ :title="btnTitle"
10
+ >赠礼</el-button
11
+ >
12
+
13
+ <el-dialog
14
+ title="赠礼"
15
+ :visible.sync="visible"
16
+ :append-to-body="true"
17
+ class="c-author-gift-dialog"
18
+ v-if="status"
19
+ >
20
+ <div class="u-content">
21
+ <div class="u-left">
22
+ <em class="u-label">🌟 金箔</em>
23
+ <b>{{ this.left }}</b>
24
+ </div>
25
+ <div class="u-list">
26
+ <em class="u-label">❤️ 赠送</em>
27
+ <div class="u-points">
28
+ <el-radio-group v-model="count">
29
+ <el-radio :label="item" v-for="item in fitPoints" :key="item" border>
30
+ <b>{{ item }}</b
31
+ >金箔
32
+ </el-radio>
33
+ </el-radio-group>
34
+ </div>
35
+ </div>
36
+ <div class="u-msg">
37
+ <em class="u-label">📝 寄语</em>
38
+ <div class="u-input">
39
+ <el-input
40
+ v-model="remark"
41
+ placeholder="请输入寄语(必填)"
42
+ :minlength="2"
43
+ :maxlength="30"
44
+ show-word-limit
45
+ ></el-input>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <span slot="footer" class="dialog-footer">
50
+ <el-button @click="visible = false">取 消</el-button>
51
+ <el-button type="primary" @click="submit" :disabled="!ready || loading" :loading="loading"
52
+ >确 定</el-button
53
+ >
54
+ </span>
55
+ </el-dialog>
56
+ </div>
57
+ </template>
58
+
59
+ <script>
60
+ import User from "@jx3box/jx3box-common/js/user";
61
+ import { sendCny, checkCnyStatus, checkGiftStatus } from "../../service/thx";
62
+ export default {
63
+ name: "AuthorGift",
64
+ props: ["uid"],
65
+ components: {},
66
+ data: function () {
67
+ return {
68
+ loading: false,
69
+ visible: false,
70
+ fitPoints: [50,100, 250, 520, 666, 888, 1314, 2288, 3344, 6666, 8888, 28888, 36888, 68888],
71
+
72
+ left: 0, //剩余量
73
+ status: true, //默认可打赏
74
+
75
+ count: 0, //打赏数量
76
+ remark: "辛苦,感谢!",
77
+ };
78
+ },
79
+ computed: {
80
+ user() {
81
+ return User.getInfo();
82
+ },
83
+ isSelf() {
84
+ return this.uid == this.user.uid;
85
+ },
86
+ ready: function () {
87
+ // 不能赠送给自己
88
+ // 余额足够
89
+ // 打赏额度不能为空
90
+ // 必须填写赠言
91
+ return !this.isSelf && this.left && this.left >= this.count && this.count && this.remark;
92
+ },
93
+ btnTitle: function () {
94
+ if (this.isSelf) {
95
+ return "不能给自己赠送礼物";
96
+ } else if (!this.status) {
97
+ return "作者没有开启接受礼物";
98
+ }
99
+ return "";
100
+ },
101
+ },
102
+ watch: {
103
+ uid: {
104
+ immediate: true,
105
+ handler: function (val) {
106
+ val && this.load();
107
+ },
108
+ },
109
+ },
110
+ methods: {
111
+ openGiftDialog: function () {
112
+ if (!User.isLogin()) {
113
+ User.toLogin();
114
+ return;
115
+ } else {
116
+ this.visible = true;
117
+ }
118
+ },
119
+ submit: async function () {
120
+ this.loading = true;
121
+ sendCny(this.user.uid, this.uid, this.count, this.remark).then((res) => {
122
+ console.info("[AUTHOR.CNY]发起交易");
123
+ // 消费凭证ID
124
+ const id = res.data.data.id;
125
+
126
+ console.info("[AUTHOR.CNY]开始轮询交易结果");
127
+ // 状态轮询
128
+ const loading = this.$loading({
129
+ lock: true,
130
+ text: "正在处理中",
131
+ spinner: "el-icon-loading",
132
+ background: "rgba(255, 255, 255, 0.8)",
133
+ });
134
+
135
+ let n = 0;
136
+ const timer = setInterval(async () => {
137
+ console.info(`[AUTHOR.CNY]第${n + 1}次轮询开始`);
138
+ await checkCnyStatus(id)
139
+ .then((res) => {
140
+ // 状态
141
+ let status = res.data.data.finish;
142
+
143
+ // 交易成功
144
+ if (status) {
145
+ console.info(`[AUTHOR.CNY]交易成功`);
146
+ //关闭轮询
147
+ loading.close();
148
+ clearInterval(timer);
149
+ // 关闭加载状态 & 消息提醒
150
+ this.visible = false;
151
+ this.loading = false;
152
+ this.$message({
153
+ message: "赠送成功",
154
+ type: "success",
155
+ });
156
+
157
+ // 结算与重置
158
+ this.left = this.left - this.count;
159
+ this.count = 100;
160
+ this.remark = "辛苦,感谢!";
161
+ } else {
162
+ console.info(`[AUTHOR.CNY]重新轮询`);
163
+ }
164
+ })
165
+ .finally(() => {
166
+ n += 1;
167
+ console.info(`[AUTHOR.CNY]第${n}次轮询结束`);
168
+ });
169
+
170
+ // 最多尝试3次
171
+ if (n > 5) {
172
+ console.info(`[AUTHOR.CNY]${n}次轮询未果,退出轮询`);
173
+ //关闭轮询
174
+ loading.close();
175
+ clearInterval(timer);
176
+ // 关闭加载状态 & 消息提醒
177
+ this.visible = false;
178
+ this.loading = false;
179
+ this.$message("交易繁忙,请稍后再试");
180
+ }
181
+ }, 1000);
182
+ });
183
+ },
184
+ load: function () {
185
+ // 加载用户是否接受赠送与当前用户余额,仅当打开时执行一次
186
+ User.isLogin() &&
187
+ checkGiftStatus(this.uid).then((res) => {
188
+ this.left = res.data.data.cny || 0; // 当前登录用户的余额
189
+ this.status = res.data.data.targetUserCanReceiveCNY; // 目标用户是否接受充电
190
+ });
191
+ },
192
+ },
193
+ created: function () {},
194
+ mounted: function () {},
195
+ };
196
+ </script>
197
+
198
+ <style scoped lang="less">
199
+ .c-author-gift {
200
+ .u-btn {
201
+ @color: #f9afd4;
202
+ background-color: @color;
203
+ color: #fff;
204
+ border-color: darken(@color, 2%);
205
+
206
+ &:hover {
207
+ background-color: #fff;
208
+ color: darken(@color, 10%);
209
+ border-color: darken(@color, 10%);
210
+ }
211
+
212
+ &.is-disabled {
213
+ color: #c0c4cc;
214
+ cursor: not-allowed;
215
+ background-image: none;
216
+ background-color: #fff;
217
+ border-color: #ebeef5;
218
+ }
219
+ }
220
+ }
221
+ .c-author-gift-dialog {
222
+ .fz(14px,2);
223
+
224
+ .el-dialog__body {
225
+ padding-top: 10px;
226
+ padding-bottom: 0;
227
+ }
228
+
229
+ .u-left {
230
+ .fz(14px,24px);
231
+ .u-label {
232
+ .mr(10px);
233
+ }
234
+ b {
235
+ // color:#49c10f;
236
+ // color:@color-link;
237
+ color: #fba524;
238
+ .fz(20px,1);
239
+ .dbi;
240
+ .y;
241
+ vertical-align: text-bottom;
242
+ }
243
+ .el-progress {
244
+ margin: 10px;
245
+ }
246
+ }
247
+ .u-list {
248
+ .mt(10px);
249
+ }
250
+ .u-points {
251
+ padding: 10px;
252
+ .el-radio {
253
+ .ml(0) !important;
254
+ .mb(10px);
255
+ .w(140px);
256
+ b {
257
+ color: #e81224;
258
+ .mr(5px);
259
+ }
260
+ }
261
+ .el-input-number {
262
+ .ml(0) !important;
263
+ .mb(10px);
264
+ .w(140px);
265
+ }
266
+ }
267
+
268
+ .u-label {
269
+ font-style: normal;
270
+ background-color: @bg-gray;
271
+ padding: 5px 10px;
272
+ }
273
+ .u-input {
274
+ padding: 10px 0 10px 10px;
275
+ }
276
+ }
277
+ </style>
@@ -0,0 +1,199 @@
1
+ <template>
2
+ <div class="c-author-info">
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 && 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) }"
20
+ >Lv.{{ level }}</span
21
+ >
22
+ </el-tooltip>
23
+ <el-tooltip class="item" effect="dark" :content="vipTypeTitle" placement="top" v-if="isVip">
24
+ <a class="u-vip" href="/vip/premium?from=sidebar_author" target="_blank">
25
+ <i class="i-icon-vip on">{{ vipType }}</i>
26
+ </a>
27
+ </el-tooltip>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ <div class="u-bio">{{ data.user_bio }}</div>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ import { __server, __imgPath, __userLevel, __userLevelColor } from "@jx3box/jx3box-common/data/jx3box.json";
37
+ import { authorLink } from "@jx3box/jx3box-common/js/utils";
38
+ import User from "@jx3box/jx3box-common/js/user";
39
+ import { getUserInfo } from "../../service/author";
40
+ import Avatar from "./Avatar.vue";
41
+ export default {
42
+ name: "AuthorInfo",
43
+ props: ["uid"],
44
+ components: {
45
+ Avatar,
46
+ },
47
+ data: function () {
48
+ return {
49
+ data: {},
50
+
51
+ isVIP: false,
52
+ super_author_icon: __imgPath + "image/user/" + "superauthor.svg",
53
+ };
54
+ },
55
+ computed: {
56
+ // level
57
+ level: function () {
58
+ return User.getLevel(this.data?.experience);
59
+ },
60
+
61
+ // vip
62
+ vipType: function () {
63
+ return this.data?.is_pro ? "PRO" : "PRE";
64
+ },
65
+ vipTypeTitle: function () {
66
+ return this.data?.is_pro ? "专业版会员" : "高级版会员";
67
+ },
68
+ isVip: function () {
69
+ return this.data?.is_pro || this.data?.is_pre;
70
+ },
71
+
72
+ // sign
73
+ isSuperAuthor: function () {
74
+ return this.data?.sign;
75
+ },
76
+ },
77
+ watch: {
78
+ uid: {
79
+ immediate: true,
80
+ handler: function (val) {
81
+ val && this.loadData();
82
+ },
83
+ },
84
+ },
85
+ methods: {
86
+ loadData: function () {
87
+ return getUserInfo(this.uid).then((data) => {
88
+ if (data) {
89
+ this.data = data;
90
+ this.$emit("ready", this.data);
91
+ }
92
+ });
93
+ },
94
+ authorLink,
95
+ showLevelColor: function (level) {
96
+ return __userLevelColor[level];
97
+ },
98
+ },
99
+ created: function () {},
100
+ mounted: function () {},
101
+ };
102
+ </script>
103
+
104
+ <style scoped lang="less">
105
+ .u-author {
106
+ .clearfix;
107
+ .db;
108
+ .mb(10px);
109
+ .pr;
110
+ }
111
+ .u-avatar {
112
+ .fl;
113
+ .mr(15px);
114
+ .size(68px);
115
+ }
116
+ .u-name {
117
+ .lh(2.2);
118
+ .bold;
119
+ color: @darkblue;
120
+ &:hover {
121
+ color: #f39;
122
+ }
123
+ .nobreak;
124
+ }
125
+ .u-info {
126
+ .pr;
127
+ top: -4px;
128
+ .h(68px);
129
+ display: flex;
130
+ flex-direction: column;
131
+ justify-content: center;
132
+ }
133
+ .u-bio {
134
+ .fz(12px, 2);
135
+ .break(3);
136
+ color: #888;
137
+ padding: 0 5px;
138
+ }
139
+ .u-extend {
140
+ display: flex;
141
+ }
142
+ .u-level {
143
+ padding: 2px 8px;
144
+ .fz(12px, 14px);
145
+ color: #fff;
146
+ background-color: #aaa;
147
+ border-radius: 2px;
148
+
149
+ &.lv-1 {
150
+ background-color: #32d3c4;
151
+ }
152
+ &.lv-2 {
153
+ background-color: #86c0fb;
154
+ }
155
+ &.lv-3 {
156
+ background-color: #33d9ff;
157
+ }
158
+ &.lv-4 {
159
+ background-color: #ffdb2a;
160
+ }
161
+ &.lv-5 {
162
+ background-color: #ffa739;
163
+ }
164
+ &.lv-6 {
165
+ background-color: #ff70b2;
166
+ }
167
+ &.lv-7 {
168
+ background-color: #ff3399;
169
+ }
170
+ &.lv-8 {
171
+ background-color: #f93c3c;
172
+ }
173
+ }
174
+ .u-vip {
175
+ .ml(5px);
176
+ .db;
177
+ .i-icon-vip {
178
+ .db;
179
+ vertical-align: baseline;
180
+ padding: 2px 6px;
181
+ .fz(12px, 14px);
182
+ font-style: normal;
183
+ border-radius: 2px;
184
+ background-color: #ddd;
185
+ color: #fff;
186
+ &.on {
187
+ background-color: #6f42c1;
188
+ }
189
+ }
190
+ }
191
+ .u-superauthor {
192
+ margin-left: 4px;
193
+ display: inline-block;
194
+ vertical-align: -2px;
195
+ img {
196
+ width: 16px;
197
+ }
198
+ }
199
+ </style>
@@ -0,0 +1,80 @@
1
+ <template>
2
+ <div class="c-author-link">
3
+ <!-- <AuthorMsg :uid="uid"/> -->
4
+ <a
5
+ v-if="data.weibo_name"
6
+ class="u-link u-link__weibo"
7
+ :href="weiboLink(data.weibo_id)"
8
+ target="_blank"
9
+ :title="data.weibo_name"
10
+ >
11
+ <img :src="getIcon('weibo')" />
12
+ </a>
13
+ <a
14
+ v-if="data.github_name"
15
+ class="u-link u-link__github"
16
+ :href="githubLink(data.github_name)"
17
+ target="_blank"
18
+ :title="data.github_name"
19
+ >
20
+ <img :src="getIcon('github')" />
21
+ </a>
22
+ <a
23
+ v-if="data.tv_type && data.tv_id"
24
+ class="u-link u-link__tv"
25
+ :href="tv_link"
26
+ target="_blank"
27
+ :title="`房间号:${data.tv_id}`"
28
+ >
29
+ <img :src="getIcon(data.tv_type)" />
30
+ </a>
31
+ </div>
32
+ </template>
33
+
34
+ <script>
35
+ import { tvLink } from "@jx3box/jx3box-common/js/utils";
36
+ import { __imgPath } from "@jx3box/jx3box-common/data/jx3box.json";
37
+ // import AuthorMsg from "./AuthorMsg.vue";
38
+ export default {
39
+ name: "AuthorLink",
40
+ props: ["data"],
41
+ components: {
42
+ // AuthorMsg
43
+ },
44
+ data: function () {
45
+ return {};
46
+ },
47
+ computed: {
48
+ tv_link: function () {
49
+ return tvLink(this.data.tv_type, this.data.tv_id) || "";
50
+ },
51
+ },
52
+ watch: {},
53
+ methods: {
54
+ weiboLink: function (val) {
55
+ return "https://weibo.com/" + val;
56
+ },
57
+ githubLink: function (val) {
58
+ return "https://github.com/" + val;
59
+ },
60
+ getIcon: function (val) {
61
+ return __imgPath + "image/author/" + val + ".svg";
62
+ },
63
+ },
64
+ created: function () {},
65
+ mounted: function () {},
66
+ };
67
+ </script>
68
+
69
+ <style scoped lang="less">
70
+ .c-author-link {
71
+ padding:0 2px;
72
+ .u-link {
73
+ .mr(3px);
74
+ }
75
+ img,
76
+ svg {
77
+ .size(18px);
78
+ }
79
+ }
80
+ </style>
@@ -0,0 +1,86 @@
1
+ <template>
2
+ <div class="c-author-medals" v-if="ready">
3
+ <div class="u-label">
4
+ <i class="el-icon-trophy"></i>
5
+ <span>作者荣誉</span>
6
+ </div>
7
+ <div class="u-medals" v-if="medals && medals.length">
8
+ <a
9
+ :href="getMedalLink(item)"
10
+ target="_blank"
11
+ class="u-medal"
12
+ v-for="item in medals"
13
+ :key="item.id"
14
+ :title="item.medal_desc"
15
+ >
16
+ <img class="u-medal-img" :src="showIcon(item.medal)" />
17
+ </a>
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script>
23
+ import { getMedalLink } from "@jx3box/jx3box-common/js/utils";
24
+ import { getUserMedals } from "../../service/author";
25
+ import { __imgPath } from "@jx3box/jx3box-common/data/jx3box.json";
26
+ export default {
27
+ name: "AuthorMedals",
28
+ props: ["uid"],
29
+ components: {},
30
+ data: function () {
31
+ return {
32
+ medals: [],
33
+ };
34
+ },
35
+ computed: {
36
+ ready: function () {
37
+ return this.uid && this.medals && this.medals.length;
38
+ },
39
+ },
40
+ watch: {
41
+ uid: {
42
+ immediate: true,
43
+ handler: function (val) {
44
+ val && this.loadMedals();
45
+ },
46
+ },
47
+ },
48
+ methods: {
49
+ loadMedals: function () {
50
+ getUserMedals(this.uid).then((data) => {
51
+ this.medals = data || [];
52
+ });
53
+ },
54
+ showIcon(medal) {
55
+ return __imgPath + "image/medals/user/" + medal + ".gif";
56
+ },
57
+ getMedalLink(medal) {
58
+ return getMedalLink(medal.rank_id, (medal.medal_type = "rank"));
59
+ },
60
+ },
61
+ created: function () {},
62
+ mounted: function () {},
63
+ };
64
+ </script>
65
+
66
+ <style scoped lang="less">
67
+ .c-author-medals {
68
+ .u-label {
69
+ i {
70
+ .y;
71
+ }
72
+ }
73
+ .u-medals {
74
+ padding:0 3px;
75
+ display: flex;
76
+ .u-medal {
77
+ cursor: pointer;
78
+ .mr(2px);
79
+ .u-medal-img {
80
+ width: 20px;
81
+ height: 20px;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ </style>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <div class="c-author-msg">
3
+ <img src="../../assets/img/author/msg.svg" svg-inline title="短消息" />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: "AuthorMsg",
10
+ props: ["uid"],
11
+ components: {},
12
+ data: function () {
13
+ return {};
14
+ },
15
+ computed: {},
16
+ watch: {},
17
+ methods: {},
18
+ created: function () {},
19
+ mounted: function () {
20
+ // 需要判断是否接受私信
21
+ },
22
+ };
23
+ </script>
24
+
25
+ <style scoped lang="less"></style>