14 |
15 | @implementation AppDelegate
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
18 | {
19 | NSURL *jsCodeLocation;
20 |
21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
22 |
23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
24 | moduleName:@"AwesomeProject"
25 | initialProperties:nil
26 | launchOptions:launchOptions];
27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
28 |
29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
30 | UIViewController *rootViewController = [UIViewController new];
31 | rootViewController.view = rootView;
32 | self.window.rootViewController = rootViewController;
33 | [self.window makeKeyAndVisible];
34 | return YES;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/client/actions/app.js:
--------------------------------------------------------------------------------
1 | import { getOrgUrl, getParamByName, _localStorage } from '../common/bbPlugin'
2 | export function updateSelectedTab(tabName){
3 | return{
4 | type: 'UPDATE_SELECTEDTAB',
5 | tabName
6 | }
7 | }
8 |
9 | export function ddConfigSuccess(ddConfig) {
10 | return{
11 | type: 'DDCONFIG_SUCCESS',
12 | ddConfig
13 | }
14 | }
15 |
16 | export function ddConfigError() {
17 | return{
18 | type: 'DDCONFIG_ERROR',
19 | }
20 | }
21 |
22 | export function updateCode(code) {
23 | return{
24 | type: 'DDCONFIG_ERROR',
25 | code
26 | }
27 | }
28 |
29 | export function getUserInfo() {
30 | const infoJson = _localStorage.getItem('infoJson') || {};
31 | const uuid = infoJson.empId || 0;
32 | return {
33 | type: 'GET_USERINFO',
34 | payload: {
35 | request:{
36 | url: getOrgUrl() +'/empl/'+uuid
37 | }
38 | }
39 | }
40 | }
41 |
42 | export function updateUserInfo(userInfo) {
43 | return {
44 | type: 'UPDATE_USERINFO',
45 | userInfo
46 | }
47 | }
48 |
49 | export function signOutApp() {
50 | const infoJson = _localStorage.getItem('infoJson') || {};
51 | return {
52 | type: 'SIGN_OUT_APP',
53 | payload: {
54 | request:{
55 | method: 'delete',
56 | url: getOrgUrl() +'/loginOut',
57 | data: {
58 | corpId: getParamByName('corpid'),
59 | userId: infoJson.dingUserId,
60 | }
61 | }
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/client/components/RejectBox.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Flex, TextareaItem, Button } from 'antd-mobile'
3 |
4 |
5 | const RejectBox = React.createClass({
6 |
7 | getInitialState() {
8 | return {
9 | type: this.props.type || '',
10 | reasons: {
11 | '': [],
12 | businessOut: ['暂缓','工作无法排期','没有必要'],
13 | leave: ['时间过长','影响工作','不符公司规定'],
14 | sign: ['理由不充分','时间异常']
15 | },
16 | reason: '',
17 | }
18 | },
19 |
20 | onReasonChange(value){
21 | this.setState({reason: value}, ()=>{
22 | this.props.onChange && this.props.onChange(this.state.reason)
23 | })
24 | },
25 |
26 | render(){
27 |
28 | return (
29 |
30 |
31 | {this.state.reasons[this.state.type].map((item, index)=> (
32 |
36 |
37 |
38 | ))}
39 |
40 |
46 |
47 | )
48 | }
49 |
50 | })
51 |
52 | export default RejectBox
--------------------------------------------------------------------------------
/client/common/axiosConfig.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | // import { _localStorage } from './bbPlugin'
3 | // import { logException } from './ravenConfig'
4 | import env from '../env/env'
5 |
6 | require('promise.prototype.finally').shim() //给axios添加finally方法
7 |
8 | const config = {
9 |
10 | // 请求方法同上
11 | method: 'get', // default
12 |
13 | // 基础url前缀
14 | // baseURL: 'http://116.236.230.131:55002',
15 | baseURL: env.API_HOST + '/rest/ding',
16 |
17 | //设置超时时间
18 | timeout: 20000,
19 |
20 | }
21 |
22 | //全局配置axios
23 | for(let key in config){
24 | axios.defaults[key] = config[key];
25 | }
26 | axios.interceptors.request.use(function (request) {
27 | let infoJson = {}
28 | let token = infoJson.token;
29 | if(token && (!request.params || request.params.send_token !== false)){
30 | if(request.params){
31 | request.params.dtoken = token
32 | }else{
33 | request.params = {
34 | dtoken : token
35 | }
36 | }
37 | }else{
38 | if(request.params){
39 | delete request.params.send_token;
40 | }
41 | }
42 | return request
43 | })
44 | //response过滤
45 | axios.interceptors.response.use(function (response) {
46 | // 这里提前处理返回的数据
47 | // if(typeof response == 'object'){
48 | // if(response.status == 200){
49 | // return response.data;
50 | // }else{
51 | // logException(new Error(response.status+' 错误'), response)
52 | // }
53 | // }else{
54 | // logException(new Error('接口返回不是一个对象'), response)
55 | // }
56 | return response;
57 | }, function (error) {
58 |
59 | return Promise.reject(error);
60 | });
61 |
62 | export default config;
--------------------------------------------------------------------------------
/android/app/BUCK:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | # To learn about Buck see [Docs](https://buckbuild.com/).
4 | # To run your application with Buck:
5 | # - install Buck
6 | # - `npm start` - to start the packager
7 | # - `cd android`
8 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
9 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
10 | # - `buck install -r android/app` - compile, install and run application
11 | #
12 |
13 | lib_deps = []
14 | for jarfile in glob(['libs/*.jar']):
15 | name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
16 | lib_deps.append(':' + name)
17 | prebuilt_jar(
18 | name = name,
19 | binary_jar = jarfile,
20 | )
21 |
22 | for aarfile in glob(['libs/*.aar']):
23 | name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
24 | lib_deps.append(':' + name)
25 | android_prebuilt_aar(
26 | name = name,
27 | aar = aarfile,
28 | )
29 |
30 | android_library(
31 | name = 'all-libs',
32 | exported_deps = lib_deps
33 | )
34 |
35 | android_library(
36 | name = 'app-code',
37 | srcs = glob([
38 | 'src/main/java/**/*.java',
39 | ]),
40 | deps = [
41 | ':all-libs',
42 | ':build_config',
43 | ':res',
44 | ],
45 | )
46 |
47 | android_build_config(
48 | name = 'build_config',
49 | package = 'com.awesomeproject',
50 | )
51 |
52 | android_resource(
53 | name = 'res',
54 | res = 'src/main/res',
55 | package = 'com.awesomeproject',
56 | )
57 |
58 | android_binary(
59 | name = 'app',
60 | package_type = 'debug',
61 | manifest = 'src/main/AndroidManifest.xml',
62 | keystore = '//android/keystores:debug',
63 | deps = [
64 | ':app-code',
65 | ],
66 | )
67 |
--------------------------------------------------------------------------------
/ios/AwesomeProject-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UIViewControllerBasedStatusBarAppearance
38 |
39 | NSLocationWhenInUseUsageDescription
40 |
41 | NSAppTransportSecurity
42 |
43 |
44 | NSExceptionDomains
45 |
46 | localhost
47 |
48 | NSExceptionAllowsInsecureHTTPLoads
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/ios/AwesomeProject/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | AwesomeProject
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/client/components/Avatar.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | Text,
4 | View,
5 | StyleSheet,
6 | Platform,
7 | Image,
8 | } from 'react-native';
9 | import { Badge, Flex } from 'antd-mobile'
10 | import AvatarService from '../common/ddAvatar'
11 |
12 | const sizeStyle = {
13 | md: 40,
14 | lg: 55,
15 | xlg: 100,
16 | }
17 | const fontSize = {
18 | md: 14,
19 | lg: 20,
20 | xlg: 30,
21 | }
22 |
23 | class Avatar extends Component{
24 |
25 | constructor(props) {
26 | super(props);
27 | };
28 |
29 | static get defaultProps() {
30 | return {
31 | src: false,
32 | nick: '',
33 | name: '',
34 | size: 'md'
35 | }
36 | }
37 |
38 | getUserAvatar = function(){
39 | const user = AvatarService.getAvatar(this.props.nick, this.props.name);
40 | return user
41 | }
42 |
43 | render(){
44 | let avatar = ;
45 | if(this.props.size == 'lg'){
46 |
47 | }else{
48 |
49 | }
50 | if(!this.props.src || this.props.src == ''){
51 | const user = this.getUserAvatar();
52 | avatar = (
53 |
54 | {user.name || '12'}
55 |
56 | )
57 | }else{
58 | avatar = ()
59 | }
60 |
61 | return (
62 | {avatar}
63 | )
64 | }
65 |
66 | }
67 |
68 | export default Avatar
--------------------------------------------------------------------------------
/ios/AwesomeProjectTests/AwesomeProjectTests.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 | #import
12 |
13 | #import
14 | #import
15 |
16 | #define TIMEOUT_SECONDS 600
17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
18 |
19 | @interface AwesomeProjectTests : XCTestCase
20 |
21 | @end
22 |
23 | @implementation AwesomeProjectTests
24 |
25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
26 | {
27 | if (test(view)) {
28 | return YES;
29 | }
30 | for (UIView *subview in [view subviews]) {
31 | if ([self findSubviewInView:subview matching:test]) {
32 | return YES;
33 | }
34 | }
35 | return NO;
36 | }
37 |
38 | - (void)testRendersWelcomeScreen
39 | {
40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
42 | BOOL foundElement = NO;
43 |
44 | __block NSString *redboxError = nil;
45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
46 | if (level >= RCTLogLevelError) {
47 | redboxError = message;
48 | }
49 | });
50 |
51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
54 |
55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
57 | return YES;
58 | }
59 | return NO;
60 | }];
61 | }
62 |
63 | RCTSetLogFunction(RCTDefaultLogFunction);
64 |
65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
67 | }
68 |
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/client/components/MonthChoose.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { Badge, Flex, Icon } from 'antd-mobile'
3 |
4 |
5 | const Component = React.createClass({
6 |
7 | getInitialState() {
8 | return {
9 | canChooseFuture: this.props.chooseFuture || false,
10 | currentYear: this.props.year || new Date().getFullYear(),
11 | currentMonth: this.props.mouth || (new Date().getMonth()+1),
12 | }
13 | },
14 | // shouldComponentUpdate(){
15 | // return
16 | // },
17 | preMonth(){
18 | let state = {};
19 |
20 | if(this.state.currentMonth <= 1){
21 | state = {
22 | currentYear: this.state.currentYear - 1,
23 | currentMonth: 12,
24 | }
25 | }else{
26 | state = {
27 | currentMonth: this.state.currentMonth - 1,
28 | }
29 | }
30 | this.setState(state,()=>{
31 | this.props.onClickPreMonth && this.props.onClickPreMonth(this.state.currentYear,this.state.currentMonth)
32 | })
33 | },
34 | nextMonth(){
35 | if(!this.state.canChooseFuture &&
36 | this.state.currentYear == new Date().getFullYear() &&
37 | this.state.currentMonth == (new Date().getMonth()+1)){
38 | return
39 | }
40 | let state = {};
41 |
42 | if(this.state.currentMonth >= 12){
43 | state = {
44 | currentYear: this.state.currentYear + 1,
45 | currentMonth: 1,
46 | }
47 | }else{
48 | state = {
49 | currentMonth: this.state.currentMonth + 1,
50 | }
51 | }
52 | this.setState(state,()=>{
53 | this.props.onClickNextMonth && this.props.onClickNextMonth(this.state.currentYear,this.state.currentMonth)
54 | })
55 | },
56 | render(){
57 |
58 | return (
59 |
60 |
61 |
62 |
63 |
64 | {this.state.currentYear}年{this.state.currentMonth}月
65 |
66 |
67 |
68 |
69 |
70 | )
71 | }
72 | })
73 |
74 | export default Component
75 |
76 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Disabling obfuscation is useful if you collect stack traces from production crashes
20 | # (unless you are using a system that supports de-obfuscate the stack traces).
21 | -dontobfuscate
22 |
23 | # React Native
24 |
25 | # Keep our interfaces so they can be used by other ProGuard rules.
26 | # See http://sourceforge.net/p/proguard/bugs/466/
27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
30 |
31 | # Do not strip any method/class that is annotated with @DoNotStrip
32 | -keep @com.facebook.proguard.annotations.DoNotStrip class *
33 | -keep @com.facebook.common.internal.DoNotStrip class *
34 | -keepclassmembers class * {
35 | @com.facebook.proguard.annotations.DoNotStrip *;
36 | @com.facebook.common.internal.DoNotStrip *;
37 | }
38 |
39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
40 | void set*(***);
41 | *** get*();
42 | }
43 |
44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; }
46 | -keepclassmembers,includedescriptorclasses class * { native ; }
47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
50 |
51 | -dontwarn com.facebook.react.**
52 |
53 | # okhttp
54 |
55 | -keepattributes Signature
56 | -keepattributes *Annotation*
57 | -keep class okhttp3.** { *; }
58 | -keep interface okhttp3.** { *; }
59 | -dontwarn okhttp3.**
60 |
61 | # okio
62 |
63 | -keep class sun.misc.Unsafe { *; }
64 | -dontwarn java.nio.file.*
65 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
66 | -dontwarn okio.**
67 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/ios/AwesomeProject/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/client/data/user.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 |
3 | const listData = {
4 | pageParam: {
5 | pageIndex: 1,
6 | pageLength: 20,
7 |
8 | },
9 | pageData: {
10 | list: [],
11 | hasNextPage: true
12 | },
13 | loading: false,
14 | }
15 |
16 | const user = {
17 | //yjj
18 | //公出详情
19 | businessOutDetail: {},
20 | //审批中心
21 | approvalListData: {
22 | "tabSelected": '2',
23 | "summary": {
24 | "checkInOutCount": 0,
25 | "workOutCount": 0,
26 | "leaveCount": 0
27 | },
28 | timestamp: {
29 | "1": 0,
30 | "2": 0,
31 | "3": 0
32 | },
33 | "1": {
34 | pageData: {
35 | list: [],
36 | total: 0,
37 | hasNextPage: true
38 | },
39 | pageParam: {
40 | pageIndex: 1,
41 | pageLength: 20,
42 | type: 1,
43 | },
44 | loading: false,
45 | },
46 | "2": {
47 | pageData: {
48 | list: [],
49 | total: 0,
50 | hasNextPage: true
51 | },
52 | pageParam: {
53 | pageIndex: 1,
54 | pageLength: 20,
55 | type: 2,
56 | },
57 | loading: false,
58 | },
59 | "3": {
60 | pageData: {
61 | list: [],
62 | total: 0,
63 | hasNextPage: true
64 | },
65 | pageParam: {
66 | pageIndex: 1,
67 | pageLength: 20,
68 | type: 3,
69 | },
70 | loading: false,
71 | }
72 | },
73 |
74 | //考勤中心
75 | attendanceData:{
76 | //选择的
77 | selected: {
78 | dept:{
79 | id: '',
80 | name: ''
81 | },
82 | date: moment().format('YYYY-MM-DD')
83 | },
84 | data: {
85 | "listOrg": [
86 |
87 | ],
88 | "recordSummary": {
89 | "checkInOutCount": 0,
90 | "workOutCount": 0,
91 | "leaveCount": 0,
92 | "emplCount": 0,
93 | "checkInOutInfo": "",
94 | "leaveInfo": "",
95 | "workOutInfo": ""
96 | },
97 | "listLeave": [],
98 | "listBusiness": [],
99 | "listSignRecord": []
100 | }
101 | },
102 |
103 | //公司默认上下班时间
104 | defaultTime: {
105 | signIn: '',
106 | signOut: ''
107 | },
108 |
109 | //班步列表
110 | categoryListData: {
111 | //部门动态
112 | 'DEPT_EMPLOYEE_ENTRY,DEPT_EMPLOYEE_RESIGN,INTERVIEW': {
113 | title: '部门动态',
114 | list: [],
115 | loading: false
116 | }
117 |
118 | },
119 |
120 | //班步详情列表
121 | categoryDetail:{
122 | //公司公告
123 | COMP_ANNOUNCEMENTS: {
124 | ...listData
125 | },
126 | //祝福提醒
127 | WISH_REMIND: {
128 | ...listData
129 | },
130 | //班步动态
131 | BAMBOO_TRENDS: {
132 | ...listData
133 | },
134 | //员工入职
135 | DEPT_EMPLOYEE_ENTRY: {
136 | ...listData
137 | },
138 | //员工离职
139 | DEPT_EMPLOYEE_RESIGN: {
140 | ...listData
141 | },
142 | //面试提醒
143 | INTERVIEW: {
144 | ...listData
145 | }
146 | },
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | //zj
155 | userHome:[],
156 | userPast:{},
157 | holidayType:[],
158 | offWorkApply:{},
159 | getOffWorkDetail:{},
160 | messageList:[],
161 | pastBuDetail:{},
162 | benedictionIndex:[],
163 | benedictionDetail:{}
164 | }
165 | export default user;
166 |
--------------------------------------------------------------------------------
/client/components/ListItem.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | Text,
4 | View,
5 | StyleSheet,
6 | Platform,
7 | Image,
8 | } from 'react-native';
9 | import { Badge, Flex } from 'antd-mobile'
10 | import Avatar from './Avatar'
11 |
12 | export const style = StyleSheet.create({
13 | box: {
14 | height: 65,
15 | // marginLeft: 15,
16 | paddingRight:15,
17 | paddingVertical:9,
18 | backgroundColor: '#fff',
19 | },
20 | boxBorder: {
21 | borderBottomWidth: 0.5,
22 | borderBottomColor: '#dcdcdc',
23 | },
24 | title: {
25 | fontSize: 15,
26 | color: '#333',
27 | marginBottom: 6
28 | },
29 | subTitle: {
30 | fontSize: 13,
31 | color: '#7b7b7b'
32 | }
33 | });
34 |
35 | class ListItem extends Component{
36 |
37 | static get defaultProps () {
38 | return {
39 | img: false,
40 | nick: '',
41 | name: '',
42 |
43 | title: '',
44 | desc: '',
45 | oneline: true,
46 | hasBorder: true
47 | };
48 | }
49 |
50 | render(){
51 |
52 | let title = typeof this.props.title === 'string'
53 | ? {this.props.title}
54 | : this.props.title
55 |
56 | return (
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {title}
66 |
67 | {this.props.desc || ' '}
68 |
69 |
70 | {this.props.children}
71 |
72 |
73 |
74 |
75 |
76 | )
77 | }
78 |
79 | }
80 |
81 | export default ListItem
82 |
83 |
84 | export function getCategoryPathAndIcon(category, uuid){
85 | let path, image;
86 | switch (category) {
87 | case '0':
88 | path = '/boss-company-management'
89 | image = require('../../img/icon-category-0.png')
90 | break;
91 | case '1': //公司公告
92 | path = '/category/COMP_ANNOUNCEMENTS'
93 | image = require('../../img/icon-category-1.png')
94 | break;
95 | case '2': //祝福提醒
96 | path = '/category/WISH_REMIND'
97 | image = require('../../img/icon-category-2.png')
98 | break;
99 | case '3': //审批中心
100 | path = '/approval-center'
101 | image = require('../../img/icon-category-3.png')
102 | break;
103 | case '4': //考勤中心
104 | path = '/attendance-center'
105 | image = require('../../img/icon-category-4.png')
106 | break;
107 | case '5': //部门动态
108 | path = '/category-list/DEPT_EMPLOYEE_ENTRY,DEPT_EMPLOYEE_RESIGN,INTERVIEW'
109 | image = require('../../img/icon-category-5.png')
110 | break;
111 | case '6': //云档案
112 | path = null
113 | image = require('../../img/icon-category-6.png')
114 | break;
115 | case '7': //班步动态
116 | path = '/category/BAMBOO_TRENDS'
117 | image = require('../../img/icon-category-7.png')
118 | break;
119 |
120 | case '8': //生日祝福
121 | image = require('../../img/icon-category-8.png')
122 | break;
123 | case '10': //新人入职
124 | image = require('../../img/icon-category-10.png')
125 | break;
126 |
127 | case '20': //面试提醒
128 | path = '/category/INTERVIEW'
129 | image = require('../../img/icon-category-20.png')
130 | break;
131 | case '29': //员工入职
132 | path = '/category/DEPT_EMPLOYEE_ENTRY'
133 | image = require('../../img/icon-category-29.png')
134 | break;
135 | case '30': //员工离职
136 | path = '/category/DEPT_EMPLOYEE_RESIGN'
137 | image = require('../../img/icon-category-30.png')
138 | break;
139 |
140 | }
141 | return {
142 | path,
143 | image
144 | }
145 | }
--------------------------------------------------------------------------------
/client/styles/style.scss:
--------------------------------------------------------------------------------
1 | @media only screen and (min-device-width: 320px) and (max-device-width: 374px) and (orientation : portrait) {
2 | /*iPhone 5 Portrait*/
3 | html{
4 | font-size: 48px;
5 | }
6 | }
7 |
8 | @media only screen and (min-device-width: 320px) and (max-device-width: 374px) and (orientation : landscape) {
9 | /*iPhone 5 landscape*/
10 | html{
11 | font-size: 48px;
12 | }
13 | }
14 |
15 | @media only screen and (min-device-width: 374px) and (max-device-width: 666px) and (orientation : portrait) {
16 | /*iPhone 6 Portrait*/
17 | html{
18 | font-size: 50px;
19 | }
20 | }
21 |
22 | @media only screen and (min-device-width: 374px) and (max-device-width: 666px) and (orientation : landscape) {
23 | /*iPhone 6 landscape*/
24 | html{
25 | font-size: 50px;
26 | }
27 | }
28 |
29 | @media only screen and (min-device-width: 414px) and (max-device-width: 736px) and (orientation : portrait) {
30 | /*iPhone 6+ Portrait*/
31 | html{
32 | font-size: 52px;
33 | }
34 | }
35 |
36 | @media only screen and (min-device-width: 414px) and (max-device-width: 736px) and (orientation : landscape) {
37 | /*iPhone 6+ landscape*/
38 | html{
39 | font-size: 52px;
40 | }
41 | }
42 |
43 | @import "var";
44 |
45 | body {
46 | a {
47 | color: #474747;
48 | }
49 | * {
50 | box-sizing: border-box;
51 | }
52 | .am-tab-bar-bar{
53 | z-index: 999;
54 | }
55 | img{
56 | max-width: 100%;
57 | }
58 | .audit_icon{
59 | color: $danger;
60 | }
61 | .check_icon{
62 | color: $primary;
63 | }
64 | }
65 | .am-button-primary{
66 | background-color: $primary;
67 | border: 1PX solid $primary;
68 |
69 | &.am-button-active{
70 | background: darken($primary, 10%);
71 | }
72 | }
73 |
74 | .am-button-ghost{
75 |
76 | &.btn-danger{
77 | color: $danger;
78 | border: 1PX solid $danger;
79 |
80 | &.am-button-active{
81 | color: #fff;
82 | background-color: $danger;
83 | border: 1PX solid $danger;
84 | }
85 | }
86 | }
87 |
88 | .bb{
89 | .am-list-item{
90 |
91 | .am-list-line{
92 |
93 | &:after{
94 | border-color: $fenge;
95 | }
96 | }
97 | .am-input-label,.am-list-content{
98 | font-size: 0.32rem;
99 | color: $black;
100 | }
101 | .am-list-extra{
102 | font-size: 0.32rem;
103 | color: $gray;
104 | }
105 | .am-input-control{
106 | input{
107 | font-size: 0.32rem;
108 | color: $gray;
109 | }
110 | }
111 | .am-textarea-control{
112 | textarea{
113 | font-size: 0.32rem;
114 | color: $gray;
115 | }
116 | }
117 | }
118 |
119 |
120 | //全局实心按钮设置
121 | .am-button{
122 |
123 | &.btn-md{
124 | height: .78rem;
125 | width: 2.58rem;
126 | line-height: .78rem;
127 | font-size: .36rem;
128 | }
129 | &.btn-sm{
130 | height: .56rem;
131 | width: 1.04rem;
132 | line-height: .56rem;
133 | font-size: .24rem;
134 | padding: 0 .1rem;
135 | }
136 |
137 | &.btn-primary{
138 | color: #fff;
139 | background-color: $primary;
140 | border: 1PX solid $primary;
141 |
142 | &.am-button-active{
143 | background: darken($primary, 10%);
144 | }
145 | }
146 | &.btn-waring{
147 | color: #fff;
148 | background-color: $waring;
149 | border: 1PX solid $waring;
150 |
151 | &.am-button-active{
152 | background: darken($waring, 10%);
153 | }
154 | }
155 | &.btn-danger{
156 | color: #fff;
157 | background-color: $danger;
158 | border: 1PX solid $danger;
159 |
160 | &.am-button-active{
161 | background: darken($waring, 10%);
162 | }
163 | }
164 |
165 | &:disabled{
166 | background-color: $gray!important;
167 | }
168 | }
169 |
170 | //全局空心按钮设置
171 | .am-button.am-button-ghost{
172 | &.btn-primary{
173 | color: $primary;
174 | background: none;
175 | border: 1PX solid $primary;
176 |
177 | &.am-button-active{
178 | color: #fff;
179 | background-color: $primary;
180 | border: 1PX solid $primary;
181 | }
182 | }
183 | &.btn-waring{
184 | color: $waring;
185 | background: none;
186 | border: 1PX solid $waring;
187 |
188 | &.am-button-active{
189 | color: #fff;
190 | background-color: $waring;
191 | border: 1PX solid $waring;
192 | }
193 | }
194 | &.btn-danger{
195 | color: $danger;
196 | background: none;
197 | border: 1PX solid $danger;
198 |
199 | &.am-button-active{
200 | color: #fff;
201 | background-color: $danger;
202 | border: 1PX solid $danger;
203 | }
204 | }
205 |
206 |
207 |
208 | }
209 |
210 | }
211 |
212 | .left-60{
213 | .am-list-content{
214 | -ms-flex-preferred-size: initial!important;
215 | flex-basis: initial!important;
216 | }
217 | }
218 | .right-60{
219 | .am-list-extra{
220 | -ms-flex-preferred-size: initial!important;
221 | flex-basis: initial!important;
222 | }
223 | }
--------------------------------------------------------------------------------
/client/common/gps.js:
--------------------------------------------------------------------------------
1 | var GPS = {
2 | PI: 3.14159265358979324,
3 | x_pi: 3.14159265358979324 * 3000.0 / 180.0,
4 | delta: function (lat, lon) {
5 | // Krasovsky 1940
6 | //
7 | // a = 6378245.0, 1/f = 298.3
8 | // b = a * (1 - f)
9 | // ee = (a^2 - b^2) / a^2;
10 | var a = 6378245.0;
11 | var ee = 0.00669342162296594323;
12 | var dLat = this.transformLat(lon - 105.0, lat - 35.0);
13 | var dLon = this.transformLon(lon - 105.0, lat - 35.0);
14 | var radLat = lat / 180.0 * this.PI;
15 | var magic = Math.sin(radLat);
16 | magic = 1 - ee * magic * magic;
17 | var sqrtMagic = Math.sqrt(magic);
18 | dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
19 | dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
20 | return {'lat': dLat, 'lon': dLon};
21 | },
22 | //WGS-84 to GCJ-02
23 | gcj_encrypt: function (wgsLat, wgsLon) {
24 | if (this.outOfChina(wgsLat, wgsLon))
25 | return {'lat': wgsLat, 'lon': wgsLon};
26 |
27 | var d = this.delta(wgsLat, wgsLon);
28 | return {'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon};
29 | },
30 | //GCJ-02 to WGS-84
31 | gcj_decrypt: function (gcjLat, gcjLon) {
32 | if (this.outOfChina(gcjLat, gcjLon))
33 | return {'lat': gcjLat, 'lon': gcjLon};
34 |
35 | var d = this.delta(gcjLat, gcjLon);
36 | return {'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon};
37 | },
38 | //GCJ-02 to WGS-84 exactly
39 | gcj_decrypt_exact: function (gcjLat, gcjLon) {
40 | var initDelta = 0.01;
41 | var threshold = 0.000000001;
42 | var dLat = initDelta, dLon = initDelta;
43 | var mLat = gcjLat - dLat, mLon = gcjLon - dLon;
44 | var pLat = gcjLat + dLat, pLon = gcjLon + dLon;
45 | var wgsLat, wgsLon, i = 0;
46 | while (1) {
47 | wgsLat = (mLat + pLat) / 2;
48 | wgsLon = (mLon + pLon) / 2;
49 | var tmp = this.gcj_encrypt(wgsLat, wgsLon)
50 | dLat = tmp.lat - gcjLat;
51 | dLon = tmp.lon - gcjLon;
52 | if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))
53 | break;
54 |
55 | if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;
56 | if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;
57 |
58 | if (++i > 10000) break;
59 | }
60 | //console.log(i);
61 | return {'lat': wgsLat, 'lon': wgsLon};
62 | },
63 | //GCJ-02 to BD-09
64 | bd_encrypt: function (gcjLat, gcjLon) {
65 | var x = gcjLon, y = gcjLat;
66 | var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
67 | var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
68 | var bdLon = z * Math.cos(theta) + 0.0065;
69 | var bdLat = z * Math.sin(theta) + 0.006;
70 | return {'lat': bdLat, 'lon': bdLon};
71 | },
72 | //BD-09 to GCJ-02
73 | bd_decrypt: function (bdLat, bdLon) {
74 | var x = bdLon - 0.0065, y = bdLat - 0.006;
75 | var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
76 | var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
77 | var gcjLon = z * Math.cos(theta);
78 | var gcjLat = z * Math.sin(theta);
79 | return {'lat': gcjLat, 'lon': gcjLon};
80 | },
81 | distance: function (latA, logA, latB, logB) {
82 | var earthR = 6371000;
83 | var x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((logA - logB) * Math.PI / 180);
84 | var y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180);
85 | var s = x + y;
86 | if (s > 1)
87 | s = 1;
88 | if (s < -1)
89 | s = -1;
90 | var alpha = Math.acos(s);
91 | var distance = alpha * earthR;
92 | return distance;
93 | },
94 | outOfChina: function (lat, lon) {
95 | if (lon < 72.004 || lon > 137.8347)
96 | return true;
97 | if (lat < 0.8293 || lat > 55.8271)
98 | return true;
99 | return false;
100 | },
101 | transformLat: function (x, y) {
102 | var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
103 | ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
104 | ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
105 | ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
106 | return ret;
107 | },
108 | transformLon: function (x, y) {
109 | var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
110 | ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
111 | ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
112 | ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
113 | return ret;
114 | }
115 | };
116 |
117 | export default GPS;
--------------------------------------------------------------------------------
/client/components/AddressPopup.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { List, Icon, Flex, SwipeAction } from 'antd-mobile'
3 | import { _localStorage } from '../common/bbPlugin'
4 |
5 | const ListItem = React.createClass({
6 |
7 | getInitialState() {
8 | return {
9 | address_list: _localStorage.getItem('address_list') || []
10 | }
11 | },
12 |
13 | setStar(e, index) {
14 | e.stopPropagation();
15 | let item = this.state.address_list[index];
16 | item.star = !item.star;
17 |
18 | let tmp_list = [
19 | ...this.state.address_list.slice(0,index),
20 | item,
21 | ...this.state.address_list.slice(index+1)
22 | ];
23 | this.setState({
24 | address_list: tmp_list
25 | });
26 | _localStorage.setItem('address_list', tmp_list)
27 | },
28 | deleteAddress(index){
29 |
30 | let tmp_list = [
31 | ...this.state.address_list.slice(0, index),
32 | ...this.state.address_list.slice(index+1)
33 | ]
34 | this.setState({
35 | address_list: tmp_list
36 | });
37 | _localStorage.setItem('address_list', tmp_list)
38 | },
39 | setCompany(item){
40 | this.props.onAddressChange && this.props.onAddressChange(item)
41 | },
42 |
43 | getAddressList(list, star = true){
44 | let dom, count = 0;
45 | dom = list.map((item, index)=>{
46 | let flag;
47 | if(star){
48 | flag = true
49 | }else{
50 | flag = false
51 | }
52 | if(item.star == flag || (flag == false && !item.star)) {
53 | count++;
54 | return (
55 | console.log('取消'),
64 | style: { backgroundColor: '#ddd', color: 'white' },
65 | },
66 | {
67 | text: '删除',
68 | onPress: () => { this.deleteAddress(index) },
69 | style: { backgroundColor: '#F4333C', color: 'white' },
70 | },
71 | ]}
72 | >
73 | { this.setStar(e,index) }} type={star?'star':'star-o'} style={{padding:'.2rem',color: star?'orange':''}}/>}
75 | onClick={this.setCompany.bind(null, item)}>
76 | {item.company}
77 | {item.address}
78 |
79 |
80 | )
81 | }
82 | })
83 | return {
84 | dom : dom,
85 | count: count
86 | };
87 | },
88 | render(){
89 |
90 | const { address_list } = this.state;
91 |
92 | const use_list = this.getAddressList(address_list, true);
93 | const last_list = this.getAddressList(address_list, false);
94 |
95 | return (
96 |
97 |
98 |
{ this.setCompany(false) } }
101 | >
102 |
103 |
104 |
105 |
0 ? '': 'none'}}
107 | className="popup-list"
108 | renderHeader={() => '常用地址'}
109 | >
110 | { use_list.dom }
111 |
112 |
113 |
0 ? '': 'none'}}
115 | className="popup-list"
116 | renderHeader={() => '最近' }
117 | >
118 | { last_list.dom }
119 |
120 |
121 |
124 | 您还没有常用地址
125 |
126 |
127 | )
128 | }
129 |
130 | })
131 |
132 | export default ListItem
133 |
134 |
135 | export function addAddress(item) {
136 | let list = _localStorage.getItem('address_list') || [];
137 | let flag = false;
138 | for(let i=0; i
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
61 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
92 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
113 |
119 |
120 |
121 |
122 |
124 |
125 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
61 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
92 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
113 |
119 |
120 |
121 |
122 |
124 |
125 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation
19 | * entryFile: "index.android.js",
20 | *
21 | * // whether to bundle JS and assets in debug mode
22 | * bundleInDebug: false,
23 | *
24 | * // whether to bundle JS and assets in release mode
25 | * bundleInRelease: true,
26 | *
27 | * // whether to bundle JS and assets in another build variant (if configured).
28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
29 | * // The configuration property can be in the following formats
30 | * // 'bundleIn${productFlavor}${buildType}'
31 | * // 'bundleIn${buildType}'
32 | * // bundleInFreeDebug: true,
33 | * // bundleInPaidRelease: true,
34 | * // bundleInBeta: true,
35 | *
36 | * // the root of your project, i.e. where "package.json" lives
37 | * root: "../../",
38 | *
39 | * // where to put the JS bundle asset in debug mode
40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
41 | *
42 | * // where to put the JS bundle asset in release mode
43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
44 | *
45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
46 | * // require('./image.png')), in debug mode
47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
48 | *
49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
50 | * // require('./image.png')), in release mode
51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
52 | *
53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
57 | * // for example, you might want to remove it from here.
58 | * inputExcludes: ["android/**", "ios/**"],
59 | *
60 | * // override which node gets called and with what additional arguments
61 | * nodeExecutableAndArgs: ["node"]
62 | *
63 | * // supply additional arguments to the packager
64 | * extraPackagerArgs: []
65 | * ]
66 | */
67 |
68 | apply from: "../../node_modules/react-native/react.gradle"
69 |
70 | /**
71 | * Set this to true to create two separate APKs instead of one:
72 | * - An APK that only works on ARM devices
73 | * - An APK that only works on x86 devices
74 | * The advantage is the size of the APK is reduced by about 4MB.
75 | * Upload all the APKs to the Play Store and people will download
76 | * the correct one based on the CPU architecture of their device.
77 | */
78 | def enableSeparateBuildPerCPUArchitecture = false
79 |
80 | /**
81 | * Run Proguard to shrink the Java bytecode in release builds.
82 | */
83 | def enableProguardInReleaseBuilds = false
84 |
85 | android {
86 | compileSdkVersion 23
87 | buildToolsVersion "23.0.1"
88 |
89 | defaultConfig {
90 | applicationId "com.awesomeproject"
91 | minSdkVersion 16
92 | targetSdkVersion 22
93 | versionCode 1
94 | versionName "1.0"
95 | ndk {
96 | abiFilters "armeabi-v7a", "x86"
97 | }
98 | }
99 | splits {
100 | abi {
101 | reset()
102 | enable enableSeparateBuildPerCPUArchitecture
103 | universalApk false // If true, also generate a universal APK
104 | include "armeabi-v7a", "x86"
105 | }
106 | }
107 | buildTypes {
108 | release {
109 | minifyEnabled enableProguardInReleaseBuilds
110 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
111 | }
112 | }
113 | // applicationVariants are e.g. debug, release
114 | applicationVariants.all { variant ->
115 | variant.outputs.each { output ->
116 | // For each separate APK per architecture, set a unique version code as described here:
117 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
118 | def versionCodes = ["armeabi-v7a":1, "x86":2]
119 | def abi = output.getFilter(OutputFile.ABI)
120 | if (abi != null) { // null for the universal-debug, universal-release variants
121 | output.versionCodeOverride =
122 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
123 | }
124 | }
125 | }
126 | }
127 |
128 | dependencies {
129 | compile fileTree(dir: "libs", include: ["*.jar"])
130 | compile "com.android.support:appcompat-v7:23.0.1"
131 | compile "com.facebook.react:react-native:+" // From node_modules
132 | }
133 |
134 | // Run this once to be able to run the application with BUCK
135 | // puts all compile dependencies into folder libs for BUCK to use
136 | task copyDownloadableDepsToLibs(type: Copy) {
137 | from configurations.compile
138 | into 'libs'
139 | }
140 |
--------------------------------------------------------------------------------
/client/page/home/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Actions } from 'react-native-router-flux';
3 | import { View, Image, Text, Alert, TouchableHighlight } from 'react-native'
4 | import { Icon, TabBar, Flex, Popover } from 'antd-mobile'
5 | import connectRedux from '../../connectRedux'
6 | import Banbu from './Banbu'
7 | // import BossHome from './BossHome'
8 | import UserHome from './UserHome'
9 | import Personal from './personal'
10 | import {styles} from '../../styles/styles'
11 |
12 | class Home extends Component{
13 | static selectedTab = 'home'
14 | static renderTitle = function () {
15 | let navbar =
16 | if(Home.selectedTab == 'home'){
17 | navbar = (
18 |
19 | 上海云才网络科技有限公司),
23 | (上海云才网络科技有限公司1122143),
24 | (上海云才网络科技有限公司2),
25 | ]}
26 | onSelect={ ()=>{ console.log('onSelect') }}
27 | >
28 |
29 | 上海云才网络科技有限公司
30 |
31 |
32 |
33 |
34 |
35 | )
36 | }else if (Home.selectedTab === 'banbu') {
37 | navbar = (
38 |
39 | 班步
40 |
41 | )
42 | }else if (Home.selectedTab === 'member') {
43 | navbar = (
44 |
45 | 我的
46 |
47 | )
48 | }
49 | return (
50 |
51 | {navbar}
52 |
53 | )
54 | }
55 |
56 | constructor(props) {
57 | super(props);
58 | this.state = {
59 | hidden: false,
60 | }
61 | }
62 |
63 | setSelectedTab = function(tabName) {
64 | this.props.updateSelectedTab(tabName)
65 | this.setTitle(tabName)
66 | }
67 | setTitle = function(tabName){
68 | let title = '';
69 | switch (tabName){
70 | case 'home':
71 | title = '首页'
72 | break;
73 | case 'member':
74 | title = '我的'
75 | break;
76 | case 'banbu':
77 | title = '消息'
78 | break;
79 | }
80 | Home.selectedTab = tabName
81 | Actions.refresh({ selectedTab: tabName })
82 | }
83 | getHomeByUserType = function(){
84 |
85 | const user = this.props.$$app.get('user');
86 | const boss = this.props.$$app.get('boss');
87 |
88 | // if(boss !== null){
89 | // return ()
90 | // }
91 | // if(user !== null){
92 | // return ()
93 | // }
94 |
95 | return ()
96 | }
97 | componentDidMount(){
98 | let {selectedTab} = this.props.$$app.toJS();
99 | this.setTitle(selectedTab)
100 | }
101 | render(){
102 |
103 | let {selectedTab} = this.props.$$app.toJS();
104 |
105 | return (
106 |
107 |
113 |
121 |
122 |
123 |
131 | {this.getHomeByUserType()}
132 |
133 |
141 |
142 |
143 |
144 |
145 |
146 | )
147 | }
148 | }
149 |
150 | export default connectRedux(Home);
--------------------------------------------------------------------------------
/client/page/home/Banbu.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | StyleSheet,
4 | View,
5 | Text,
6 | Image,
7 | Platform,
8 | BackAndroid,
9 | DeviceEventEmitter,
10 | } from 'react-native';
11 | import {Badge, Flex, Button, ListView, RefreshControl, Tag} from 'antd-mobile';
12 | import {is} from 'immutable'
13 | import ListItem, {getCategoryPathAndIcon, style as listItemStyle} from '../../components/ListItem'
14 | import {styles} from '../../styles/styles'
15 |
16 | const dataSource = new ListView.DataSource({
17 | rowHasChanged: (row1, row2) => !is(row1, row2) || row1 !== row2,
18 | });
19 |
20 | const _style = StyleSheet.create({
21 | date: {
22 | color: '#959595',
23 | fontSize: 11,
24 | marginBottom: 10
25 | },
26 | smallTag: {
27 | width: 27,
28 | height: 15,
29 | borderRadius: 7.5,
30 | borderWidth: 0.5,
31 | borderColor: '#1ab394',
32 | borderStyle: 'solid',
33 | },
34 | smallTagText: {
35 | fontSize: 10,
36 | color: '#1ab394',
37 | backgroundColor: 'transparent',
38 | }
39 | });
40 |
41 | class Banbu extends Component{
42 |
43 | constructor(props) {
44 | super(props);
45 | this.state = {
46 | refreshing: false
47 | }
48 | }
49 |
50 | renderRow = function(item,s,index){
51 |
52 | const {path, image} = getCategoryPathAndIcon(item.category, item.uuid);
53 |
54 | if(!item.category){
55 | return ()
56 | }
57 | const {routes} = this.context;
58 |
59 | if(item.category == '7'){
60 | item.title = (
61 |
62 | {item.title}
63 |
64 |
65 | 官方
66 |
67 |
68 | )
69 | }
70 | return (
71 | { console.log(123) }} hasBorder={item.border}
73 | key={index} title={item.title} desc={item.subTitle || ' '} img={image}>
74 |
75 | {item.showDate}
76 | { item.count>0 ? : }
77 |
78 |
79 | )
80 | }
81 | onRefresh = function () {
82 | console.log(this)
83 | if(this.state.refreshing){
84 | return;
85 | }
86 | this.setState({ refreshing: true });
87 |
88 | this.props.messageList()
89 | .catch((err)=>{
90 | console.log(err)
91 | })
92 | .finally(()=>{
93 | this.setState({ refreshing: false });
94 | })
95 |
96 | }
97 | componentWillMount(){
98 | this.props.messageList().then((data)=>{
99 | console.log(data)
100 | }).catch((err)=>{
101 | console.log(err)
102 | })
103 | }
104 | render(){
105 | let messageList = this.props.$$user.get('messageList')?this.props.$$user.get('messageList').toJS():[];
106 |
107 | const showCompanyManagement = this.props.$$app.get('showCompanyManagement');
108 | messageList = [
109 | {
110 | category: "1",
111 | count: 1,
112 | data:[],
113 | showDate:"11:18",
114 | subTitle:"公司域名即日起更改为:www.hr.ibanbu.com",
115 | title: "公司公告"
116 | },
117 | {
118 | category: "2",
119 | count: 1,
120 | data:[],
121 | showDate:"10:22",
122 | subTitle:"销售一组张有学入职,快去送上祝福吧",
123 | title: "祝福提醒",
124 | border: false
125 | },
126 | {
127 |
128 | },
129 | {
130 | category: "5",
131 | count: 0,
132 | data:[],
133 | showDate:"",
134 | subTitle:"李晓华将于2016-06-01入职",
135 | title: "部门动态"
136 | },
137 | {
138 | category: "3",
139 | count: 1,
140 | data:[],
141 | showDate:"10:10",
142 | subTitle:"吴彦祖将于2016-06-01公出",
143 | title: "审批中心"
144 | },
145 | {
146 | category: "4",
147 | count: 0,
148 | data:[],
149 | showDate:"",
150 | subTitle:"",
151 | title: "考勤中心",
152 | border: false
153 | },
154 | {
155 |
156 | },
157 | {
158 | category: "6",
159 | count: 0,
160 | data:[],
161 | showDate:"",
162 | subTitle:"",
163 | title: "云档案",
164 | border: false
165 | },
166 | {
167 |
168 | },
169 | {
170 | category: "7",
171 | count: 0,
172 | data:[],
173 | showDate:"",
174 | subTitle:"",
175 | title: "班步动态",
176 | border: false
177 | },
178 | ]
179 |
180 | const data = dataSource.cloneWithRows(messageList)
181 |
182 | return (
183 |
184 |
185 | }
194 | />
195 |
196 |
197 | )
198 | }
199 | }
200 |
201 | export default Banbu
--------------------------------------------------------------------------------
/client/page/home/BossHome.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import {
3 | StyleSheet,
4 | View,
5 | Text,
6 | Platform,
7 | } from 'react-native';
8 | import { List, Flex, WhiteSpace, Badge } from 'antd-mobile'
9 | import ECharts from '../../components/native-echarts'
10 | // import style from './BossHome.scss'
11 | import ListItem, { getCategoryPathAndIcon } from '../../components/ListItem'
12 |
13 | class Home extends Component{
14 |
15 | componentDidMount(){
16 |
17 | const homeTopDesc = this.props.$$boss.get('homeTopDesc').toJS();
18 | if(homeTopDesc.compEmplCount == 0 ){
19 | this.props.getTopCount()
20 | }
21 |
22 | const pie_bmtj = this.props.$$boss.get('pie_bmtj').toJS();
23 | if(pie_bmtj.failed !== false ){
24 | this.props.getPie_bmtj()
25 | }
26 |
27 | const line_cdtj = this.props.$$boss.get('line_cdtj').toJS();
28 | if(line_cdtj.failed !== false ){
29 | this.props.getLine_cdtj()
30 | }
31 |
32 | const withRemind = this.props.$$boss.get('withRemind').toJS();
33 | if(withRemind.length == 0) {
34 | this.props.getWishRemindMsg()
35 | }
36 |
37 | }
38 |
39 | render(){
40 | const $$pie_bmtj = this.props.$$boss.get('pie_bmtj');
41 | const $$line_cdtj = this.props.$$boss.get('line_cdtj');
42 | const homeTopDesc = this.props.$$boss.get('homeTopDesc').toJS();
43 | const withRemind = this.props.$$boss.get('withRemind').toJS();
44 |
45 | return (
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 试用期/总人数
55 | {homeTopDesc.trialCount}人/{homeTopDesc.compEmplCount}人
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 新人人数/离职人数
66 | {homeTopDesc.newEmplCount}人/{homeTopDesc.leaveOfficeCount}人
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | 本月工资成本
79 | {homeTopDesc.thisMonthTotalWages|| '0'}元
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | 在招岗位/待招岗位
90 | {homeTopDesc.recruitingPostCount}人/{homeTopDesc.theNumberToBeRecruited}人
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | 部门统计
100 |
101 | {homeTopDesc.compEmplCount || '--'}
102 | 全部
103 |
104 |
105 |
106 |
107 |
108 | 迟到统计
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | 祝福提醒
117 |
118 | {withRemind.map((item, index)=>
119 |
120 |
121 |
122 | {item.showDate}
123 |
124 |
125 |
126 |
127 |
128 |
129 | )}
130 |
131 |
132 |
133 |
134 | )
135 |
136 | }
137 | }
138 |
139 | export default Home;
--------------------------------------------------------------------------------
/client/actions/boss.js:
--------------------------------------------------------------------------------
1 | import {getOrgUrl} from '../common/bbPlugin'
2 | let nowDate = new Date();
3 | let nowYear = nowDate.getFullYear();
4 | export function getWishRemindMsg() {
5 | return {
6 | type: 'WISH_REMIND',
7 | payload: {
8 | request: {
9 | url: getOrgUrl() + '/msg/index/WISH_REMIND'
10 | }
11 | }
12 | }
13 | }
14 | export function getTopCount(config) {
15 | return {
16 | type: 'TOP_COUNT',
17 | payload: {
18 | request: {
19 | url: getOrgUrl() + '/statistica/index'
20 | }
21 | }
22 | }
23 | }
24 |
25 | export function getTodoList(config) {
26 | return {
27 | type: 'TODO_LIST',
28 | payload: {
29 | request: {
30 | url: getOrgUrl() + '/notification/taskcount.json'
31 | }
32 | }
33 | }
34 | }
35 |
36 | export function getPie_bmtj(config) {
37 | return {
38 | type: 'PIE_BMTJ',
39 | payload: {
40 | request: {
41 | url: getOrgUrl() + '/statistica/dept-empl'
42 | }
43 | }
44 | }
45 | }
46 | export function getLine_mygzcb(config) {
47 | return {
48 | type: 'LINE_MYGZCB',
49 | payload: {
50 | request:{
51 | url: getOrgUrl()+'/statistica/empl-salaries'
52 | }
53 | }
54 | }
55 | }
56 |
57 | export function getBar_bmgzcb() {
58 | return {
59 | type: 'BAR_BMGZCB',
60 | payload: {
61 | request:{
62 | url: getOrgUrl()+'/statistica/dept-salaries'
63 | }
64 | }
65 | }
66 | }
67 | export function getBar_bmpjgz() {
68 | return {
69 | type: 'BAR_BMPJGZ',
70 | payload: {
71 | request:{
72 | url: getOrgUrl()+'/statistica/dept-salaries'
73 | }
74 | }
75 | }
76 | }
77 |
78 | export function getLine_cdtj(config) {
79 | return {
80 | type: 'LINE_CDTJ',
81 | payload: {
82 | request:{
83 | url: getOrgUrl()+'/statistica/late-times-and-no-begin-end-times'
84 | }
85 | }
86 | }
87 | }
88 |
89 |
90 | export function getLine_mypjcql(config) {
91 | return {
92 | type: 'LINE_MYPJCQL',
93 | payload: {
94 | request: {
95 | url: getOrgUrl() + '/statistica/'
96 | }
97 | }
98 | }
99 | }
100 |
101 | //在职统计
102 | export function getPie_bossEmployIn() {
103 | return {
104 | type: 'PIE_BEIN',
105 | payload: {
106 | request: {
107 | url: getOrgUrl() + '/statistica/empl'
108 | }
109 | }
110 | }
111 | }
112 | //年龄统计
113 | export function getPie_bossEmployAge() {
114 | return {
115 | type: 'PIE_BEage',
116 | payload: {
117 | request: {
118 | url: getOrgUrl() + '/empls/pieChart/age/' + nowYear + '.json'
119 | }
120 | }
121 | }
122 | }
123 | //学历统计
124 | export function getPie_bossEmployEdu() {
125 | return {
126 | type: 'PIE_BEedu',
127 | payload: {
128 | request: {
129 | url: getOrgUrl() + '/empls/pieChart/education/' + nowYear + '.json'
130 | }
131 | }
132 | }
133 | }
134 | //性别统计
135 | export function getPie_bossEmploySex() {
136 | return {
137 | type: 'PIE_BEsex',
138 | payload: {
139 | request: {
140 | url: getOrgUrl() + '/empls/pieChart/sex/' + nowYear + '.json'
141 | }
142 | }
143 | }
144 | }
145 | //婚姻统计
146 | export function getPie_bossEmployMar() {
147 | return {
148 | type: 'PIE_BEmar',
149 | payload: {
150 | request: {
151 | url: getOrgUrl() + '/empls/pieChart/maritalStatus/' + nowYear + '.json'
152 | }
153 | }
154 | }
155 | }
156 | //生育统计
157 | export function getPie_bossEmployBorn() {
158 | return {
159 | type: 'PIE_BEborn',
160 | payload: {
161 | request: {
162 | url: getOrgUrl() + '/empls/pieChart/fertStatus/' + nowYear + '.json'
163 | }
164 | }
165 | }
166 | }
167 | //在职时间统计
168 | export function getPie_bossEmployYear(type) {
169 | return {
170 | type: type,
171 | payload: {
172 | request: {
173 | url: getOrgUrl() + '/empl-in-date-asc.json'
174 | }
175 | }
176 | }
177 | }
178 |
179 | //缺勤统计
180 | export function getGrid_bossEmployWorkTime() {
181 | return {
182 | type: 'Grid_BENcome',
183 | payload: {
184 | request: {
185 | url: getOrgUrl() + '/statistica/abse-times'
186 | }
187 | }
188 | }
189 | }
190 |
191 | //迟到未打卡统计
192 | export function getGrid_bossEmployLateNoCard() {
193 | return {
194 | type: 'Grid_BELNC',
195 | payload: {
196 | request: {
197 | url: getOrgUrl() + '/statistica/late-times-and-no-begin-end-times'
198 | }
199 | }
200 | }
201 | }
202 |
203 | //请假统计
204 | export function getGrid_bossEmployOffWork() {
205 | return {
206 | type: 'Grid_BEOFW',
207 | payload: {
208 | request: {
209 | url: getOrgUrl() + '/statistica/leave-times'
210 | }
211 | }
212 | }
213 | }
214 |
215 | //公出统计
216 | export function getGrid_bossEmployOutBuss() {
217 | return {
218 | type: 'Grid_BEOFB',
219 | payload: {
220 | request: {
221 | url: getOrgUrl() + '/statistica/busi-away-times'
222 | }
223 | }
224 | }
225 | }
226 |
227 | //今日公出统计
228 | export function getGrid_bossEmployOutBussToday(type) {
229 | return {
230 | type: type,
231 | payload: {
232 | request: {
233 | url: getOrgUrl() + '/offic-busi-away-table.json?draw=1&start=0&length=4'
234 | }
235 | }
236 | }
237 | }
238 |
239 | //今日请假统计
240 |
241 | export function getGrid_bossEmployOffWorkToday(type) {
242 | return {
243 | type: type,
244 | payload: {
245 | request: {
246 | url: getOrgUrl() + '/leave-record-list.json?draw=1&start=0&length=4'
247 | }
248 | }
249 | }
250 | }
251 |
252 | //生日祝福列表
253 | export function getGrid_bossCompanyCulBirth(type) {
254 | return {
255 | type: type,
256 | payload: {
257 | request: {
258 | url: getOrgUrl() + '/publish-msg-list.json?draw=1&start=0&length=4&type=1'
259 | }
260 | }
261 | }
262 | }
263 | //司龄祝福列表
264 | export function getGrid_bossCompanyCulBeDate(type) {
265 | return {
266 | type: type,
267 | payload: {
268 | request: {
269 | url: getOrgUrl() + '/publish-msg-list.json?draw=1&start=0&length=4&type=2'
270 | }
271 | }
272 | }
273 | }
--------------------------------------------------------------------------------
/client/page/home/personal.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | StyleSheet,
4 | View,
5 | Text,
6 | Platform,
7 | BackAndroid,
8 | Image,
9 | ScrollView
10 | } from 'react-native';
11 | import { Flex, List, WhiteSpace, Modal } from 'antd-mobile';
12 | import { _localStorage } from '../../common/bbPlugin'
13 | import Avatar from '../../components/Avatar'
14 | import ListItem from '../../components/ListItem'
15 | import { styles } from '../../styles/styles'
16 |
17 |
18 | const _style = StyleSheet.create({
19 | item: {
20 | height: 50,
21 | },
22 | itemTitle: {
23 | color: '#333',
24 | fontSize: 15,
25 | },
26 | itemTitleGray: {
27 | color: '#aaa',
28 | fontSize: 15,
29 | },
30 | itemText13: {
31 | color: '#aaa',
32 | fontSize: 13,
33 | },
34 | itemImage: {
35 | width:20,
36 | height:20,
37 | marginRight: 16.5,
38 | },
39 |
40 | itemBig: {
41 | height: 80,
42 | },
43 | itemAvatar: {
44 | width: 55,
45 | height: 55,
46 | marginRight: 15,
47 | }
48 | });
49 |
50 |
51 | class Personal extends React.Component {
52 |
53 | constructor(){
54 | super();
55 | this.state = {
56 | showModal: false
57 | }
58 | }
59 |
60 | render() {
61 | const infoJson = _localStorage.getItem('infoJson');
62 | const boss = this.props.$$app.get('boss');
63 | const user = this.props.$$app.get('user');
64 | let userInfo = null;
65 | if(boss){
66 | userInfo = boss
67 | }else{
68 | userInfo = user
69 | }
70 | const {routes} = this.context
71 | return (
72 |
75 |
76 |
80 | }
81 | arrow="horizontal"
82 | extra={}
83 | onClick={() => { console.log('头像') }}
84 | >
85 |
86 | 张三
87 |
88 | 产品规划部
89 | 产品经理
90 |
91 | 智者千虑,必有一失;愚者千虑,必有一得
92 |
93 |
94 |
95 |
96 |
97 | }
100 | arrow="horizontal"
101 | extra={
102 |
103 | 完成度
104 | 80%
105 |
106 |
107 | }
108 | onClick={() => {
109 | console.log('个人信息')
110 | }}
111 | >
112 |
113 | 个人信息
114 |
115 |
116 |
117 |
118 | }
121 | onClick={()=>{
122 |
123 | }}
124 | >
125 | 工资查询
126 |
127 | }
129 | onClick={()=>{
130 |
131 | }}
132 | >
133 | 社保查询
134 |
135 | }
137 | onClick={()=>{
138 |
139 | }}
140 | >
141 | 医保查询
142 |
143 | }
145 | onClick={()=>{
146 |
147 | }}
148 | >
149 | 公积金查询
150 |
151 |
152 |
153 |
154 |
155 | }
158 | onClick={()=>{
159 |
160 | }}
161 | >
162 | 设置
163 |
164 | }
167 | onClick={()=>{
168 |
169 | }}
170 | >
171 | 帮助
172 |
173 | }
175 | onClick={()=>{
176 |
177 | }}
178 | >
179 | 反馈
180 |
181 |
182 |
183 |
184 |
185 | )
186 | }
187 | }
188 |
189 | export default Personal
--------------------------------------------------------------------------------
/client/page/home/UserHome.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import { Actions } from 'react-native-router-flux';
3 | import {
4 | StyleSheet,
5 | View,
6 | Text,
7 | Platform,
8 | BackAndroid,
9 | DeviceEventEmitter,
10 | TouchableHighlight,
11 | Image,
12 | ScrollView
13 | } from 'react-native';
14 | import { is } from 'immutable'
15 | import {Button, List, Flex, WhiteSpace, Badge, Icon, ActionSheet, ListView, RefreshControl} from 'antd-mobile'
16 | import moment from 'moment'
17 | import TouchView from '../../components/TouchView'
18 |
19 | moment.locale('zh-cn');
20 |
21 | const styles = StyleSheet.create({
22 | btnSign: {
23 | position: 'relative',
24 | width: 92,
25 | height: 92,
26 | backgroundColor: '#1ab394',
27 | borderRadius: 92,
28 | },
29 | btnSignBorder: {
30 | position: 'absolute',
31 | left: 0.5,
32 | top: 0.5,
33 | backgroundColor: 'transparent',
34 | width: 91,
35 | height: 91,
36 | borderRadius: 91,
37 | borderWidth: 4,
38 | borderColor: '#fff',
39 | borderStyle: 'solid'
40 | },
41 | btnSignText: {
42 | fontSize: 16,
43 | textAlign: 'center',
44 | color: '#fff',
45 | backgroundColor: 'transparent',
46 | },
47 | textTime: {
48 | textAlign: 'center',
49 | color: '#1ab394',
50 | fontSize: 20,
51 | marginBottom: 10
52 | },
53 | textDate: {
54 | textAlign: 'center',
55 | color: '#aaa',
56 | fontSize: 13,
57 | marginBottom: 10
58 | },
59 | textType: {
60 | textAlign: 'center',
61 | color: '#aaa',
62 | fontSize: 14
63 | },
64 |
65 | line: {
66 | position: 'absolute',
67 | left: 0,
68 | top: 9,
69 | right: 0,
70 | width: 375,
71 | height: 1,
72 | backgroundColor: '#dcdcdc',
73 | },
74 |
75 | gridTextNumber: {
76 | textAlign: 'center',
77 | fontSize: 20,
78 | color: '#535353',
79 | marginBottom: 15,
80 | fontWeight: '200'
81 | },
82 | gridImage: {
83 | width: 31,
84 | height: 31,
85 | marginBottom: 10,
86 | },
87 | gridTextDesc: {
88 | textAlign: 'center',
89 | fontSize: 13,
90 | color: '#7d7d7d'
91 | },
92 | gridLine: {
93 | backgroundColor: '#dcdcdc',
94 | width: 0.5,
95 | height: 50
96 | }
97 |
98 | });
99 |
100 | class Home extends Component{
101 | constructor(props) {
102 | super(props);
103 | this.state = {
104 | refreshing: false
105 | }
106 | };
107 |
108 | componentDidMount() {
109 | console.log('123')
110 | this.props.userHome()
111 | .then((data)=>{
112 | console.log(data)
113 | })
114 | .catch(err=>{
115 | console.log(err)
116 | })
117 | .finally((err)=>{
118 |
119 | })
120 | }
121 | renderRow = function(list, sectionID, rowID,){
122 | return (
123 |
124 |
125 |
126 | )
127 | }
128 | onRefresh = function(){
129 | if(this.state.refreshing){
130 | return;
131 | }
132 | this.setState({ refreshing: true });
133 |
134 | this.props.userHome().then(()=>{
135 | this.setState({ refreshing: false });
136 | })
137 |
138 | }
139 | render(){
140 | console.log(this.props.$$user)
141 | const userHome = this.props.$$user.get('userHome') ? this.props.$$user.get('userHome').toJS() : [];
142 |
143 | return (
144 |
147 |
148 |
149 |
150 |
151 | 签到
152 |
153 |
154 |
155 | 15:26
156 | 2017/01/12 腊月十五
157 | 常规考勤
158 |
159 |
160 | 签退
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | 09:00
175 |
176 | 18:00
177 |
178 |
179 |
180 |
181 |
182 | 当前不在考情范围内
183 |
184 |
185 |
186 | 刷新位置
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | 21
195 | 出勤天数
196 |
197 |
198 |
199 | 0
200 | 迟到天数
201 |
202 |
203 |
204 | 1
205 | 缺卡天数
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 | 请假
214 |
215 |
216 |
217 |
218 |
219 |
220 | 公出
221 |
222 |
223 |
224 |
225 |
226 |
227 | 补签
228 |
229 |
230 |
231 |
232 |
233 | )
234 |
235 | }
236 | }
237 |
238 | export default Home;
--------------------------------------------------------------------------------
/client/actions/user.js:
--------------------------------------------------------------------------------
1 | import {getOrgUrl} from '../common/bbPlugin'
2 | import storage from '../common/storage'
3 |
4 | //yjj
5 |
6 | //公出申请
7 | export function businessOutApply(data) {
8 | return {
9 | type: 'APPLY_BUSINESS_OUT',
10 | payload: {
11 | request: {
12 | method: 'post',
13 | url: getOrgUrl() + '/apply-busi-out.json',
14 | data: {detail: data}
15 | }
16 | }
17 | }
18 | }
19 |
20 | //查询公出详情信息
21 | export function getBusinessOutDetail(id) {
22 | return {
23 | type: 'GET_BUSINESS_OUT',
24 | payload: {
25 | request: {
26 | url: getOrgUrl() + `/busi-outRecord/${id}.json`,
27 | }
28 | }
29 | }
30 | }
31 |
32 | //撤销公出详情信息
33 | export function removeBusinessOut(id) {
34 | return {
35 | type: 'DELETE_BUSINESS_OUT',
36 | payload: {
37 | request: {
38 | method: 'delete',
39 | url: getOrgUrl() + `/busi-outRecord/${id}.json`,
40 | }
41 | }
42 | }
43 | }
44 |
45 | //公出签到
46 | export function signInBusinessOut(form) {
47 | return {
48 | type: 'SIGN_BUSINESS_OUT',
49 | payload: {
50 | request: {
51 | method: 'post',
52 | url: getOrgUrl() + `/busi-outRecord/sign.json`,
53 | data: form
54 | }
55 | }
56 | }
57 | }
58 |
59 | //公出驳回
60 | export function rejectBusinessOut(data) {
61 | return {
62 | type: 'REJECT_BUSINESS_OUT',
63 | payload: {
64 | request: {
65 | method: 'post',
66 | url: getOrgUrl() + `/busi-outRecords/reply.json`,
67 | data: {
68 | ...data,
69 | isRefuse: true,
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
76 | //审批中心列表
77 | export function getApprovalList(data, timestamp) {
78 | return {
79 | type: 'GET_APPROVAL_LIST',
80 | payload: {
81 | request: {
82 | method: 'post',
83 | url: getOrgUrl() + `/audit/list.json`,
84 | data: {
85 | "pageIndex": data.pageIndex,
86 | "pageLength": data.pageLength,
87 | "type": data.type,
88 | "timestamp": timestamp
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
95 | //审批中心 tab切换
96 | export function selectApprovalTab(tabIndex) {
97 | return {
98 | type: 'UPDATE_APPROVAL_TAB',
99 | tabIndex,
100 | }
101 | }
102 |
103 | //请假驳回
104 | export function rejectLeave(data) {
105 | return {
106 | type: 'REJECT_LEAVE',
107 | payload: {
108 | request: {
109 | method: 'post',
110 | url: getOrgUrl() + `/leave/reply.json`,
111 | data: data
112 | }
113 | }
114 | }
115 | }
116 |
117 | //补签驳回
118 | export function rejectSign(data) {
119 | return {
120 | type: 'REJECT_SIGN',
121 | payload: {
122 | request: {
123 | method: 'post',
124 | url: getOrgUrl() + `/makeuptime/reply.json`,
125 | data: data
126 | }
127 | }
128 | }
129 | }
130 |
131 | //获取考勤中心首页
132 | export function getAttendanceData(data) {
133 | return {
134 | type: 'GET_ATTENDANCE',
135 | payload: {
136 | request: {
137 | method: 'get',
138 | url: getOrgUrl() + `/statisics/${data.date}/${data.deptUuid}.json`,
139 | deptUuid: data.deptUuid
140 | }
141 | }
142 | }
143 | }
144 |
145 | //更新考勤中心选择
146 | export function updateAttendanceSelect(data) {
147 | return {
148 | type: 'UPDATE_ATTENDANCE_SELECTED',
149 | data,
150 | }
151 | }
152 |
153 | //班步列表
154 | export function getCategoryDetail(category, data) {
155 | return {
156 | type: 'GET_CATEGORY_DETAIL',
157 | category,
158 | payload: {
159 | request: {
160 | method: 'get',
161 | url: getOrgUrl() + '/msg/detail/' + category,
162 | params: {
163 | start: data.pageIndex-1,
164 | length: data.pageLength,
165 | draw: 1,
166 | }
167 | },
168 | }
169 | }
170 | }
171 |
172 | //班步首页
173 | export function getCategoryList(categoryList, data) {
174 | return {
175 | type: 'GET_CATEGORY_LIST',
176 | categoryList,
177 | payload: {
178 | request: {
179 | method: 'get',
180 | url: getOrgUrl() + '/msg/index/' + categoryList,
181 | },
182 | }
183 | }
184 | }
185 |
186 | //反馈
187 | export function feedback(text) {
188 | return {
189 | type: 'FEEDBACK',
190 | payload: {
191 | request: {
192 | method: 'post',
193 | url: getOrgUrl() + '/feedback.json',
194 | data: {
195 | detail: text
196 | }
197 | },
198 | }
199 | }
200 | }
201 |
202 |
203 | //zj
204 | let date = new Date();
205 | let sjc = date.getTime();
206 |
207 | //员工首页
208 | export async function userHome() {
209 | let local = await storage.getItem('approvalListData.timestamp')
210 | console.log('员工首页', local)
211 | return {
212 | type: 'USER_HOME_INITIAL',
213 | payload: {
214 | request: {
215 | url: getOrgUrl() + '/index'
216 | }
217 | }
218 | }
219 | }
220 | //上班签到
221 | export function userPastIn(data, cb) {
222 | return {
223 | type: 'USER_PASTIN',
224 | payload: {
225 | request: {
226 | method: 'post',
227 | data: {detail: data},
228 | url: getOrgUrl() + '/signin.json'
229 | },
230 | callBack: cb
231 | }
232 | }
233 | }
234 | //下班签退
235 | export function userPastOut(data, cb) {
236 | return {
237 | type: 'USER_PASTOUT',
238 | payload: {
239 | request: {
240 | method: 'post',
241 | data: {detail: data},
242 | url: getOrgUrl() + '/signout.json'
243 | },
244 | callBack: cb
245 | }
246 | }
247 | }
248 |
249 | //补打卡
250 | export function userPastBU(data, cb) {
251 | return {
252 | type: 'USER_PASTBU',
253 | payload: {
254 | request: {
255 | method: 'post',
256 | data: data,
257 | url: getOrgUrl() + '/apply-makeuptime.json'
258 | },
259 | callBack: cb
260 | }
261 | }
262 | }
263 |
264 | //假期类型
265 | export function getHolidayType() {
266 | return {
267 | type: 'GET_HOLIDAY_TYPE',
268 | payload: {
269 | request: {
270 | method: 'GET',
271 | url: getOrgUrl() + '/leave-setting.json'
272 | },
273 | }
274 | }
275 | }
276 |
277 | //提交请假申请
278 | export function submitOffApply(data) {
279 | return {
280 | type: 'SUBMIT_OFF_APPLY',
281 | payload: {
282 | request: {
283 | method: 'POST',
284 | data: {detail: data},
285 | url: getOrgUrl() + '/apply-leave.json'
286 | },
287 | }
288 | }
289 | }
290 |
291 | //提交请假图片
292 | export function updateWorkOffImg(id, file) {
293 | return {
294 | type: 'UPDATE_WORK_OFF',
295 | payload: {
296 | request: {
297 | method: 'POST',
298 | data: {
299 | file : file
300 | },
301 | url: getOrgUrl() + `/apply-leave/${id}/upload.json`
302 | },
303 | }
304 | }
305 | }
306 |
307 | //获取请假详情
308 | export function getOffWorkDetail(data) {
309 | return {
310 | type: 'GET_OFF_DETAIL',
311 | payload: {
312 | request: {
313 | method: 'get',
314 | url: getOrgUrl() + '/apply-leave/' + data + '.json'
315 | },
316 | }
317 | }
318 | }
319 |
320 | //撤销请假
321 | export function cancelOffWork(data) {
322 | return {
323 | type: 'CANCEL_OFF_WORK',
324 | payload: {
325 | request: {
326 | method: 'DELETE',
327 | url: getOrgUrl() + '/apply-leave/' + data + '.json'
328 | },
329 | }
330 | }
331 | }
332 |
333 | //班步首页
334 | export async function messageList() {
335 | let local = await storage.getItem('approvalListData.timestamp')
336 | let past = local ? local['1'] : '0';
337 | let outWork = local ? local['2'] : '0';
338 | let offWork = local ? local['3'] : '0';
339 | return {
340 | type: 'MESSAGE_LIST',
341 | payload: {
342 | request: {
343 | method: 'get',
344 | url: `${getOrgUrl()}/msg/index/COMP_ANNOUNCEMENTS,WISH_REMIND,APPROVAL,ATTENDANCE,DEPARTMENT_TRENDS,DOCUMENT,BAMBOO_TRENDS?WORK_OUT=${outWork}&ASK_FOR_LEAVE=${offWork}&CLOCK_OUT=${past}&CLOCK_IN=${past}`
345 | },
346 | }
347 | }
348 | }
349 |
350 | //补签详情
351 | export function pastBuDetail(uuid) {
352 | return {
353 | type: 'PAST_BU_DETAIL',
354 | payload: {
355 | request: {
356 | method: 'get',
357 | url: getOrgUrl() + '/makeuptime/' + uuid + '.json'
358 | },
359 | }
360 | }
361 | }
362 |
363 | //同意补签
364 | export function pastAgree(uuid, isRefuse) {
365 | return {
366 | type: 'PAST_BU_DETAIL',
367 | payload: {
368 | request: {
369 | method: 'post',
370 | data: {
371 | uuid,
372 | isRefuse
373 | },
374 | url: getOrgUrl() + '/makeuptime/reply.json'
375 | },
376 | }
377 | }
378 | }
379 |
380 | //祝福列表
381 | //start表示页码 length表示每次返回的数据长 draw不用管
382 | export function benedictionIndex(pageNum = 0) {
383 | return {
384 | type: 'BENEDICTION_INDEX',
385 | payload: {
386 | request: {
387 | method: 'get',
388 | url: getOrgUrl() + '/msg/detail/WISH_REMIND?start=' + pageNum + '&length=10&draw=1'
389 | },
390 | }
391 | }
392 | }
393 |
394 | //新人 生日 周年 生日贺卡 周年贺卡
395 |
396 | //祝福详情
397 | export function benedictionDetail(uuid) {
398 | return {
399 | type: 'BENEDICTION_DETAIL',
400 | payload: {
401 | request: {
402 | method: 'get',
403 | url: getOrgUrl() + '/support/detail/' + uuid
404 | },
405 | }
406 | }
407 | }
408 |
409 | //祝福图标
410 | export function benedictionIcon(uuid, icon) {
411 | return {
412 | type: 'BENEDICTION_ICON',
413 | payload: {
414 | request: {
415 | method: 'POST',
416 | url: getOrgUrl() + '/support/sources/' + uuid + '/' + icon
417 | },
418 | }
419 | }
420 | }
--------------------------------------------------------------------------------
/client/reducers/user.js:
--------------------------------------------------------------------------------
1 | import {Map, List, fromJS} from 'immutable'
2 | import storage from '../common/storage'
3 |
4 | function user(state = Map({}), aciton) {
5 |
6 |
7 | let data = {};
8 | switch (aciton.type) {
9 |
10 | //yjj
11 | //获取公出详情
12 | case 'GET_BUSINESS_OUT':
13 | return state;
14 | case 'GET_BUSINESS_OUT_SUCCESS':
15 | data = aciton.payload.data;
16 | return state.setIn(['businessOutDetail', data.uuid], data);
17 | case 'GET_BUSINESS_OUT_FAIL':
18 | return state;
19 |
20 | //公出签到
21 | case 'SIGN_BUSINESS_OUT_SUCCESS':
22 | data = aciton.payload.data;
23 | return state.setIn(['businessOutDetail', data.uuid], data);
24 | //公出驳回
25 | case 'REJECT_BUSINESS_OUT_SUCCESS':
26 | data = aciton.payload.data;
27 | return state.setIn(['businessOutDetail', data.uuid], data);
28 |
29 | //撤销公出信息
30 | case 'DELETE_BUSINESS_OUT':
31 | return state;
32 | case 'DELETE_BUSINESS_OUT_SUCCESS':
33 | data = aciton.payload.data;
34 | return state.deleteIn(['businessOutDetail', data.uuid]);
35 | case 'DELETE_BUSINESS_OUT_FAIL':
36 | return state;
37 |
38 | //获取审批中心 列表
39 | case 'UPDATE_APPROVAL_TAB':
40 | return state.setIn(['approvalListData', 'tabSelected'], String(aciton.tabIndex))
41 | case 'GET_APPROVAL_LIST':
42 | let type1 = aciton.payload.request.data.type;
43 | return state.setIn(['approvalListData', String(type1), 'loading'], true);
44 | case 'GET_APPROVAL_LIST_SUCCESS':
45 | let {pageIndex, type} = aciton.meta.previousAction.payload.request.data;
46 | let {summary, timestamp, pageData} = aciton.payload.data;
47 |
48 | let oldList = state.getIn(['approvalListData', String(type), 'pageData', 'list']);
49 | if (!(pageIndex == 1)) {
50 | //合并列表
51 | pageData.list = oldList.toJS().concat(pageData.list);
52 | }
53 | state = state.setIn(['approvalListData', 'summary'], fromJS(summary))
54 | state = state.setIn(['approvalListData', 'timestamp'], fromJS(timestamp))
55 | state = state.setIn(['approvalListData', String(type), 'pageData'], fromJS(pageData))
56 | state = state.setIn(['approvalListData', String(type), 'pageParam', 'pageIndex'], pageIndex + 1)
57 | return state.setIn(['approvalListData', String(type), 'loading'], false);
58 | case 'GET_APPROVAL_LIST_FAIL':
59 | let type3 = aciton.meta.previousAction.payload.request.data.type;
60 | return state.setIn(['approvalListData', String(type3), 'loading'], false);
61 |
62 | case 'UPDATE_ATTENDANCE_SELECTED':
63 | console.log(aciton, state);
64 | for (let key in aciton.data) {
65 | state = state.setIn(['attendanceData', 'selected', key], aciton.data[key])
66 | }
67 | return state;
68 | //考勤中心主页
69 | case 'GET_ATTENDANCE':
70 | return state;
71 | case 'GET_ATTENDANCE_SUCCESS':
72 | let detpId = aciton.meta.previousAction.payload.request.deptUuid;
73 | data = aciton.payload.data || {};
74 |
75 | if (data && detpId == '' && data.listOrg && data.listOrg[0]) {
76 | state = state.setIn(['attendanceData', 'selected', 'dept'], {
77 | id: data.listOrg[0].id,
78 | name: data.listOrg[0].name
79 | })
80 | state = state.setIn(['attendanceData', 'data'], fromJS(data))
81 | }
82 | return state;
83 | case 'GET_ATTENDANCE_FAIL':
84 | return state
85 |
86 |
87 | //班步列表
88 | case 'GET_CATEGORY_LIST':
89 | return state.setIn(['categoryListData', aciton.categoryList, 'loading'], true);
90 | break;
91 |
92 | case 'GET_CATEGORY_LIST_SUCCESS':
93 | const categoryList = aciton.meta.previousAction.categoryList;
94 | state = state.setIn(['categoryListData', categoryList, 'list'], fromJS(aciton.payload.data))
95 | return state.setIn(['categoryListData', categoryList, 'loading'], false);
96 | break;
97 | case 'GET_CATEGORY_LIST_FAIL':
98 | const categoryList_1 = aciton.meta.previousAction.categoryList;
99 | return state.setIn(['categoryListData', categoryList_1, 'loading'], false);
100 | break;
101 |
102 |
103 | //班步详情列表
104 | case 'GET_CATEGORY_DETAIL':
105 | return state.setIn(['categoryDetail', aciton.category, 'loading'], true);
106 | break;
107 | case 'GET_CATEGORY_DETAIL_SUCCESS':
108 | const category = aciton.meta.previousAction.category;
109 | let {start, length} = aciton.meta.previousAction.payload.request.params;
110 | let b_data = aciton.payload.data.data;
111 |
112 | //判断最后一页
113 | if (b_data.length < length) {
114 | state = state.setIn(['categoryDetail', category, 'pageData', 'hasNextPage'], false)
115 | }else{
116 | state = state.setIn(['categoryDetail', category, 'pageData', 'hasNextPage'], true)
117 | }
118 |
119 | let b_oldList = state.getIn(['categoryDetail', category, 'pageData', 'list']);
120 | if (!(start == 0)) {
121 | //合并列表
122 | b_data = b_oldList.toJS().concat(b_data);
123 | }
124 | state = state.setIn(['categoryDetail', category, 'pageData', 'list'], fromJS(b_data))
125 | state = state.setIn(['categoryDetail', category, 'pageParam', 'pageIndex'], start + 2 )
126 |
127 | return state.setIn(['categoryDetail', category, 'loading'], false);
128 | break;
129 | case 'GET_CATEGORY_DETAIL_FAIL':
130 | const category_1 = aciton.meta.previousAction.category;
131 | state = state.setIn(['categoryDetail', category_1, 'pageData', 'hasNextPage'], false)
132 | return state.setIn(['categoryDetail', category_1, 'loading'], false);
133 | break;
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | //zj
363 | //员工首页
364 | case 'USER_HOME_INITIAL':
365 | return state;
366 | case 'USER_HOME_INITIAL_SUCCESS':
367 | let userHomeInitial = state.get('userHome') ? state.get('userHome').toJS() : [];
368 | userHomeInitial = aciton.payload.data;
369 |
370 | userHomeInitial.map((item, index)=>{
371 | if(item.type == 'SIGN_IN'){
372 | state = state.setIn(['defaultTime', 'signIn'], item.startDate);
373 | }else if(item.type == 'SIGN_OUT'){
374 | state = state.setIn(['defaultTime', 'signOut'], item.startDate);
375 | }
376 | })
377 |
378 |
379 | return state.setIn(['userHome'], fromJS(userHomeInitial));
380 | case 'USER_HOME_INITIAL_FAIL':
381 | return state;
382 |
383 | //员工上班签到
384 | case 'USER_PASTIN':
385 | return state;
386 | case 'USER_PASTIN_SUCCESS':
387 | aciton.meta.previousAction.payload.callBack(aciton.payload);
388 | return state;
389 | case 'USER_PASTIN_FAIL':
390 | aciton.meta.previousAction.payload.callBack(aciton.error.message);
391 | return state;
392 | //员工下班打卡
393 | case 'USER_PASTOUT':
394 | return state;
395 | case 'USER_PASTOUT_SUCCESS':
396 | aciton.meta.previousAction.payload.callBack(aciton.payload);
397 | return state;
398 | case 'USER_PASTOUT_FAIL':
399 | aciton.meta.previousAction.payload.callBack(aciton.error.message);
400 | return state;
401 |
402 | // 员工补打卡
403 | case 'USER_PASTBU':
404 | return state;
405 | case 'USER_PASTBU_SUCCESS':
406 | aciton.meta.previousAction.payload.callBack(aciton.payload.data.message);
407 | return state;
408 | case 'USER_PASTBU_FAIL':
409 | aciton.meta.previousAction.payload.callBack(aciton.error.message);
410 | return state;
411 |
412 | //假期类型
413 | case 'GET_HOLIDAY_TYPE':
414 | return state;
415 | case 'GET_HOLIDAY_TYPE_SUCCESS':
416 | let getHolidayType = state.get('holidayType') ? state.get('holidayType').toJS() : [];
417 | getHolidayType = aciton.payload.data;
418 | return state.setIn(['holidayType'], fromJS(getHolidayType));
419 | case 'GET_HOLIDAY_TYPE_FAIL':
420 | return state;
421 |
422 | //请假申请
423 | case 'SUBMIT_OFF_APPLY':
424 | return state;
425 | case 'SUBMIT_OFF_APPLY_SUCCESS':
426 | let offWorkApply = state.get('offWorkApply') ? state.get('offWorkApply').toJS() : [];
427 | offWorkApply = aciton.payload;
428 | return state.setIn(['offWorkApply'], fromJS(offWorkApply));
429 | case 'SUBMIT_OFF_APPLY_FAIL':
430 | return state;
431 | //提交请假证明
432 | case 'UPDATE_WORK_OFF_SUCCESS':
433 | return state.setIn(['getOffWorkDetail', aciton.payload.data.uuid], fromJS(aciton.payload.data))
434 | //请假详情
435 | case 'GET_OFF_DETAIL':
436 | return state;
437 | case 'GET_OFF_DETAIL_SUCCESS':
438 | let getOffWorkDetail = state.get('getOffWorkDetail') ? state.get('getOffWorkDetail').toJS() : [];
439 | getOffWorkDetail = aciton.payload.data;
440 | return state.setIn(['getOffWorkDetail', aciton.payload.data.uuid], fromJS(getOffWorkDetail));
441 | case 'GET_OFF_DETAIL_FAIL':
442 | return state;
443 | //班步首页
444 | case 'MESSAGE_LIST':
445 | return state;
446 | case 'MESSAGE_LIST_SUCCESS':
447 |
448 | let aa = storage.getItem('approvalListData.timestamp')
449 | console.log('aa', aa)
450 | return state
451 |
452 | let messageList = state.get('messageList') ? state.get('messageList').toJS() : [];
453 | messageList = aciton.payload.data;
454 | return state.setIn(['messageList'], fromJS(messageList));
455 | case 'MESSAGE_LIST_FAIL':
456 | return state;
457 |
458 | //补签详情 PAST_BU_DETAIL
459 | case 'PAST_BU_DETAIL':
460 | return state;
461 | case 'PAST_BU_DETAIL_SUCCESS':
462 | let pastBuDetail = state.get('pastBuDetail') ? state.get('pastBuDetail').toJS() : [];
463 | pastBuDetail = aciton.payload.data;
464 | return state.setIn(['pastBuDetail', aciton.payload.data.uuid], fromJS(pastBuDetail));
465 | case 'PAST_BU_DETAIL_FAIL':
466 | return state;
467 |
468 | //祝福详情BENEDICTION_DETAIL
469 | case 'BENEDICTION_DETAIL':
470 | return state;
471 | case 'BENEDICTION_DETAIL_SUCCESS':
472 | let benedictionDetail = state.get('benedictionDetail') ? state.get('benedictionDetail').toJS() : {};
473 | benedictionDetail = aciton.payload.data;
474 | return state.setIn(['benedictionDetail'], fromJS(benedictionDetail));
475 | case 'BENEDICTION_DETAIL_FAIL':
476 | return state;
477 |
478 | default:
479 | return state;
480 | }
481 | }
482 |
483 |
484 | export default user;
--------------------------------------------------------------------------------