Commit 11d974ad by wufan

fix:合并企微

parents e926cbc4 493c9ba4
...@@ -64,6 +64,8 @@ module.exports = { ...@@ -64,6 +64,8 @@ module.exports = {
appPublic: resolveApp('public'), appPublic: resolveApp('public'),
appHtml: resolveApp('src/index.html'), appHtml: resolveApp('src/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'), appIndexJs: resolveModule(resolveApp, 'src/index'),
h5Html: resolveApp('src/h5.html'),
h5IndexJs: resolveModule(resolveApp, 'src/h5'),
appPackageJson: resolveApp('package.json'), appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'), appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'), appTsConfig: resolveApp('tsconfig.json'),
......
<!--
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: wufan
* @LastEditTime: 2021-01-09 11:18:27
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="icon" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/KGSYFEpcHT.png">
<title>小麦企培</title>
<script type="text/javascript" charset="utf-8" src="./jquery.min.js"></script>
<style type="text/css">
.box {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background:rgba(244, 246, 250, 1) ;
}
p {
font-size: 17px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 24px;
margin-top: 12px;
}
.hide {
display: none;
text-align: center;
}
</style>
</head>
<body>
<div class="box">
<div id='success' class='hide'>
<img src="https://image.xiaomaiketang.com/xm/iRkcMHPHba.png" style='width:60px' alt="">
<p>
扫码成功
</p>
</div>
<div id="error" class='hide'>
<img src="https://image.xiaomaiketang.com/xm/6kSAYFMm2r.png
" style='width:60px' alt="">
<p id='message'>
</p>
</div>
</div>
</body>
<script>
$(document).ready(function () {
var BASIC_HOST_MAP = {
dev: 'https://dev-heimdall.xiaomai5.com/',
dev1: 'https://dev1-heimdall.xiaomai5.com/',
rc: 'https://rc-heimdall.xiaomai5.com/',
gray: 'https://gray-heimdall.xiaomai5.com/',
prod: 'https://gateway-heimdall.xiaomai5.com/'
};
function getParameterByName(name) {
name = name.replace(/[\\[]/, '\\[').replace(/[\]]/, '\\]')
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)')
const results = regex.exec(window.location.href)
return results === null
? ''
: decodeURIComponent(results[1].replace(/\+/g, ' '))
}
const env = getParameterByName('env');
const appTermEnum = getParameterByName('appTermEnum');
const code = getParameterByName('code');
const ticket = getParameterByName('ticket');
console.log(appTermEnum, code, ticket);
if (!code) {
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww80fd6928a46cf33a&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_privateinfo&state=STATE#wechat_redirect`
location.href = url
return
}
const ajaxOptions = {
data: JSON.stringify({
appTermEnum: appTermEnum,
code: code,
ticket: ticket
}),
type: 'POST',
url: BASIC_HOST_MAP[env] + "hades/anon/hades/wXWorkUserTicketLogin",
contentType: 'application/json; charset=UTF-8',
timeout: 20000,
dataType: 'json',
success(res, status, xhr) {
if (res.code == 200) {
$('#success').show()
} else {
$('#error').show();
var message = res.message.split(',').join('<br />')
$('#message').html(message)
}
},
};
$.ajax(ajaxOptions)
});
</script>
</html>
\ No newline at end of file
...@@ -77,6 +77,7 @@ checkBrowsers(paths.appPath, isInteractive) ...@@ -77,6 +77,7 @@ checkBrowsers(paths.appPath, isInteractive)
} }
const config = configFactory('development'); const config = configFactory('development');
console.log(config.entry)
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name; const appName = require(paths.appPackageJson).name;
const useTypeScript = fs.existsSync(paths.appTsConfig); const useTypeScript = fs.existsSync(paths.appTsConfig);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-31 09:34:25 * @Date: 2020-08-31 09:34:25
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-26 14:19:23 * @LastEditTime: 2021-01-09 15:50:08
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -20,6 +20,10 @@ class User { ...@@ -20,6 +20,10 @@ class User {
return Storage.get(`${PREFIX}_storeName`) return Storage.get(`${PREFIX}_storeName`)
} }
getStoreType(){
return Storage.get(`${PREFIX}_storeType`)
}
getStoreUserId(){ getStoreUserId(){
return Storage.get(`${PREFIX}_storeUserId`) return Storage.get(`${PREFIX}_storeUserId`)
} }
...@@ -43,6 +47,10 @@ class User { ...@@ -43,6 +47,10 @@ class User {
return Storage.set(`${PREFIX}_storeName`,value) return Storage.set(`${PREFIX}_storeName`,value)
} }
setStoreType(value:any){
return Storage.set(`${PREFIX}_storeType`,value)
}
setStoreUserId(value:any){ setStoreUserId(value:any){
return Storage.set(`${PREFIX}_storeUserId`,value) return Storage.set(`${PREFIX}_storeUserId`,value)
} }
......
@font-face { @font-face {
font-family: 'iconfont'; /* project id 2223403 */ font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.eot'); src: url('//at.alicdn.com/t/font_2223403_qb6r10go4s.eot');
src: url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.eot?#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_2223403_qb6r10go4s.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.woff2') format('woff2'), url('//at.alicdn.com/t/font_2223403_qb6r10go4s.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.woff') format('woff'), url('//at.alicdn.com/t/font_2223403_qb6r10go4s.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.ttf') format('truetype'), url('//at.alicdn.com/t/font_2223403_qb6r10go4s.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_w7su9rdwngo.svg#iconfont') format('svg'); url('//at.alicdn.com/t/font_2223403_qb6r10go4s.svg#iconfont') format('svg');
} }
.iconfont{ .iconfont{
font-family:"iconfont" !important; font-family:"iconfont" !important;
......
'use strict';
var extend = require('extend');
var qrcodeAlgObjCache = [];
var QRCodeAlg = require('./qrcodealg');
/**
* 计算矩阵点的前景色
* @param {Obj} config
* @param {Number} config.row 点x坐标
* @param {Number} config.col 点y坐标
* @param {Number} config.count 矩阵大小
* @param {Number} config.options 组件的options
* @return {String}
*/
var getForeGround = function getForeGround(config) {
var options = config.options;
if (options.pdground && (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5 || config.row > config.count - 6 && config.row < config.count - 2 && config.col > 1 && config.col < 5 || config.row > 1 && config.row < 5 && config.col > config.count - 6 && config.col < config.count - 2)) {
return options.pdground;
}
return options.foreground;
};
/**
* 点是否在Position Detection
* @param {row} 矩阵行
* @param {col} 矩阵列
* @param {count} 矩阵大小
* @return {Boolean}
*/
var inPositionDetection = function inPositionDetection(row, col, count) {
if (row < 7 && col < 7 || row > count - 8 && col < 7 || row < 7 && col > count - 8) {
return true;
}
return false;
};
/**
* 二维码构造函数,主要用于绘制
* @param {参数列表} opt 传递参数
* @return {}
*/
var qrcode = function qrcode(opt) {
if (typeof opt === 'string') {
// 只编码ASCII字符串
opt = {
text: opt
};
}
//设置默认参数
this.options = extend({}, {
text: '',
render: '',
size: 256,
correctLevel: 3,
background: '#ffffff',
foreground: '#000000',
image: '',
imageSize: 30
}, opt);
//使用QRCodeAlg创建二维码结构
var qrCodeAlg = null;
for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
qrCodeAlg = qrcodeAlgObjCache[i].obj;
break;
}
}
if (i == l) {
qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
qrcodeAlgObjCache.push({ text: this.options.text, correctLevel: this.options.correctLevel, obj: qrCodeAlg });
}
if (this.options.render) {
switch (this.options.render) {
case 'canvas':
return this.createCanvas(qrCodeAlg);
case 'table':
return this.createTable(qrCodeAlg);
case 'svg':
return this.createSVG(qrCodeAlg);
default:
return this.createDefault(qrCodeAlg);
}
}
return this.createDefault(qrCodeAlg);
};
extend(qrcode.prototype, {
// default create canvas -> svg -> table
createDefault: function createDefault(qrCodeAlg) {
var canvas = document.createElement('canvas');
if (canvas.getContext) {
return this.createCanvas(qrCodeAlg);
}
var SVG_NS = 'http://www.w3.org/2000/svg';
if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect) {
return this.createSVG(qrCodeAlg);
}
return this.createTable(qrCodeAlg);
},
// canvas create
createCanvas: function createCanvas(qrCodeAlg) {
var options = this.options;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var count = qrCodeAlg.getModuleCount();
// preload img
var loadImage = function loadImage(url, callback) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
img.onload = function () {
callback(this);
img.onload = null;
};
};
//计算每个点的长宽
var tileW = (options.size / count).toPrecision(4);
var tileH = (options.size / count).toPrecision(4);
canvas.width = options.size;
canvas.height = options.size;
//绘制
for (var row = 0; row < count; row++) {
for (var col = 0; col < count; col++) {
var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW);
var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW);
var foreground = getForeGround({
row: row,
col: col,
count: count,
options: options
});
ctx.fillStyle = qrCodeAlg.modules[row][col] ? foreground : options.background;
ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
}
}
if (options.image) {
loadImage(options.image, function (img) {
var x = ((options.size - options.imageSize) / 2).toFixed(2);
var y = ((options.size - options.imageSize) / 2).toFixed(2);
ctx.drawImage(img, x, y, options.imageSize, options.imageSize);
});
}
return canvas;
},
// table create
createTable: function createTable(qrCodeAlg) {
var options = this.options;
var count = qrCodeAlg.getModuleCount();
// 计算每个节点的长宽;取整,防止点之间出现分离
var tileW = Math.floor(options.size / count);
var tileH = Math.floor(options.size / count);
if (tileW <= 0) {
tileW = count < 80 ? 2 : 1;
}
if (tileH <= 0) {
tileH = count < 80 ? 2 : 1;
}
//创建table节点
//重算码大小
var s = [];
s.push('<table style="border:0px; margin:0px; padding:0px; border-collapse:collapse; background-color:' + options.background + ';">');
// 绘制二维码
for (var row = 0; row < count; row++) {
s.push('<tr style="border:0px; margin:0px; padding:0px; height:' + tileH + 'px">');
for (var col = 0; col < count; col++) {
var foreground = getForeGround({
row: row,
col: col,
count: count,
options: options
});
if (qrCodeAlg.modules[row][col]) {
s.push('<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color:' + foreground + '"></td>');
} else {
s.push('<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color:' + options.background + '"></td>');
}
}
s.push('</tr>');
}
s.push('</table>');
if (options.image) {
// 计算表格的总大小
var width = tileW * count;
var height = tileH * count;
var x = ((width - options.imageSize) / 2).toFixed(2);
var y = ((height - options.imageSize) / 2).toFixed(2);
s.unshift('<div style=\'position:relative; \n width:' + width + 'px; \n height:' + height + 'px;\'>');
s.push('<img src=\'' + options.image + '\' \n width=\'' + options.imageSize + '\' \n height=\'' + options.imageSize + '\' \n style=\'position:absolute;left:' + x + 'px; top:' + y + 'px;\'>');
s.push('</div>');
}
var span = document.createElement('span');
span.innerHTML = s.join('');
return span.firstChild;
},
// create svg
createSVG: function createSVG(qrCodeAlg) {
var options = this.options;
var count = qrCodeAlg.getModuleCount();
var scale = count / options.size;
// create svg
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', options.size);
svg.setAttribute('height', options.size);
svg.setAttribute('viewBox', '0 0 ' + count + ' ' + count);
for (var row = 0; row < count; row++) {
for (var col = 0; col < count; col++) {
var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
var foreground = getForeGround({
row: row,
col: col,
count: count,
options: options
});
rect.setAttribute('x', col);
rect.setAttribute('y', row);
rect.setAttribute('width', 1);
rect.setAttribute('height', 1);
rect.setAttribute('stroke-width', 0);
if (qrCodeAlg.modules[row][col]) {
rect.setAttribute('fill', foreground);
} else {
rect.setAttribute('fill', options.background);
}
svg.appendChild(rect);
}
}
// create image
if (options.image) {
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', options.image);
img.setAttribute('x', ((count - options.imageSize * scale) / 2).toFixed(2));
img.setAttribute('y', ((count - options.imageSize * scale) / 2).toFixed(2));
img.setAttribute('width', options.imageSize * scale);
img.setAttribute('height', options.imageSize * scale);
svg.appendChild(img);
}
return svg;
}
});
module.exports = qrcode;
\ No newline at end of file
/* /*
* @Author: wufan * @Author: wufan
* @Date: 2020-11-25 18:25:02 * @Date: 2020-11-25 18:25:02
* @LastEditors: zhangleyuan * @LastEditors: wufan
* @LastEditTime: 2020-12-23 16:52:56 * @LastEditTime: 2021-01-11 19:38:50
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -41,7 +41,7 @@ export function addEmployee(params: object) { ...@@ -41,7 +41,7 @@ export function addEmployee(params: object) {
} }
export function editEmployee(params: object) { export function editEmployee(params: object) {
return Service.Hades("public/hades/editStoreUser", params); return Service.Hades("public/hades/editOneselfMsg", params);
} }
export function deleteEmployee(params: object) { export function deleteEmployee(params: object) {
......
<!--
* @Author: 吴文洁
* @Date: 2020-08-24 12:20:57
* @LastEditors: wufan
* @LastEditTime: 2021-01-12 13:52:14
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="icon" href="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<!-- <link rel="apple-touch-icon" href="../src/common/images/logo.png" /> -->
<link rel="shortcut icon" href="https://image.xiaomaiketang.com/xm/KGSYFEpcHT.png">
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_qb6r10go4s.css">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>小麦企培</title>
<script type="text/javascript" charset="utf-8" src="//g.alicdn.com/sd/ncpc/nc.js?t=2015052012"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
import React, { useEffect, useState } from "react";
import ReactDOM from 'react-dom';
// import '@/core/function';
// import Service from "@/common/js/service";
// declare var getParameterByName: any;
function mount() {
ReactDOM.render(
<Main />,
document.getElementById('root'));
}
mount()
function Main() {
return <div>212121</div>
}
<!-- <!--
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan * @LastEditors: wufan
* @LastEditTime: 2021-01-12 15:26:36 * @LastEditTime: 2021-01-15 20:48:20
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_w7su9rdwngo.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_qb6r10go4s.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
...@@ -18,6 +18,11 @@ import 'antd/dist/antd.less'; ...@@ -18,6 +18,11 @@ import 'antd/dist/antd.less';
import 'video-react/dist/video-react.css'; import 'video-react/dist/video-react.css';
import '@/common/less/index.less'; import '@/common/less/index.less';
import '@/core/function'; import '@/core/function';
import User from '@/common/js/user';
import Service from "@/common/js/service";
declare var getParameterByName: any;
const history = createHashHistory(); const history = createHashHistory();
...@@ -25,23 +30,35 @@ window.RCHistory = _.extend({}, history, { ...@@ -25,23 +30,35 @@ window.RCHistory = _.extend({}, history, {
push: (obj: any) => { push: (obj: any) => {
history.push(obj) history.push(obj)
}, },
pushState: (obj: any) => { pushState: (obj: any) => {
history.push(obj) history.push(obj)
}, },
pushStateWithStatus: (obj: any) => { pushStateWithStatus: (obj: any) => {
history.push(obj) history.push(obj)
}, },
goBack: history.goBack, goBack: history.goBack,
location: history.location, location: history.location,
replace: (obj: any) => { replace: (obj: any) => {
history.replace(obj) history.replace(obj)
} }
}); });
export async function mount() { function mount() {
ReactDOM.render( ReactDOM.render(
<RootRouter/>, <RootRouter />,
document.getElementById('root')); document.getElementById('root'));
}
if (getParameterByName('code')) {
Service.Hades('anon/hades/wXWorkUserLogin', {
appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN',
code: getParameterByName('code')
}).then((res) => {
User.setUserId(res.result.loginInfo.userId);
User.setToken(res.result.loginInfo.xmToken);
mount()
})
} else {
mount()
} }
mount()
\ No newline at end of file
...@@ -43,7 +43,7 @@ class AbnormalModal extends React.Component { ...@@ -43,7 +43,7 @@ class AbnormalModal extends React.Component {
</div> </div>
) : ( ) : (
<div <div
className="content"> 你的小麦云课堂余额不足(<span className="high-light">{balance.toFixed(2)}</span>元),为保障您直播间的正常使用,请您及时充值。余额耗尽后将无法进行直播,学员无法观看回放视频。 className="content"> 你的小麦云企培余额不足(<span className="high-light">{balance.toFixed(2)}</span>元),为保障您直播间的正常使用,请您及时充值。余额耗尽后将无法进行直播,学员无法观看回放视频。
</div> </div>
); );
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-05 10:12:45 * @Date: 2020-08-05 10:12:45
* @LastEditors: zhangleyuan * @LastEditors: wufan
* @LastEditTime: 2021-01-15 19:58:12 * @LastEditTime: 2021-01-15 20:48:29
* @Description: 视频课-列表模块 * @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
......
.personal-info-page{ .personal-info-page{
.page-content{ .page-content{
.box{ .box{
padding:60px !important; padding: 60px 60px 60px 40px !important;
} }
.label{ .label{
width:56px; width:84px;
text-align:right; text-align:right;
font-size: 14px; font-size: 14px;
color: #666666; color: #666666;
...@@ -31,7 +30,7 @@ ...@@ -31,7 +30,7 @@
background: #000; background: #000;
opacity:0; opacity:0;
position: absolute; position: absolute;
left:63px; left:92px;
text-align:center; text-align:center;
line-height:60px; line-height:60px;
.pen{ .pen{
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2019-07-10 10:30:49 * @Date: 2019-07-10 10:30:49
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-26 14:47:37 * @LastEditTime: 2021-01-09 15:06:50
* @Description: * @Description:
*/ */
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
...@@ -39,13 +39,14 @@ const App: React.FC = (props: any) => { ...@@ -39,13 +39,14 @@ const App: React.FC = (props: any) => {
BaseService.getUserStore({ userId }).then((res) => { BaseService.getUserStore({ userId }).then((res) => {
const { storeGroupVOS = [], storeVOS = [] } = res.result; const { storeGroupVOS = [], storeVOS = [] } = res.result;
const { id, storeUserId, storeName, userRole } = storeVOS[0]; const { id, storeUserId, storeName, userRole, storeType } = storeVOS[0];
console.log("userRole----app",userRole)
User.setStoreId(id); User.setStoreId(id);
User.setStoreUserId(storeUserId); User.setStoreUserId(storeUserId);
User.setStoreName(storeName); User.setStoreName(storeName);
User.setUserRole(userRole); User.setUserRole(userRole);
User.setStoreType(storeType);
ctx.dispatch(setStoreGroupList(storeGroupVOS)) ctx.dispatch(setStoreGroupList(storeGroupVOS))
ctx.dispatch(setStoreList(storeVOS)); ctx.dispatch(setStoreList(storeVOS));
serStoreUserId(storeUserId) serStoreUserId(storeUserId)
......
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: wufan
* @LastEditTime: 2021-01-12 17:25:20
* @Description:
*/
import React, { useContext, useEffect, useState } from "react";
import "./Header.less";
import { Menu, Dropdown, Modal, Tooltip, message } from "antd";
import { LIVE_SHARE } from "@/domains/course-domain/constants";
import User from "@/common/js/user";
import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from "@/store/context";
import logoImg from "@/common/images/logo.png";
import CourseService from "@/domains/course-domain/CourseService";
import qrcode from "@/libs/qrcode/qrcode.js";
const baseImg = "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png";
const { confirm } = Modal;
function Header(props) {
const { menuType, handleMenuType } = props;
const ctx = useContext(XMContext);
const htmlUrl = `${LIVE_SHARE}store/index?id=${User.getStoreId()}&userId=${User.getUserId()}&from=work_weixin`;
useEffect(() => {
htmlUrl && handleConvertShortUrl();
}, []);
function userMenu() {
return (
<Menu
style={{
maxWidth: "250px",
marginTop: 5,
}}
>
<Menu.Item
style={{ whiteSpace: "normal", wordBreak: "break-all" }}
key="1"
onClick={() => toPersonalInfoPage()}
>
个人设置
</Menu.Item>
<Menu.Item
style={{ whiteSpace: "normal", wordBreak: "break-all" }}
key="2"
onClick={(e) => {
handleLogoutConfirm();
}}
>
退出登录
</Menu.Item>
</Menu>
);
}
function handleMenu() {
handleMenuType();
}
function toPersonalInfoPage() {
window.RCHistory.push({
pathname: `/personal-info`,
});
}
function handleLogoutConfirm() {
return confirm({
title: "你确定要退出登录吗?",
content: "退出后,需重新登录",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "退出登录",
cancelText: "点错了",
onOk: () => {
handleLogout();
},
});
}
function handleLogout() {
BaseService.logout({}).then((res) => {
User.removeUserId();
User.removeToken();
window.RCHistory.push({
pathname: `/login`,
});
});
}
function handleConvertShortUrl() {
CourseService.getQrcode({
urls: [htmlUrl],
}).then((res) => {
const { result = [] } = res;
const qrcodeWrapDom = document.querySelector("#h5-qrcode");
const qrcodeNode = new qrcode({
text: result[0].shortUrl,
size: 110,
});
qrcodeWrapDom && qrcodeWrapDom.appendChild(qrcodeNode);
});
}
// 复制分享链接
function handleCopy() {
window.copyText(htmlUrl);
message.success('已复制店铺地址,快去分享吧~');
}
return (
<div id="top-container" className="top-container">
<div className="top top-nav">
<div>
<img src={logoImg} className="logo" alt="" />
{menuType && <span className="logo-name">小麦企培</span>}
</div>
{menuType ? (
<span
className="icon iconfont cursor ml20 handLike"
onClick={handleMenu}
>
&#xe83d;
</span>
) : (
<span
className="icon iconfont cursor ml20 handLike"
onClick={handleMenu}
>
&#xe615;
</span>
)}
<div className="message-help">
<div className="store-related">
<div className="store-name">{User.getStoreName()}</div>
<div className="line"></div>
<div className="link-to-store">
<div className="link">
<span className="icon iconfont tool-tip-right">&#xe85d;</span>
<div className="text">前往店铺</div>
<div className="store-popover">
<div className="pc-url">
<div className="name">网页端店铺</div>
<div
className="url-link"
onClick={() => {
window.open(htmlUrl);
}}
>
{"立即前往 >"}
</div>
</div>
<div className="h5-url">
<div className="name">手机端店铺</div>
<div id="h5-qrcode"></div>
<div className="tip">微信扫码,打开店铺</div>
</div>
</div>
</div>
<div className="share" onClick={handleCopy}>
<Tooltip title="分享店铺" placement="bottom">
<span className="icon iconfont tool-tip-right">&#xe85e;</span>
</Tooltip>
<div className="text">分享店铺</div>
</div>
</div>
</div>
<Dropdown overlay={userMenu()}>
<div className="user">
<img
style={{
width: 32 + "px",
height: 32 + "px",
borderRadius: "50%",
overflow: "hidden",
flexShrink: 0,
}}
src={
ctx.xmState &&
ctx.xmState.storeList &&
ctx.xmState.storeList[0].avatar
? ctx.xmState.storeList[0].avatar
: baseImg
}
/>
{ctx.xmState && ctx.xmState.storeList && (
<span className="name">
{ctx.xmState.storeList[0].nickName}
</span>
)}
</div>
</Dropdown>
</div>
</div>
</div>
);
}
export default Header;
@import '../../core/variables.less'; @import "../../core/variables.less";
@top-height: 50px; @top-height: 50px;
@icon-color:#939393; @icon-color: #939393;
.top-container { .top-container {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
height: @top-height; height: @top-height;
background-color: #FFF; background-color: #fff;
z-index: 112; z-index: 112;
.logo{ .logo {
display: inline-block; display: inline-block;
height: 24px; height: 24px;
margin-left: 20px; margin-left: 20px;
} }
.logo-name{ .logo-name {
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
color: #FFB714; color: #ffb714;
line-height: 20px; line-height: 20px;
vertical-align: middle; vertical-align: middle;
font-weight:bold; font-weight: bold;
margin-left:11px; margin-left: 11px;
} }
.top { .top {
display: flex; display: flex;
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
height: 100%; height: 100%;
justify-content: space-between; justify-content: space-between;
-webkit-justify-content: space-between; -webkit-justify-content: space-between;
border-bottom:1px solid @xm-color-border; border-bottom: 1px solid @xm-color-border;
.backCenter{ .backCenter {
color:rgba(0,0,0,1); color: rgba(0, 0, 0, 1);
font-size: 16px; font-size: 16px;
} }
.top-left { .top-left {
...@@ -109,11 +109,11 @@ ...@@ -109,11 +109,11 @@
overflow-y: hidden; overflow-y: hidden;
border-radius: 4px; border-radius: 4px;
padding: 4px 0; padding: 4px 0;
-webkit-transition: all .3s; -webkit-transition: all 0.3s;
-moz-transition: all .3s; -moz-transition: all 0.3s;
-ms-transition: all .3s; -ms-transition: all 0.3s;
-o-transition: all .3s; -o-transition: all 0.3s;
transition: all .3s; transition: all 0.3s;
li { li {
margin: 2px 10px; margin: 2px 10px;
font-size: 12px; font-size: 12px;
...@@ -123,16 +123,16 @@ ...@@ -123,16 +123,16 @@
&:hover { &:hover {
.area-list { .area-list {
height: auto; height: auto;
background: rgba(0, 0, 0, .6); background: rgba(0, 0, 0, 0.6);
li { li {
-webkit-transition: all .3s; -webkit-transition: all 0.3s;
-moz-transition: all .3s; -moz-transition: all 0.3s;
-ms-transition: all .3s; -ms-transition: all 0.3s;
-o-transition: all .3s; -o-transition: all 0.3s;
transition: all .3s; transition: all 0.3s;
} }
li:hover { li:hover {
background-color: rgba(255, 255, 255, .2); background-color: rgba(255, 255, 255, 0.2);
} }
} }
} }
...@@ -177,16 +177,118 @@ ...@@ -177,16 +177,118 @@
flex: 1; flex: 1;
-webkit-flex: 1; -webkit-flex: 1;
justify-content: space-between; justify-content: space-between;
.store-name { .store-related {
width: 200px; width: 500px;
height: 20px; height: 49px;
font-size: 14px; display: flex;
color: #666; position: relative;
line-height: 20px; .store-name {
margin-left: 36px; font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 36px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 230px;
margin-right: 32px;
}
.line {
width: 1px;
height: 16px;
background-color: #f4f4f4;
position: absolute;
left: 122px;
top: 50%;
transform: translateY(-50%);
}
.link-to-store {
display: flex;
height: 49px;
line-height: 49px;
.text {
font-size: 14px;
color: #666;
line-height: 49px;
margin-left: 7px;
}
.iconfont {
color: #8c8e93;
&:hover {
color: #555;
}
}
.link {
display: flex;
cursor: pointer;
position: relative;
.store-popover {
display: none;
}
&:hover {
.store-popover {
position: absolute;
display: flex;
width: 216px;
height: 260px;
top: 49px;
left: 0;
background-color: #fff;
flex-wrap: wrap;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
.pc-url {
display: flex;
justify-content: space-between;
width: 100%;
height: 56px;
padding: 16px;
border-bottom: 1px solid #e8e8e8;
.name {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 20px;
}
.url-link {
color: #5289fa;
width: 70px;
font-size: 14px;
line-height: 20px;
}
}
.h5-url {
width: 100%;
.name,
.tip {
width: 70px;
font-size: 14px;
color: #333333;
line-height: 52px;
margin: 0 auto;
}
#h5-qrcode {
width: 110px;
height: 110px;
margin: 0 auto;
}
.tip {
line-height: 41px;
width: 130px;
}
}
}
}
}
.share {
cursor: pointer;
display: flex;
margin-left: 16px;
}
}
} }
.inst-container { .inst-container {
width: calc(~'100% - 420px'); width: calc(~"100% - 420px");
position: relative; position: relative;
.inst { .inst {
margin-right: 12px; margin-right: 12px;
...@@ -203,7 +305,7 @@ ...@@ -203,7 +305,7 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
max-width:230px; max-width: 230px;
} }
.icon { .icon {
font-size: 16px; font-size: 16px;
...@@ -237,7 +339,7 @@ ...@@ -237,7 +339,7 @@
} }
.ant-radio-wrapper { .ant-radio-wrapper {
display: inline-block; display: inline-block;
width: calc(~'100% - 28px'); width: calc(~"100% - 28px");
margin: 8px 0; margin: 8px 0;
.ant-radio { .ant-radio {
float: left; float: left;
...@@ -274,8 +376,8 @@ ...@@ -274,8 +376,8 @@
padding: 0 12px; padding: 0 12px;
width: 106px; width: 106px;
.icon-text { .icon-text {
margin-left:4px; margin-left: 4px;
color:#333; color: #333;
} }
} }
.icon { .icon {
...@@ -300,7 +402,7 @@ ...@@ -300,7 +402,7 @@
} }
.help-menu { .help-menu {
.help-center { .help-center {
box-shadow: 0 2px 8px rgba(0,0,0,0.15); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
top: 50px; top: 50px;
...@@ -333,7 +435,7 @@ ...@@ -333,7 +435,7 @@
} }
.message-menu { .message-menu {
.message-center { .message-center {
box-shadow: 0 0 8px rgba(0,0,0,0.15); box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
position: absolute; position: absolute;
overflow: hidden; overflow: hidden;
top: 50px; top: 50px;
...@@ -352,12 +454,13 @@ ...@@ -352,12 +454,13 @@
overflow: auto; overflow: auto;
// max-height: 255px; // max-height: 255px;
.message-item:hover { .message-item:hover {
background: #F3F6FA; background: #f3f6fa;
} }
li,a { li,
a {
width: 100%; width: 100%;
display: block; display: block;
border-bottom: 1px solid @xm-color-border; border-bottom: 1px solid @xm-color-border;
cursor: pointer; cursor: pointer;
padding: 16px; padding: 16px;
&.load-more { &.load-more {
...@@ -428,4 +531,4 @@ ...@@ -428,4 +531,4 @@
} }
} }
} }
} }
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-22 15:39:35
* @Description:
*/
import React , { useContext, useState}from 'react';
import './Header.less';
import {
Menu,
Dropdown,
Modal
} from 'antd';
import { QuestionCircleOutlined } from "@ant-design/icons";
import { withRouter } from 'react-router-dom';
import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from '@/store/context';
import logoImg from '@/common/images/logo.png';
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
const { confirm } = Modal;
interface headerProps {
menuType:boolean,
handleMenuType:() => void
}
function Header(props:headerProps){
const { menuType ,handleMenuType} = props;
const ctx: any = useContext(XMContext);
function userMenu() {
return (
<Menu
style={{
maxWidth: "250px",
marginTop: 5,
}}
>
<Menu.Item
style={{whiteSpace: "normal", wordBreak: "break-all"}}
key="1"
onClick={() => toPersonalInfoPage()}
>
个人设置
</Menu.Item>
<Menu.Item
style={{whiteSpace: "normal", wordBreak: "break-all"}}
key="2"
onClick={e => {
handleLogoutConfirm();
}}
>
退出登录
</Menu.Item>
</Menu>
);
}
function handleMenu(){
handleMenuType();
};
function toPersonalInfoPage(){
window.RCHistory.push({
pathname: `/personal-info`,
})
}
function handleLogoutConfirm(){
return confirm({
title: "你确定要退出登录吗?",
content: "退出后,需重新登录",
icon: <span className="icon iconfont default-confirm-icon">&#xe839; </span>,
okText: "退出登录",
cancelText: "点错了",
onOk: () => {
handleLogout();
},
});
}
function handleLogout(){
BaseService.logout({}).then((res) => {
User.removeUserId();
User.removeToken();
window.RCHistory.push({
pathname: `/login`,
})
});
}
return (
<div id="top-container" className="top-container">
<div className="top top-nav">
<div>
<img src={logoImg} className="logo" alt="" />
{menuType && (
<span className="logo-name">小麦企培</span>
)}
</div>
{menuType ? (
<span className="icon iconfont cursor ml20 handLike" onClick={handleMenu}>
&#xe83d;
</span>
) : (
<span className="icon iconfont cursor ml20 handLike" onClick={handleMenu}>
&#xe615;
</span>
)}
<div className="message-help">
<div className="store-name">{User.getStoreName()}</div>
<Dropdown overlay={userMenu()}>
<div className="user">
<img
style={{
width: 32 + "px",
height: 32 + "px",
borderRadius: "50%",
overflow: "hidden",
flexShrink: 0,
}}
src={(ctx.xmState && ctx.xmState.storeList &&ctx.xmState.storeList[0].avatar) ? ctx.xmState.storeList[0].avatar:baseImg}
/>
{ ctx.xmState && ctx.xmState.storeList && (
<span className="name">{ctx.xmState.storeList[0].nickName}</span>
)
}
</div>
</Dropdown>
</div>
</div>
</div>
);
}
export default Header;
import React, { useEffect, useState} from 'react'; import React, { useEffect, useState } from 'react';
import { import {
withRouter withRouter
} from 'react-router-dom'; } from 'react-router-dom';
import './Login.less'; import './Login.less';
import {Input,Popover,message} from 'antd'; import { Input, Popover, message, Tabs } from 'antd';
import CheckBeforeSendCode from '../../components/CheckBeforeSendCode'; import CheckBeforeSendCode from '../../components/CheckBeforeSendCode';
import User from '@/common/js/user'; import User from '@/common/js/user';
import WechatLogin from './WechatLogin'
import BaseService from "@/domains/basic-domain/baseService"; import BaseService from "@/domains/basic-domain/baseService";
import axios from 'axios'; import axios from 'axios';
import _ from 'underscore'; import _ from 'underscore';
const { TabPane } = Tabs;
function Login(props) { function Login(props) {
const [phone, setPhone] = useState(''); // 登录手机号 const [phone, setPhone] = useState(''); // 登录手机号
...@@ -17,10 +20,10 @@ function Login(props) { ...@@ -17,10 +20,10 @@ function Login(props) {
const [checking1, setChecking1] = useState(false); const [checking1, setChecking1] = useState(false);
const [codeText, setCodeText] = useState('获取验证码'); // 验证码提示语 const [codeText, setCodeText] = useState('获取验证码'); // 验证码提示语
const [waitStatus, setWaitStatus] = useState(false); // 验证码是否在倒计时 const [waitStatus, setWaitStatus] = useState(false); // 验证码是否在倒计时
const [errorMessage,setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
const [phoneError,setPhoneError] = useState(false); const [phoneError, setPhoneError] = useState(false);
const [checkObject1, setCheckObject1] = useState({}); const [checkObject1, setCheckObject1] = useState({});
async function checkAccount(code, callback = () => { }) { async function checkAccount(code, callback = () => { }) {
callback(); callback();
} }
...@@ -48,7 +51,7 @@ function Login(props) { ...@@ -48,7 +51,7 @@ function Login(props) {
token: checkData.token, token: checkData.token,
scene: 'nc_login', scene: 'nc_login',
serverType: "CLOUD_CLASS_LOGIN", serverType: "CLOUD_CLASS_LOGIN",
appTermEnum:'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN' appTermEnum: 'XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN'
} }
BaseService.sendLoginAuthCode(params).then((res) => { BaseService.sendLoginAuthCode(params).then((res) => {
if (!res.success) { if (!res.success) {
...@@ -86,14 +89,14 @@ function Login(props) { ...@@ -86,14 +89,14 @@ function Login(props) {
setErrorMessage("请输入11位手机号") setErrorMessage("请输入11位手机号")
return; return;
} }
if(!phoneverify){ if (!phoneverify) {
setErrorMessage("请输入验证码"); setErrorMessage("请输入验证码");
return; return;
} }
const params = { const params = {
phone, phone,
authCode:phoneverify, authCode: phoneverify,
appTermEnum:"XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN" appTermEnum: "XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN"
} }
BaseService.login(params).then((res) => { BaseService.login(params).then((res) => {
if (!res.success) { if (!res.success) {
...@@ -112,44 +115,46 @@ function Login(props) { ...@@ -112,44 +115,46 @@ function Login(props) {
<div className="login-page" > <div className="login-page" >
<div className="login-main"> <div className="login-main">
<div className="left-banner"> <div className="left-banner">
<div><img src={require("../../common/images/logo.png")} alt="" style={{ width: 60,height:61}} /></div> <div><img src={require("../../common/images/logo.png")} alt="" style={{ width: 60, height: 61 }} /></div>
<div className="name">小麦企培</div> <div className="name">小麦企培</div>
<div className="desc">一键开启直播授课 让知识更有价值</div> <div className="desc">一键开启直播授课 让知识更有价值</div>
</div> </div>
<div className="login-box"> <div className="login-box">
<div className="login"> <div className="login">
<div className="r"> <div className="r">
<div className="title"> <Tabs defaultActiveKey="1" >
手机号登录 <TabPane tab="企业微信登录" key="1">
</div> <WechatLogin></WechatLogin>
<div className="login-form"> </TabPane>
<div className="form"> <TabPane tab="手机号登录" key="2">
<div className="username" style={{ marginBottom: 16 }}> <div className="login-form">
<Input <div className="form">
type="phone" <div className="username" style={{ marginBottom: 16 }}>
autoComplete="off" <Input
name="account" type="phone"
maxLength={11} autoComplete="off"
placeholder="手机号" name="account"
value={phone} maxLength={11}
onChange={(e) => { setPhone(e.target.value) }} placeholder="手机号"
/> value={phone}
</div> onChange={(e) => { setPhone(e.target.value) }}
<div className="error-message"> />
</div>
</div> <div className="error-message">
<div className="phoneverify">
<Input </div>
type="text" <div className="phoneverify">
id="phoneverify" <Input
name="phoneverify" type="text"
placeholder="验证码" id="phoneverify"
autoComplete="off" name="phoneverify"
value={phoneverify} placeholder="验证码"
maxLength={4} autoComplete="off"
onChange={(e) => { setPhoneverify(e.target.value) }} value={phoneverify}
/> maxLength={4}
<Popover onChange={(e) => { setPhoneverify(e.target.value) }}
/>
<Popover
visible={openCheck1} visible={openCheck1}
trigger="click" trigger="click"
title="" title=""
...@@ -183,19 +188,23 @@ function Login(props) { ...@@ -183,19 +188,23 @@ function Login(props) {
}} }}
>{codeText}</div> >{codeText}</div>
</Popover> </Popover>
</div> </div>
<div className="error-message"> <div className="error-message">
{errorMessage} {errorMessage}
</div> </div>
<div className="submit"> <div className="submit">
<div className="btn"> <div className="btn">
<button id='loginIn' onClick={ () => { handleSubmit() } } >登录</button> <button id='loginIn' onClick={() => { handleSubmit() }} >登录</button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </TabPane>
</Tabs>
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -78,6 +78,38 @@ ...@@ -78,6 +78,38 @@
overflow: hidden; overflow: hidden;
background-color: #ffffff; background-color: #ffffff;
border-radius: 4px; //box-shadow: 0 0 17px @sun; border-radius: 4px; //box-shadow: 0 0 17px @sun;
.ant-tabs-tab-btn{
color: #999999;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
line-height: 25px;
&.ant-tabs-tab-active{
color: #333333;
}
}
.ant-tabs-tab-active{
.ant-tabs-tab-btn{
color: #333333;
}
}
.ant-tabs-nav::before{
display: none;
}
.ant-tabs-tab{
width: 105px;
text-align: center;
}
.ant-tabs > .ant-tabs-nav .ant-tabs-nav-list{
margin: 0 auto;
}
.ant-tabs-top > .ant-tabs-nav .ant-tabs-ink-bar{
width: 24px !important;
height: 4px;
margin-left: 30px;
}
.l { .l {
width: 280px; width: 280px;
height: 100%; height: 100%;
...@@ -420,4 +452,5 @@ ...@@ -420,4 +452,5 @@
} }
} }
} }
} }
\ No newline at end of file
.wechatLoginBox{
height: 320px;
text-align: center;
.text{
margin-top: 12px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
}
.rwm{
position: relative;
width: 160px;
height: 160px;
text-align: center;
display: inline-block;
margin-top: 24px;
.error{
position: absolute;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.95);
display: flex;
align-items:center;
justify-content:center;
left:0px;
top: 0px;
div{
margin: 0 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
}
.ope{
cursor: pointer;
color:rgba(82, 137, 250, 1);
}
}
}
.ant-tabs-tab-active{
.ant-tabs-tab-btn{
color: #333333;
}
}
.ant-tabs-tab-btn{
color: #999999;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
line-height: 25px;
}
.ant-tabs-nav::before{
display: none;
}
.ant-tabs-tab{
width: 105px;
text-align: center;
}
.ant-tabs > .ant-tabs-nav .ant-tabs-nav-list{
margin: 0 auto;
}
.ant-tabs-top > .ant-tabs-nav .ant-tabs-ink-bar{
width: 24px !important;
height: 4px;
margin-left: 30px;
}
}
import React, { useState, useRef, useEffect } from 'react';
import qrcode from '@/core/qrcode/qrcode.js'
import Service from "@/common/js/service";
import User from '@/common/js/user';
import './WechatLogin.less'
const Logo = require("@/common/images/logo.png")
declare var location: any;
export default function WechatLogin(props: any) {
const freshTime = 60;
const init: any = null;
const [status, setStatus] = useState(0);
const [ticket, setTicket] = useState('');
const [leftTime, setLeftTime] = useState(freshTime)
const QRCode = useRef(init);
const timer = useRef(init);
const leftTimeRef = useRef(init);
useEffect(() => {
leftTimeRef.current = leftTime;
}, [leftTime])
useEffect(() => {
clearInterval(timer.current as any);
if (status === 0) {
Service.Hades("anon/hades/getTicket", {}).then((res: any) => {
setTicket(res.result)
const redirect = `${location.origin + location.pathname.replace('index.html', 'h5.html')}?ticket=${res.result}&appTermEnum=XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN&env=${process.env.DEPLOY_ENV || 'dev'}`
// console.log(redirect)
// const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww409ccf9c6e31f19e&redirect_uri=${encodeURIComponent(redirect)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`
// console.log(url)
let qrnode = new qrcode({
text: redirect,
correctLevel: 2,
size: 160,
image: Logo,
imageSize: 50
});
QRCode.current.innerHTML = ''
QRCode.current.prepend(qrnode);
setLeftTime(freshTime);
timer.current = setInterval(() => {
if (leftTimeRef.current == 0) {
clearInterval(timer.current);
setStatus(1);
return
}
setLeftTime(leftTimeRef.current - 1);
}, 1000)
})
}
return () => {
clearInterval(timer.current);
}
}, [status])
useEffect(() => {
if (leftTime == 60 || !ticket) {
return
}
Service.Hades('anon/hades/getTicketState', {
ticket
}).then((res: any) => {
if (res.result === 'AUTH_SUCCESS') {
Service.Hades('anon/hades/getTicketWXWorkLogin', {
ticket
}).then((_res: any) => {
User.setUserId(_res.result.loginInfo.userId);
User.setToken(_res.result.loginInfo.xmToken);
window.RCHistory.push({
pathname: `/switch-route`,
})
})
}
})
}, [leftTime])
return <div className='wechatLoginBox'>
<div className="rwm">
<div id="qrcode" ref={(dom) => {
QRCode.current = dom
}}></div>
{
status === 1 && <div className="error">
<div>二维码已过期
<p className="ope" onClick={() => {
setStatus(0)
}}>刷新</p>
</div>
</div>
}
{
status === 2 && <div className="error">
<div>所在企业还未注册店铺
<p className="ope" onClick={() => {
setStatus(0)
}}>我知道了</p>
</div>
</div>
}
{
status === 3 && <div className="error">
<div>你还不是店铺员工,请联系企业管理员
<p className="ope" onClick={() => {
setStatus(0)
}}>我知道了</p>
</div>
</div>
}
</div>
<p className='text'>请使用企业微信扫码登录</p>
</div>
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-11-27 16:21:49 * @Date: 2020-11-27 16:21:49
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-28 10:21:12 * @LastEditTime: 2021-01-09 16:32:41
* @Description: Description * @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
...@@ -35,17 +35,23 @@ interface AddEmployeeModalProps { ...@@ -35,17 +35,23 @@ interface AddEmployeeModalProps {
role: Array<string>; role: Array<string>;
avatar?: string; avatar?: string;
storeUserId?: string; storeUserId?: string;
weChatAccount?: string
}; };
onClose: () => void; onClose: () => void;
isWorkWechat: boolean;
} }
function AddEmployeeModal(props: AddEmployeeModalProps) { function AddEmployeeModal(props: AddEmployeeModalProps) {
const [nickName, setName] = useState(""); const [nickName, setName] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
const [role, setRole] = useState("CloudLecturer"); const [role, setRole] = useState("CloudLecturer");
const [avatar, setAvatar] = useState("https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"); const [avatar, setAvatar] = useState(
"https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"
);
const storeUserId = props.choosedItem.storeUserId; const storeUserId = props.choosedItem.storeUserId;
const [imgUrl, setImgUrl] = useState(avatar || 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'); const [imgUrl, setImgUrl] = useState(
avatar || "https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"
);
const [nameErrorMsg, setNameErrorMsg] = useState(""); const [nameErrorMsg, setNameErrorMsg] = useState("");
const [nameStatus, setNameStatus] = useState< const [nameStatus, setNameStatus] = useState<
"" | "error" | "success" | "warning" | "validating" | undefined "" | "error" | "success" | "warning" | "validating" | undefined
...@@ -64,14 +70,16 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -64,14 +70,16 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
props.choosedItem.phone && setPhone(props.choosedItem.phone); props.choosedItem.phone && setPhone(props.choosedItem.phone);
props.choosedItem.role && setRole(props.choosedItem.role[0]); props.choosedItem.role && setRole(props.choosedItem.role[0]);
props.choosedItem.avatar && setAvatar(props.choosedItem.avatar); props.choosedItem.avatar && setAvatar(props.choosedItem.avatar);
const _role = props.choosedItem.role[0] === "CloudLecturer" ? "CloudLecturer" : "CloudManager"; const _role =
form.setFieldsValue({ props.choosedItem.role[0] === "CloudLecturer"
? "CloudLecturer"
: "CloudManager";
form.setFieldsValue({
nickName: props.choosedItem.nickName, nickName: props.choosedItem.nickName,
role: _role, role: _role,
phone: props.choosedItem.phone, phone: props.choosedItem.phone,
avatar: props.choosedItem.avatar avatar: props.choosedItem.avatar,
}); });
} }
}, [props.choosedItem.nickName]); }, [props.choosedItem.nickName]);
...@@ -97,9 +105,9 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -97,9 +105,9 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
} }
function changeAvatar(img: string): any { function changeAvatar(img: string): any {
form.setFieldsValue({ form.setFieldsValue({
avatar: img avatar: img,
}); });
setAvatar(img); setAvatar(img);
setImgUrl(img); setImgUrl(img);
} }
...@@ -118,7 +126,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -118,7 +126,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
setNameErrorMsg(""); setNameErrorMsg("");
setNameStatus(""); setNameStatus("");
if (!String(values.phone)) { if (!String(values.phone) && !props.isWorkWechat) {
setPhoneErrorMessage("请输入手机号码"); setPhoneErrorMessage("请输入手机号码");
setPhoneStatus("error"); setPhoneStatus("error");
return; return;
...@@ -126,7 +134,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -126,7 +134,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
setPhoneErrorMessage(""); setPhoneErrorMessage("");
setPhoneStatus(""); setPhoneStatus("");
if (String(values.phone).length !== 11) { if (String(values.phone).length !== 11 && !props.isWorkWechat) {
setPhoneErrorMessage("请输入11位手机号"); setPhoneErrorMessage("请输入11位手机号");
setPhoneStatus("error"); setPhoneStatus("error");
return; return;
...@@ -134,8 +142,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -134,8 +142,7 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
setPhoneErrorMessage(""); setPhoneErrorMessage("");
setPhoneStatus(""); setPhoneStatus("");
props.choosedItem.nickName ? handleEditEmployee() : handleAddEmployee(); props.choosedItem.nickName ? handleEditEmployee() : handleAddEmployee();
} }
function handleChangeValues(name: string, value: any) { function handleChangeValues(name: string, value: any) {
...@@ -160,17 +167,16 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -160,17 +167,16 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
default: default:
break; break;
} }
} }
function handleAddEmployee() { function handleAddEmployee() {
const params = { const params = {
nickName, nickName,
phone: String(phone), phone: String(phone),
roleCodes:[role], roleCodes: [role],
avatar avatar,
}; };
console.log("params",params); console.log("params", params);
StoreService.addEmployee(params).then((res) => { StoreService.addEmployee(params).then((res) => {
message.success("保存成功"); message.success("保存成功");
props.onClose(); props.onClose();
...@@ -181,11 +187,11 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -181,11 +187,11 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
const params = { const params = {
nickName, nickName,
phone: String(phone), phone: String(phone),
roleCodes:[role], roleCodes: [role],
avatar, avatar,
storeUserId:storeUserId storeUserId: storeUserId,
}; };
console.log("params",params); console.log("params", params);
StoreService.editEmployee(params).then((res) => { StoreService.editEmployee(params).then((res) => {
message.success("编辑成功"); message.success("编辑成功");
...@@ -226,32 +232,38 @@ function AddEmployeeModal(props: AddEmployeeModalProps) { ...@@ -226,32 +232,38 @@ function AddEmployeeModal(props: AddEmployeeModalProps) {
onChange={(e) => handleChangeValues("nickName", e.target.value)} onChange={(e) => handleChangeValues("nickName", e.target.value)}
/> />
</Form.Item> </Form.Item>
{props.isWorkWechat ? (
<Form.Item <Form.Item
label="手机号码" label="企业微信账号"
name="phone" name="weChatAccount"
rules={[{ required: true }]} >
validateStatus={phoneStatus} <div>{props.choosedItem.weChatAccount}</div>
help={phoneErrorMessage} </Form.Item>
> ) : (
<Input <Form.Item
style={{ width: 200 }} label="手机号码"
placeholder="请输入手机号" name="phone"
maxLength={11} rules={[{ required: true }]}
autoComplete="off" validateStatus={phoneStatus}
disabled={!!props.choosedItem.nickName} help={phoneErrorMessage}
onChange={(e) => { >
if((e.target.value).match(/^\d+$/)){ <Input
handleChangeValues("phone", e.target.value); style={{ width: 200 }}
} else { placeholder="请输入手机号"
setPhoneErrorMessage("只能输入数字"); maxLength={11}
setPhoneStatus("error"); autoComplete="off"
} disabled={!!props.choosedItem.nickName}
} onChange={(e) => {
} if (e.target.value.match(/^\d+$/)) {
/> handleChangeValues("phone", e.target.value);
</Form.Item> } else {
setPhoneErrorMessage("只能输入数字");
setPhoneStatus("error");
}
}}
/>
</Form.Item>
)}
<Form.Item <Form.Item
label="员工身份" label="员工身份"
name="role" name="role"
......
...@@ -15,4 +15,12 @@ ...@@ -15,4 +15,12 @@
color: #BFBFBF; color: #BFBFBF;
} }
} }
.employee-info {
img {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 20px;
}
}
} }
...@@ -17,6 +17,7 @@ import EmployeeAddOrEditModal from "./EmployeeAddOrEditModal"; ...@@ -17,6 +17,7 @@ import EmployeeAddOrEditModal from "./EmployeeAddOrEditModal";
import User from "@/common/js/user"; import User from "@/common/js/user";
import "./EmployeesManagePage.less"; import "./EmployeesManagePage.less";
import Item from "antd/lib/list/Item";
const { confirm } = Modal; const { confirm } = Modal;
const { Search } = Input; const { Search } = Input;
...@@ -29,6 +30,7 @@ interface RecordTypes { ...@@ -29,6 +30,7 @@ interface RecordTypes {
nickName: string; nickName: string;
phone: string; phone: string;
avatar?: string; avatar?: string;
weChatAccount?: string;
} }
interface RoleItemType { interface RoleItemType {
...@@ -52,6 +54,7 @@ interface ChoosedItemType { ...@@ -52,6 +54,7 @@ interface ChoosedItemType {
role: Array<string>; role: Array<string>;
avatar?: string; avatar?: string;
storeUserId?: string; storeUserId?: string;
weChatAccount?: string;
} }
function EmployeesManagePage() { function EmployeesManagePage() {
...@@ -61,7 +64,7 @@ function EmployeesManagePage() { ...@@ -61,7 +64,7 @@ function EmployeesManagePage() {
size: 10, size: 10,
nickName: "", nickName: "",
phone: "", phone: "",
roleCodes: [] roleCodes: [],
}); });
const [valueLike, setValueLike] = useState(); const [valueLike, setValueLike] = useState();
...@@ -83,6 +86,8 @@ function EmployeesManagePage() { ...@@ -83,6 +86,8 @@ function EmployeesManagePage() {
StoreManager: "店铺管理员", StoreManager: "店铺管理员",
}; };
const storeId = User.getStoreId(); const storeId = User.getStoreId();
const StoreType = User.getStoreType();
const isWorkWechat = !!(StoreType === "WE_CHAT_STORE");
useEffect(() => { useEffect(() => {
getEmployeeList(); getEmployeeList();
...@@ -110,8 +115,8 @@ function EmployeesManagePage() { ...@@ -110,8 +115,8 @@ function EmployeesManagePage() {
const data = [...res.result]; const data = [...res.result];
const _query = { ...query }; const _query = { ...query };
let _data = _.filter(data, _item => { let _data = _.filter(data, (_item) => {
return _item.roleCode !== "StoreManager"; return _item.roleCode !== "StoreManager";
}); });
setRoleIds(_data); setRoleIds(_data);
...@@ -119,13 +124,23 @@ function EmployeesManagePage() { ...@@ -119,13 +124,23 @@ function EmployeesManagePage() {
} }
function parseColumn() { function parseColumn() {
return [ const columns = [
{ {
title: "员工", title: "员工",
dataIndex: "nickName", dataIndex: "nickName",
render: (val: string) => { render: (val: string, record: RecordTypes) => {
return ( return (
<div className="coupon-info"> <div className="employee-info">
{isWorkWechat && (
<img
src={
record.avatar ||
"https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png"
}
alt=""
/>
)}
<span className="title">{val}</span> <span className="title">{val}</span>
</div> </div>
); );
...@@ -162,7 +177,11 @@ function EmployeesManagePage() { ...@@ -162,7 +177,11 @@ function EmployeesManagePage() {
<span className="divider-line">{" | "}</span> <span className="divider-line">{" | "}</span>
<span <span
className="delete" className="delete"
onClick={() => handleDeleteEmployeeConfirm(record)} onClick={() =>{
isWorkWechat?
handleDeleteWorkWechatEmployeeConfirm(record) :
handleDeleteEmployeeConfirm(record)
}}
> >
删除 删除
</span> </span>
...@@ -171,16 +190,30 @@ function EmployeesManagePage() { ...@@ -171,16 +190,30 @@ function EmployeesManagePage() {
}, },
}, },
]; ];
if (isWorkWechat && columns) {
const item = {
title: "企业微信账号",
dataIndex: "weChatAccount",
key: "weChatAccount",
render: (val: string) => {
return <div>{val}</div>;
},
};
columns.splice(1, 1, item);
}
return columns;
} }
function handleEditEmployee(record: RecordTypes) { function handleEditEmployee(record: RecordTypes) {
const { nickName, phone, roleCodes, avatar, id } = record; const { nickName, phone, roleCodes, avatar, id, weChatAccount } = record;
const _choosesItem = { const _choosesItem = {
nickName: nickName, nickName: nickName,
phone: phone, phone: phone,
role: roleCodes, role: roleCodes,
avatar: avatar, avatar: avatar,
storeUserId: id, storeUserId: id,
weChatAccount
}; };
setChooseItem(_choosesItem); setChooseItem(_choosesItem);
const model: React.ReactNode = ( const model: React.ReactNode = (
...@@ -194,9 +227,11 @@ function EmployeesManagePage() { ...@@ -194,9 +227,11 @@ function EmployeesManagePage() {
phone: "", phone: "",
role: [], role: [],
avatar: "", avatar: "",
storeUserId: "" storeUserId: "",
weChatAccount:""
}); });
}} }}
isWorkWechat={isWorkWechat}
/> />
); );
setModel(model); setModel(model);
...@@ -206,9 +241,27 @@ function EmployeesManagePage() { ...@@ -206,9 +241,27 @@ function EmployeesManagePage() {
return confirm({ return confirm({
title: "你确定要删除此讲师吗?", title: "你确定要删除此讲师吗?",
content: "删除后,讲师将不能登录系统,此操作不能被撤销", content: "删除后,讲师将不能登录系统,此操作不能被撤销",
icon: <span className="icon iconfont default-confirm-icon">&#xe839; </span>, icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "删除",
okType: "danger",
cancelText: "取消",
onOk: () => {
handleDeleteEmployee(record.id);
},
});
}
function handleDeleteWorkWechatEmployeeConfirm(record: RecordTypes) {
return confirm({
title: "你确定要删除此员工吗?",
content: "管理员需在企业微信后台的“小麦企培”应用管理中移除此员工,此员工才无法继续登陆小麦企培",
icon: (
<span className="icon iconfont default-confirm-icon">&#xe839; </span>
),
okText: "删除", okText: "删除",
okType: 'danger', okType: "danger",
cancelText: "取消", cancelText: "取消",
onOk: () => { onOk: () => {
handleDeleteEmployee(record.id); handleDeleteEmployee(record.id);
...@@ -228,17 +281,19 @@ function EmployeesManagePage() { ...@@ -228,17 +281,19 @@ function EmployeesManagePage() {
phone: "", phone: "",
role: [], role: [],
avatar: "", avatar: "",
storeUserId: "" storeUserId: "",
}); });
}} }}
isWorkWechat={isWorkWechat}
/> />
); );
setModel(model); setModel(model);
} }
function handleDeleteEmployee(storeUserId: string) { function handleDeleteEmployee(storeUserId: string) {
StoreService.deleteEmployee({ storeUserId }).then((res: any) => { StoreService.deleteEmployee({ storeUserId }).then((res: any) => {
message.success("讲师已删除"); const msg = isWorkWechat ? "员工已删除":"讲师已删除";
message.success(msg);
getEmployeeList(); getEmployeeList();
}); });
} }
...@@ -269,17 +324,26 @@ function EmployeesManagePage() { ...@@ -269,17 +324,26 @@ function EmployeesManagePage() {
width: 300, width: 300,
marginRight: 40, marginRight: 40,
}} }}
placeholder="搜索员工昵称/手机号" placeholder={
isWorkWechat ? "请输入员工昵称" : "搜索员工昵称/手机号"
}
onSearch={(value) => { onSearch={(value) => {
const _query = { ...query }; const _query = { ...query };
// 企业微信用户只能搜索员工昵称
if (isWorkWechat) {
_query.nickName = value;
_query.current = 0;
setQuery(_query);
return;
}
if (value) { if (value) {
const isPhone = (value || "").match(/^\d+$/); const isPhone = (value || "").match(/^\d+$/);
const name = isPhone ? "phone" : "nickName"; const name = isPhone ? "phone" : "nickName";
const otherName = isPhone ? "nickName" : "phone"; const otherName = isPhone ? "nickName" : "phone";
_query[name] = value; _query[name] = value;
_query[otherName] = ''; _query[otherName] = "";
_query.current = 0; _query.current = 0;
} else { } else {
_query.nickName = ""; _query.nickName = "";
_query.phone = ""; _query.phone = "";
...@@ -327,15 +391,17 @@ function EmployeesManagePage() { ...@@ -327,15 +391,17 @@ function EmployeesManagePage() {
})} })}
</div> </div>
</div> </div>
<Button {!isWorkWechat && (
onClick={() => { <Button
handleToAddEmployee(); onClick={() => {
}} handleToAddEmployee();
type="primary" }}
className="add-show-btn" type="primary"
> className="add-show-btn"
添加员工 >
</Button> 添加员工
</Button>
)}
</div> </div>
<div className="box-body"> <div className="box-body">
<Table <Table
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* @Author: wufan * @Author: wufan
* @Date: 2020-11-30 10:47:38 * @Date: 2020-11-30 10:47:38
* @LastEditors: wufan * @LastEditors: wufan
* @LastEditTime: 2020-12-22 11:52:56 * @LastEditTime: 2021-01-09 15:59:32
* @Description: 员工管理页面 * @Description: 店铺装修页面
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment