Commit 210549fc authored by wwccw0591's avatar wwccw0591

test

parents
Pipeline #31 failed with stages
{
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": [
"transform-decorators-legacy",
"transform-react-jsx",
"syntax-dynamic-import",
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}
node_modules
dist
.idea
target
\ No newline at end of file
CC0 1.0 Universal
==================
Statement of Purpose
---------------------
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights.
--------------------------------
A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver.
-----------
To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback.
----------------------------
Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
--------------------------------
a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
# electron-quick-start
**Clone and run for a quick way to see Electron in action.**
This is a minimal Electron application based on the [Quick Start Guide](https://electronjs.org/docs/tutorial/quick-start) within the Electron documentation.
**Use this app along with the [Electron API Demos](https://electronjs.org/#get-started) app for API code examples to help you get started.**
A basic Electron application needs just these files:
- `package.json` - Points to the app's main file and lists its details and dependencies.
- `main.js` - Starts the app and creates a browser window to render HTML. This is the app's **main process**.
- `index.html` - A web page to render. This is the app's **renderer process**.
You can learn more about each of these components within the [Quick Start Guide](https://electronjs.org/docs/tutorial/quick-start).
## To Use
To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:
```bash
# Clone this repository
git clone https://github.com/electron/electron-quick-start
# Go into the repository
cd electron-quick-start
# Install dependencies
npm install
# Run the app
npm start
```
Note: If you're using Linux Bash for Windows, [see this guide](https://www.howtogeek.com/261575/how-to-run-graphical-linux-desktop-applications-from-windows-10s-bash-shell/) or use `node` from the command prompt.
## Resources for Learning Electron
- [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation
- [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - sample starter apps created by the community
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - a very basic starter Electron app
- [electron/simple-samples](https://github.com/electron/simple-samples) - small applications with ideas for taking them further
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - an Electron app that teaches you how to use Electron
- [hokein/electron-sample-apps](https://github.com/hokein/electron-sample-apps) - small demo apps for the various Electron APIs
## License
[CC0 1.0 (Public Domain)](LICENSE.md)
; 该脚本使用 HM VNISEdit 脚本编辑器向导产生
; 安装程序初始定义常量
!define PRODUCT_NAME "Shenbd"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_PUBLISHER "福州千盟经贸有限公司"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\ordermgr.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
SetCompressor lzma
; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------
!include "MUI.nsh"
; MUI 预定义常量
!define MUI_ABORTWARNING
!define MUI_ICON "..\logo.ico"
!define MUI_UNICON "..\logo.ico"
; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 安装目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面
!define MUI_FINISHPAGE_RUN "$INSTDIR\ordermgr.exe"
!insertmacro MUI_PAGE_FINISH
; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES
; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "SimpChinese"
; 安装预释放文件
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Setup.exe"
InstallDir "$PROGRAMFILES\Shenbd"
InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
ShowInstDetails show
ShowUnInstDetails show
BrandingText "我的身边店商户端"
Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File "ordermgr-win32-x64\ordermgr.exe"
CreateDirectory "$SMPROGRAMS\Shenbd"
CreateShortCut "$SMPROGRAMS\Shenbd\Shenbd.lnk" "$INSTDIR\ordermgr.exe"
CreateShortCut "$DESKTOP\Shenbd.lnk" "$INSTDIR\ordermgr.exe"
File /r "ordermgr-win32-x64\*.*"
SectionEnd
Section -AdditionalIcons
CreateShortCut "$SMPROGRAMS\Shenbd\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd
Section -Post
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\ordermgr.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\ordermgr.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
/******************************
* 以下是安装程序的卸载部分 *
******************************/
Section Uninstall
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\ordermgr.exe"
Delete "$SMPROGRAMS\Shenbd\Uninstall.lnk"
Delete "$DESKTOP\Shenbd.lnk"
Delete "$SMPROGRAMS\Shenbd\Shenbd.lnk"
RMDir "$SMPROGRAMS\Shenbd"
RMDir /r "$INSTDIR\resources"
RMDir /r "$INSTDIR\locales"
RMDir "$INSTDIR"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
SectionEnd
#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#
Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) ,及其所有的组件?" IDYES +2
Abort
FunctionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。"
FunctionEnd
logo.ico

16.6 KB

// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, Tray, Menu, dialog } = require('electron')
//const resURI = './resources/app.asar'
const resURI = '.'
const logoURI = resURI + '/logo.ico'
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
let dlg;
let tray;
function createWindow() {
dlg = new BrowserWindow({
width: 400,
height: 500,
frame: false
})
dlg.loadFile('public/about.html')
dlg.setIcon(logoURI)
dlg.hide()
// dlg.webContents.openDevTools()
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
frame: false
})
mainWindow.setIcon(logoURI)
// and load the index.html of the app.
mainWindow.loadFile('dist/index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
if (tray) {
tray.destroy()
}
})
mainWindow.on('show', () => {
tray.setHighlightMode('always')
mainWindow.focus();
mainWindow.focusOnWebView();
})
mainWindow.on('hide', () => {
tray.setHighlightMode('never')
})
function about() {
dlg.show()
}
function quit() {
app.quit()
}
function set() {
mainWindow.show();
mainWindow.webContents.send('SYS_SHOW_SETTING')
}
tray = new Tray(logoURI)
tray.setToolTip('我的身边店商户端')
const contextMenu = Menu.buildFromTemplate([
{ label: '关于我的身边店', click: function () { about() } },
{ label: '退出我的身边店', click: function () { quit() } }
])
tray.setContextMenu(contextMenu)
tray.on('click', () => {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
})
ipcMain.on('WINDOW_CLOSE', (event, arg) => {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
})
ipcMain.on('WINDOW_MIN', (event, arg) => {
mainWindow.minimize()
})
ipcMain.on('ABOUT_CLOSE', (event, arg) => {
dlg.hide()
})
ipcMain.on('WINDOW_FULLSCREEN', (event, arg) => {
mainWindow.isMaximized() ? mainWindow.unmaximize() : mainWindow.maximize();
})
ipcMain.on('USER_LOGIN', (event, arg) => {
tray.setContextMenu(Menu.buildFromTemplate([
{ label: '设置', click: function () { set() } },
{ label: '关于我的身边店', click: function () { about() } },
{ label: '退出我的身边店', click: function () { quit() } }
]))
})
ipcMain.on('USER_LOGOUT', (event, arg) => {
tray.setContextMenu(Menu.buildFromTemplate([
{ label: '关于我的身边店', click: function () { about() } },
{ label: '退出我的身边店', click: function () { quit() } }
]))
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', function () {
createWindow();
})
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
process.on('uncaughtException', function (err) {
app.quit();
});
\ No newline at end of file
This diff is collapsed.
{
"name": "Shenbd",
"version": "1.0.0",
"description": "我的身边店商户端",
"main": "main.js",
"scripts": {
"start": "webpack && electron .",
"build": "webpack && electron-packager . Shenbd --platform win32 --arch x64 --out target/ --icon=./logo.ico --asar --overwrite --ignore=\"(.history|resources|docs|.gitignore|LICENSE|README.md|webpack.config.js)\"",
"msi": "node installer",
"setup": "electron-installer-windows --src target/ordermgr-win32-x64/ --dest target/xinstallers/",
"start:dev": "webpack-dev-server",
"build:dev": "webpack",
"dev": "./node_modules/.bin/webpack-dev-server --config ./webpack.config.dev.js --progress --color",
"setup:win": "node wininstaller",
"package:dev": "webpack"
},
"repository": "",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "福州千盟经贸有限公司",
"license": "CC0-1.0",
"devDependencies": {
"autoprefixer": "^9.3.1",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-import": "^1.8.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"copy-webpack-plugin": "^4.5.4",
"css-loader": "^1.0.1",
"electron": "^3.0.4",
"electron-installer-windows": "^1.1.0",
"electron-packager": "^12.2.0",
"electron-winstaller": "^2.7.0",
"electron-wix-msi": "^2.1.1",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"immutable": "^4.0.0-rc.12",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"postcss-loader": "^3.0.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.23.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
},
"dependencies": {
"antd": "^3.10.3",
"axios": "^0.18.0",
"jquery": "^3.3.1",
"md5": "^2.2.1",
"qs": "^6.5.2",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-router-dom": "^4.3.1",
"react-zmage": "^0.4.0"
}
}
This diff is collapsed.
var Bridge = function(){
var runtimeMapping = {
"AndroidInterface": "mobile",
"PCInterface": "pc"
}
var bridgeInterface, runtime = "";
for (var name in runtimeMapping) {
if (name in window) {
bridgeInterface = window[name];
runtime = runtimeMapping[name];
break;
}
}
var o= {
init:function(){
},
getRuntime: function () {
return runtime;
},
callNative: function (){
var number_of_params = arguments.length;
var className = arguments[0];
var methodName = arguments[1];
var argLen = number_of_params - 2;
switch(argLen){
case 0:
return bridgeInterface.invokeMethod(className + "." + methodName);
case 1:
bridgeInterface.printLog('==IcPlayer Player callNative: ' + className + "." + methodName + " arg=" + JSON.stringify(arguments[2]));
result = bridgeInterface.invokeMethod(className + "." + methodName, JSON.stringify(arguments[2]));
return JSON.parse(result);
default:
break;
}
},
callNativeAsync:function(){
var number_of_params = arguments.length;
var className = arguments[0];
var methodName = arguments[1];
var func = arguments[2];
var callBack ;
if(typeof func=="function"){
callBack = o.addCallBackFunc(func);
return bridgeInterface.invokeMethodAsync(className + "." + methodName, callBack);
}
else {
var param = func;
func = arguments[3];
if(typeof func!="function"){
o.log("invalid call back func")
return;
}
callBack = o.addCallBackFunc(func);
return bridgeInterface.invokeMethodAsync(className + "." + methodName, callBack, JSON.stringify(param));
}
},
registerListener: function (eventName,func){
o.log("register event for "+eventName);
var key = o.addListenerFunc(eventName,func);
var callBack ="Bridge.listenerInvokeFromNative('"+key+"',==param==)";
bridgeInterface.registerListener(eventName, callBack);
return key;
},
unRegisterListener: function(eventName,key){
o.log("unRegister event for "+eventName);
var callBack= "Bridge.listenerInvokeFromNative('"+key+"',==param==)";
o.removeListenerFunc(key);
bridgeInterface.unRegisterListener(eventName, callBack);
},
log: function (str){
bridgeInterface.printLog(str)
},
takePhoto: function(){
},
goPage: function(index){
bridgeInterface.prepareSwitchPage(JSON.stringify(index));
},
funcMap:{},
listenerMap:{},
listenerMapByEvent:{},
listenerInvokeFromNative:function(callId,param){
o.log("param="+param);
var func = o.listenerMap[callId];
if(func==undefined){
o.log("call back func not found");
o.listenerMap[callId] = null;
return;
}
func(param);
},
callBackFromNative:function(callId,param){
o.log("param="+param);
var func = o.funcMap[callId];
if(func==undefined){
o.log("call back func not found");
o.funcMap[callId] = null;
return;
}
func(param);
o.funcMap[callId] = null;
},
addListenerFunc: function(eventName,func){
var key = o.randomkey(10);
o.listenerMap[key] = func;
return key;
//return "Bridge.listenerInvokeFromNative('"+key+"',==param==)";
},
removeListenerFunc: function(key){
delete o.listenerMap[key] ;
},
addCallBackFunc: function(func){
var key = o.randomkey(10);
o.funcMap[key] = func;
return "Bridge.callBackFromNative('"+key+"',==param==)";
},
onPageLoaded: function(){
bridgeInterface.onPageLoaded();
},
randomkey: function(l) {
var x="0123456789qwertyuioplkjhgfdsazxcvbnm";
var tmp="";
var timestamp = new Date().getTime();
for(var i=0;i<l;i++) {
tmp += x.charAt(Math.ceil(Math.random()*100000000)%x.length);
}
return timestamp+tmp;
}
}
return o;
}();
Bridge.init();
This diff is collapsed.
//download.js v4.2, by dandavis; 2008-2016. [CCBY2] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
// v4 adds AMD/UMD, commonJS, and plain browser support
// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
// https://github.com/rndme/download
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.download = factory();
}
}(this, function () {
return function download(data, strFileName, strMimeType) {
var self = window, // this script is only for browsers anyway...
defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
mimeType = strMimeType || defaultMime,
payload = data,
url = !strFileName && !strMimeType && payload,
anchor = document.createElement("a"),
toString = function(a){return String(a);},
myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),
fileName = strFileName || "download",
blob,
reader;
myBlob= myBlob.call ? myBlob.bind(self) : Blob ;
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
payload=[payload, mimeType];
mimeType=payload[0];
payload=payload[1];
}
if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument
fileName = url.split("/").pop().split("?")[0];
anchor.href = url; // assign href prop to temp anchor
if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path:
var ajax=new XMLHttpRequest();
ajax.open( "GET", url, true);
ajax.responseType = 'blob';
ajax.onload= function(e){
download(e.target.response, fileName, defaultMime);
};
setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:
return ajax;
} // end if valid url?
} // end if url?
//go ahead and download dataURLs right away
if(/^data\:[\w+\-]+\/[\w+\-]+[,;]/.test(payload)){
if(payload.length > (1024*1024*1.999) && myBlob !== toString ){
payload=dataUrlToBlob(payload);
mimeType=payload.type || defaultMime;
}else{
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
navigator.msSaveBlob(dataUrlToBlob(payload), fileName) :
saver(payload) ; // everyone else can save dataURLs un-processed
}
}//end if dataURL passed?
blob = payload instanceof myBlob ?
payload :
new myBlob([payload], {type: mimeType}) ;
function dataUrlToBlob(strUrl) {
var parts= strUrl.split(/[:;,]/),
type= parts[1],
decoder= parts[2] == "base64" ? atob : decodeURIComponent,
binData= decoder( parts.pop() ),
mx= binData.length,
i= 0,
uiArr= new Uint8Array(mx);
for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);
return new myBlob([uiArr], {type: type});
}
function saver(url, winMode){
if ('download' in anchor) { //html5 A[download]
anchor.href = url;
anchor.setAttribute("download", fileName);
anchor.className = "download-js-link";
anchor.innerHTML = "downloading...";
anchor.style.display = "none";
document.body.appendChild(anchor);
setTimeout(function() {
anchor.click();
document.body.removeChild(anchor);
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}
}, 66);
return true;
}
// handle non-a[download] safari as best we can:
if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
url=url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
if(!window.open(url)){ // popup blocked, offer direct download:
if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }
}
return true;
}
//do iframe dataURL download (old ch+FF):
var f = document.createElement("iframe");
document.body.appendChild(f);
if(!winMode){ // force a mime that will download:
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
}
f.src=url;
setTimeout(function(){ document.body.removeChild(f); }, 333);
}//end saver
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
return navigator.msSaveBlob(blob, fileName);
}
if(self.URL){ // simple fast and modern way using Blob and URL:
saver(self.URL.createObjectURL(blob), true);
}else{
// handle non-Blob()+non-URL browsers:
if(typeof blob === "string" || blob.constructor===toString ){
try{
return saver( "data:" + mimeType + ";base64," + self.btoa(blob) );
}catch(y){
return saver( "data:" + mimeType + "," + encodeURIComponent(blob) );
}
}
// Blob but not URL support:
reader=new FileReader();
reader.onload=function(e){
saver(this.result);
};
reader.readAsDataURL(blob);
}
return true;
}; /* end download() */
}));
\ No newline at end of file
This diff is collapsed.
(function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},h=0,c=0,l=[];function g(e,d,g,i){var c={data:i||(d?d.data:{}),_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};e&&a.extend(c,e,{nodes:[],parent:d});if(g){c.tmpl=g;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++h;(l.length?f:b)[h]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h<m;h++){c=h;k=(h>0?this.clone(true):this).get();a.fn[d].apply(a(i[h]),k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,l,j){if(d[0]&&d[0].nodeType){var f=a.makeArray(arguments),g=d.length,i=0,h;while(i<g&&!(h=a.data(d[i++],"tmplItem")));if(g>1)f[0]=[a.makeArray(d)];if(h&&c)f[2]=function(b){a.tmpl.afterManip(this,b,j)};r.apply(this,f)}else r.apply(this,arguments);c=0;!e&&a.tmpl.complete(b);return this}});a.extend({tmpl:function(d,h,e,c){var j,k=!c;if(k){c=p;d=a.template[d]||a.template(null,d);f={}}else if(!d){d=c.tmpl;b[c.key]=c;c.nodes=[];c.wrapped&&n(c,c.wrapped);return a(i(c,null,c.tmpl(a,c)))}if(!d)return[];if(typeof h==="function")h=h.call(c||{});e&&e.wrapped&&n(e,e.wrapped);j=a.isArray(h)?a.map(h,function(a){return a?g(e,c,d,a):null}):[g(e,c,d,h)];return k?a(i(c,null,j)):j},tmplItem:function(b){var c;if(b instanceof a)b=b[0];while(b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode));return c||p},template:function(c,b){if(b){if(typeof b==="string")b=o(b);else if(b instanceof a)b=b[0]||{};if(b.nodeType)b=a.data(b,"tmpl")||a.data(b,"tmpl",o(b.innerHTML));return typeof c==="string"?(a.template[c]=b):b}return c?typeof c!=="string"?a.template(null,c):a.template[c]||a.template(null,q.test(c)?c:a(c)):null},encode:function(a){return(""+a).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){_=_.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(_,$1,$2);_=[];",close:"call=$item.calls();_=call._.concat($item.wrap(call,_));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){_.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){_.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function i(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:i(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=j(c).concat(b);if(d)b=b.concat(j(d))});return b?b:j(c)}function j(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,_=[],$data=$item.data;with($data){_.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,j,d,b,c,e){var i=a.tmpl.tag[j],h,f,g;if(!i)throw"Template command not found: "+j;h=i._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=k(b);e=e?","+k(e)+")":c?")":"";f=c?b.indexOf(".")>-1?b+c:"("+b+").call($item"+e:b;g=c?f:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else g=f=h.$1||"null";d=k(d);return"');"+i[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(g).split("$1").join(f).split("$2").join(d?d.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g,function(d,c,b,a){a=a?","+a+")":b?")":"";return a?"("+c+").call($item"+a:d}):h.$2||"")+"_.push('"})+"');}return _;")}function n(c,b){c._wrap=i(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function k(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,i;for(e=0,p=o.length;e<p;e++){if((k=o[e]).nodeType!==1)continue;j=k.getElementsByTagName("*");for(i=j.length-1;i>=0;i--)m(j[i]);m(k)}function m(j){var p,i=j,k,e,m;if(m=j.getAttribute(d)){while(i.parentNode&&(i=i.parentNode).nodeType===1&&!(p=i.getAttribute(d)));if(p!==m){i=i.parentNode?i.nodeType===11?0:i.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[i]||f[i],null,true);e.key=++h;b[h]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;i=a.data(j.parentNode,"tmplItem");i=i?i.key:0}if(e){k=e;while(k&&k.key!=i){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent,null,true)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery)
\ No newline at end of file
body{ color: #212121; font: 14px/1.5 "Helvetica Neue", Tahoma, "Microsoft Yahei", "PingFang SC", "ST Heiti", SimHei, sans-serif, "Helvetica Neue", Tahoma, SimSun, "PingFang SC", "ST Heiti", sans-serif; margin:0; background: #fff;}
.w80{ width: 80px;}
.w200{width: 200px !important;}
.orderprint{background: #FFF; padding:20px; color:#000000; position:relative;}
.orderprint .top{font-family:"microsoft yahei"; line-height:60px; height:60px; overflow:hidden; font-size:24px;}
.orderprint .top .logo{width:200px; height:60px; float:left;}
.orderprint .top .logo-title{text-align: left; width:450px; height: 60px; float:left; margin-left:10px; overflow:hidden;}
.orderprint .top .full-title{width:100%; text-align:center;}
.orderprint .explain{color: #212121; line-height: 20px; width:100%; font-size: 12px; margin-top: 15px;}
.orderprint .seal{position: absolute; top:120px; right:50px;}
.orderprint .page{line-height:18px; color:#999; position: absolute; bottom:0px; left:50%; margin-left:-30px;}
.orderprint table{font-family:Arial, Helvetica, sans-serif; font-size:12px; line-height:18px; width:100%; border-collapse: collapse;}
.orderprint .logo img{width: 60px; height: 60px;}
.buyer-info{margin: 15px 0;}
.order-info th , .order-info td{padding: 8px 10px; text-align: center;}
.order-info thead th{font-weight:normal;background: #f7f7f7; border-bottom: solid 1px #000; border-top: solid 1px #000;}
.order-info tbody tr th{font-weight:600; border-bottom: solid 1px #000; border-top: solid 1px #000;}
.order-info tfoot tr th{border-bottom: solid 1px #000; font-weight:normal; text-align: right;}
.order-info tfoot tr th span{line-height:20px; white-space:nowrap; display:inline-block; height: 20px; padding:0; margin:0; border:0; overflow:hidden; text-overflow:ellipsis; padding-left: 20px}
.order-info .col1{width: 8%;}
.order-info .col3, .order-info .col4,.order-info .col5{width: 12%;}
.order-info .col4{width: 8%;}
.order-info .col5{text-align: right;}
.orderprint .message{margin-top: 15px;}
.printBtn{position: absolute; top: 100px; right: 50px; z-index: 99; background:none; color:#212121; font-size: 14px; height: 26px; outline:none; padding: 0 15px; border:1px solid #bbb; border-radius:13px;}
<html>
<head>
<!-- <link rel="stylesheet" href="//static.shenbd.com/lib/css/reset.css"> -->
<link type="text/css" rel="stylesheet" href="print.css">
<script src='jquery-3.3.1.min.js'></script>
<script src='jquery.tmpl.min.js'></script>
</head>
<body>
<button class="printBtn" onClick="window.print()">打印</button>
<div class="undefined" id="wrap">
</div>
<script id="orderprint_tmpl" type="text/x-jquery-tmpl">
<div class="orderprint">
<div class="top">
<div class="full-title">${storeName} 发货单</div>
</div>
<table class="buyer-info">
<tbody>
<tr>
<td class="logo w80" rowspan="3"><img src="${storeLabel}"></td>
<td class="w200">订单号:${orderSn}</td>
<td>下单时间:${timeStamp2String(addTime * 1000)}</td>
<td></td>
</tr>
<tr>
<td class="w200">收货人:${reciverInfo.trueName}</td>
<td>电话:${reciverInfo.mobPhone}</td>
<td></td>
</tr>
<tr>
<td colspan="3">地址:${reciverInfo.address}</td>
</tr>
</tbody>
</table>
<table class="order-info">
<thead>
<tr>
<th class="col1">序号</th>
<th class="col2">商品名称</th>
<th class="col3">单价()</th>
<th class="col4">数量</th>
<th class="col5">小计()</th>
</tr>
</thead>
<tbody>
{{each(i, goods) orderGoods}}
<tr>
<td class="col1">${i+1}</td>
<td class="col2">${goods.goodsName}</td>
<td class="col3">¥ ${toFixed(goods.goodsPayPrice)}</td>
<td class="col4">${goods.goodsNum}</td>
<td class="col5">¥ ${toFixed(goods.goodsPayPrice*goods.goodsNum)}</td>
</tr>
{{each(j , group) goods.goodsGroup}}
<tr>
<td class="col1"></td>
<td class="col2">${group.goodsName}</td>
<td class="col3">¥ ${toFixed(group.discountPrice)}</td>
<td class="col4">${group.num}</td>
<td class="col5">¥ ${toFixed(group.discountPrice*group.num)}</td>
</tr>
{{/each}}
{{/each}}
</tbody>
<tfoot>
<tr>
<th colspan="5"><span>总计:¥${toFixed(goodsAmount)}</span><span>运费:¥${toFixed(shippingFee)}</span><span>优惠:¥ ${toFixed(couponAmount)}</span><span>订单总额:¥ ${toFixed(orderAmount)}</span>
</th>
</tr>
</tfoot>
</table>
{{if orderMessage}}
<div class="explain">
买家留言:${orderMessage}
</div>
{{/if}}
</div>
</script>
<script type="text/javascript">
//在Jquery里格式化Date日期时间数据
function timeStamp2String(time) {
var datetime = new Date();
datetime.setTime(time);
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
// var hour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
// var minute = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
// var second = datetime.getSeconds() < 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();
return year + "-" + month + "-" + date;
}
function toFixed(money) {
money = money || 0;
var m = (money / 100);
return m.toFixed(2)
}
function render(order) {
$('#orderprint_tmpl').tmpl(order).appendTo('#wrap');
}
window.addEventListener('message', function (e) {
var order = e.data;
render(order)
});
</script>
</body>
</html>
\ No newline at end of file
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.
var EventBus = require('./src/app/service/EventBus');
const { ipcRenderer ,shell } = require('electron')
EventBus.on('WINDOW_CLOSE', function () {
ipcRenderer.send('WINDOW_CLOSE')
})
EventBus.on('WINDOW_MIN', function () {
ipcRenderer.send('WINDOW_MIN')
})
EventBus.on('WINDOW_FULLSCREEN', function () {
ipcRenderer.send('WINDOW_FULLSCREEN')
})
EventBus.on('OPEN_URL', function (URL) {
shell.openExternal(URL)
})
EventBus.on('USER_LOGIN_SYS', function (key) {
ipcRenderer.send('USER_LOGIN',key)
})
EventBus.on('USER_LOGOUT_SYS', function () {
ipcRenderer.send('USER_LOGOUT')
})
ipcRenderer.on('SYS_SHOW_SETTING',function(){
EventBus.emit('SYS_SHOW_SETTING')
})
\ No newline at end of file
import axios from 'axios'
import qs from 'qs'
import md5 from 'md5'
import EventBus from '../service/EventBus'
import Version from '../../../version'
class API {
static ERROR_API = 'ERROR_API'
apiHost;
secret;
constructor() {
this.apiHost = Version().api_url;
this.secret = '~!@#$`1234qwert';
}
/** this.apiHost = 'https://api.shenbd.com/client/';
* 获取授权相关
* authInfo/takeAccess.php
*/
getAuthToken() {
var url = 'authInfo/takeAccess';
var request = {
"nonce": "abcdef",
"deviceType": 1
}
return this.post(url, request);
}
//"8ec749e9de775b4b6ae77f8c6cf3b7cf"
wrap(_data) {
var data = _data || {}
data["timestamp"] = Math.floor(new Date().getTime() / 1000)
var keys = Object.keys(data);
keys.sort();
var vals = [];
keys.map(function (k) {
vals.push(data[k])
})
var val = vals.join('');
var sign = md5(val + this.secret);
return {
"data": data,
"sign": sign,
"encryptType": 2,
"responseType": "json"
}
}
/**
*
* @param {*} url
* @param {*} data
*/
post(url, data) {
var wrap = this.wrap(data);
return axios.post(
this.apiHost + url,
// 2、将请求数据转换为form-data格式
qs.stringify(wrap),
// 3、设置请求头Content-Type
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },
).then(resp => {
if (resp.status == 200) {
var result = resp.data;
if (result.resultCode != 1) {
EventBus.emit(API.ERROR_API, result.shortMessage)
}
return result
} else {
EventBus.emit(API.ERROR_API, resp.statusText)
return { resultCode: resp.status, longMessage: resp.statusText }
}
}).catch(err => {
EventBus.emit(API.ERROR_API, err)
return { resultCode: -101, longMessage: err }
})
}
get(url, data) {
var wrap = this.wrap(data);
var params = qs.stringify(wrap)
return axios.get(
this.apiHost + url + "?" + params,
// 3、设置请求头Content-Type
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },
).then(resp => {
if (resp.status == 200) {
return resp.data
} else {
return { resultCode: resp.status, longMessage: resp.statusText }
}
}).catch(err => {
return { resultCode: -101, longMessage: err }
})
}
}
var api = new API()
module.exports = api;
\ No newline at end of file
import api from './api'
import { DataBusInstance } from '../service/databus'
import EventBus from '../service/EventBus'
import AlertTip from '../service/alerttip'
class LoginApi {
alertTip;
constructor() {
this.alertTip = new AlertTip();
}
login(name, pwd) {
var self = this;
return api.getAuthToken().then((result) => {
var resp = result.responseContent;
var url = 'user/login';
var data = {
key: resp.key,
sellerName: name,
password: pwd
}
return api.post(url, data);
}).then(function (loginData) {
if (loginData.resultCode == 1) {
var url = 'shopkeeper/count';
var p = {
key: loginData.responseContent.key
}
self.alertTip.createSocket(p.key);
return api.post(url, p).then(function (_res) {
var datas = _res.responseContent;
Object.assign(loginData.responseContent, datas);
return loginData;
});
} else {
return loginData;
}
})
}
/**
* 各个菜单的数据
*/
count() {
var url = 'shopkeeper/count';
var p = {
key: DataBusInstance.getSessionKey().key
}
return api.post(url, p);
}
/**
* 退出登录
*/
logout() {
var url = 'member/logOut';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
// DataBusInstance.setSessionKey(null)
if (self.alertTip.Socket) {
try {
self.alertTip.Socket.close()
} catch (e) { }
}
}
return res;
})
}
}
var loginApi = new LoginApi()
module.exports = loginApi;
\ No newline at end of file
import api from './api'
import { DataBusInstance } from '../service/databus'
class MoreApi {
constructor() {
}
/**
* feedback/saveFeedback
* 意见反馈保存
*/
saveFeedback(desc) {
var url = 'feedback/saveFeedback';
var p = {
key: DataBusInstance.getSessionKey().key,
feedbackDescribe: desc
}
return api.post(url, p)
}
/**
* shopkeeper/getVersion
* 获取当前版本
*/
getVersion(_v) {
var url = 'shopkeeper/getVersion';
var p = {
key: DataBusInstance.getSessionKey().key,
opSystem: _v
}
return api.post(url, p)
}
}
var moreApi = new MoreApi()
module.exports = moreApi;
\ No newline at end of file
import api from './api'
import { DataBusInstance } from '../service/databus'
import refundsApi from './refundsApi'
class OrderApi {
constructor() {
}
/**
* 店铺订单列表(分页数据)
* @param {*} page
* @param {*} state
* @param {*} keyword
*/
orderList(page, state, keyword) {
var url = 'shopkeeper/orders';
var p = {
key: DataBusInstance.getSessionKey().key,
orderState: state || 0,
pageSize: 10,
pageIndex: page - 1 || 0
}
if (keyword) {
Object.assign(p, { keyword: keyword })
}
return api.post(url, p);
}
/**
* 商家接单操作
*/
orderReceive(orderId) {
var self = this;
var url = 'shopkeeper/orderReceive';
var p = {
key: DataBusInstance.getSessionKey().key,
orderId: orderId
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.orderDetail(orderId)
} else {
return res
}
})
}
/**
* 确认收款
*/
receivePayment(orderId) {
var self = this;
var url = 'shopkeeper/receivePayment';
var p = {
key: DataBusInstance.getSessionKey().key,
orderId: orderId
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.orderDetail(orderId)
} else {
return res
}
})
}
/**
* 获得配送员列表
*/
getDeliveriers() {
var url = 'delivery/getDeliveriers';
var p = {
key: DataBusInstance.getSessionKey().key
}
return api.post(url, p);
}
/**
* 添加配送员
*/
addDelivery(memberMobile, trueName) {
var url = 'delivery/addDelivery';
var p = {
key: DataBusInstance.getSessionKey().key,
memberMobile: memberMobile,
trueName: trueName
}
return api.post(url, p);
}
/**
* 搜索配送员(不使用)
* @param {*} mobile
*/
searchDelivery(mobile) {
var url = 'delivery/searchDelivery';
var p = {
key: DataBusInstance.getSessionKey().key,
mobile: mobile
}
return api.post(url, p);
}
/**
* 选择配送员
* @param {*} orderId 订单
* @param {*} id 用户
* @param {*} distributionFee 费率
* @param {*} orderType 1 购买 2 退货
*/
selectDelivery(orderId, id, distributionFee, orderType) {
var url = 'delivery/selectDelivery';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
orderId: orderId,
id: id,
distributionFee: distributionFee * 100,
orderType: orderType || 1
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
if (p.orderType == 1) {
return self.orderDetail(orderId)
} else if (p.orderType == 2) {
return refundsApi.getRefundDetail(orderId)
}
} else {
return res
}
})
}
/**
* shopkeeper/modifyOrderAmount
*/
modifyOrderAmount(orderId, p) {
var self = this;
var url = 'shopkeeper/modifyOrderAmount';
var p = {
key: DataBusInstance.getSessionKey().key,
orderId: orderId,
orderAmount: p
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.orderDetail(orderId)
} else {
return res
}
});
}
/**
* shopkeeper/orderDetail
*/
orderDetail(orderId) {
var url = 'shopkeeper/orderDetail';
var p = {
key: DataBusInstance.getSessionKey().key,
orderId: orderId
}
return api.post(url, p);
}
}
module.exports = new OrderApi();
\ No newline at end of file
import api from './api'
import { DataBusInstance } from '../service/databus'
class RefundsApi {
constructor() {
}
/**
* 退款退货列表
* 1:待处理 2:待收货 0全部
*/
getRefunds(page, type) {
var url = 'shopkeeper/getRefunds';
var p = {
key: DataBusInstance.getSessionKey().key,
type: type || 0,
pageSize: 10,
pageIndex: page - 1 || 0
}
return api.post(url, p);
}
/**
* 确认收货
* shopkeeper/confirmReceive
*/
confirmReceive(refundId, goodsState) {
var url = 'shopkeeper/confirmReceive';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId,
goodsState: goodsState
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.getRefundDetail(refundId)
} else {
return res
}
});
}
/**
* 同意
* shopkeeper/agree
*/
agree(refundId, refundAmount, text, isGiveUp) {
var url = 'shopkeeper/agree';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId,
refundAmount: refundAmount,
text: text,
isGiveUp: isGiveUp
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.getRefundDetail(refundId)
} else {
return res
}
});
}
/**
* 拒绝
* shopkeeper/refuse
*/
refuse(refundId, text) {
var url = 'shopkeeper/refuse';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId,
text: text
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.getRefundDetail(refundId)
} else {
return res
}
});
}
/**
* shopkeeper/getRefundDetail
*/
getRefundDetail(refundId) {
var url = 'shopkeeper/getRefundDetail';
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId
}
return api.post(url, p);
}
/**
* 设置收货时间
* shopkeeper/setReceiveTime
*/
setReceiveTime(refundId, reciveTime) {
var url = 'shopkeeper/setReceiveTime';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId,
receiveTime: reciveTime
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.getRefundDetail(refundId)
} else {
return res
}
});
}
makeRefund(refundId) {
var url = 'shopkeeper/makeRefund';
var self = this;
var p = {
key: DataBusInstance.getSessionKey().key,
refundId: refundId
}
return api.post(url, p).then(function (res) {
if (res.resultCode == 1) {
return self.getRefundDetail(refundId)
} else {
return res
}
});
}
}
module.exports = new RefundsApi();
\ No newline at end of file
import api from './api'
import { DataBusInstance } from '../service/databus'
class StoreWarnApi {
constructor() {
}
/**
*shopkeeper/warning
*/
getWarningList() {
var url = 'shopkeeper/warning';
var p = {
key: DataBusInstance.getSessionKey().key
}
return api.post(url, p);
}
/**
* shopkeeper/addStock
* set:设置(设置预警值为0) add:为添加(增补库存)
*/
addStock(goodsId, num , type) {
var url = 'shopkeeper/addStock';
var p = {
key: DataBusInstance.getSessionKey().key,
goodsId:goodsId,
num:num,
type:type
}
return api.post(url, p);
}
}
module.exports = new StoreWarnApi();
\ No newline at end of file
import React from 'react';
import { DataBusInstance } from '../service/databus'
export default class BaseCmpt extends React.Component {
session = null;
constructor(props) {
super(props)
this.session = DataBusInstance.getSessionKey();
if (!!!this.session) {
props.history.push('/');
}
}
}
\ No newline at end of file
import React from 'react'
import EventBus from '../../../service/EventBus'
export default class AudioPlayer extends React.PureComponent {
myAudio;
constructor(props) {
super(props)
}
componentDidMount() {
this.getAudio();
EventBus.onSingle('PLAY_AUDIO',this.play.bind(this))
}
// 获取音频
getAudio = () => {
const myAudio = this.myAudio = new Audio()
myAudio.preload = true;
myAudio.loop = false;
myAudio.src = './public/dingdong.ogg';
document.getElementById("audioBox").appendChild(myAudio);
}
play() {
this.myAudio.play();
}
render() {
return (
<div id='audioBox' />
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import IconUser from '../../imgs/ava.png';
import { Button ,Input} from 'antd';
import orderApi from '../../../api/orderApi'
import EventBus from '../../../service/EventBus'
export default class AddDistributer extends React.Component {
constructor(props) {
super(props)
this.props = props;
this.state = {
mobile: '',
name: ''
}
}
changeText(e, label) {
var val = e.target.value;
if (label == 'm') {
this.setState({
mobile: val,
})
} else if (label == 'n') {
this.setState({
name: val,
})
}
}
onAdded() {
var mobile = this.state.mobile;
if(!!!mobile) {
EventBus.emit('ERROR_API','请输入手机号')
return;
}
var name = this.state.name;
var self = this;
orderApi.addDelivery(mobile, name).then(function (res) {
if (res.resultCode == 1) {
if (self.props.onAdded) {
self.props.onAdded()
}
} else {
}
})
}
render() {
let { mobile, name } = this.state;
return (
<Modal close={this.props.close} title='新增配送员'>
<div className='modal-content-content modal-content-content-style'>
<div className='colory'>
配送员需先注册成为【我的身边店】用户。
</div>
<div className='clear-float clear-float-wrap'>
<span className='modal-form-label'>手机号码:</span>
<Input type="text" className='add-input width300' placeholder='请输入配送员手机号码' value={mobile} onChange={(e) => { this.changeText(e, 'm') }} />
</div>
<div className='clear-float clear-float-wrap'>
<span className='modal-form-label'>&emsp;&emsp;名:</span>
<Input type="text" className='add-input width300' placeholder='请输入配送员姓名' value={name} onChange={(e) => { this.changeText(e, 'n') }} />
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onAdded() }}>添加</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import { Button ,Input} from 'antd'
import ZZmage from '../../commonComponent/ZZmage'
export default class AddStock extends React.Component {
constructor(props) {
super(props)
this.props = props
this.state = {
num: ''
}
}
changeText(e) {
let val = e.target.value;
this.setState({
num: val
})
}
ok() {
if (this.props.onHandle) {
this.props.onHandle(this.state.num)
}
}
render() {
let { stock } = this.props
let { num } = this.state
return (
<Modal close={this.props.close} title='增补库存' height={'300px'}>
<div className='modal-content-content modal-content-content-style'>
<div className="info-box">
<div className="pic">
<img className='add-stock-img' src={stock.goodsImage} alt="" />
</div>
<div className="detail">
<div className="tit">{stock.goodsName}</div>
<div className="fonts12 colorg margint5">
{
stock.goodsAttr && stock.goodsAttr.map(function (r) {
return <span key={r.attrValue}> {r.attrName + ' '} </span>
})
}
</div>
</div>
</div>
<div className='clear-float margint20'>
<span>增补库存:</span>
<Input type="text" className='add-input width300' value={num} placeholder='请输入库存数量' onChange={(e) => { this.changeText(e) }} />
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.ok() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import { Button, InputNumber, Checkbox } from 'antd';
import { MoneytoFixed } from '../../../service/utils'
import EventBus from '../../../service/EventBus'
export default class AgreeRefund extends React.Component {
constructor(props) {
super(props)
this.state = {
val: '',
reson: '',
isGiveUp: 0
}
}
allIn() {
var k = MoneytoFixed(this.props.refundAmount || 0)
this.setState({
val: k
})
}
onTextChange(e, t) {
if (t == 'v') {
var _val = e
this.setState({
val: _val
})
} else if (t == 'r') {
var _val = e.target.value
this.setState({
reson: _val
})
}
}
onHandle() {
var n = Number(this.state.val)
if (Number.isNaN(n) || '' === this.state.val) {
EventBus.emit('ERROR_API', '请输入有效金额')
return;
}
if (this.props.title == '同意退款') {
this.state.isGiveUp = 1
}
if (this.props.onHandle) {
this.props.onHandle(n, this.state.reson, this.state.isGiveUp)
}
}
limitDecimals(value) {
const reg = /^(\-)*(\d+)\.(\d\d).*$/;
if (typeof value === 'string') {
return !isNaN(Number(value)) ? value.replace(reg, '$1$2.$3') : ''
} else if (typeof value === 'number') {
return !isNaN(value) ? String(value).replace(reg, '$1$2.$3') : ''
} else {
return ''
}
}
checkBoxChange(e) {
var checked = e.target.checked;
this.state.isGiveUp = checked ? 1 : 0;
}
render() {
let {
val,
reson
} = this.state
return (
<Modal close={this.props.close} title={this.props.title} height={'350px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='colory dlg-agree-refund-tip marginb10'>
若买家是线下付款或到货收款,请跟买家沟通退款方式。
</div>
{
this.props.title == '同意退款' ? null :
<div className='clear-float marginb10 margint10'>
<p className="width80"></p> <Checkbox onChange={(e) => { this.checkBoxChange(e) }}>弃货</Checkbox>
</div>
}
<div className='clear-float' className="marginb10 ">
<p className="width80">退款金额:</p>
<InputNumber className="width240" min={0}
step={1.00}
formatter={this.limitDecimals}
parser={this.limitDecimals}
value={val} onChange={(e) => { this.onTextChange(e, 'v') }} />
<Button className="width80 btn-refund-all" onClick={() => { this.allIn() }}>全额退款</Button>
</div>
<div className='clear-float'>
<p className="width80">备注说明:</p>
<textarea className="width320" name="" id="" cols="40" rows="4" value={reson} onChange={(e) => { this.onTextChange(e, 'r') }}></textarea>
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onHandle() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import moment from 'moment';
moment.locale('zh-cn');
import { Button, DatePicker } from 'antd';
export default class CheckUpdateModal extends React.Component {
constructor(props) {
super(props)
this.props = props;
this.req = null;
this.state = {
updateProgress: 0
}
}
onHandle() {
this.onHandleDownPackage()
}
onHandleDownPackage() {
let self = this;
var req = this.req = new XMLHttpRequest();
//监听进度事件
req.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentComplete = Math.floor((evt.loaded / evt.total) * 100);
if (percentComplete == 100) {
//self.props.close()
}
self.setState({
updateProgress: percentComplete
})
}
}, false);
req.open("GET", self.props.updateUrl, true);
req.responseType = 'blob';
req.onload = function (e) { download(req.response, "Shenbd_Setup_Lastest.zip"); }
req.send();
}
componentWillUnmount() {
if (this.req) {
this.req.abort();//请求中止
}
}
render() {
let { updateProgress } = this.state
return (
<div>
<Modal close={this.props.close} title='提示' height={'200px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='tc marginTop10'>
{
updateProgress <= 0 ? <div>有新的版本,请及时更新!</div> : (updateProgress == 100 ?
<div>下载完成,请前往安装新版本!</div> :
<div>下载进度:{updateProgress + '%'}</div>
)
}
</div>
</div>
<div className='modal-content-btn'>
{
updateProgress > 0 ? null :
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onHandle() }}>确定</Button>
}
<Button className='modal-footer-btn-white' onClick={this.props.close}>
{
updateProgress == 100 ? '确定' : '取消'
}
</Button>
</div>
</Modal>
</div>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import IconUser from '../../imgs/ava.png';
import orderApi from '../../../api/orderApi'
import EventBus from '../../../service/EventBus'
import { Button, Radio, Input, InputNumber, Checkbox} from 'antd';
const RadioGroup = Radio.Group;
export default class ChooseDistributor extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [],
selected: this.props.selectedDeliverierId,
radioVal: this.props.payDeliverier,
mobile: '',
name: '',
isCreated: 0
}
}
/**
* 1、配送员列表
* 2、新增配送员
* 3、确认
*/
componentDidMount() {
this.loadList()
}
loadList = () => {
let self = this;
return orderApi.getDeliveriers().then(function (res) {
self.setState({
list: res.responseContent
})
})
}
changeTextX(e, label) {
var val = e.target.value;
if (label == 'm') {
this.setState({
mobile: val,
})
} else if (label == 'n') {
this.setState({
name: val,
})
}
}
checkBoxChange(e) {
var checked = e.target.checked;
this.setState({
isCreated: checked ? 1 : 0,
selected: ''
})
}
onAdded() {
var mobile = this.state.mobile;
var name = this.state.name;
if(!!!name&&!!!mobile){
EventBus.emit('ERROR_API', '请输入配送员名字和手机号')
return;
}else if (!!!name) {
EventBus.emit('ERROR_API', '请输入配送员名字')
return;
}else if (!!!mobile) {
EventBus.emit('ERROR_API', '请输入配送员手机号')
return;
}
var name = this.state.name;
var self = this;
orderApi.addDelivery(mobile, name).then(function (res) {
if (res.resultCode == 1) {
self.state.selected = res.responseContent ;
self.loadList().then(function (resp) {
self.handleSelected()
})
}
})
}
onSelected() {
if ((this.state.radioVal == undefined)) {
EventBus.emit("ERROR_API", "请输入有效配送费")
return;
}
if (this.state.isCreated == 1) {
this.onAdded()
} else {
this.handleSelected()
}
}
handleSelected() {
const id = this.state.selected;
let filters = this.state.list.filter(function (item) {
return item.id == id
})
if (filters.length == 0) {
EventBus.emit("ERROR_API", "请选择一个配送人员")
return;
}
if (this.props.onSelected) {
this.props.onSelected(filters[0], this.state.radioVal)
}
}
handleChange = (e) => {
var val = e.target.value;
this.setState({
selected: val,
isCreated: 0
})
}
changeText(e) {
this.setState({
radioVal: e
})
}
limitDecimals(value) {
const reg = /^(\-)*(\d+)\.(\d\d).*$/;
if (typeof value === 'string') {
return !isNaN(Number(value)) ? value.replace(reg, '$1$2.$3') : ''
} else if (typeof value === 'number') {
return !isNaN(value) ? String(value).replace(reg, '$1$2.$3') : ''
} else {
return ''
}
}
render() {
let { list, selected, radioVal, mobile, name, isCreated } = this.state;
let self = this;
return (
<Modal close={this.props.close} title='选择配送员' height='100%'>
<div className='modal-content-content modal-content-content-style dlg-choose-wrap'>
<div className='clear-float'>
{
list ?
<RadioGroup onChange={this.handleChange} value={this.state.selected}>
{
list.map(function (item, index) {
return <div className="dlg-item" key={index}><Radio className="dlg-choose-radiostyle" value={item.id}><img src={item.memberAvatar} /><span className="name">{item.trueName}</span></Radio></div>
})
}
</RadioGroup> : null
}
</div>
<div className='clear-float marginb10 margint20'>
<Checkbox checked={isCreated == 1 ? true : false} onChange={(e) => { this.checkBoxChange(e) }}>新增并选定配送员</Checkbox>
</div>
{
isCreated == 1 ?
<div className='new-diliveryman'>
<div className='colory fonts12'>
配送员需先注册成为【我的身边店】用户。
</div>
<div className='margint10'>
<Input type="text" className='add-input width170' placeholder='请输入配送员姓名' value={name} onChange={(e) => { this.changeTextX(e, 'n') }} />
<Input type="text" className='add-input width170' placeholder='请输入配送员手机号码' value={mobile} onChange={(e) => { this.changeTextX(e, 'm') }} />
</div>
</div> : null
}
<div className="dlg-choose-wrap-div marginTop20">
<span className='modal-form-label' >配送费用:</span>
<InputNumber type="text" className='add-input width300'
min={0}
step={1.00}
formatter={this.limitDecimals}
parser={this.limitDecimals} placeholder='请输入支付给配送员的金额' value={radioVal} onChange={(e) => { this.changeText(e) }} />
</div>
<div className='modal-content-btn'>
{/* <Button className='modal-footer-btn-white marginRight10' onClick={this.props.onAddDistributer}>新增配送员</Button> */}
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onSelected() }}>确认</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import './ModalSubject.less';
import { Modal } from 'antd';
export default class ModalSubject extends React.Component {
handleClose = () => {
this.props.close();
}
render() {
return (
<Modal
visible={true}
centered={true}
closable={true}
footer={null}
width={460}
onCancel={this.props.close} bodyStyle={{ height: this.props.height ? this.props.height : '320px', width: '460px', padding: '0' }}>
<div className='modal-content-header' style={{textAlign:this.props.textAlign?this.props.textAlign:'center',paddingLeft:this.props.paddingLeft?this.props.paddingLeft:'0px'}}>
{this.props.title}
</div>
{this.props.children}
</Modal>
// <div className='modal-body'>
// <div className='modal-content'>
// <div className='modal-div'>
// <div className='modal-content-header'>
// <span className='modal-content-header-close' onClick={this.handleClose}>X</span>
// {this.props.title}
// </div>
// {this.props.children}
// </div>
// </div>
// </div>
);
}
}
\ No newline at end of file
@basefont:"Helvetica Neue", Tahoma, "Microsoft Yahei", "PingFang SC", "ST Heiti", SimHei, sans-serif, "Helvetica Neue", Tahoma, SimSun, "PingFang SC", "ST Heiti", sans-serif, "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
.ant-radio-wrapper{ font-family: @basefont; margin-right: 0; color:#212121;}
.modal-body{
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
display: table;
z-index: 10000;
background: rgba(0,0,0,0.3);
text-align: center;
}
.modal-div{
width: 468px;
background: #FFFFFF;
display: inline-block;
}
.modal-content{
display: table-cell;
vertical-align: middle;
}
.modal-content-header{
height: 54px;
background-image: url("../../imgs/modal-header.png");
background-size: 100% 100%;
line-height: 54px;
color:#FFFFFF;
position: relative;
text-align: center;
font-size: 20px;
}
.modal-content-header-close{
position: absolute;
top: 10px;
right: 10px;
line-height: normal;
cursor: pointer;
}
.modal-content-content{
padding: 10px;
padding: 20px 20px 70px;
}
.modal-cotent-input{
display: inline-block;
}
.modal-content-content-style{
p{
display: inline-block;
vertical-align: top;
line-height: 30px;
}
textarea{
vertical-align: top;
}
}
.modal-content-content-style:after{
content: '';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.modal-content-btn{ position: absolute; text-align: right; padding: 0 10px; right: 0; bottom: 20px;}
.ant-modal-close{ right: 10px; top: 10px; z-index: 100;}
.add-input{
font-size: 14px;
outline: none;
border: solid 1px #dbdbdb;
margin: 0;
padding: 0;
width: 400px;
border-radius:0;
}
.ant-input-number-focused, .ant-input-number:hover{ border-color: #dbdbdb; -webkit-box-shadow:none; box-shadow:none;}
.add-user-icon{
width: 24px;
height: 24px;
border-radius: 12px;
}
.agree-input{
outline: none;
border: solid 1px #dbdbdb;
margin: 0;
padding: 0;
height: 24px;
float: left;
}
.agree-input-btn{
display: inline-block;
text-align: center;
background: #dbdbdb;
height: 24px;
float: left;
font-size: 14px;
padding: 0 10px;
}
.clear-float-wrap{
margin-top: 10px;
display: block;
height: 35px;
}
.clear-float:after{
content: '';
height: 0;
display: block;
clear: both;
visibility: hidden;
}
.ant-modal-close-icon{
color: #ffffff;
}
.modal-form-label{
width: 80px;
margin-top:5px;
text-align:right;
}
.dlg-agree-refund-tip{
margin-bottom: '10px'
}
.dlg-agree-refund-title{
margin-bottom: 10px;
}
.dlg-item{
float: left;
width: 45%;
margin:6px 0;
padding-right: 5%;
span, img{ display: inline-block; vertical-align: middle;}
img{ width: 26px; height: 26px; border-radius:100%; margin-right: 10px; margin-bottom: 3px;}
.name{ max-width: 8em; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
}
.dlg-choose-radiostyle{
display: block;
height:30px;
line-height: 30px;
}
.dlg-choose-wrap{
overflow: auto;
// max-height:200px;
display:block;
.ant-radio-group{
overflow: hidden;
display: block;
}
}
.new-diliveryman{ padding:0 0 20px 20px; border-bottom: 1px solid #eee;
.ant-input{ margin-right: 10px;}
}
.ant-modal{ padding-bottom: 0;}
.ant-modal-wrap{
.ant-modal-close-x{
width: 24px;
height: 24px;
background-image: url("../../imgs/close-white.png");
background-repeat: no-repeat;
background-position: center center;
padding: 5px;
svg{ display: none;}
}
}
.CustmeModal{
.ant-modal-close-x{ background-image: url("../../imgs/close.png");}
}
.CustmeModalX{
.ant-modal-close-x{ background-image: url("../../imgs/close.png");}
}
import React from 'react';
import Modal from './ModalSubject';
export default class ModalTextarea extends React.Component{
render() {
return (
<Modal close={this.props.close} title='取消订单'>
<div className='modal-content-content modal-content-content-style'>
<p className='colory'>
请谨慎操作,取消订单前请跟买家沟通并经过同意。
</p>
<div className='clear-float'>
<p>取消原因:</p>
<textarea name="" id="" cols="40" rows="6"></textarea>
</div>
</div>
<div className='modal-content-btn'>
<div className='modal-footer-btn ant-btn-orange'>确定取消订单</div>
<div className='modal-footer-btn-white'>点错了,不取消订单</div>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import moment from 'moment';
moment.locale('zh-cn');
import { Button, DatePicker} from 'antd';
const { RangePicker } = DatePicker;
import EventBus from '../../../service/EventBus'
export default class ModifyModal extends React.Component {
constructor(props) {
super(props)
this.props = props;
this.timestamp = 0;
}
onChange(value, dateString) {
if(value) {
this.timestamp = new Date(dateString).getTime();
}else{
this.timestamp = 0;
}
}
onOk(value) {
}
onHandle() {
if (!!!this.timestamp || this.timestamp <= 0) {
EventBus.emit('ERROR_API', '请输入有效时间')
return;
}
if (this.props.onHandle) {
this.props.onHandle(this.timestamp)
}
}
render() {
let { type } = this.props
return (
<Modal close={this.props.close} title='修改收货时间' height={'250px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='colory'>
请跟买家沟通后再进行修改。
</div>
<div className='clear-float clear-float-wrap'>
<p className='modal-form-label'>收货时间:</p>
{
type == 1 ?
<DatePicker
showTime={{ defaultValue: moment('00:00', 'HH:mm'),format: 'HH:mm'}}
format="YYYY-MM-DD HH:mm"
placeholder="选择时间"
className="width300"
onChange={(v, dt) => { this.onChange(v, dt) }}
showToday={false}
onOk={(v) => { this.onOk(v) }}
/> :
<RangePicker
showTime={{
hideDisabledOptions: true,
defaultValue: [moment('00:00', 'HH:mm'), moment('11:59', 'HH:mm')],
}}
showToday={false}
format="YYYY-MM-DD HH:mm"
placeholder={['开始时间', '结束时间']}
onChange={(v, dt) => { this.onChange(v, dt) }}
onOk={(v) => { this.onOk(v) }}
/>
}
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onHandle() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import { Button, InputNumber, Input } from 'antd';
import EventBus from '../../../service/EventBus'
export default class ModifyPriceModal extends React.Component {
constructor(props) {
super(props)
this.props = props;
this.state = {
price: ''
}
}
onHandle() {
var n = Number(this.state.price)
if (Number.isNaN(n) || ''=== this.state.price) {
EventBus.emit('ERROR_API', '请输入有效金额')
return;
}
if (this.props.onHandle) {
this.props.onHandle(n)
}
}
textChange(e) {
this.setState({
price: e
})
}
limitDecimals(value) {
const reg = /^(\-)*(\d+)\.(\d\d).*$/;
if (typeof value === 'string') {
return !isNaN(Number(value)) ? value.replace(reg, '$1$2.$3') : ''
} else if (typeof value === 'number') {
return !isNaN(value) ? String(value).replace(reg, '$1$2.$3') : ''
} else {
return ''
}
}
render() {
let { price } = this.state
return (
<Modal close={this.props.close} title='修改订单总价' height={'280px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='colorg'>
请跟买家沟通后再进行修改。
</div>
<div className='clear-float clear-float-wrap'>
<p className='modal-form-label'>原订单金额:</p>
<Input type='text' readOnly={true} disabled={true} className='add-input dlg-price-input fonts20' value={'¥ ' + this.props.price} ></Input>
</div>
<div className='clear-float clear-float-wrap'>
<p className='modal-form-label'>调整后价格:</p>
<InputNumber type='text' min={0} className='add-input width200'
value={price}
step={1.00}
formatter={this.limitDecimals}
parser={this.limitDecimals}
onChange={(e) => { this.textChange(e) }}></InputNumber>
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={(e) => { this.onHandle() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import moment from 'moment';
moment.locale('zh-cn');
import { Button, DatePicker } from 'antd';
export default class OkModal extends React.Component {
constructor(props) {
super(props)
this.props = props;
}
onHandle() {
if (this.props.onHandle) {
this.props.onHandle()
}
}
render() {
return (
<Modal close={this.props.close} title='提示' height={'200px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='tc marginTop10'>
{this.props.tipCon}
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onHandle() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import { Button } from 'antd';
import EventBus from '../../../service/EventBus'
export default class RejectRefund extends React.Component {
constructor(props) {
super(props)
this.state = {
reson: ''
}
}
onTextChange(e, t) {
var _val = e.target.value
if (t == 'r') {
this.setState({
reson: _val
})
}
}
onHandle() {
if (this.state.reson.replace(/(^\s*)|(\s*$)/g, "") === '') {
EventBus.emit('ERROR_API', '请输入拒绝理由')
return;
}
if (this.props.onHandle) {
this.props.onHandle(this.state.reson)
}
}
render() {
let {
reson
} = this.state
return (
<Modal close={this.props.close} title={this.props.title} height={'300px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='colory marginb10'>
建议您拒绝之前跟买家先沟通。
</div>
<div className='clear-float'>
<p>拒绝理由:</p>
<textarea name="" id="" className="width320" cols="40" rows="4" value={reson} onChange={(e) => { this.onTextChange(e, 'r') }}></textarea>
</div>
</div>
<div className='modal-content-btn'>
<Button className='modal-footer-btn ant-btn-orange' onClick={() => { this.onHandle() }}>确定</Button>
<Button className='modal-footer-btn-white' onClick={this.props.close}>取消</Button>
</div>
</Modal>
);
}
}
\ No newline at end of file
import React from 'react';
import Modal from './ModalSubject';
import moment from 'moment';
moment.locale('zh-cn');
import { Button, DatePicker } from 'antd';
export default class SuccessModal extends React.Component {
constructor(props) {
super(props)
this.props = props;
}
componentDidMount() {
let self = this;
var so = setTimeout(function(){
clearTimeout(so)
if(self.props.close) {
self.props.close()
}
},2000)
}
render() {
return (
<Modal close={this.props.close} title='提示' height={'200px'}>
<div className='modal-content-content modal-content-content-style'>
<div className='tc marginTop10'>
操作成功
</div>
</div>
<div className='modal-content-btn'>
2秒后窗口关闭
</div>
</Modal>
);
}
}
\ No newline at end of file
/**
* 【待付款 10; 已取消 0 ; 已关闭 -1 ; 待接单 20 ; 待收货 (25 /30) ; 已完成 40】
* 【0:到店自提 1:商家配送 2:快递配送】
* 【支付方式 0:线下付款;1:微信支付;2:货到付款;3:支付宝支付 4qq支付 5 微信小程序】
*/
import React from 'react'
import { Button } from 'antd'
import { MoneytoFixed, TimeFormat,SingleTimeFormat } from '../../../../service/utils'
import TimeCutDown from '../../../../service/TimeCutDown'
module.exports = {
/**
* 配送信息
*/
getShipingLabel(order) {
let shipingLable =
<div class="address">
<p class="mb0">送达时间</p>
<p className='fonts16 fontweightbold' >{TimeFormat(order.deliveryTime, order.deliveryTimeEnd)}</p>
<p className='fonts16 fontweightbold'>{order.reciverInfo.address}</p>
<p className='fonts16 fontweightbold'>{order.reciverInfo.trueName} {order.reciverInfo.mobPhone || order.reciverInfo.telPhone} </p>
</div>;
if (order.shippingType == 0) {
shipingLable =
<div class="delivery-msg part-bd">
<p>买家自提(自提时间:{SingleTimeFormat(order.deliveryTime)})</p>
<p className='fonts20 colorblue'>取件码:{order.dlyoPickupCode}</p>
<p>{order.reciverInfo.trueName} {order.reciverInfo.mobPhone || order.reciverInfo.telPhone} </p>
</div>
}
return shipingLable;
},
/**
* 状态
*/
getStatusLabel(order,master) {
let statusLable = '';
switch (order.orderState) {
case 20:
statusLable =
<div>
<div className="colory"><TimeCutDown startTime={order.serverTime} endTime={order.addTime} timeEnd={()=>{master.timeEnd()}}/>后自动关闭</div>
</div>
break;
case 10:
statusLable = '待线上付款'
break;
case 25:
case 30:
if (order.shippingType == 0) {
statusLable = '待到店自取'
} else {
statusLable = '待配送'
}
break;
case 40:
statusLable = '已完成'
break;
case 0:
statusLable = '已取消'
break;
case -1:
statusLable = '已关闭'
break;
default: break;
}
return statusLable;
},
/**
* 订单配送费用信息
* @param {*} order
*/
getLabelShow(order) {
let payState = '';
let payLabelState = '';
if (order.isReceivePayment > 0) { //已支付
payState = <div><div className='money-title'>实付金额:</div>
<div className='money-content'>{MoneytoFixed(order.orderAmount)}</div> </div>
switch (order.paymentType) {
case 0:
payLabelState = <span>线下付款,已核实</span>
break;
case 1:
payLabelState = <span>线上付款</span>
break;
case 2:
payLabelState = <span>货到付款</span>
break;
case 3:
payLabelState = <span>线上付款</span>
break;
default: break;
}
} else {//未支付
payState = <div className='colory'><div className='money-title'>应收金额:</div>
<div className='money-content'>{MoneytoFixed(order.orderAmount)}</div> </div>
switch (order.paymentType) {
case 0:
payLabelState = <span className='colory'>线下付款,请核实</span>
break;
case 1:
payLabelState = <span>待线上支付</span>
payState = <div className='colory'><div className='money-title'>待付金额:</div>
<div className='money-content'>{MoneytoFixed(order.orderAmount)}</div> </div>
break;
case 2:
payLabelState = <span className='colory'>货到付款</span>
break;
case 3:
payLabelState = <span>待线上支付</span>
payState = <div className='colory'><div className='money-title'>待付金额:</div>
<div className='money-content'>{MoneytoFixed(order.orderAmount)}</div> </div>
break;
default: break;
}
}
return { payState, payLabelState }
},
/**
* 店家操作
*/
getOptLabel(order, master) {
let opts = '';
order._deliver = order._deliver || order.deliveryman;
if (order.isReceivePayment > 0) { //已支付
switch (order.orderState) {
case 20: //待接单
opts = <Button className='footer-button-white' onClick={() => { master.onOrderReceive(order) }}>接单</Button>
break;
case 25:
case 30:
if (order.shippingType != 0) {
opts =
<div>
{
(order._deliver && order._deliver.trueName) ?
<Button className='footer-button-white' onClick={() => { master.onGetDeliveriers(order) }}>配送员:{order._deliver.trueName}</Button> :
<Button className='footer-button-white' onClick={() => { master.onGetDeliveriers(order) }}>选择配送人员</Button>
}
<Button className='footer-button-white' onClick={() => { master.onPrint(order) }}>打印订单</Button>
</div>
} else {
opts =
<div>
<Button className='footer-button-white' onClick={() => { master.onPrint(order) }}>打印订单</Button>
</div>
}
break;
default: break;
}
} else {//未支付
switch (order.orderState) {
case 20:
opts =
<div>
<Button className='footer-button-white' onClick={() => { master.onModifyPrice(order) }}>修改价格</Button>
<Button className='footer-button-white' onClick={() => { master.onOrderReceive(order) }}>接单</Button>
</div>
break;
case 10:
opts =
<div>
<Button className='footer-button-white' onClick={() => { master.onModifyPrice(order) }}>修改价格</Button>
</div>
break;
case 25:
case 30:
if (order.shippingType == 0) {
opts =
<div>
<Button className='footer-button-white' onClick={() => { master.onModifyPrice(order) }}>修改价格</Button>
<Button className='footer-button-white' onClick={() => { master.onReceivePayment(order) }}>确认收款</Button>
<Button className='footer-button-white' onClick={() => { master.onPrint(order) }}>打印订单</Button>
</div>
} else {
opts =
<div>
<Button className='footer-button-white' onClick={() => { master.onModifyPrice(order) }}>修改价格</Button>
<Button className='footer-button-white' onClick={() => { master.onReceivePayment(order) }}>确认收款</Button>
{
(order._deliver && order._deliver.trueName)?
<Button className='footer-button-white' onClick={() => { master.onGetDeliveriers(order) }}>配送员:{order._deliver.trueName}</Button> :
<Button className='footer-button-white' onClick={() => { master.onGetDeliveriers(order) }}>选择配送人员</Button>
}
<Button className='footer-button-white' onClick={() => { master.onPrint(order) }}>打印订单</Button>
</div>
}
break;
default:
break;
}
}
return opts;
}
}
\ No newline at end of file
import React from 'react'
import { Button, TimePicker } from 'antd';
import Utils from '../../../service/utils'
module.exports = {
getTimeRank(t1) {
var t = new Date(t1 * 1000);
var m = t.getMinutes();
var s = t.getSeconds();
var st = t.getHours() + ":" + (m < 10 ? ('0' + m) : ('' + m)) + ":" + (s < 10 ? ('0' + s) : ('' + s));
return st;
},
/**
*
* @param retItem
*/
getRefundsTypePanel(retItem) {
var tpl = '';
if(retItem.refundType==1){
tpl =
<div className='content-each-left-part1'>
<div className='delivery-msg part-bd'><div className='fonts20 colorblue fontweightbold'>买家申请退款</div></div>
</div>
}else{
if (retItem.refundShippingType == 0) {
tpl =
<div className='content-each-left-part1'>
<div className='delivery-msg part-bd'><div className='fonts20 colorblue fontweightbold'>买家到店退货</div></div>
</div>
} else {
tpl =
<div className='content-each-left-part1'>
<div className="address">
{
retItem.receiveTime > 0 ?
<div>
<p className="mb0">收货时间</p>
<p className="fonts16 fontweightbold">
{
Utils.SingleTimeFormat(retItem.receiveTime)
}
</p>
</div>:null
}
{
(retItem.receiveTime<=0 && retItem.goodsState < 3 && retItem.refundShippingType==1 && retItem.sellerState==2 && retItem.shippingOver==0) ? <p>请跟买家协商时间</p> :null
}
{
(retItem.refundShippingType == 1 && retItem.sellerState == 3 && retItem.isPlatformIn == 1 && retItem.refundType == 2 && retItem.goodsState < 3 && retItem.platformState == 1 && retItem.receiveTime<=0) ? <p>请跟买家协商时间</p> :null
}
<p className='fonts16 fontweightbold'>{retItem.reciverInfo && retItem.reciverInfo.address}</p>
<p className='fonts16'>{retItem.reciverInfo && retItem.reciverInfo.trueName} {retItem.reciverInfo && (retItem.reciverInfo.mobPhone || retItem.reciverInfo.telPhone)} </p>
</div>
</div>
}
}
return (
tpl
)
},
/**
* 【支付方式 0:线下付款;1:微信支付;2:货到付款;3:支付宝支付 4qq支付 5 微信小程序】
* @param {*} retItem
*/
getPaymentTypePanel(retItem) {
var paymentType = '';
switch (retItem.paymentType) {
case 0:
paymentType =
<p className='fonts16 fontweightbold'>线下付款</p>
break;
case 2:
paymentType =
<p className='fonts16 fontweightbold'>货到付款</p>
break;
case 1:
case 3:
paymentType =
<p className='fonts16 fontweightbold'>线上付款</p>
break;
default: break;
}
return { paymentType };
},
getRefundsInfoPanel(retItem) {
var tpl = '';
return tpl;
},
getRefundsState(retItem) {
var tpl = '';
return tpl;
},
getRefundsOpt(retItem, self) {
var tpl = [];
retItem._deliver = retItem._deliver || retItem.deliveryman;
if (retItem.shippingOver == 0) {
if (retItem.sellerState == 2) {
if (retItem.refundShippingType == 0) {
if (retItem.returnType == 2 && retItem.goodsState < 3) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGotGoods(retItem, 1) }}>确认收货</Button>)
}
} else if (retItem.refundShippingType == 1) {
if (retItem.returnType == 2 && retItem.goodsState < 3) {
if (retItem.refundType == 2) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGotGoods(retItem, 1) }}>确认收货</Button>)
}
if (retItem.receiveTime <=0) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onModifyTime(retItem, 1) }}>修改收货时间</Button>)
}
if (retItem._deliver && retItem._deliver.trueName) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGetDeliveriers(retItem) }}>配送员:{retItem._deliver.trueName}</Button>)
}else{
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGetDeliveriers(retItem) }}>选择配送人员</Button>)
}
}
}
} else if (retItem.sellerState == 1) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onAgree(retItem, 1) }}>同意</Button>)
tpl.push(<Button className='footer-button-white' onClick={() => { self.onAgree(retItem, -1) }}>不同意</Button>)
}
}
if ( retItem.sellerState == 3 && retItem.isPlatformIn == 1 && retItem.refundType == 2 && retItem.goodsState < 3 && retItem.platformState == 1) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGotGoods(retItem, 1) }}>确认收货</Button>)
if( retItem.refundShippingType == 1){
if (retItem.receiveTime <=0) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onModifyTime(retItem, 1) }}>修改收货时间</Button>)
}
if (retItem._deliver && retItem._deliver.trueName) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGetDeliveriers(retItem) }}>配送员:{retItem._deliver.trueName}</Button>)
}else{
tpl.push(<Button className='footer-button-white' onClick={() => { self.onGetDeliveriers(retItem) }}>选择配送人员</Button>)
}
}
}
if (retItem.markRefundButton == 1) {
tpl.push(<Button className='footer-button-white' onClick={() => { self.markRefundEnd(retItem) }}>标记为已退款</Button>)
}
return <React.Fragment>
{
tpl.map(function (item) {
return item
})
}
</React.Fragment>;
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import Zmage from '../../service/zmage.development'
import React from 'react'
export default class ZZmage extends React.Component {
handleDown(src) {
var req = new XMLHttpRequest();
req.open("GET", src, true);
req.responseType = 'blob';
req.onload = function (e) {
var ks = src.split('?');
var splits = ks[0].split('/')
download(req.response, splits[splits.length-1]);
}
req.send();
}
render() {
let { src } = this.props;
return (
<React.Fragment>
<Zmage handleDown={(e) => { this.handleDown(e) }}
className={this.props.className?this.props.className:'book-img'}
src={src} alt={this.props.alt?this.props.alt:''} />
</React.Fragment>
)
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment