Browse Source

Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap

pull/2977/head
zouap 2 years ago
parent
commit
35da55c29c
20 changed files with 459 additions and 6 deletions
  1. +1
    -0
      options/locale/locale_en-US.ini
  2. +1
    -0
      options/locale/locale_zh-CN.ini
  3. BIN
      public/img/ad/ad01.png
  4. BIN
      public/img/ad/ad02.png
  5. BIN
      public/img/ad/ad03.jpg
  6. +4
    -0
      templates/base/head_navbar.tmpl
  7. +4
    -0
      templates/base/head_navbar_fluid.tmpl
  8. +4
    -0
      templates/base/head_navbar_home.tmpl
  9. +4
    -0
      templates/base/head_navbar_pro.tmpl
  10. +13
    -0
      templates/user/auth/signup_inner.tmpl
  11. +3
    -0
      templates/user/dashboard/repolist.tmpl
  12. +6
    -0
      templates/user/profile.tmpl
  13. +7
    -0
      templates/user/settings/invite.tmpl
  14. +87
    -0
      web_src/js/features/ad.js
  15. +1
    -0
      web_src/js/index.js
  16. +15
    -5
      web_src/js/standalone/phoneverify.js
  17. +2
    -1
      web_src/less/standalone/_phoneverify.less
  18. +11
    -0
      web_src/vuepages/apis/modules/userinvite.js
  19. +279
    -0
      web_src/vuepages/pages/user/invite/index.vue
  20. +17
    -0
      web_src/vuepages/pages/user/invite/vp-user-invite.js

+ 1
- 0
options/locale/locale_en-US.ini View File

@@ -69,6 +69,7 @@ your_dashboard = Dashboard
your_profile = Profile
your_starred = Starred
your_settings = Settings
invite_friends = Invite Friends

all = All
sources = Sources


+ 1
- 0
options/locale/locale_zh-CN.ini View File

@@ -69,6 +69,7 @@ your_dashboard=个人中心
your_profile=个人信息
your_starred=已点赞
your_settings=设置
invite_friends=邀请好友

all=所有
sources=自建


BIN
public/img/ad/ad01.png View File

Before After
Width: 144  |  Height: 108  |  Size: 14 kB

BIN
public/img/ad/ad02.png View File

Before After
Width: 405  |  Height: 60  |  Size: 32 kB

BIN
public/img/ad/ad03.jpg View File

Before After
Width: 800  |  Height: 80  |  Size: 37 kB

+ 4
- 0
templates/base/head_navbar.tmpl View File

@@ -180,6 +180,10 @@
</i>
{{.i18n.Tr "custom.Platform_Tutorial"}}
</a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>



+ 4
- 0
templates/base/head_navbar_fluid.tmpl View File

@@ -177,6 +177,10 @@
</svg>
</i>
{{.i18n.Tr "custom.Platform_Tutorial"}}
</a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>


+ 4
- 0
templates/base/head_navbar_home.tmpl View File

@@ -160,6 +160,10 @@
</i>
{{.i18n.Tr "custom.Platform_Tutorial"}}
</a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>



+ 4
- 0
templates/base/head_navbar_pro.tmpl View File

@@ -181,6 +181,10 @@
</i>
{{.i18n.Tr "custom.Platform_Tutorial"}}
</a>
<a class="item" href="{{AppSubUrl}}/user/invitation_tpl">
<i class="icon users"></i>
{{.i18n.Tr "invite_friends"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>



+ 13
- 0
templates/user/auth/signup_inner.tmpl View File

@@ -35,6 +35,9 @@
{{if .DisableRegistration}}
<p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
{{else}}
<div class="field" style="font-weight:400;font-size:14px;color:rgba(250,140,22,1);">
<span>您的好友 <span>Itx003</span> 邀请你加入启智社区AI协作平台,畅享充沛的免费算力资源!</span>
</div>
<div class="field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<input id="user_name" name="user_name" value="{{.user_name}}" placeholder="{{.i18n.Tr "username"}}" autofocus required>
</div>
@@ -71,6 +74,16 @@
{{template "user/auth/phone_verify" .}}
</div>
{{end}}
<div class="field">
<div style="display:flex;">
<div style="display:flex;align-items:center;">
<span>推荐人</span>
</div>
<input style="flex:1;margin-left:12px;" id="shared_user" name="shared_user" value="{{.password}}" autocomplete="off" />
</div>
</div>

<div class="field">
<div class="ui checkbox">
<input name="agree" type="checkbox" tabindex="0" class="hidden" {{if .agree}}checked{{end}}><label>{{.i18n.Tr "use_and_privacy_agree" "/home/term" "/home/privacy" | Safe}}</label>


+ 3
- 0
templates/user/dashboard/repolist.tmpl View File

@@ -18,6 +18,9 @@
v-cloak
>
<div>
<div style="height:60px;">
<a href="/user/invitation_tpl"><img src="/img/ad/ad02.png" style="width:100%;height:100%" /></a>
</div>
<div v-if="!isOrganization" class="ui two item tabable menu">
<a :class="{item: true, active: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a>
<a :class="{item: true, active: tab === 'organizations'}" @click="changeTab('organizations')">{{.i18n.Tr "organization"}}</a>


+ 6
- 0
templates/user/profile.tmpl View File

@@ -48,6 +48,12 @@
</li>
{{end}}
{{end}}
<li>
{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}
<div style="margin-top:6px;height:50px;">
<a href="/user/invitation_tpl"><img src="/img/ad/ad02.png" style="width:100%;height:100%" /></a>
</div>
</li>
<li>{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}</li>
{{if and .Orgs .HasOrgsVisible}}


+ 7
- 0
templates/user/settings/invite.tmpl View File

@@ -0,0 +1,7 @@
{{template "base/head" .}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-user-invite.css?v={{MD5 AppVer}}" />
<div class="user settings invite">
<div id="__vue-root"></div>
</div>
<script src="{{StaticUrlPrefix}}/js/vp-user-invite.js?v={{MD5 AppVer}}"></script>
{{template "base/footer" .}}

+ 87
- 0
web_src/js/features/ad.js View File

@@ -0,0 +1,87 @@
; (function () {
const adList = [{
id: 1,
pos: {
left: 50,
bottom: 50,
},
src: '/img/ad/ad01.png',
url: '/user/invitation_tpl',
width: 144,
height: 108,
}/*, {
id: 2,
pos: {
right: 50,
bottom: 50,
},
src: '/img/ad/ad01.png',
url: '/user/invitation_tpl',
width: 144,
height: 108,
}*/];

function createAd(adList) {
const adInfoStr = window.localStorage.getItem('ads') || '{}';
let adInfoObj = JSON.parse(adInfoStr);
const today = new Date();
const timeEnd = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1).getTime();
const now = Date.now();
if (!adInfoObj.expires || adInfoObj.expires <= now) {
adInfoObj = {
expires: timeEnd,
};
}
for (var i = 0, iLen = adList.length; i < iLen; i++) {
var adI = adList[i];
var showOr = adInfoObj[adI.id] === false ? false : true;
adInfoObj[adI.id] = showOr;
if (!showOr) continue;
var adEl = $(`<div class="__ad_c__" _id="${adI.id}" style="position:fixed;z-index:99999999;
width:${adI.width}px;height:${adI.height}px;
left:${adI.pos.left !== undefined ? adI.pos.left + 'px' : ''};
top:${adI.pos.top !== undefined ? adI.pos.top + 'px' : ''};
right:${adI.pos.right !== undefined ? adI.pos.right + 'px' : ''};
bottom:${adI.pos.bottom !== undefined ? adI.pos.bottom + 'px' : ''};">
<a style="" href="${adI.url}" target="_blank">
<img style="height:100%;width:100%;" src="${adI.src}" />
</a>
<div class="__ad_close_c__" style="position:absolute;top:6px;right:6px;">
<i class="ri-close-circle-line __ad_close__" style="color:white;font-size:18px;cursor:pointer;"></i>
</div>
</div>`);
$('body').append(adEl);
}
window.localStorage.setItem('ads', JSON.stringify(adInfoObj));
}

function initAdEvent() {
$('body').on('click', '.__ad_c__ .__ad_close__', function () {
var self = $(this);
var adEl = self.closest('.__ad_c__');
var adId = adEl.attr('_id');
const adInfoStr = window.localStorage.getItem('ads') || '{}';
const adInfoObj = JSON.parse(adInfoStr);
adInfoObj[adId] = false;
window.localStorage.setItem('ads', JSON.stringify(adInfoObj));
adEl.remove();
});
var scrollTopOld = $(document).scrollTop();
var timeHandler = null;
$(window).scroll(function (e) {
var scrollTop = $(document).scrollTop();
var offSet = scrollTop - scrollTopOld;
scrollTopOld = scrollTop;
timeHandler && clearTimeout(timeHandler);
$('.__ad_c__').animate({ bottom: 50 + offSet + 'px' }, 0);
timeHandler = setTimeout(function () {
$('.__ad_c__').animate({ bottom: 50 + 'px' }, 0);
}, 20);
});
}

setTimeout(function () {
createAd(adList);
initAdEvent();
}, 0);
})();

+ 1
- 0
web_src/js/index.js View File

@@ -52,6 +52,7 @@ import router from "./router/index.js";
import { Message } from "element-ui";

import { i18nVue } from "./features/i18nVue.js";
import './features/ad.js';

Vue.use(ElementUI);
Vue.prototype.$axios = axios;


+ 15
- 5
web_src/js/standalone/phoneverify.js View File

@@ -77,7 +77,7 @@
});

function mouseMove(e) {
var _clientX = e.clientX;
var _clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX;
var offset = _clientX - clientX;
var triggerEl = self.dom.find('.slide-trigger');
var triggerWidth = triggerEl.width();
@@ -99,6 +99,8 @@
function mouseUp(e) {
$(document).off('mousemove', mouseMove);
$(document).off('mouseup', mouseUp);
$(document).off('touchmove', mouseMove);
$(document).off('touchend', mouseUp);
self.isMoving = false;
$.ajax({
url: '/verifySlideImage',
@@ -106,7 +108,7 @@
dataType: 'json',
data: {
slide_id: self.imgID,
x: parseInt(self.dom.find('.slide-image-small').position().left)
x: parseInt(self.dom.find('.slide-image-small').position().left / self.dom.find('.slide-image-big').attr('scale'))
},
success: function (res) {
if (res && res.Code === 0) {
@@ -138,13 +140,18 @@
});
}

this.dom.find('.slide-trigger').on('mousedown', function (e) {
function mouseDown(e) {
if (self.verifySucess) return;
clientX = e.clientX;
clientX = e.clientX !== undefined ? e.clientX : e.targetTouches[0].clientX;
oLeft = $(this).position().left;
$(document).on('mousemove', mouseMove);
$(document).on('mouseup', mouseUp);
});
$(document).on('touchmove', mouseMove);
$(document).on('touchend', mouseUp);
}

this.dom.find('.slide-trigger').on('mousedown', mouseDown);
this.dom.find('.slide-trigger').on('touchstart', mouseDown);

this.dom.find('.verify-code-send-btn').on('click', function () {
if (!self.canSendCode) return;
@@ -199,6 +206,7 @@
self.dom.find('.slide-bar-wrap').css('display', 'flex');
self.dom.find('.verify-code-c').css('display', 'flex');
self.dom.find('.modify-phone-number').hide();
self.refreshImages();
});
};

@@ -210,6 +218,8 @@
this.imgID = '';
this.dom.find('.slide-bar').removeClass('sucess error').css('width', '30px');
this.dom.find('.slide-trigger').removeClass('sucess error').css('left', '0px');
var scale = this.dom.find('.slide-bar-bg').width() / 391;
this.dom.find('.slide-image-big').css('transform', `scale(${scale})`).attr('scale', scale);
this.dom.find('.slide-trigger .icon').hide();
this.dom.find('.slide-trigger .icon.arrow').show();
this.dom.find('.slide-txt').show();


+ 2
- 1
web_src/less/standalone/_phoneverify.less View File

@@ -174,10 +174,11 @@
width: 391px;
height: 196px;
top: 36px;
left: 0;
left: 1px;
border-radius: 2px;
z-index: 100;
display: none;
transform-origin: 0 0;
}

.__phone-verify-code .slide-bar-c .slide-image-small {


+ 11
- 0
web_src/vuepages/apis/modules/userinvite.js View File

@@ -0,0 +1,11 @@
import service from '../service';

// 邀请好友页面数据
export const getUserInvitationCode = () => {
return service({
url: '/user/invitation_code',
method: 'get',
params: {},
data: {},
});
}

+ 279
- 0
web_src/vuepages/pages/user/invite/index.vue View File

@@ -0,0 +1,279 @@
<template>
<div class="ui container">
<div class="title">
<div class="title-1"><span>邀请好友</span></div>
<div class="title-2"><span>复制二维码或者邀请注册链接分享给好友</span></div>
</div>
<div class="content-1">
<div class="img-c">
<img class="img" src="/img/ad/ad03.jpg" />
<div class="txt">邀请好友来启智,用免费算力还能赚奖金!</div>
</div>
<div class="descr">
<span>新一期的开源打榜活动,每邀请一名好友注册并激活,就可以获得5打榜积分。快快邀请更多好友帮你冲击榜单吧~ </span>
<a>点击查看活动详情</a>
</div>
</div>
<div class="content-2">
<div class="txt-c">
<div class="txt-1">
<span>启智AI协作平台是启智社区面向AI开发者提供的一站式AI开发协作平台,提供了代码托管、数据集管理、基于异构计算资源的模型调试与训练等功能。目前已经与鹏城云脑、中国算力网(C²NET)一期打通,免费提供丰富算力资源,支撑大家完成AI开发任务。</span>
</div>
<div class="txt-2"><span>{{ sharedLink }}</span></div>
<div class="txt-3"><span>推荐人:</span><span>{{ sharedUser }}</span></div>
<el-button class="__copy_link_btn__" type="primary">复制注册邀请链接</el-button>
</div>
<div class="qr-code">
<img src="" alt="" style="width:120px;height:120px;">
</div>
</div>
<div class="table-container">
<div>
<el-table border :data="tableData" style="width:100%" v-loading="loading" stripe>
<el-table-column prop="ID" label="已邀请好友" align="left" header-align="center">
<template slot-scope="scope">
<div style="display:flex;align-items:center;padding-left:20px;">
<img src="" alt="" style="height:45px;width:45px;margin-right:10px;" />
<a :href="scope.row.userLink" style="font-weight:500;font-size:15px;">{{ scope.row.userName }}</a>
</div>
</template>
</el-table-column>
<el-table-column prop="statusStr" label="状态" align="center" header-align="center">
<template slot-scope="scope">
<span :style="{ color: scope.row.statusColor }">{{ scope.row.statusStr }}</span>
</template>
</el-table-column>
<el-table-column prop="regTime" label="注册时间" align="center" header-align="center">

</el-table-column>
<template slot="empty">
<span style="font-size: 12px">{{
loading ? $t('loading') : $t('noData')
}}</span>
</template>
</el-table>
</div>
<div class="__r_p_pagination">
<div style="margin-top: 2rem">
<div class="center">
<el-pagination background @current-change="currentChange" :current-page="pageInfo.curpage"
:page-sizes="pageInfo.pageSizes" :page-size="pageInfo.pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="pageInfo.total">
</el-pagination>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
import { formatDate } from 'element-ui/lib/utils/date-util';
import Clipboard from 'clipboard';

export default {
data() {
return {
sharedLink: 'https://git.openi.org.cn/user/sign_up?sharedUser=Openihu',
sharedUser: 'Openihu',
loading: false,
tableData: [],
pageInfo: {
curpage: 1,
pageSize: 10,
pageSizes: [10],
total: 0,
},
};
},
components: {},
methods: {
initCopy() {
const clipboard = new Clipboard('.__copy_link_btn__', {
text: () => {
return this.sharedLink;
},
})
clipboard.on('success', (e) => {
this.$message({
type: 'success',
message: '分享内容已复制到剪切板'
});
});
},
getTableData() {
const data = new Array(10).fill(0).map((item, index) => {
const status = Math.random() > 0.5 ? '1' : '2';
return {
userName: 'userName-' + index + '-' + Math.random().toFixed(2),
userLink: 'userLink-' + index + '-' + Math.random().toFixed(2),
status: status,
statusStr: status == '1' ? '已激活' : '未激活',
statusColor: status == '1' ? 'rgb(82, 196, 26)' : 'rgb(245, 34, 45)',
regTime: 'regTime' + index + Math.random().toFixed(2),
}
});
this.tableData = data;

return;
const params = {
page: this.pageInfo.curpage,
pagesize: this.pageInfo.pageSize,
};
this.loading = true;
getResSceneList(params).then(res => {
this.loading = false;
res = res.data;
if (res.Code === 0) {
const list = res.Data.List;
const data = list.map((item) => {
return {

}
});
this.tableData = data;
this.pageInfo.total = res.Data.TotalSize;
}
}).catch(err => {
console.log(err);
this.loading = false;
});
},
currentChange(val) {
this.pageInfo.curpage = val;
this.getTableData();
},
},
mounted() {
this.initCopy();
this.getTableData();
},
beforeDestroy() {
},
};
</script>

<style scoped lang="less">
.title {
margin-top: 15px;
margin-bottom: 15px;

.title-1 {
font-weight: 500;
font-size: 20px;
color: rgba(16, 16, 16, 1);
margin-bottom: 10px;
}

.title-2 {
font-weight: 400;
font-size: 14px;
color: rgba(136, 136, 136, 1);
}
}

.content-1 {
margin-bottom: 32px;

.img-c {
height: 80px;
position: relative;

.img {
width: 100%;
height: 100%;
}

.txt {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
line-height: 80px;
padding-left: 25px;
font-weight: 500;
font-size: 24px;
color: rgb(255, 255, 255);
}
}

.descr {
font-weight: 300;
font-size: 16px;
color: rgb(16, 16, 16);
padding: 25px;
border-left: 1px solid rgba(0, 0, 0, 0.1);
border-right: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 0px 0px 4px 4px;
}
}

.content-2 {
display: flex;
background-color: rgb(228, 242, 255);
border-color: rgb(228, 242, 255);
border-width: 1px;
border-style: solid;
border-radius: 5px;
padding: 25px;
margin-bottom: 32px;

.txt-c {
flex: 1;
font-weight: 300;
font-size: 16px;
color: rgb(16, 16, 16);

span {
line-height: 24px;
}

div {
margin-bottom: 6px;
}

.txt-3 {
margin-bottom: 15px;
}
}

.qr-code {
width: 150px;
display: flex;
flex-direction: column;
align-items: end;
}
}

.table-container {
margin-bottom: 16px;

/deep/ .el-table__header {
th {
background: rgb(245, 245, 246);
font-size: 12px;
color: rgb(36, 36, 36);
}
}

/deep/ .el-table__body {
td {
font-size: 12px;
}
}

.op-btn {
cursor: pointer;
font-size: 12px;
color: rgb(25, 103, 252);
margin: 0 5px;
}
}

.center {
display: flex;
justify-content: center;
}
</style>

+ 17
- 0
web_src/vuepages/pages/user/invite/vp-user-invite.js View File

@@ -0,0 +1,17 @@
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import localeEn from 'element-ui/lib/locale/lang/en';
import localeZh from 'element-ui/lib/locale/lang/zh-CN';
import { i18n, lang } from '~/langs';
import App from './index.vue';

Vue.use(ElementUI, {
locale: lang === 'zh-CN' ? localeZh : localeEn,
size: 'small',
});

new Vue({
i18n,
render: (h) => h(App),
}).$mount('#__vue-root');

Loading…
Cancel
Save