Commit da821d55 by zhuxiaomei

温湿度登记

parents
NODE_ENV=development
VUE_APP_BASE_URL=http://api.dev.patzn.com:7000
NODE_ENV=test
VUE_APP_BASE_URL=http://api.pertest.patzn.com
NODE_ENV=production
VUE_APP_BASE_URL=http://api.patzn.com
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# my-app
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your tests
```
npm run test
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.20.0",
"core-js": "^3.6.5",
"dateformat": "^3.0.3",
"store2": "^2.7.0",
"vant": "^2.10.9",
"view-design": "^4.4.0",
"vue": "^2.6.11",
"vue-navigation": "^1.1.4",
"vue-router": "^3.4.6",
"vue2-touch-events": "^2.3.2",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.0",
"@vue/cli-plugin-eslint": "^4.5.0",
"@vue/cli-service": "^4.5.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.13.1",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"less": "^3.12.2",
"less-loader": "^7.0.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"globals": {
"BMap": true,
"plus": true,
"mui": true
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>温湿度</title>
<script src="<%= BASE_URL %>js/mui.min.js"></script>
<script src="<%= BASE_URL %>js/back.js"></script>
</head>
<body>
<!--<noscript>-->
<!--<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.-->
<!--Please enable it to continue.</strong>-->
<!--</noscript>-->
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<!-- 判断ios版本 -->
<script>
var str = navigator.userAgent.toLowerCase();
var ver = str.match(/cpu iphone os (.*?) like mac os/);
if (!ver) {//非IOS系统
// 引入fastclick文件
includeFastclickJsFile();
// alert('安卓')
} else {
// alert('ios')
console.log("你当前的Ios系统版本为:" + ver[1].replace(/_/g, "."));
if (parseInt(ver[1]) >= 11) {
//不必引入fastclick文件
} else {
// 引入fastclick文件
includeFastclickJsFile();
}
}
function includeFastclickJsFile() {
var oHead = document.getElementsByTagName('HEAD').item(0);
let fastclick = document.createElement("script");
fastclick.type = "text/javascript";
fastclick.src = "<%= BASE_URL %>/js/fastclick.js";
oHead.appendChild(fastclick);
}
</script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=33d56f06483ab332151b14e85bbb8405"></script>
</html>
//取消浏览器的所有事件,使得active的样式在手机上正常生效
document.addEventListener('touchstart',function(){
return false;
},true);
document.addEventListener('plusready', function() {
var webview = plus.webview.currentWebview().setStyle({scrollIndicator:'none'});
plus.key.addEventListener('backbutton', function() {
console.log(webview.canBack,'webview.canBack')
webview.canBack(function(e) {
if(e.canBack) {
webview.back();
} else {
//webview.close(); //hide,quit
//plus.runtime.quit();
mui.plusReady(function() {
//首页返回键处理
//处理逻辑:1秒内,连续两次按返回键,则退出应用;
var first = null;
plus.key.addEventListener('backbutton', function() {
//首次按键,提示‘再按一次退出应用’
if (!first) {
first = new Date().getTime();
mui.toast('再按一次退出应用');
setTimeout(function() {
first = null;
}, 1000);
} else {
if (new Date().getTime() - first < 1500) {
plus.runtime.quit();
}
}
}, false);
});
}
})
});
// 关闭启动界面
plus.navigator.setStatusBarBackground('#00a0e9');
});
;(function () {
'use strict';
/**
* @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
*
* @codingstandard ftlabs-jsv2
* @copyright The Financial Times Limited [All Rights Reserved]
* @license MIT License (see LICENSE.txt)
*/
/*jslint browser:true, node:true*/
/*global define, Event, Node*/
/**
* Instantiate fast-clicking listeners on the specified layer.
*
* @constructor
* @param {Element} layer The layer to listen on
* @param {Object} [options={}] The options to override the defaults
*/
function FastClick(layer, options) {
var oldOnClick;
options = options || {};
/**
* Whether a click is currently being tracked.
*
* @type boolean
*/
this.trackingClick = false;
/**
* Timestamp for when click tracking started.
*
* @type number
*/
this.trackingClickStart = 0;
/**
* The element being tracked for a click.
*
* @type EventTarget
*/
this.targetElement = null;
/**
* X-coordinate of touch start event.
*
* @type number
*/
this.touchStartX = 0;
/**
* Y-coordinate of touch start event.
*
* @type number
*/
this.touchStartY = 0;
/**
* ID of the last touch, retrieved from Touch.identifier.
*
* @type number
*/
this.lastTouchIdentifier = 0;
/**
* Touchmove boundary, beyond which a click will be cancelled.
*
* @type number
*/
this.touchBoundary = options.touchBoundary || 10;
/**
* The FastClick layer.
*
* @type Element
*/
this.layer = layer;
/**
* The minimum time between tap(touchstart and touchend) events
*
* @type number
*/
this.tapDelay = options.tapDelay || 200;
/**
* The maximum time for a tap
*
* @type number
*/
this.tapTimeout = options.tapTimeout || 700;
if (FastClick.notNeeded(layer)) {
return;
}
// Some old versions of Android don't have Function.prototype.bind
function bind(method, context) {
return function() { return method.apply(context, arguments); };
}
var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
var context = this;
for (var i = 0, l = methods.length; i < l; i++) {
context[methods[i]] = bind(context[methods[i]], context);
}
// Set up event handlers as required
if (deviceIsAndroid) {
layer.addEventListener('mouseover', this.onMouse, true);
layer.addEventListener('mousedown', this.onMouse, true);
layer.addEventListener('mouseup', this.onMouse, true);
}
layer.addEventListener('click', this.onClick, true);
layer.addEventListener('touchstart', this.onTouchStart, false);
layer.addEventListener('touchmove', this.onTouchMove, false);
layer.addEventListener('touchend', this.onTouchEnd, false);
layer.addEventListener('touchcancel', this.onTouchCancel, false);
// Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
// which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
// layer when they are cancelled.
if (!Event.prototype.stopImmediatePropagation) {
layer.removeEventListener = function(type, callback, capture) {
var rmv = Node.prototype.removeEventListener;
if (type === 'click') {
rmv.call(layer, type, callback.hijacked || callback, capture);
} else {
rmv.call(layer, type, callback, capture);
}
};
layer.addEventListener = function(type, callback, capture) {
var adv = Node.prototype.addEventListener;
if (type === 'click') {
adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
if (!event.propagationStopped) {
callback(event);
}
}), capture);
} else {
adv.call(layer, type, callback, capture);
}
};
}
// If a handler is already declared in the element's onclick attribute, it will be fired before
// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
// adding it as listener.
if (typeof layer.onclick === 'function') {
// Android browser on at least 3.2 requires a new reference to the function in layer.onclick
// - the old one won't work if passed to addEventListener directly.
oldOnClick = layer.onclick;
layer.addEventListener('click', function(event) {
oldOnClick(event);
}, false);
layer.onclick = null;
}
}
/**
* Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
*
* @type boolean
*/
var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
/**
* Android requires exceptions.
*
* @type boolean
*/
var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
/**
* iOS requires exceptions.
*
* @type boolean
*/
var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
/**
* iOS 4 requires an exception for select elements.
*
* @type boolean
*/
var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
/**
* iOS 6.0-7.* requires the target element to be manually derived
*
* @type boolean
*/
var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);
/**
* BlackBerry requires exceptions.
*
* @type boolean
*/
var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
/**
* Determine whether a given element requires a native click.
*
* @param {EventTarget|Element} target Target DOM element
* @returns {boolean} Returns true if the element needs a native click
*/
FastClick.prototype.needsClick = function(target) {
switch (target.nodeName.toLowerCase()) {
// Don't send a synthetic click to disabled inputs (issue #62)
case 'button':
case 'select':
case 'textarea':
if (target.disabled) {
return true;
}
break;
case 'input':
// File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
if ((deviceIsIOS && target.type === 'file') || target.disabled) {
return true;
}
break;
case 'label':
case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
case 'video':
return true;
}
return (/\bneedsclick\b/).test(target.className);
};
/**
* Determine whether a given element requires a call to focus to simulate click into element.
*
* @param {EventTarget|Element} target Target DOM element
* @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
*/
FastClick.prototype.needsFocus = function(target) {
switch (target.nodeName.toLowerCase()) {
case 'textarea':
return true;
case 'select':
return !deviceIsAndroid;
case 'input':
switch (target.type) {
case 'button':
case 'checkbox':
case 'file':
case 'image':
case 'radio':
case 'submit':
return false;
}
// No point in attempting to focus disabled inputs
return !target.disabled && !target.readOnly;
default:
return (/\bneedsfocus\b/).test(target.className);
}
};
/**
* Send a click event to the specified element.
*
* @param {EventTarget|Element} targetElement
* @param {Event} event
*/
FastClick.prototype.sendClick = function(targetElement, event) {
var clickEvent, touch;
// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
if (document.activeElement && document.activeElement !== targetElement) {
document.activeElement.blur();
}
touch = event.changedTouches[0];
// Synthesise a click event, with an extra attribute so it can be tracked
clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
clickEvent.forwardedTouchEvent = true;
targetElement.dispatchEvent(clickEvent);
};
FastClick.prototype.determineEventType = function(targetElement) {
//Issue #159: Android Chrome Select Box does not open with a synthetic click event
if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
return 'mousedown';
}
return 'click';
};
/**
* @param {EventTarget|Element} targetElement
*/
FastClick.prototype.focus = function(targetElement) {
var length;
// Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month' && targetElement.type !== 'email') {
length = targetElement.value.length;
targetElement.setSelectionRange(length, length);
} else {
targetElement.focus();
}
};
/**
* Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
*
* @param {EventTarget|Element} targetElement
*/
FastClick.prototype.updateScrollParent = function(targetElement) {
var scrollParent, parentElement;
scrollParent = targetElement.fastClickScrollParent;
// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
// target element was moved to another parent.
if (!scrollParent || !scrollParent.contains(targetElement)) {
parentElement = targetElement;
do {
if (parentElement.scrollHeight > parentElement.offsetHeight) {
scrollParent = parentElement;
targetElement.fastClickScrollParent = parentElement;
break;
}
parentElement = parentElement.parentElement;
} while (parentElement);
}
// Always update the scroll top tracker if possible.
if (scrollParent) {
scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
}
};
/**
* @param {EventTarget} targetElement
* @returns {Element|EventTarget}
*/
FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
// On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
if (eventTarget.nodeType === Node.TEXT_NODE) {
return eventTarget.parentNode;
}
return eventTarget;
};
/**
* On touch start, record the position and scroll offset.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.onTouchStart = function(event) {
var targetElement, touch, selection;
// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
if (event.targetTouches.length > 1) {
return true;
}
targetElement = this.getTargetElementFromEventTarget(event.target);
touch = event.targetTouches[0];
if (deviceIsIOS) {
// Only trusted events will deselect text on iOS (issue #49)
selection = window.getSelection();
if (selection.rangeCount && !selection.isCollapsed) {
return true;
}
if (!deviceIsIOS4) {
// Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
// when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
// with the same identifier as the touch event that previously triggered the click that triggered the alert.
// Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
// immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
// Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
// which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
// random integers, it's safe to to continue if the identifier is 0 here.
if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
event.preventDefault();
return false;
}
this.lastTouchIdentifier = touch.identifier;
// If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
// 1) the user does a fling scroll on the scrollable layer
// 2) the user stops the fling scroll with another tap
// then the event.target of the last 'touchend' event will be the element that was under the user's finger
// when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
// is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
this.updateScrollParent(targetElement);
}
}
this.trackingClick = true;
this.trackingClickStart = event.timeStamp;
this.targetElement = targetElement;
this.touchStartX = touch.pageX;
this.touchStartY = touch.pageY;
// Prevent phantom clicks on fast double-tap (issue #36)
if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
event.preventDefault();
}
return true;
};
/**
* Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.touchHasMoved = function(event) {
var touch = event.changedTouches[0], boundary = this.touchBoundary;
if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
return true;
}
return false;
};
/**
* Update the last position.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.onTouchMove = function(event) {
if (!this.trackingClick) {
return true;
}
// If the touch has moved, cancel the click tracking
if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
this.trackingClick = false;
this.targetElement = null;
}
return true;
};
/**
* Attempt to find the labelled control for the given label element.
*
* @param {EventTarget|HTMLLabelElement} labelElement
* @returns {Element|null}
*/
FastClick.prototype.findControl = function(labelElement) {
// Fast path for newer browsers supporting the HTML5 control attribute
if (labelElement.control !== undefined) {
return labelElement.control;
}
// All browsers under test that support touch events also support the HTML5 htmlFor attribute
if (labelElement.htmlFor) {
return document.getElementById(labelElement.htmlFor);
}
// If no for attribute exists, attempt to retrieve the first labellable descendant element
// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
};
/**
* On touch end, determine whether to send a click event at once.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.onTouchEnd = function(event) {
var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
if (!this.trackingClick) {
return true;
}
// Prevent phantom clicks on fast double-tap (issue #36)
if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
this.cancelNextClick = true;
return true;
}
if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
return true;
}
// Reset to prevent wrong click cancel on input (issue #156).
this.cancelNextClick = false;
this.lastClickTime = event.timeStamp;
trackingClickStart = this.trackingClickStart;
this.trackingClick = false;
this.trackingClickStart = 0;
// On some iOS devices, the targetElement supplied with the event is invalid if the layer
// is performing a transition or scroll, and has to be re-detected manually. Note that
// for this to function correctly, it must be called *after* the event target is checked!
// See issue #57; also filed as rdar://13048589 .
if (deviceIsIOSWithBadTarget) {
touch = event.changedTouches[0];
// In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
}
targetTagName = targetElement.tagName.toLowerCase();
if (targetTagName === 'label') {
forElement = this.findControl(targetElement);
if (forElement) {
this.focus(targetElement);
if (deviceIsAndroid) {
return false;
}
targetElement = forElement;
}
} else if (this.needsFocus(targetElement)) {
// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
this.targetElement = null;
return false;
}
this.focus(targetElement);
this.sendClick(targetElement, event);
// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
if (!deviceIsIOS || targetTagName !== 'select') {
this.targetElement = null;
event.preventDefault();
}
return false;
}
if (deviceIsIOS && !deviceIsIOS4) {
// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
scrollParent = targetElement.fastClickScrollParent;
if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
return true;
}
}
// Prevent the actual click from going though - unless the target node is marked as requiring
// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
if (!this.needsClick(targetElement)) {
event.preventDefault();
this.sendClick(targetElement, event);
}
return false;
};
/**
* On touch cancel, stop tracking the click.
*
* @returns {void}
*/
FastClick.prototype.onTouchCancel = function() {
this.trackingClick = false;
this.targetElement = null;
};
/**
* Determine mouse events which should be permitted.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.onMouse = function(event) {
// If a target element was never set (because a touch event was never fired) allow the event
if (!this.targetElement) {
return true;
}
if (event.forwardedTouchEvent) {
return true;
}
// Programmatically generated events targeting a specific element should be permitted
if (!event.cancelable) {
return true;
}
// Derive and check the target element to see whether the mouse event needs to be permitted;
// unless explicitly enabled, prevent non-touch click events from triggering actions,
// to prevent ghost/doubleclicks.
if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
// Prevent any user-added listeners declared on FastClick element from being fired.
if (event.stopImmediatePropagation) {
event.stopImmediatePropagation();
} else {
// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
event.propagationStopped = true;
}
// Cancel the event
event.stopPropagation();
event.preventDefault();
return false;
}
// If the mouse event is permitted, return true for the action to go through.
return true;
};
/**
* On actual clicks, determine whether this is a touch-generated click, a click action occurring
* naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
* an actual click which should be permitted.
*
* @param {Event} event
* @returns {boolean}
*/
FastClick.prototype.onClick = function(event) {
var permitted;
// It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
if (this.trackingClick) {
this.targetElement = null;
this.trackingClick = false;
return true;
}
// Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
if (event.target.type === 'submit' && event.detail === 0) {
return true;
}
permitted = this.onMouse(event);
// Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
if (!permitted) {
this.targetElement = null;
}
// If clicks are permitted, return true for the action to go through.
return permitted;
};
/**
* Remove all FastClick's event listeners.
*
* @returns {void}
*/
FastClick.prototype.destroy = function() {
var layer = this.layer;
if (deviceIsAndroid) {
layer.removeEventListener('mouseover', this.onMouse, true);
layer.removeEventListener('mousedown', this.onMouse, true);
layer.removeEventListener('mouseup', this.onMouse, true);
}
layer.removeEventListener('click', this.onClick, true);
layer.removeEventListener('touchstart', this.onTouchStart, false);
layer.removeEventListener('touchmove', this.onTouchMove, false);
layer.removeEventListener('touchend', this.onTouchEnd, false);
layer.removeEventListener('touchcancel', this.onTouchCancel, false);
};
/**
* Check whether FastClick is needed.
*
* @param {Element} layer The layer to listen on
*/
FastClick.notNeeded = function(layer) {
var metaViewport;
var chromeVersion;
var blackberryVersion;
var firefoxVersion;
// Devices that don't support touch don't need FastClick
if (typeof window.ontouchstart === 'undefined') {
return true;
}
// Chrome version - zero for other browsers
chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
if (chromeVersion) {
if (deviceIsAndroid) {
metaViewport = document.querySelector('meta[name=viewport]');
if (metaViewport) {
// Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
return true;
}
// Chrome 32 and above with width=device-width or less don't need FastClick
if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
return true;
}
}
// Chrome desktop doesn't need FastClick (issue #15)
} else {
return true;
}
}
if (deviceIsBlackBerry10) {
blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
// BlackBerry 10.3+ does not require Fastclick library.
// https://github.com/ftlabs/fastclick/issues/251
if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
metaViewport = document.querySelector('meta[name=viewport]');
if (metaViewport) {
// user-scalable=no eliminates click delay.
if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
return true;
}
// width=device-width (or less than device-width) eliminates click delay.
if (document.documentElement.scrollWidth <= window.outerWidth) {
return true;
}
}
}
}
// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
return true;
}
// Firefox version - zero for other browsers
firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
if (firefoxVersion >= 27) {
// Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896
metaViewport = document.querySelector('meta[name=viewport]');
if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
return true;
}
}
// IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
// http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
return true;
}
return false;
};
/**
* Factory method for creating a FastClick object
*
* @param {Element} layer The layer to listen on
* @param {Object} [options={}] The options to override the defaults
*/
FastClick.attach = function(layer, options) {
return new FastClick(layer, options);
};
if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
// AMD. Register as an anonymous module.
define(function() {
return FastClick;
});
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = FastClick.attach;
module.exports.FastClick = FastClick;
} else {
window.FastClick = FastClick;
}
}());
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
/**
* 系统相关
*/
import http from '../http'
export default {
//意见反馈
advise: data => http.post('/base/v1/advise/', data).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
import Global from '../config'
export default {
//检测版本,自动更新
version: data => http.post('/base/v1/app_version/' + data.name + '_' + data.device + '?version=' + Global.version()).then(res => res),
}
/**
* 城市
*/
import http from '../http'
export default {
// 地址
list: () => http.post('/base/v1/country/list').then(res => res)
}
/**
* 系统相关
*/
import http from '../http'
export default {
//获取邮箱验证码
getEmailCode: data => http.post('/base/v1/email/send/', data).then(res => res),
//绑定邮箱
bindEmail: data => http.post('/base/v1/email/bind_' + data.code).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
submitExperience: data => http.post('/base/v1/experience/' + data.code, data).then(res => res),
}
/**
* 报告模板
*/
import http from '../http'
export default {
page: data => http.post('/base/v1/file_template/page', data).then(res => res)
}
/**
* 工作流相关
*/
import http from '../http'
export default {
//任务
listTask: data => http.post('/base/v1/flow_process/list_task', data).then(res => res),
//认领
claimTask: data => http.post('/base/v1/flow_process/claim_task/' + data).then(res => res),
fromKey: data => http.post('/base/v1/flow_process/fromKey', {taskId: data}).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
appMenu: data => http.post('/base/v1/resource/app_menu', data).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
getCode: data => http.post('/base/v1/sms/send_' + data.module + '/' + data.mobile).then(res => res),
//修改手机号
changeBindMobile: data => http.post('/base/v1/sms/change_bind_' + data).then(res => res),
}
/**
* sso
*/
import http from '../http'
export default {
//登录
login: data => http.post('/base/v1/sso/app_login', data).then(res => res),
//验证码登录
loginByCode: data => http.post('/base/v1/sso/ajax_login_back', data).then(res => res),
//注册
register: data => http.post('/base/v1/sso/register', data).then(res => res),
//修改密码
changPwd: data => http.post('/base/v1/sso/change_password', data).then(res => res),
//退出
logout: () => http.get('/base/v1/sso/logout').then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
import httpJson from '../httpJson'
export default {
//个人模块-save
userRelResourceAdd: data => httpJson.post('/base/v1/user_rel_resource/', JSON.stringify(data)).then(res => res),
//个人模块-list
userRelResource: () => http.post('/base/v1/user_rel_resource/my_list').then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
//用户修改密码
editPsd: data => http.put('/base/v1/user/password', data).then(res => res),
//获取用户信息
getUserInfo: () => http.get('/base/v1/user/info').then(res => res),
userEdit: data => http.put('/base/v1/user/' + data.id, data.obj).then(res => res),
// 人员查询
orginTreeList: () => http.post('/base/v1/org/org_tree').then(res => res),
userSelect: data => http.post('/base/v1/user/list_org/' + data.orgId).then(res => res),
userSelectByKeyword: data => http.post('/base/v1/user/list?realname=' + data).then(res => res),
}
/**
* 全局相关配置
*/
// 对外暴露全局常量及函数
export default {
//localStorage
setUserInfo: function (user) {
localStorage.setItem('fLoginUser', JSON.stringify(user));
},
//clear
logout: function () {
localStorage.removeItem('fLoginUser');
localStorage.removeItem('accessToken');
},
getUserInfo: function () {
return JSON.parse(localStorage.getItem('fLoginUser'));
},
//token
setToken: function (data) {
localStorage.setItem('accessToken', data);
},
//获取token
getToken: function () {
return localStorage.getItem('accessToken');
},
baseURL: process.env.VUE_APP_BASE_URL,
//version
version: function () {
return '1.0.1'
},
}
/**
* HTTP 请求 axios 封装
*/
import Qs from "qs";
import axios from 'axios'
import global from './config'
import loading from './loading'
// Axios 全局配置
const http = axios.create()
http.defaults.baseURL = process.env.VUE_APP_BASE_URL
http.defaults.withCredentials = true
// 添加请求拦截器
http.interceptors.request.use(
config => {
let tk = localStorage.getItem('accessToken');
if (tk) {
config.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
config.headers.accessToken = tk;
}
config.transformRequest = [
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
function (data) {
return Qs.stringify(data);
}
]
return config
},
error => {
return Promise.reject(error)
}
)
// 返回数据处理
// 返回格式 {code:业务码 , data: 内容 , msg: 描述}
http.interceptors.response.use(
response => {
switch (response.data.code) {
case '-2':
global.logout()
// location.reload()
break
case '1':
return response.data.data
default:
loading.toast.show(response.data.code, response.data.msg)
}
},
error => {
return Promise.reject(error)
}
)
export default http
/**
* HTTP 请求 axios dto封装
*/
import axios from 'axios'
import global from './config'
import loading from './loading'
// Axios 全局配置
const httpJson = axios.create()
httpJson.defaults.baseURL = process.env.VUE_APP_BASE_URL
httpJson.defaults.withCredentials = true
// 添加请求拦截器
httpJson.interceptors.request.use(
config => {
let tk = localStorage.getItem('accessToken');
if (tk) {
config.headers = {
'Content-Type': 'application/json'
};
config.headers.accessToken = tk;
}
return config
},
error => {
return Promise.reject(error)
}
)
// 返回数据处理
// 返回格式 {code:业务码 , data: 内容 , msg: 描述}
httpJson.interceptors.response.use(
response => {
switch (response.data.code) {
case '-2':
global.logout()
location.reload();
break
case '1':
return response.data.data
default:
loading.toast.show(response.data.code, response.data.msg)
}
},
error => {
if (error.response.status === 401) {
console.log('unauthorized, logging out ...')
}
return Promise.reject(error)
}
)
export default httpJson
/**
* base
*/
export {default as sso} from './base/sso'
// export {default as resource} from './base/resource'
// export {default as userRelResource} from './base/user-rel-resource'
export {default as sysUser} from './base/user'
// export {default as appVersion} from './base/app-version'
// export {default as flowProcess} from './base/flow-process'
// export {default as email} from './base/email'
export {default as sms} from './base/sms'
export {default as advise} from './base/advise'
// export {default as country} from './base/country'
// export {default as fileTemplate} from './base/file-template'
/**
* res
*/
export {default as envMonitor} from './res/env-monitor'
export {default as envMonitorRecord} from './res/env-monitor-record'
// export {default as dict} from './res/dict'
// export {default as serviceType} from './res/service-type'
// export {default as car} from './res/car'
/**
* message
*/
export {default as message} from './message/message'
/**
* 加载
*/
import Vue from 'vue'
import { Toast } from 'vant';
Vue.use(Toast);
function toasts(message) {
Toast(message);
}
var toast = {
show: function (type, message) {
console.log('===message==' + message);
var finalMessage = message;
if (!finalMessage) {
switch (type) {
case 1000:
finalMessage = '没有权限';
break;
case -201:
finalMessage = '没有用户';
break;
case -1:
finalMessage = '没有权限';
break;
case 500:
finalMessage = '网络错误';
break;
default:
finalMessage = '网络错误';
break;
}
finalMessage += type;
}
if (message === 'inactivate') {
//未激活状态
localStorage.setItem('inactivate', message);
} else {
toasts(finalMessage);
}
},
// showMessage: function (message) {
// toasts(message);
// },
//
// showLoading: function (show) {
// if (show) {
// // iView.LoadingBar.start();
// } else {
// // iView.LoadingBar.finish();
// }
// }
};
export default {
toast
}
/**
* 系统消息表相关
*/
import http from '../http'
export default {
deleteByIds: ids => http.delete('/message/v1/message/?ids=' + ids).then(res => res),
getById: id => http.get('/message/v1/message/' + id).then(res => res),
myPage: data => http.post('/message/v1/message/page_my', data).then(res => res),
read: ids => http.post('/message/v1/message/read?relIds=' + ids).then(res => res),
}
/**
* 资源-客户
*/
import http from '../http'
export default {
//客户
list: data => http.get('/res/v1/customer/list?cname=' + data).then(res => res)
}
/**
* 资源-字典
*/
import http from '../http'
export default {
// 多个字典查询
listDict: data => http.post('/res/v1/dict/list_dict', {'classTypeList': data.join(',')}).then(res => res),
// 单个字典查询
getItem: data => http.get('/res/v1/dict/dict_class_item?classType=' + data).then(res => res)
}
import http from '../../api/http'
export default {
page: data => http.post('/res/v1/env_monitor_record/page', data).then(res => res),
}
/**
* 环境监测管理相关
*/
import http from '../../api/http'
export default {
page: data => http.post('/res/v1/env_monitor/page', data).then(res => res),
add: data => http.post('/res/v1/env_monitor/', data).then(res => res),
edit: data => http.put('/res/v1/env_monitor/' + data.id, data.obj).then(res => res),
deleteByIds: ids => http.delete('/res/v1/env_monitor/?ids=' + ids).then(res => res),
getById: id => http.get('/res/v1/env_monitor/' + id).then(res => res),
}
/**
* 资源-服务类型
*/
import http from '../http'
export default {
list: data => {
let obj = ''
if (data) {
obj = http.get('/res/v1/service_type/list?name=' + data).then(res => res)
} else {
obj = http.get('/res/v1/service_type/list', data).then(res => res)
}
return obj
}
}
/**
* 资源-用户编组
*/
import http from '../http'
export default {
//用户编组
userGroupList: () => http.post('/res/v1/user_group/list').then(res => res),
//编组关联用户(默认500条)
groupUserPage: data => http.post('/res/v1/user_group/page_rel_user', data).then(res => res),
}
<template>
<div>
<van-field
readonly
v-model="dateValue"
label="省市区"
placeholder="点击选择省市区"
@click="showPicker = true"
></van-field>
<van-field
readonly
clickable
label="城市"
:value="value"
placeholder="选择城市"
@click="showPicker = true"
></van-field>
<van-popup v-model="showPicker" round position="bottom">
<van-picker
show-toolbar
:columns="columns"
@cancel="showPicker = false"
@confirm="onConfirm"
></van-picker>
</van-popup>
</div>
</template>
<script>
/**
* 该组件不可用 请自行修改
*/
export default {
name: "CascadeCity"
}
</script>
<style scoped>
</style>
<template>
<van-popup v-model="showPopup" round :style="{ width:'75%'}">
<div>
{{title}}
</div>
<div style="margin: 20px 10px">
<slot></slot>
</div>
<div>
<van-button type="primary" @click="onCancel">取消</van-button>
<van-button type="info" @click="onConfirm">确定</van-button>
</div>
</van-popup>
</template>
<script>
export default {
name: "ConfirmDialog",
props: {
title: String,
},
data() {
return {
showPopup: true
}
},
methods: {
onCancel() {
this.$emit('close')
},
onConfirm() {
this.$emit('confirm')
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<!--https://youzan.github.io/vant/#/zh-CN/form#biao-dan-xiang-lei-xing---shi-jian-xuan-ze-qi-->
<van-field
readonly
v-model="dateValue"
:label="label"
:placeholder="'点击选择'+label"
@click="showPicker = true"
></van-field>
<van-popup v-model="showPicker" position="bottom"
:safe-area-inset-bottom="true"
:close-on-popstate="true">
<van-datetime-picker
:type="type"
v-model="currentDate"
@confirm="onConfirm"
@cancel="showPicker = false"
></van-datetime-picker>
</van-popup>
</div>
</template>
<script>
export default {
name: "DateTimeField",
props: {
label: String,
value: {type: String, default: ''}, //默认值
type: {type: String, default: 'date'},
format: {type: String, default: 'yyyy-mm-dd'},
// startDate: String
},
data() {
return {
showPicker: false,
currentDate: new Date(),
// minDate:this.startDate?new Date(this.startDate):new Date()
}
},
computed: {
dateValue: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
},
watch: {
showPicker: function (newVal) {
if (newVal) {
this.currentDate = new Date()
}
}
},
methods: {
onConfirm(date) {
this.dateValue = this.$dateformat(date, this.format)
this.showPicker = false
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<datetime-field label="计划日期" v-model="planDate"></datetime-field>
<van-button type="info" @click="_clear">
清空
</van-button>
</div>
</template>
<script>
import DatetimeField from './DatetimeField'
export default {
name: "Search",
components: {
DatetimeField
},
data() {
return {
planDate: ''
}
},
methods: {
_clear() {
this.planDate = ''
}
}
}
</script>
<style scoped>
</style>
<template>
<!--https://youzan.github.io/vant/#/zh-CN/tabbar-->
<van-tabbar route fixed>
<van-tabbar-item replace to="/home" icon="home-o">
首页
</van-tabbar-item>
<van-tabbar-item replace to="/mine/mine" icon="friends-o">
个人中心
</van-tabbar-item>
</van-tabbar>
</template>
<script>
export default {
name: "FooterBar"
}
</script>
<style scoped>
</style>
<template>
<!--https://youzan.github.io/vant/#/zh-CN/search-->
<div class="search-bar-box-fixed-top" :class="{'search-bar-box':fixed===false}">
<van-search
v-model="searchValue"
show-action
:placeholder="'请输入搜索'+labelText"
@search="onSearch"
>
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<div @click="showHighSearch = true" v-if="highSearch" class="high-search-text">高级查询</div>
<div class="high-search-cont" v-if="showHighSearch">
<van-nav-bar title="高级搜索"
:left-arrow="true"
@click-left="showHighSearch=false"></van-nav-bar>
<slot name="highSearch"></slot>
<div class="btn-box">
<van-button block type="info" @click="onHighSearch">搜索</van-button>
<van-button block type="default" @click="onReset" style="margin-top: 10px">清空</van-button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "SearchBar",
props: {
label: String,
//是否展示高级查询按钮
highSearch: {type: Boolean, default: false},
fixed: {type: Boolean, default: true}
},
data() {
return {
showHighSearch: false,
searchValue: '',
}
},
computed: {
labelText: {
get() {
return this.label ? this.label : '关键字'
},
}
},
watch: {
showHighSearch: function (val) {
let that = this
mui.init({
beforeback: function () {
if (val) {
that._hideHighSearch()
return false;
} else {
return true
}
}
});
}
},
methods: {
onSearch() {
this.$emit('search', this.searchValue)
},
onHighSearch() {
this.searchValue = ''
this.$emit('high-search')
},
_hideHighSearch() {
this.showHighSearch = false
},
onReset() {
this.$emit('clear-high')
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<slot name="navBar"></slot>
<div class="main-layout-cont">
<div>
<slot name="content"></slot>
</div>
</div>
<!--其他使用的组件等-->
<slot></slot>
</div>
</template>
<script>
/**
* 自定义标题栏布局
*/
export default {
name: "NavBarLayout"
}
</script>
<style scoped>
</style>
This source diff could not be displayed because it is too large. You can view the blob instead.
// 加载百度地图js
const map = {
init: function () {
const AK = '7aLLv8GDWaDFLiBlCrctGnq3vTFsHEWf'
const BMapURL = 'http://api.map.baidu.com/api?v=2.0' + AK + '&s=1&callback=onBMapCallback'
return new Promise((resolve) => {
// 如果已加载直接返回
if (typeof BMap !== 'undefined') {
resolve(BMap)
return true
}
// 百度地图异步加载回调处理
window.onBMapCallback = function () {
// console.log('百度地图脚本初始化成功...')
resolve(BMap)
};
// 插入script脚本
let scriptNode = document.createElement('script')
scriptNode.setAttribute('type', 'text/javascript')
scriptNode.setAttribute('src', BMapURL)
document.body.appendChild(scriptNode)
})
}
}
export default map
import dateformat from 'dateformat';
import global from '../api/config';
export default {
install(Vue) {
/**
* 日期格式化
* https://www.npmjs.com/package/dateformat
*/
Vue.prototype.$dateformat = function (date, format) {
return date ? dateformat(date, format) : ''
};
/**
* 重置数据
* */
Vue.prototype.$resetFields = function (formObj) {
let newFormObj = {}
for (let key in formObj) {
newFormObj[key] = ''
}
return newFormObj;
};
/**
* 序列化formObj 只返回有值的
* @param formObj
*/
Vue.prototype.$serializeForm = function (formObj) {
const newFormObj = {}
for (const key in formObj) {
// 不为空的时候传值
if (formObj[key] !== '') {
newFormObj[key] = formObj[key]
}
}
return newFormObj
}
/**
* 将经纬度转化为度分秒的格式
* ****/
Vue.prototype.$changeToDFM = function (du, type) {
let duStr = du.toString()
const arr1 = duStr.split(".");
const d = arr1[0];
let tp = "0." + arr1[1]
tp = String(tp * 60); //这里进行了强制类型转换
const arr2 = tp.split(".");
const f = arr2[0];
tp = "0." + arr2[1];
tp = tp * 60;
let mStr = tp.toString();
const arr3 = mStr.split(".")
const subStr = arr3[1].substring(0, 2)
const m = arr3[0] + "." + subStr;
const dfm = d + "°" + f + "'" + m + "\"" + type;
return dfm;
};
/**
* 全局的配置
* @type
*/
Vue.prototype.$global = global
},
}
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import plugins from './lib/plugins'
Vue.use(plugins)
// import Navigation from 'vue-navigation'
// Vue.use(Navigation, {router});
import Vue2TouchEvents from 'vue2-touch-events'
Vue.use(Vue2TouchEvents)
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
import ViewUI from 'view-design';
import 'view-design/dist/styles/iview.css';
Vue.use(ViewUI);
import '@/styles/main.less'
import SearchBar from '@/components/SearchBar.vue'
import DatetimeField from '@/components/DatetimeField.vue'
import ConfirmDialog from '@/components/ConfirmDialog.vue'
import CustomerNavBarLayout from '@/layout/CustomerNavBarLayout.vue'
Vue.component('search-bar', SearchBar)
Vue.component('datetime-field', DatetimeField)
Vue.component('confirm-dialog', ConfirmDialog)
Vue.component('customer-navBar-layout', CustomerNavBarLayout)
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
<template>
<div class="login-cont">
<div class="login-main login-main-forget">
<div class="logo-text">
<img src="@/assets/forgetPwd.png" height="40">
</div>
<van-form @submit="onSubmit">
<div class="field-input">
<van-field
v-model="formObj.mobile"
:left-icon="require('../assets/user.png')"
label-width="4.2em"
name="mobile"
label="手机号"
placeholder="请输入您的手机号"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<van-field
v-model="formObj.code"
center
:left-icon="require('../assets/code.png')"
label-width="4.2em"
name="code"
label="验证码"
placeholder="请输入验证码"
:rules="[{ required: true, message: '' }]">
<template #button>
<!--native-type="button" 阻止触发表单提交-->
<van-button size="small" type="info" native-type="button" @click="_getCode">
发送验证码
</van-button>
</template>
</van-field>
</div>
<div class="field-input">
<van-field
v-model="formObj.password"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="password"
label="新密码"
placeholder="请输入新密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<van-field
v-model="confirmPwd"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="confirmPwd"
label="确认密码"
placeholder="请确认密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="btn-box" style="margin-top: 30px">
<van-button block type="info" native-type="submit">
确认并登录
</van-button>
</div>
</van-form>
</div>
</div>
</template>
<script>
import {sms, sso} from '@/api'
export default {
name: "ForgetPwd",
data() {
return {
confirmPwd: '',
formObj: {
mobile: '',
password: '',
code: ''
},
}
},
methods: {
_getCode: async function () {
if (this.formObj.mobile === '') {
this.$toast('请输入手机号');
} else {
if (!/^((1[3,5,8][0-9])|(14[5,7])|(17[0,6,7,8])|(19[7]))\d{8}$/.test(this.formObj.mobile)) {
this.$toast('手机号格式不正确');
} else {
let result = await sms.getCode({
module: 'changePasswordByMobile',
mobile: this.formObj.mobile
})
if (result) {
this.$toast.success('发送成功!');
}
}
}
},
onSubmit() {
if (this.formObj.password !== this.confirmPwd) {
this.$toast('两次填写的密码不一致');
} else {
this._save()
}
},
_save: async function () {
let result = await sso.changPwd(this.formObj)
if (result) {
this.$toast.success('密码修改成功!');
setTimeout(() => {
this._toLogin();
}, 1000)
}
},
//跳到注册界面
_toLogin() {
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
<style scoped>
</style>
<template>
<div>
<!--https://youzan.github.io/vant/#/zh-CN/grid-->
<div class="layout-cont home-cont">
<van-grid :gutter="10" :column-num="3" :icon-size="40">
<!--1、icon参数引入使用,否则不显示-->
<van-grid-item v-for="item in menuList" :key="item.title" :icon="item.img"
:text="item.title" @click="_goto(item)"></van-grid-item>
<!--2、require使用 详见:https://youzan.github.io/vant/#/zh-CN/image#chang-jian-wen-ti-->
<!--<van-grid-item v-for="item in menuList" :key="item.title" :icon="require('../assets/index/1.png')"-->
<!--:text="item.title" ></van-grid-item>-->
<!--3、使用该组件的icon插槽 详见:https://youzan.github.io/vant/#/zh-CN/grid#api-->
</van-grid>
</div>
<FooterBar></FooterBar>
</div>
</template>
<script>
// import indexImg10 from '../assets/index/10.png'
import indexImg1 from '../assets/index/1.png'
// import indexImg11 from '../assets/index/11.png'
import FooterBar from '@/components/FooterBar.vue'
export default {
name: "Home",
components: {
FooterBar
},
data() {
return {
menuList: [
// {img: indexImg10, title: '抽样任务', uri: '/sampling_task/sampling_task'},
{img: indexImg1, title: '温湿度登记', uri: '/register/register'},
// {img: indexImg11, title: '历史抽样单', uri: '/history_sampling/sampling_list'},
],
}
},
methods: {
_goto(item) {
this.$router.push(item.uri)
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="main-content-con">
<!--https://youzan.github.io/vant/#/zh-CN/nav-bar-->
<van-nav-bar :title="title"
:left-arrow="$route.meta.leftArrow!==false"
v-if="$route.meta.hideNavBar!==true"
@click-left="_back"></van-nav-bar>
<div class="main-layout-cont" :class="[{'main-layout-cont-hide-navbar':$route.meta.hideNavBar===true}]">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Index",
computed: {
title: {
get() {
let title = ''
if (this.$route.meta.customerNavBarTitle !== true) {
title = this.$route.meta.title
} else {
title = this.$route.query.title
}
return title
}
}
},
mounted() {
this._login()
},
methods: {
_login() {
if (this.$global.getToken) {
console.log('已登录')
} else {
//无权限的时候退出登录
this.$router.replace('/login');
}
},
_back() {
if (this.$route.meta.leftArrow !== false) {
this.$router.go(-1)
}
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="login-cont">
<div class="login-main">
<h1>欢迎登录</h1>
<van-form @submit="onSubmit">
<div class="field-input">
<van-field
v-model="formObj.username"
:left-icon="require('../assets/user.png')"
label-width="4.2em"
name="username"
label="用户名"
placeholder="请填写用户名"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<!--todo form表单回车提交-->
<van-field
v-model="formObj.password"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="password"
label="密码"
placeholder="请填写密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="forget-text">
<div>
<van-checkbox shape="square" v-model="checked" icon-size="18px">记住密码</van-checkbox>
</div>
<div @click="_forgetPwd">忘记密码?</div>
</div>
<div class="btn-box">
<van-button block type="info" native-type="submit">
立即登录
</van-button>
</div>
</van-form>
</div>
<confirm-dialog v-if="showPopup" title="请输入您的新密码" @confirm="_toLogin" @close="showPopup=false">
<van-field v-model="formObj.newPwd" label="密码" placeholder="请输入您的新密码"></van-field>
</confirm-dialog>
</div>
</template>
<script>
import {sso, sysUser} from '../api'
export default {
name: "Login",
data() {
return {
formObj: {
username: '',
password: '',
newPwd: ''
},
checked: false,
showPopup: false
}
},
mounted() {
this._inactivate()
},
methods: {
onSubmit(res) {
// console.log(res, 'login-info')
this._login(res)
},
_login: async function (res) {
let token = await sso.login(res)
if (token) {
console.log('token')
this.$global.setToken(token)
if (this.checked) {
localStorage.setItem('username', this.formObj.username);
if (localStorage.getItem('inactivate')) {
//第一次激活后保存密码
localStorage.setItem('password', this.formObj.newPwd);
} else {
//已经激活状态保存密码
localStorage.setItem('password', this.formObj.password);
}
} else {
localStorage.removeItem('username');
localStorage.removeItem('password');
}
this._getUserInfo();
} else {
console.log('_inactivate')
//激活
this._inactivate();
}
},
//获取用户信息
async _getUserInfo() {
console.log('_getUserInfo')
let user = await sysUser.getUserInfo();
if (user) {
this.$global.setUserInfo(user);
this.$router.replace('/home');
//todo 清空路由 报错问题 需要降低vue-router版本
// this.$navigation.cleanRoutes();
}
},
_forgetPwd() {
this.$router.push('/forget_pwd')
},
//激活
_inactivate() {
if (localStorage.getItem('inactivate') === 'inactivate') {
this.formObj.newPwd = ''
this.showPopup = true
}
},
_toLogin() {
if (this.formObj.newPwd === '') {
this.$toast('请输入新密码!');
return
}
let data = {
username: this.formObj.username,
password: this.formObj.newPwd
}
this._login(data)
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<van-field
v-model="content"
rows="5"
autosize
label="留言"
label-width="50px"
type="textarea"
maxlength="200"
placeholder="请输入您的宝贵建议与意见(200字以内)"
show-word-limit
></van-field>
<div style="height: 44px;width: 80%;margin: 20px auto 0">
<van-button block type="info" @click="_ok">保存</van-button>
</div>
</div>
</template>
<script>
import {advise} from '../../api'
export default {
name: "FeedBack",
data() {
return {
content: ''
}
},
methods: {
async _ok() {
if (this.content === '') {
this.$toast('请输入内容');
} else {
let result = await advise.advise({content: this.content})
if (result) {
this.content = '';
this.$toast.success('提交成功!您的意见我们会慎重考虑!')
setTimeout(() => {
this.$router.go(-1)
}, 2000)
}
}
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="personal-cont">
<div class="layout-cont">
<div class="personal-top-img">
<img src="@/assets/touxiang2.png" @click="_goto">
</div>
<div>
<van-cell-group>
<van-cell title="账号信息" icon="user-o" is-link to="/mine/user_info"></van-cell>
</van-cell-group>
</div>
<div style="margin-top: 10px">
<van-cell-group>
<van-cell title="服务热线:0532-67760070 / 13335043671" icon="phone-o"></van-cell>
</van-cell-group>
</div>
<div style="margin-top: 10px">
<van-cell-group>
<van-cell title="意见反馈" icon="edit" is-link to="/mine/feed_back"></van-cell>
</van-cell-group>
</div>
<div style="margin: 20px 20px 0">
<van-button block type="info" @click="_exit">
安全退出当前账户
</van-button>
</div>
</div>
<FooterBar></FooterBar>
</div>
</template>
<script>
import FooterBar from '@/components/FooterBar.vue'
export default {
name: "Mine",
components:{
FooterBar
},
methods: {
_goto() {
this.$router.push('/mine/user_info')
},
_exit() {
this.$global.logout();
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
<style scoped>
</style>
<template>
<div>
<div style="margin-top: 20px">
<van-cell title="用户名" :value="userInfo.username"></van-cell>
<van-cell title="真实姓名" :value="userInfo.realname"></van-cell>
<van-cell title="性别" :value="userInfo.sex==1?'女':'男'"></van-cell>
</div>
<div style="margin-top: 20px">
<van-cell title="所属部门" :value="userInfo.orgNames"></van-cell>
<van-cell title="所属角色" :value="userInfo.roleNames"></van-cell>
</div>
<div style="margin-top: 20px">
<van-cell title="手机号" :value="userInfo.mobile"></van-cell>
<van-cell title="个人邮箱" :value="userInfo.email"></van-cell>
<van-cell title="联系QQ" :value="userInfo.qq"></van-cell>
</div>
<div style="margin: 40px auto 0;width: 80%;">
<van-button icon="edit" block type="info" @click="_editPwd">修改密码</van-button>
</div>
</div>
</template>
<script>
import {sysUser} from '../../api'
export default {
data() {
return {
userInfo: {},
id: '',
}
},
mounted() {
this._getUserInfo()
},
methods: {
//跳转
_editPwd() {
this.$router.push('/mine/pwd_edit');
},
//用户信息
async _getUserInfo() {
//重新获取用户信息
let user = await sysUser.getUserInfo();
if (user) {
this.$global.setUserInfo(user);
this.userInfo = user;
this.id = user.id;
}
},
//退出
_exit() {
this.$global.logout();
// this.$navigation.cleanRoutes(); //清空路由了,但是浏览器中的路由仍在
this.$router.replace('/login')
},
}
}
</script>
<style scoped>
.header-top-title {
margin: 65px auto 10px auto;
text-align: center;
}
</style>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px;text-align: center">更改邮箱需要短信验证。</p>
<div class="phone_edit">
<group>
<x-input title="邮箱" v-model="email" placeholder="请输入邮箱" is-type="email"></x-input>
</group>
</div>
<div style="margin-top: 20px" class="login-exit" @click="_next">下一步</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group,
},
data() {
return {
title: '邮箱',
email: ''
}
},
methods: {
//获取验证码
_next() {
if (this.email) {
let myReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
if (myReg.test(this.email)) {
this._ok();
} else {
this._msg('邮箱填写错误');
}
} else {
this._msg('请输入邮箱');
}
},
_ok() {
let data = {
email: this.email,
};
this.$store.dispatch('SystemManage/getEmailCode', data).then(() => {
if (this.$store.state.SystemManage.success) {
this.$router.push({path: '/sys/email_sms', query: {email: this.email}});
} else {
this._msg('验证码发送失败');
}
});
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px">我们已经给您的邮箱<a> {{email}} </a>发送了一条验证码,请及时查看邮件。</p>
<div class="phone_edit">
<group>
<x-input placeholder="请输入验证码" v-model="code">
<span slot="right" v-show="selected" class="phone_vcode" @click="_getCode"><a>重新发送</a></span>
<span slot="right" v-show="!selected" class="phone_vcode">重新发送({{second}}s)</span>
</x-input>
</group>
</div>
<div style="margin-top: 20px;background: #ccc" class="login-exit" v-show="!code">完成</div>
<div style="margin-top: 20px" class="login-exit" @click="_ok" v-show="code">完成</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group
},
data() {
return {
title: '请输入验证码',
code: '',
email: '',
second: 59,
selected: false,
id: '',
obj: {}
}
},
mounted() {
this._getQuery();
},
methods: {
_getQuery() {
this.email = this.$route.query.email;
this.obj = JSON.parse(localStorage.getItem('fLoginUser'));
this.id = this.obj.id;
this.selected = false;
this.second = 59;
this._count();
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
//完成
_ok() {
this.$store.dispatch('SystemManage/bindEmail', {code: this.code}).then(() => {
if (this.$store.state.SystemManage.model) {
this._msg('修改成功');
this.$router.go(-2);
}
});
},
//发送验证码
_getCode() {
this.selected = false;
this.second = 59;
let data = {
email: this.email,
};
this.$store.dispatch('SystemManage/getEmailCode', data).then(() => {
if (this.$store.state.SystemManage.success) {
this._count();
} else {
this._msg('验证码发送失败');
}
});
},
//计数
_count() {
let second = this.second;
if (second === 0) {
this.selected = true;
this.second = 59;
return;
}
setTimeout(() => {
this.second = second - 1;
this._count();
}, 1000)
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px;text-align: center">更改手机号码需要短信验证。</p>
<div class="phone_edit">
<group>
<x-input title="+86" v-model="mobile" :max="11" is-type="china-mobile" keyboard="number"
placeholder="请输入手机号"></x-input>
</group>
</div>
<div style="margin-top: 20px" class="login-exit" @click="_next">下一步</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group,
},
name: "phone-edit",
data() {
return {
title: '手机号码',
mobile: ''
}
},
methods: {
//获取验证码
_next() {
if (this.mobile) {
let myReg = /^1\d{10}$/;
if (myReg.test(this.mobile)) {
this._ok();
} else {
this._msg('号码填写错误');
}
} else {
this._msg('请输入手机号');
}
},
_ok() {
let data = {
mobile: this.mobile,
module: 'bindChangeMobile'
};
this.$store.dispatch('SystemManage/getCode', data).then(() => {
if (this.$store.state.SystemManage.model) {
this.$router.push({path: '/sys/sms', query: {mobile: this.mobile}});
} else {
this._msg('验证码发送失败');
}
});
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px">我们已经给您的手机号<a> +86 {{mobile}} </a>发送了一条验证短信,请及时查看。</p>
<div class="phone_edit">
<group>
<x-input placeholder="请输入短信验证码" v-model="code">
<span slot="right" v-show="selected" class="phone_vcode" @click="_getCode"><a>重新发送</a></span>
<span slot="right" v-show="!selected" class="phone_vcode">重新发送({{second}}s)</span>
</x-input>
</group>
</div>
<div style="margin-top: 20px;background: #ccc" class="login-exit" v-show="!code">完成</div>
<div style="margin-top: 20px" class="login-exit" @click="_ok" v-show="code">完成</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group
},
name: "sms",
data() {
return {
title: '请输入短信验证码',
code: '',
mobile: '',
second: 59,
selected: false
}
},
mounted() {
this._getQuery();
},
methods: {
_getQuery() {
this.mobile = this.$route.query.mobile;
this.selected = false;
this.second = 59;
this._count();
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
//完成
_ok() {
this.$store.dispatch('SystemManage/changeBindMobile', this.code).then(() => {
if (this.$store.state.SystemManage.model) {
this._msg('修改成功');
this.$router.go(-2);
}
});
},
//发送验证码
_getCode() {
this.selected = false;
this.second = 59;
let data = {
mobile: this.mobile,
module: 'bindChangeMobile'
};
this.$store.dispatch('SystemManage/getCode', data).then(() => {
if (this.$store.state.SystemManage.model) {
this._count();
} else {
this._msg('验证码发送失败');
}
});
},
//计数
_count() {
let second = this.second;
if (second === 0) {
this.selected = true;
this.second = 59;
return;
}
setTimeout(() => {
this.second = second - 1;
this._count();
}, 1000)
},
}
}
</script>
<template>
<div>
<van-form @submit="onSubmit">
<div style="margin-top: 20px">
<van-field v-model="oldPwd" label="旧密码" placeholder="请输入旧密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin-top: 20px">
<van-field v-model="newPwd" label="新密码" placeholder="请输入新密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin-top: 20px">
<van-field v-model="newPwds" label="确认密码" placeholder="请确认密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin: 40px 16px;">
<van-button block type="info" native-type="submit">
保存
</van-button>
</div>
</van-form>
</div>
</template>
<script>
import {sysUser} from '@/api'
export default {
name: "pwd-edit",
data() {
return {
title: '修改密码',
oldPwd: '',
newPwd: '',
newPwds: '',
}
},
methods: {
onSubmit() {
if (this.newPwds !== this.newPwd) {
this.$toast('两次填写的密码不一致');
} else {
this._save()
}
},
_save: async function () {
let data = {
oldPwd: this.oldPwd,
newPwd: this.newPwd
};
let result = await sysUser.editPsd(data)
if (result) {
let that = this;
this.$dialog.confirm({
title: '提示',
message: '登录密码已被修改,请重新登录!',
}).then(() => {
that._exit(); //退出重新登录
}).catch(() => {
// on cancel
});
}
},
//退出
_exit() {
this.$global.logout();
localStorage.removeItem('password'); //清空密码
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
<template>
<div>
<!--标题-->
<div class="top-bar">
<div @click="_back">
<img src="../../../../static/image/back.png">
</div>
<div>{{title}}</div>
<div @click="_save">完成</div>
</div>
<!--提示信息-->
<div class="result-cont" style="margin-top: 60px">
<div class="phone_edit">
<group>
<x-input title="联系QQ" v-model="qq" placeholder="请输入联系QQ"></x-input>
</group>
</div>
</div>
</div>
</template>
<script>
import {XInput, Group} from 'vux'
import Global from '../../../api/config'
export default {
components: {
XInput,
Group,
},
data() {
return {
title: '修改联系QQ',
id: this.$route.query.id,
qq: this.$route.query.data.qq,
}
},
methods: {
//保存信息
_save() {
if (this.qq) {
let data = {
qq: this.qq
};
this.$store.dispatch('SystemManage/userEdit', {id: this.id, obj: data}).then(() => {
if (this.$store.state.SystemManage.success) {
this._back();
}
});
} else {
this._msg('QQ不能为空!');
}
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
_back() {
this.$router.go(-1);
},
}
}
</script>
<template>
<div>
<!--标题-->
<div class="top-bar">
<div @click="_back">
<img src="../../../../static/image/back.png">
</div>
<div>{{title}}</div>
<div @click="_save">完成</div>
</div>
<!--提示信息-->
<div class="result-cont" style="margin-top: 60px">
<div class="phone_edit">
<group>
<x-input title="真实姓名" v-model="realname" placeholder="请输入真实姓名"></x-input>
</group>
</div>
</div>
</div>
</template>
<script>
import {XInput, Group} from 'vux'
import Global from '../../../api/config'
export default {
components: {
XInput,
Group,
},
data() {
return {
title: '修改真实姓名',
id: this.$route.query.id,
realname: this.$route.query.data.realname,
}
},
methods: {
//保存信息
_save() {
if (this.realname) {
let data = {
realname: this.realname
};
this.$store.dispatch('SystemManage/userEdit', {id: this.id, obj: data}).then(() => {
if (this.$store.state.SystemManage.success) {
this._back();
}
});
} else {
this._msg('真实姓名不能为空!');
}
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
_back() {
this.$router.go(-1);
},
}
}
</script>
<template>
<div>
<!--标题-->
<div class="top-bar">
<div @click="_back">
<img src="../../../../static/image/back.png">
</div>
<div>{{title}}</div>
<div @click="_save">完成</div>
</div>
<!--提示信息-->
<div class="result-cont" style="margin-top: 60px">
<div class="phone_edit">
<group>
<x-input title="用户名" v-model="username" placeholder="请输入用户名称"></x-input>
</group>
</div>
</div>
</div>
</template>
<script>
import {XInput, Group} from 'vux'
import Global from '../../../api/config'
export default {
components: {
XInput,
Group,
},
data() {
return {
title: '修改用户名',
id: this.$route.query.id,
username: this.$route.query.data.username,
}
},
methods: {
_ok() {
let that = this;
this.$vux.confirm.show({
title: '提示',
content: '用户名已被修改成 ' + this.username + ' ,请重新登录!',
theme: 'ios',
showCancelButton: false,
onConfirm() {
that._exit(); //退出重新登录
}
});
},
//保存信息
_save() {
if (this.username) {
let data = {
username: this.username
};
this.$store.dispatch('SystemManage/userEdit', {id: this.id, obj: data}).then(() => {
if (this.$store.state.SystemManage.success) {
this._ok();
}
});
} else {
this._msg('用户名不能为空!');
}
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
//退出
_exit() {
Global.logout();
localStorage.setItem('username', this.username); //设置用户名
this.$navigation.cleanRoutes(); //清空路由了,但是浏览器中的路由仍在
this.$router.replace('/login');
},
_back() {
this.$router.go(-1);
},
}
}
</script>
<template>
<customer-navBar-layout>
<template #navBar>
<van-nav-bar v-if="showCheck"
:title="$route.meta.title"
right-text="取消"
left-arrow
@click-left="_back"
@click-right="_hideCheck">
</van-nav-bar>
<van-nav-bar
v-else
:title="$route.meta.title"
right-text="添加"
left-arrow
@click-left="_back"
@click-right="_add"
></van-nav-bar>
</template>
<template #content>
<search-bar label="位置" ref="searchBar"
highSearch @search="_search" @high-search="_highSearch"
@clear-high="_clearHigh">
<template #highSearch>
<van-field v-model="formObj.location" label="位置" placeholder="请输入位置" clearable></van-field>
<datetime-field label="监测开始日期" v-model="formObj.startDate"></datetime-field>
<datetime-field label="监测结束日期" v-model="formObj.endDate"></datetime-field>
</template>
</search-bar>
<div class="layout-cont-sh" :class="{'layout-cont-sh-btn':showCheck}">
<!--下拉刷新 https://vant-contrib.gitee.io/vant/#/zh-CN/pull-refresh-->
<van-pull-refresh v-model="refreshing" @refresh="_refresh">
<!--上拉加载 https://vant-contrib.gitee.io/vant/#/zh-CN/list-->
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="_load">
<van-checkbox-group v-model="checkListValue" ref="checkboxGroup">
<van-swipe-cell v-for="item in resultList" :key="item.id">
<div class="result-item" @click="_tapItem(item)" v-touch:longtap="_longtapHandler">
<!--<div style="width: 100%;display: flex;justify-content: space-between;border-bottom: 1px solid #eeeeee">-->
<div style="display: flex">
<div style="margin-right: 20px" v-if="showCheck">
<van-checkbox :name="item.id" shape="square"></van-checkbox>
</div>
<div>位置:{{item.location}}</div>
</div>
<!--<div @click.stop="_goFile(item.id)">-->
<!--<img src="../../assets/file-nav.png" style="width: 20px">-->
<!--</div>-->
<!--</div>-->
<div>相对湿度(%):{{item.humidity}}</div>
<div>温度(℃):{{item.temperature}}</div>
<div>设备编号:{{item.equipNum}}</div>
<div>监测日期:{{$dateformat(item.monitorDate,'yyyy-mm-dd')}}</div>
<div>记录人:{{item.recorderName}}</div>
</div>
<template #right>
<van-button square type="info" text="编辑" class="swipe-cell-btn"
@click="_edit(item)"></van-button>
<van-button square type="danger" text="删除" class="swipe-cell-btn"
@click="_del([item.id])"></van-button>
<!--<van-button square type="default" text="操作日志" class="swipe-cell-btn"-->
<!--@click="_records(item)"></van-button>-->
</template>
</van-swipe-cell>
</van-checkbox-group>
</van-list>
</van-pull-refresh>
</div>
<div class="bottom-btn bottom-btn-two" v-if="showCheck">
<van-button square @click="_checkAll">{{checkAll?'取消全选':'全选'}}</van-button>
<van-button square type="danger" @click="_del(checkListValue)">删除</van-button>
</div>
</template>
</customer-navBar-layout>
</template>
<script>
import {envMonitor} from '../../api'
export default {
data() {
return {
formObj: {
location: '',
startDate: '',
endDate: '',
},
key: '',
showPopup: true,
showCheck: false,
checkListValue: [],
resultList: [],
page: 1,
rows: 10,
refreshing: false,//刷新中...
loading: false,//加载中...
finished: false,//没有更多数据
planId: this.$route.query.planId
}
},
watch: {
checkListValue: function (oldVal, newVal) {
console.log(oldVal, newVal)
}
},
computed: {
checkAll: function () {
if (this.resultList.length) {
return this.checkListValue.length === this.resultList.length;
} else {
return false
}
}
},
mounted() {
this._getData()
},
methods: {
//简单查询 清空高级查询条件 赋值简单查询数据
_search(value) {
this.key = value
this.formObj = this.$resetFields(this.formObj)
this._refresh()
},
//高级搜索 清空key 查询
_highSearch() {
this.key = ''
this.$refs.searchBar._hideHighSearch()
this._refresh()
},
_clearHigh() {
this.formObj = this.$resetFields(this.formObj)
},
_searchParams() {
let data = {
page: this.page,
rows: this.rows,
...this.formObj
};
if (this.key) {
data.location = this.key
}
return this.$serializeForm(data)
},
_getData: async function () {
let result = await envMonitor.page(this._searchParams())
this.resultList = [...(this.page === 1 ? [] : this.resultList), ...result.records]
this.refreshing = false
this.loading = false
if (this.resultList.length === result.total) {
this.finished = true
}
},
_refresh() {
this.page = 1;
this._getData()
},
_load() {
this.page = this.page + 1;
this._getData()
},
_back() {
this.$router.go(-1)
},
_add() {
this.$router.push({path: '/register/register_add', query: {title: '温湿度添加'}})
},
_longtapHandler() {
this.showCheck = true
},
_hideCheck() {
this.showCheck = false
this.checkListValue = []
},
_checkAll() {
if (this.checkAll) {
this.$refs.checkboxGroup.toggleAll();
} else {
this.$refs.checkboxGroup.toggleAll(true);
}
},
_tapItem(item) {
if (this.showCheck) {
if (this.checkListValue.indexOf(item.id) === -1) {
this.checkListValue.push(item.id);
} else {
this.checkListValue.splice(this.checkListValue.indexOf(item.id), 1);
}
}
},
_edit({id}) {
this.$router.push({path: '/register/register_add', query: {id: id, title: '温湿度编辑'}})
},
_del(ids) {
if (ids.length === 0) {
this.$toast('请至少选择一条数据!')
} else {
this._delOk(ids)
}
},
_delOk: async function (ids) {
let result = await envMonitor.deleteByIds(ids)
if (result) {
this.$toast('操作成功!')
this._refresh()
}
},
_records({id}) {
this.$router.push({path: '/register/register_records', query: {id: id}})
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<van-form @submit="onSubmit">
<van-field
v-model="formObj.location"
name="location"
label="位置"
placeholder="位置"
:rules="[{ required: true, message: '请填写位置'}]"
></van-field>
<van-field
v-model="formObj.humidity"
name="humidity"
label="相对湿度(%)"
placeholder="相对湿度(%)"
:rules="[{ required: true, message: '请填写相对湿度(%)'}]"
></van-field>
<van-field
v-model="formObj.temperature"
name="temperature"
label="温度(℃)"
placeholder="温度(℃)"
:rules="[{ required: true, message: '请填写温度(℃)'}]"
></van-field>
<van-field
v-model="formObj.equipNum"
name="equipNum"
label="设备编号"
placeholder="设备编号"
></van-field>
<van-field
v-model="formObj.monitorDate"
name="monitorDate"
label="监测日期"
placeholder="监测日期"
@click="_selectDate('formObj.monitorDate')"
></van-field>
<div style="margin: 16px;">
<van-button round block type="info" native-type="submit">
保存
</van-button>
</div>
</van-form>
<van-popup v-model="showDatePicker" position="bottom"
:safe-area-inset-bottom="true"
:close-on-popstate="true">
<van-datetime-picker
type="date"
v-model="currentDate"
@confirm="_dateConfirm"
@cancel="showDatePicker = false"
></van-datetime-picker>
</van-popup>
</div>
</template>
<script>
import {envMonitor} from '../../api'
export default {
data() {
return {
showDatePicker: false,
currentDate: new Date(),
selectDateType: '',
id: '',
formObj: {
location: '',
humidity: '',
temperature: '',
equipNum: '',
monitorDate: '',
}
}
},
mounted() {
this._open()
},
methods: {
_open() {
if (this.$route.query.id) {//编辑
this.id = this.$route.query.id
this._getData()
} else {
this.id = ''
}
},
_getData: async function () {
let result = await envMonitor.getById(this.id)
if (result) {
for (let key in this.formObj) {
if (result[key]) {
if (key === 'monitorDate') {
this.formObj[key] = this.$dateformat(result[key], 'yyyy-mm-dd')
} else {
this.formObj[key] = result[key]
}
}
}
}
},
onSubmit(res) {
if (this.id) {
this._editSave(res)
} else {
this._addSave(res)
}
},
_editSave: async function (res) {
res.type = 0
let result = await envMonitor.edit({id: this.id, obj: res})
if (result) {
this.$toast('编辑成功!')
this.$router.go(-1)
}
},
_addSave: async function (res) {
res.type = 0
let result = await envMonitor.add(res)
if (result) {
this.$toast('添加成功!')
this.$router.go(-1)
}
},
_selectDate(type) {
this.selectDateType = type
this.showDatePicker = true
},
_dateConfirm(date) {
switch (this.selectDateType) {
case 'formObj.monitorDate':
this.formObj.monitorDate = this.$dateformat(date, 'yyyy-mm-dd')
break
}
this.showDatePicker = false
},
}
}
</script>
<style scoped>
</style>
<template>
<div>
<search-bar label="操作原因"
ref="searchBar"
@search="_search">
</search-bar>
<div class="layout-cont-s">
<!--下拉刷新 https://vant-contrib.gitee.io/vant/#/zh-CN/pull-refresh-->
<van-pull-refresh v-model="refreshing" @refresh="_refresh">
<!--上拉加载 https://vant-contrib.gitee.io/vant/#/zh-CN/list-->
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="_load">
<div class="result-item" v-for="item in resultList" :key="item.name">
<div>操作类型:{{item.type===1?'流转':item.type===2?'退回':item.type===3?'更新':''}}</div>
<div>操作人:{{item.operator}}</div>
<div>操作时间:{{$dateformat(item.ctime,'yyyy-mm-dd')}}</div>
<div>责任人:{{item.liable}}</div>
<div style="width: 100%;">操作原因:{{item.remark}}</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</div>
</template>
<script>
import {envMonitorRecord} from '../../api'
export default {
components: {},
data() {
return {
formObj: {
monitorId:''
},
key: '',
resultList: [],
page: 1,
rows: 10,
refreshing: false,//刷新中...
loading: false,//加载中...
finished: false,//没有更多数据
}
},
mounted() {
this.formObj.monitorId = this.$route.query.id
this._getData()
},
methods: {
//简单查询 清空高级查询条件 赋值简单查询数据
_search(value) {
this.key = value
this.formObj = this.$resetFields(this.formObj)
this._refresh()
},
_searchParams() {
let data = {
page: this.page,
rows: this.rows,
...this.formObj
};
if (this.key) {
data.remark = this.key
}
return this.$serializeForm(data)
},
_getData: async function () {
let result = await envMonitorRecord.page(this._searchParams())
this.resultList = [...(this.page === 1 ? [] : this.resultList), ...result.records]
this.refreshing = false
this.loading = false
if (this.resultList.length === result.total) {
this.finished = true
}
},
_refresh() {
this.page = 1;
this._getData()
},
_load() {
this.page = this.page + 1;
this._getData()
},
}
}
</script>
<style scoped>
</style>
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
import global from '@/api/config'
Vue.use(VueRouter)
const router = new VueRouter({
routes // (缩写) 相当于 routes: routes
})
router.beforeEach((to, _from, next) => {
if(to.path === '/login'){
next()
}else{
if(global.getToken()){
next()
}else{
next({path: '/login'})
}
}
})
router.afterEach(() => {
// console.log(to, from)
// LoadingBar.finish();
})
export default router
import Mine from '@/page/mine/Mine.vue'
import FeedBack from '@/page/mine/FeedBack.vue'
import UserInfo from '@/page/mine/UserInfo.vue'
import PwdEdit from '@/page/mine/psd/PwdEdit.vue'
export default [
{
path: "mine",
name: "mine",
component: Mine,
meta: {title: "个人中心", leftArrow: false},
},
{
path: "feed_back",
name: "feedBack",
component: FeedBack,
meta: {title: "意见反馈"},
},
{
path: "user_info",
name: "userInfo",
component: UserInfo,
meta: {title: "个人信息"},
},
{
path: "pwd_edit",
name: "pwdEdit",
component: PwdEdit,
meta: {title: "修改密码"},
},
]
import Register from '@/page/register/Register.vue'
import RegisterAdd from '@/page/register/RegisterAdd.vue'
import RegisterRecords from '@/page/register/RegisterRecords.vue'
export default [
{path: 'register', component: Register, meta: {title: '温湿度登记', hideNavBar: true}},
{path: 'register_add', component: RegisterAdd, meta: {customerNavBarTitle: true}},
{path: 'register_records', component: RegisterRecords, meta: {title: '温湿度操作记录'}},
]
import Index from '@/page/Index'
import Home from '@/page/Home'
import Login from '@/page/Login'
import ForgetPwd from '@/page/ForgetPwd'
import RegisterRoutes from './register-routes'
import MineRoutes from './mine-routes'
import DebugComponent from '@/components/DebugComponent.vue'
export default [
{
path: '/', component: Index, redirect: '/home', children: [
{
path: "/home",
name: "home",
component: Home,
meta: {title: "温湿度", leftArrow: false},
},
{
path: "/login",
name: "login",
component: Login,
meta: {title: "登录", hideNavBar: true},
}, {
path: "/forget_pwd",
name: "forgetPwd",
component: ForgetPwd,
meta: {title: "找回密码", hideNavBar: true},
},{
path: "/debug",
name: "debug",
component: DebugComponent,
meta: {title: "调试组件页面", hideNavBar: true},
},
],
}, {
path: '/mine',
component: Index,
children: MineRoutes,
mata: {title: '个人中心'}
},{
path: '/register',
component: Index,
children: RegisterRoutes,
mata: {title: '温湿度登记'}
},
]
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
export default store
@background-color-gray: #f7f8fa;
@background-color-white: #ffffff;
@background-color-blue: #1989fa;
@background-color-cs: bisque;
@border-color: #eeeeee;
@border-color-black: #000000;
@text-color-blue: #1989fa;
@text-color-black: #323233;
@text-color-white: #ffffff;
* {
box-sizing: border-box;
}
p, h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 0;
}
html, body, #app, .main-content-con {
width: 100%;
height: 100%;
overflow: hidden;
color: @text-color-black;
}
.main-layout-cont {
width: 100%;
height: calc(100% - 46px);
overflow: hidden;
background: @background-color-gray;
> div {
width: 100%;
height: 100%;
}
}
.main-layout-cont-hide-navbar {
width: 100%;
height: 100%;
}
//主要内容 不包括navbar searchbar
.layout-cont {
width: 100%;
height: calc(100% - 50px);
}
//有底部按钮
.layout-cont-btn {
width: 100%;
height: calc(100% - 44px);
}
//有search 54
.layout-cont-s {
width: 100%;
height: calc(100% - 54px);
margin-top: 54px;
overflow: auto;
}
//有search 54 底部按钮 44
.layout-cont-s-btn {
width: 100%;
height: calc(100% - 54px - 44px);
overflow: auto;
}
//有search 54、高级搜索 31
.layout-cont-sh {
width: 100%;
height: calc(100% - 54px - 31px);
margin-top: 85px;
overflow: auto;
}
//有search 54、高级搜索31 还有底部按钮 44
.layout-cont-sh-btn {
height: calc(100% - 54px - 31px - 44px);
}
.home-cont {
padding: 10px 0;
}
.bottom-btn {
width: 100%;
height: 44px;
}
.bottom-btn-two {
> button {
width: 50%
}
}
.personal-cont {
.personal-top-img {
width: 100%;
height: 150px;
background: url("../assets/banner.png") no-repeat;
background-size: 100% 100%;
margin-bottom: 10px;
text-align: center;
img {
width: 65px;
height: 65px;
border-radius: 50%;
margin-top: 60px;
}
}
}
.login-cont {
background: url("../assets/background.png") no-repeat;
background-size: 100% 100%;
.login-main {
width: 80%;
height: 280px;
position: fixed;
top: 50%;
left: 50%;
margin-top: -180px; //居中是height/2=140px
margin-left: -40%;
> h1 {
text-align: center;
letter-spacing: 5px;
margin-bottom: 20px;
color: @text-color-white;
}
.field-input {
background: #ffffff;
border-radius: 5px;
padding: 0 5px;
.van-cell {
padding-left: 5px;
padding-right: 5px;
}
}
.field-input + .field-input {
margin-top: 20px;
}
.forget-text {
padding: 10px 0;
text-align: right;
font-size: 12px;
color: @text-color-white;
display: flex;
justify-content: space-around;
> div {
width: 50%;
}
}
.btn-box {
margin: 10px 0;
}
.van-checkbox__icon {
background: @background-color-white;
}
.van-checkbox__label {
color: @text-color-white;
}
}
.login-main-forget {
height: 420px;
margin-top: -240px;
.logo-text {
text-align: center;
margin-bottom: 20px;
}
}
}
.result-item {
width: 100%;
height: auto;
background: @background-color-white;
margin-top: 10px;
padding: 10px 0;
border-top: 1px solid @border-color;
border-bottom: 1px solid @border-color;
font-size: 12px;
display: flex;
flex-wrap: wrap;
> div {
width: 50%;
padding: 0 10px;
line-height: 24px;
}
}
.swipe-cell-btn {
height: 100%;
}
.popup-cont-btn {
width: 100%;
height: calc(100% - 44px);
}
.popup-shelves {
> div {
width: 100%;
padding: 10px;
&:first-child {
p {
margin-bottom: 10px;
}
}
&:last-child {
width: 100%;
height: calc(100% - 90px);
}
}
}
/*search-bar begin */
.search-bar-box {
position: relative !important;
top: 0px !important;
}
.search-bar-box-fixed-top {
position: fixed;
width: 100%;
top: 45px;
z-index: 1;
}
.high-search-text {
border-top: 1px solid @border-color;
border-bottom: 1px solid @border-color;
text-align: center;
color: @text-color-blue;
background: @background-color-white;
line-height: 30px;
}
.high-search-cont {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 1;
background: @background-color-gray;
.btn-box {
margin: 10px 20px;
}
}
/*search-bar end*/
.van-nav-bar {
background: @background-color-blue;
.van-icon-arrow-left::before, .van-nav-bar__title, .van-nav-bar__text {
color: @text-color-white;
}
}
// Color Palette
@black: #000;
@white: #fff;
@gray-1: #f7f8fa;
@gray-2: #f2f3f5;
@gray-3: #ebedf0;
@gray-4: #dcdee0;
@gray-5: #c8c9cc;
@gray-6: #969799;
@gray-7: #646566;
@gray-8: #323233;
@red: #ee0a24;
@blue: #1989fa;
@orange: #ff976a;
@orange-dark: #ed6a0c;
@orange-light: #fffbe8;
@green: #07c160;
// Gradient Colors
@gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
@gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
// Component Colors
@text-color: @gray-8;
@active-color: @gray-2;
@active-opacity: 0.7;
@disabled-opacity: 0.5;
@background-color: @gray-1;
@background-color-light: #fafafa;
@text-link-color: #576b95;
// Padding
@padding-base: 4px;
@padding-xs: @padding-base * 2;
@padding-sm: @padding-base * 3;
@padding-md: @padding-base * 4;
@padding-lg: @padding-base * 6;
@padding-xl: @padding-base * 8;
// Font
@font-size-xs: 10px;
@font-size-sm: 12px;
@font-size-md: 14px;
@font-size-lg: 16px;
@font-weight-bold: 500;
@line-height-xs: 14px;
@line-height-sm: 18px;
@line-height-md: 20px;
@line-height-lg: 22px;
@base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB',
'Microsoft Yahei', sans-serif;
@price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial,
sans-serif;
// Animation
@animation-duration-base: 0.3s;
@animation-duration-fast: 0.2s;
@animation-timing-function-enter: ease-out;
@animation-timing-function-leave: ease-in;
// Border
@border-color: @gray-3;
@border-width-base: 1px;
@border-radius-sm: 2px;
@border-radius-md: 4px;
@border-radius-lg: 8px;
@border-radius-max: 999px;
// ActionSheet
@action-sheet-max-height: 80%;
@action-sheet-header-height: 48px;
@action-sheet-header-font-size: @font-size-lg;
@action-sheet-description-color: @gray-6;
@action-sheet-description-font-size: @font-size-md;
@action-sheet-description-line-height: @line-height-md;
@action-sheet-item-background: @white;
@action-sheet-item-font-size: @font-size-lg;
@action-sheet-item-line-height: @line-height-lg;
@action-sheet-item-text-color: @text-color;
@action-sheet-item-disabled-text-color: @gray-5;
@action-sheet-subname-color: @gray-6;
@action-sheet-subname-font-size: @font-size-sm;
@action-sheet-subname-line-height: @line-height-sm;
@action-sheet-close-icon-size: 22px;
@action-sheet-close-icon-color: @gray-5;
@action-sheet-close-icon-active-color: @gray-6;
@action-sheet-close-icon-padding: 0 @padding-md;
@action-sheet-cancel-text-color: @gray-7;
@action-sheet-cancel-padding-top: @padding-xs;
@action-sheet-cancel-padding-color: @background-color;
@action-sheet-loading-icon-size: 22px;
// AddressEdit
@address-edit-padding: @padding-sm;
@address-edit-buttons-padding: @padding-xl @padding-base;
@address-edit-button-margin-bottom: @padding-sm;
@address-edit-detail-finish-color: @blue;
@address-edit-detail-finish-font-size: @font-size-sm;
// AddressList
@address-list-padding: @padding-sm @padding-sm 80px;
@address-list-disabled-text-color: @gray-6;
@address-list-disabled-text-padding: @padding-base * 5 0 @padding-md;
@address-list-disabled-text-font-size: @font-size-md;
@address-list-disabled-text-line-height: @line-height-md;
@address-list-add-button-z-index: 999;
@address-list-item-padding: @padding-sm;
@address-list-item-text-color: @text-color;
@address-list-item-disabled-text-color: @gray-5;
@address-list-item-font-size: 13px;
@address-list-item-line-height: @line-height-sm;
@address-list-item-radio-icon-color: @red;
@address-list-edit-icon-size: 20px;
// Button
@button-mini-height: 24px;
@button-mini-font-size: @font-size-xs;
@button-small-height: 32px;
@button-small-font-size: @font-size-sm;
@button-normal-font-size: @font-size-md;
@button-large-height: 50px;
@button-default-height: 44px;
@button-default-line-height: 1.2;
@button-default-font-size: @font-size-lg;
@button-default-color: @text-color;
@button-default-background-color: @white;
@button-default-border-color: @border-color;
@button-primary-color: @white;
@button-primary-background-color: @green;
@button-primary-border-color: @green;
@button-info-color: @white;
@button-info-background-color: @blue;
@button-info-border-color: @blue;
@button-danger-color: @white;
@button-danger-background-color: @red;
@button-danger-border-color: @red;
@button-warning-color: @white;
@button-warning-background-color: @orange;
@button-warning-border-color: @orange;
@button-border-width: @border-width-base;
@button-border-radius: @border-radius-sm;
@button-round-border-radius: @border-radius-max;
@button-plain-background-color: @white;
@button-disabled-opacity: @disabled-opacity;
// Calendar
@calendar-background-color: @white;
@calendar-popup-height: 80%;
@calendar-header-box-shadow: 0 2px 10px rgba(125, 126, 128, 0.16);
@calendar-header-title-height: 44px;
@calendar-header-title-font-size: @font-size-lg;
@calendar-header-subtitle-font-size: @font-size-md;
@calendar-weekdays-height: 30px;
@calendar-weekdays-font-size: @font-size-sm;
@calendar-month-title-font-size: @font-size-md;
@calendar-month-mark-color: fade(@gray-2, 80%);
@calendar-month-mark-font-size: 160px;
@calendar-day-height: 64px;
@calendar-day-font-size: @font-size-lg;
@calendar-range-edge-color: @white;
@calendar-range-edge-background-color: @red;
@calendar-range-middle-color: @red;
@calendar-range-middle-background-opacity: 0.1;
@calendar-selected-day-size: 54px;
@calendar-selected-day-color: @white;
@calendar-info-font-size: @font-size-xs;
@calendar-info-line-height: @line-height-xs;
@calendar-selected-day-background-color: @red;
@calendar-day-disabled-color: @gray-5;
@calendar-confirm-button-height: 36px;
@calendar-confirm-button-margin: 7px 0;
// Card
@card-padding: @padding-xs @padding-md;
@card-font-size: @font-size-sm;
@card-text-color: @text-color;
@card-background-color: @background-color-light;
@card-thumb-size: 88px;
@card-thumb-border-radius: @border-radius-lg;
@card-title-line-height: 16px;
@card-desc-color: @gray-7;
@card-desc-line-height: @line-height-md;
@card-price-color: @gray-8;
@card-origin-price-color: @gray-6;
@card-num-color: @gray-6;
@card-origin-price-font-size: @font-size-xs;
@card-price-font-size: @font-size-sm;
@card-price-integer-font-size: @font-size-lg;
@card-price-font-family: @price-integer-font-family;
// Cell
@cell-font-size: @font-size-md;
@cell-line-height: 24px;
@cell-vertical-padding: 10px;
@cell-horizontal-padding: @padding-md;
@cell-text-color: @text-color;
@cell-background-color: @white;
@cell-border-color: @border-color;
@cell-active-color: @active-color;
@cell-required-color: @red;
@cell-label-color: @gray-6;
@cell-label-font-size: @font-size-sm;
@cell-label-line-height: @line-height-sm;
@cell-label-margin-top: @padding-base;
@cell-value-color: @gray-6;
@cell-icon-size: 16px;
@cell-right-icon-color: @gray-6;
@cell-large-vertical-padding: @padding-sm;
@cell-large-title-font-size: @font-size-lg;
@cell-large-label-font-size: @font-size-md;
// CellGroup
@cell-group-background-color: @white;
@cell-group-title-color: @gray-6;
@cell-group-title-padding: @padding-md @padding-md @padding-xs;
@cell-group-title-font-size: @font-size-md;
@cell-group-title-line-height: 16px;
// Checkbox
@checkbox-size: 20px;
@checkbox-border-color: @gray-5;
@checkbox-transition-duration: @animation-duration-fast;
@checkbox-label-margin: @padding-xs;
@checkbox-label-color: @text-color;
@checkbox-checked-icon-color: @blue;
@checkbox-disabled-icon-color: @gray-5;
@checkbox-disabled-label-color: @gray-5;
@checkbox-disabled-background-color: @border-color;
// Circle
@circle-text-color: @text-color;
@circle-text-font-weight: @font-weight-bold;
@circle-text-font-size: @font-size-md;
@circle-text-line-height: @line-height-md;
// Collapse
@collapse-item-transition-duration: @animation-duration-base;
@collapse-item-content-padding: @padding-sm @padding-md;
@collapse-item-content-font-size: @font-size-md;
@collapse-item-content-line-height: 1.5;
@collapse-item-content-text-color: @gray-6;
@collapse-item-content-background-color: @white;
@collapse-item-title-disabled-color: @gray-5;
// ContactCard
@contact-card-padding: @padding-md;
@contact-card-add-icon-size: 40px;
@contact-card-add-icon-color: @blue;
@contact-card-value-line-height: @line-height-md;
// ContactEdit
@contact-edit-padding: @padding-md;
@contact-edit-fields-radius: @border-radius-md;
@contact-edit-buttons-padding: @padding-xl 0;
@contact-edit-button-margin-bottom: @padding-sm;
@contact-edit-button-font-size: 16px;
@contact-edit-field-label-width: 4.1em;
// ContactList
@contact-list-edit-icon-size: 16px;
@contact-list-add-button-z-index: 999;
@contact-list-item-padding: @padding-md;
// CountDown
@count-down-text-color: @text-color;
@count-down-font-size: @font-size-md;
@count-down-line-height: @line-height-md;
// Coupon
@coupon-margin: 0 @padding-sm @padding-sm;
@coupon-content-height: 84px;
@coupon-content-padding: 14px 0;
@coupon-background-color: @white;
@coupon-active-background-color: @active-color;
@coupon-border-radius: @border-radius-lg;
@coupon-box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
@coupon-head-width: 96px;
@coupon-amount-color: @red;
@coupon-amount-font-size: 30px;
@coupon-currency-font-size: 40%;
@coupon-name-font-size: @font-size-md;
@coupon-disabled-text-color: @gray-6;
@coupon-description-padding: @padding-xs @padding-md;
@coupon-description-border-color: @border-color;
// CouponCell
@coupon-cell-selected-text-color: @text-color;
// CouponList
@coupon-list-background-color: @background-color;
@coupon-list-field-padding: 5px 0 5px @padding-md;
@coupon-list-exchange-button-height: 32px;
@coupon-list-close-button-height: 40px;
@coupon-list-empty-image-size: 200px;
@coupon-list-empty-tip-color: @gray-6;
@coupon-list-empty-tip-font-size: @font-size-md;
@coupon-list-empty-tip-line-height: @line-height-md;
// Dialog
@dialog-width: 320px;
@dialog-small-screen-width: 90%;
@dialog-font-size: @font-size-lg;
@dialog-transition: @animation-duration-base;
@dialog-border-radius: 16px;
@dialog-background-color: @white;
@dialog-header-font-weight: @font-weight-bold;
@dialog-header-line-height: 24px;
@dialog-header-padding-top: 26px;
@dialog-header-isolated-padding: @padding-lg 0;
@dialog-message-padding: @padding-lg;
@dialog-message-font-size: @font-size-md;
@dialog-message-line-height: @line-height-md;
@dialog-message-max-height: 60vh;
@dialog-has-title-message-text-color: @gray-7;
@dialog-has-title-message-padding-top: @padding-xs;
@dialog-button-height: 48px;
@dialog-round-button-height: 36px;
@dialog-confirm-button-text-color: @red;
// Divider
@divider-margin: @padding-md 0;
@divider-text-color: @gray-6;
@divider-font-size: @font-size-md;
@divider-line-height: 24px;
@divider-border-color: @border-color;
@divider-content-padding: @padding-md;
@divider-content-left-width: 10%;
@divider-content-right-width: 10%;
// DropdownMenu
@dropdown-menu-height: 48px;
@dropdown-menu-background-color: @white;
@dropdown-menu-box-shadow: 0 2px 12px fade(@gray-7, 12);
@dropdown-menu-title-font-size: 15px;
@dropdown-menu-title-text-color: @text-color;
@dropdown-menu-title-active-text-color: @red;
@dropdown-menu-title-disabled-text-color: @gray-6;
@dropdown-menu-title-padding: 0 @padding-xs;
@dropdown-menu-title-line-height: @line-height-lg;
@dropdown-menu-option-active-color: @red;
@dropdown-menu-content-max-height: 80%;
@dropdown-item-z-index: 10;
// Empty
@empty-padding: @padding-xl 0;
@empty-image-size: 160px;
@empty-description-margin-top: @padding-md;
@empty-description-padding: 0 60px;
@empty-description-color: @gray-6;
@empty-description-font-size: @font-size-md;
@empty-description-line-height: @line-height-md;
@empty-bottom-margin-top: 24px;
// Field
@field-label-width: 6.2em;
@field-label-color: @gray-7;
@field-label-margin-right: @padding-sm;
@field-input-text-color: @text-color;
@field-input-error-text-color: @red;
@field-input-disabled-text-color: @gray-5;
@field-placeholder-text-color: @gray-5;
@field-icon-size: 16px;
@field-clear-icon-size: 16px;
@field-clear-icon-color: @gray-5;
@field-right-icon-color: @gray-6;
@field-error-message-color: @red;
@field-error-message-text-color: 12px;
@field-text-area-min-height: 60px;
@field-word-limit-color: @gray-7;
@field-word-limit-font-size: @font-size-sm;
@field-word-limit-line-height: 16px;
@field-disabled-text-color: @gray-5;
// GridItem
@grid-item-content-padding: @padding-md @padding-xs;
@grid-item-content-background-color: @white;
@grid-item-content-active-color: @active-color;
@grid-item-icon-size: 28px;
@grid-item-text-color: @gray-7;
@grid-item-text-font-size: @font-size-sm;
// GoodsAction
@goods-action-background-color: @white;
@goods-action-height: 50px;
@goods-action-icon-width: 48px;
@goods-action-icon-height: 100%;
@goods-action-icon-color: @text-color;
@goods-action-icon-size: 18px;
@goods-action-icon-font-size: @font-size-xs;
@goods-action-icon-active-color: @active-color;
@goods-action-icon-text-color: @gray-7;
@goods-action-button-height: 40px;
@goods-action-button-warning-color: @gradient-orange;
@goods-action-button-danger-color: @gradient-red;
// IndexAnchor
@index-anchor-z-index: 1;
@index-anchor-padding: 0 @padding-md;
@index-anchor-text-color: @text-color;
@index-anchor-font-weight: @font-weight-bold;
@index-anchor-font-size: @font-size-md;
@index-anchor-line-height: 32px;
@index-anchor-background-color: transparent;
@index-anchor-sticky-text-color: @green;
@index-anchor-sticky-background-color: @white;
// IndexBar
@index-bar-sidebar-z-index: 2;
@index-bar-index-font-size: @font-size-xs;
@index-bar-index-line-height: @line-height-xs;
@index-bar-index-active-color: @green;
// Info
@info-size: 16px;
@info-color: @white;
@info-padding: 0 3px;
@info-font-size: @font-size-sm;
@info-font-weight: @font-weight-bold;
@info-border-width: @border-width-base;
@info-background-color: @red;
@info-dot-color: @red;
@info-dot-size: 8px;
@info-font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif;
// Image
@image-placeholder-text-color: @gray-6;
@image-placeholder-font-size: @font-size-md;
@image-placeholder-background-color: @background-color;
@image-loading-icon-size: 32px;
@image-loading-icon-color: @gray-4;
@image-error-icon-size: 32px;
@image-error-icon-color: @gray-4;
// ImagePreview
@image-preview-index-text-color: @white;
@image-preview-index-font-size: @font-size-md;
@image-preview-index-line-height: @line-height-md;
@image-preview-index-text-shadow: 0 1px 1px @gray-8;
@image-preview-overlay-background-color: rgba(0, 0, 0, 0.9);
@image-preview-close-icon-size: 22px;
@image-preview-close-icon-color: @gray-5;
@image-preview-close-icon-active-color: @gray-6;
@image-preview-close-icon-margin: @padding-md;
@image-preview-close-icon-z-index: 1;
// List
@list-icon-margin-right: 5px;
@list-text-color: @gray-6;
@list-text-font-size: @font-size-md;
@list-text-line-height: 50px;
// Loading
@loading-text-color: @gray-6;
@loading-text-font-size: @font-size-md;
@loading-spinner-color: @gray-5;
@loading-spinner-size: 30px;
@loading-spinner-animation-duration: 0.8s;
// NavBar
@nav-bar-height: 46px;
@nav-bar-background-color: @white;
@nav-bar-arrow-size: 16px;
@nav-bar-icon-color: @blue;
@nav-bar-text-color: @blue;
@nav-bar-title-font-size: @font-size-lg;
@nav-bar-title-text-color: @text-color;
@nav-bar-z-index: 1;
// NoticeBar
@notice-bar-height: 40px;
@notice-bar-padding: 0 @padding-md;
@notice-bar-wrapable-padding: @padding-xs @padding-md;
@notice-bar-text-color: @orange-dark;
@notice-bar-font-size: @font-size-md;
@notice-bar-line-height: 24px;
@notice-bar-background-color: @orange-light;
@notice-bar-icon-size: 16px;
@notice-bar-icon-min-width: 24px;
// Notify
@notify-text-color: @white;
@notify-padding: @padding-xs @padding-md;
@notify-font-size: @font-size-md;
@notify-line-height: @line-height-md;
@notify-primary-background-color: @blue;
@notify-success-background-color: @green;
@notify-danger-background-color: @red;
@notify-warning-background-color: @orange;
// NumberKeyboard
@number-keyboard-background-color: @gray-2;
@number-keyboard-key-height: 48px;
@number-keyboard-key-font-size: 28px;
@number-keyboard-key-active-color: @gray-3;
@number-keyboard-delete-font-size: @font-size-lg;
@number-keyboard-title-color: @gray-7;
@number-keyboard-title-height: 34px;
@number-keyboard-title-font-size: @font-size-lg;
@number-keyboard-close-padding: 0 @padding-md;
@number-keyboard-close-color: @text-link-color;
@number-keyboard-close-font-size: @font-size-md;
@number-keyboard-button-text-color: @white;
@number-keyboard-button-background-color: @blue;
@number-keyboard-cursor-color: @text-color;
@number-keyboard-cursor-width: 1px;
@number-keyboard-cursor-height: 40%;
@number-keyboard-cursor-animation-duration: 1s;
@number-keyboard-z-index: 100;
// Overlay
@overlay-z-index: 1;
@overlay-background-color: rgba(0, 0, 0, 0.7);
// Pagination
@pagination-height: 40px;
@pagination-font-size: @font-size-md;
@pagination-item-width: 36px;
@pagination-item-default-color: @blue;
@pagination-item-disabled-color: @gray-7;
@pagination-item-disabled-background-color: @background-color;
@pagination-background-color: @white;
@pagination-desc-color: @gray-7;
@pagination-disabled-opacity: @disabled-opacity;
// Panel
@panel-background-color: @white;
@panel-header-value-color: @red;
@panel-footer-padding: @padding-xs @padding-md;
// PasswordInput
@password-input-height: 50px;
@password-input-margin: 0 @padding-md;
@password-input-font-size: 20px;
@password-input-border-radius: 6px;
@password-input-background-color: @white;
@password-input-info-color: @gray-6;
@password-input-info-font-size: @font-size-md;
@password-input-error-info-color: @red;
@password-input-dot-size: 10px;
@password-input-dot-color: @black;
// Picker
@picker-background-color: @white;
@picker-toolbar-height: 44px;
@picker-title-font-size: @font-size-lg;
@picker-title-line-height: @line-height-md;
@picker-action-padding: 0 @padding-md;
@picker-action-font-size: @font-size-md;
@picker-confirm-action-color: @text-link-color;
@picker-cancel-action-color: @gray-6;
@picker-option-font-size: @font-size-lg;
@picker-option-text-color: @black;
@picker-option-disabled-opacity: 0.3;
@picker-loading-icon-color: @blue;
@picker-loading-mask-color: rgba(255, 255, 255, 0.9);
// Popup
@popup-background-color: @white;
@popup-transition: transform @animation-duration-base;
@popup-round-border-radius: 20px;
@popup-close-icon-size: 22px;
@popup-close-icon-color: @gray-5;
@popup-close-icon-active-color: @gray-6;
@popup-close-icon-margin: 16px;
@popup-close-icon-z-index: 1;
// Progress
@progress-height: 4px;
@progress-color: @blue;
@progress-background-color: @gray-3;
@progress-pivot-padding: 0 5px;
@progress-pivot-text-color: @white;
@progress-pivot-font-size: @font-size-xs;
@progress-pivot-line-height: 1.6;
@progress-pivot-background-color: @blue;
// PullRefresh
@pull-refresh-head-height: 50px;
@pull-refresh-head-font-size: @font-size-md;
@pull-refresh-head-text-color: @gray-6;
// Radio
@radio-size: 20px;
@radio-border-color: @gray-5;
@radio-transition-duration: @animation-duration-fast;
@radio-label-margin: @padding-xs;
@radio-label-color: @text-color;
@radio-checked-icon-color: @blue;
@radio-disabled-icon-color: @gray-5;
@radio-disabled-label-color: @gray-5;
@radio-disabled-background-color: @border-color;
// Rate
@rate-icon-size: 20px;
@rate-icon-gutter: @padding-base;
@rate-icon-void-color: @gray-5;
@rate-icon-full-color: @red;
@rate-icon-disabled-color: @gray-5;
// ShareSheet
@share-sheet-header-padding: @padding-sm @padding-md @padding-base;
@share-sheet-title-color: @text-color;
@share-sheet-title-font-size: @font-size-md;
@share-sheet-title-line-height: @line-height-md;
@share-sheet-description-color: @gray-6;
@share-sheet-description-font-size: @font-size-sm;
@share-sheet-description-line-height: 16px;
@share-sheet-icon-size: 48px;
@share-sheet-option-name-color: @gray-7;
@share-sheet-option-name-font-size: @font-size-sm;
@share-sheet-option-description-color: @gray-5;
@share-sheet-option-description-font-size: @font-size-sm;
@share-sheet-cancel-button-font-size: @font-size-lg;
@share-sheet-cancel-button-height: 48px;
@share-sheet-cancel-button-background: @white;
// Search
@search-padding: 10px @padding-sm;
@search-background-color: @white;
@search-content-background-color: @gray-1;
@search-input-height: 34px;
@search-label-padding: 0 5px;
@search-label-color: @text-color;
@search-label-font-size: @font-size-md;
@search-left-icon-color: @gray-6;
@search-action-padding: 0 @padding-xs;
@search-action-text-color: @text-color;
@search-action-font-size: @font-size-md;
// Sidebar
@sidebar-width: 80px;
@sidebar-font-size: @font-size-md;
@sidebar-line-height: @line-height-md;
@sidebar-text-color: @text-color;
@sidebar-disabled-text-color: @gray-5;
@sidebar-padding: 20px @padding-sm;
@sidebar-active-color: @active-color;
@sidebar-background-color: @background-color;
@sidebar-selected-font-weight: @font-weight-bold;
@sidebar-selected-text-color: @text-color;
@sidebar-selected-border-width: 4px;
@sidebar-selected-border-height: 16px;
@sidebar-selected-border-color: @red;
@sidebar-selected-background-color: @white;
// Skeleton
@skeleton-row-height: 16px;
@skeleton-row-background-color: @active-color;
@skeleton-row-margin-top: @padding-sm;
@skeleton-avatar-background-color: @active-color;
@skeleton-animation-duration: 1.2s;
// Slider
@slider-active-background-color: @blue;
@slider-inactive-background-color: @gray-3;
@slider-disabled-opacity: @disabled-opacity;
@slider-bar-height: 2px;
@slider-button-width: 24px;
@slider-button-height: 24px;
@slider-button-border-radius: 50%;
@slider-button-background-color: @white;
@slider-button-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
// Step
@step-text-color: @gray-6;
@step-active-color: @green;
@step-process-text-color: @text-color;
@step-font-size: @font-size-md;
@step-line-color: @border-color;
@step-finish-line-color: @green;
@step-finish-text-color: @text-color;
@step-icon-size: 12px;
@step-circle-size: 5px;
@step-circle-color: @gray-6;
@step-horizontal-title-font-size: @font-size-sm;
// Steps
@steps-background-color: @white;
// Sticky
@sticky-z-index: 99;
// Stepper
@stepper-active-color: #e8e8e8;
@stepper-background-color: @active-color;
@stepper-button-icon-color: @text-color;
@stepper-button-disabled-color: @background-color;
@stepper-button-disabled-icon-color: @gray-5;
@stepper-button-round-theme-color: @red;
@stepper-input-width: 32px;
@stepper-input-height: 28px;
@stepper-input-font-size: @font-size-md;
@stepper-input-line-height: normal;
@stepper-input-text-color: @text-color;
@stepper-input-disabled-text-color: @gray-5;
@stepper-input-disabled-background-color: @active-color;
@stepper-border-radius: @border-radius-md;
// SubmitBar
@submit-bar-height: 50px;
@submit-bar-z-index: 100;
@submit-bar-background-color: @white;
@submit-bar-button-width: 110px;
@submit-bar-price-color: @red;
@submit-bar-price-font-size: @font-size-md;
@submit-bar-currency-font-size: @font-size-md;
@submit-bar-text-color: @text-color;
@submit-bar-text-font-size: @font-size-md;
@submit-bar-tip-padding: @padding-xs @padding-sm;
@submit-bar-tip-font-size: @font-size-sm;
@submit-bar-tip-line-height: 1.5;
@submit-bar-tip-color: #f56723;
@submit-bar-tip-background-color: #fff7cc;
@submit-bar-tip-icon-size: 12px;
@submit-bar-button-height: 40px;
@submit-bar-padding: 0 @padding-md;
@submit-bar-price-integer-font-size: 20px;
@submit-bar-price-font-family: @price-integer-font-family;
// Swipe
@swipe-indicator-size: 6px;
@swipe-indicator-margin: @padding-sm;
@swipe-indicator-active-opacity: 1;
@swipe-indicator-inactive-opacity: 0.3;
@swipe-indicator-active-background-color: @blue;
@swipe-indicator-inactive-background-color: @border-color;
// Switch
@switch-size: 30px;
@switch-width: 2em;
@switch-height: 1em;
@switch-node-size: 1em;
@switch-node-z-index: 1;
@switch-node-background-color: @white;
@switch-node-box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05),
0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
@switch-background-color: @white;
@switch-on-background-color: @blue;
@switch-transition-duration: @animation-duration-base;
@switch-disabled-opacity: @disabled-opacity;
@switch-border: @border-width-base solid rgba(0, 0, 0, 0.1);
// SwitchCell
@switch-cell-padding-top: @cell-vertical-padding - 1px;
@switch-cell-padding-bottom: @cell-vertical-padding - 1px;
@switch-cell-large-padding-top: @cell-large-vertical-padding - 1px;
@switch-cell-large-padding-bottom: @cell-large-vertical-padding - 1px;
// Tabbar
@tabbar-height: 50px;
@tabbar-z-index: 1;
@tabbar-background-color: @white;
// TabbarItem
@tabbar-item-font-size: @font-size-sm;
@tabbar-item-text-color: @gray-7;
@tabbar-item-active-color: @blue;
@tabbar-item-active-background-color: @tabbar-background-color;
@tabbar-item-line-height: 1;
@tabbar-item-icon-size: 22px;
@tabbar-item-margin-bottom: 4px;
// Tab
@tab-text-color: @gray-7;
@tab-active-text-color: @text-color;
@tab-disabled-text-color: @gray-5;
@tab-font-size: @font-size-md;
@tab-line-height: @line-height-md;
// Tabs
@tabs-default-color: @red;
@tabs-line-height: 44px;
@tabs-card-height: 30px;
@tabs-nav-background-color: @white;
@tabs-bottom-bar-width: 40px;
@tabs-bottom-bar-height: 3px;
@tabs-bottom-bar-color: @tabs-default-color;
// Tag
@tag-padding: 0 @padding-base;
@tag-text-color: @white;
@tag-font-size: @font-size-sm;
@tag-border-radius: 2px;
@tag-line-height: 16px;
@tag-medium-padding: 2px 6px;
@tag-large-padding: @padding-base @padding-xs;
@tag-large-border-radius: @border-radius-md;
@tag-large-font-size: @font-size-md;
@tag-round-border-radius: @border-radius-max;
@tag-danger-color: @red;
@tag-primary-color: @blue;
@tag-success-color: @green;
@tag-warning-color: @orange;
@tag-default-color: @gray-6;
@tag-plain-background-color: @white;
// Toast
@toast-max-width: 70%;
@toast-font-size: @font-size-md;
@toast-text-color: @white;
@toast-loading-icon-color: @white;
@toast-line-height: @line-height-md;
@toast-border-radius: @border-radius-lg;
@toast-background-color: fade(@black, 70%);
@toast-icon-size: 36px;
@toast-text-min-width: 96px;
@toast-text-padding: @padding-xs @padding-sm;
@toast-default-padding: @padding-md;
@toast-default-width: 88px;
@toast-default-min-height: 88px;
@toast-position-top-distance: 20%;
@toast-position-bottom-distance: 20%;
// TreeSelect
@tree-select-font-size: @font-size-md;
@tree-select-nav-background-color: @background-color;
@tree-select-content-background-color: @white;
@tree-select-nav-item-padding: 14px @padding-sm;
@tree-select-item-height: 48px;
@tree-select-item-active-color: @red;
@tree-select-item-disabled-color: @gray-5;
@tree-select-item-selected-size: 16px;
// Uploader
@uploader-size: 80px;
@uploader-icon-size: 24px;
@uploader-icon-color: @gray-4;
@uploader-text-color: @gray-6;
@uploader-text-font-size: @font-size-sm;
@uploader-upload-background-color: @gray-1;
@uploader-upload-active-color: @active-color;
@uploader-delete-color: @white;
@uploader-delete-icon-size: 14px;
@uploader-delete-background-color: rgba(0, 0, 0, 0.7);
@uploader-file-background-color: @background-color;
@uploader-file-icon-size: 20px;
@uploader-file-icon-color: @gray-7;
@uploader-file-name-padding: 0 @padding-base;
@uploader-file-name-margin-top: @padding-xs;
@uploader-file-name-font-size: @font-size-sm;
@uploader-file-name-text-color: @gray-7;
@uploader-mask-background-color: fade(@gray-8, 88%);
@uploader-mask-icon-size: 22px;
@uploader-mask-message-font-size: @font-size-sm;
@uploader-mask-message-line-height: @line-height-xs;
@uploader-loading-icon-size: 22px;
@uploader-loading-icon-color: @white;
@uploader-disabled-opacity: @disabled-opacity;
// Sku
@sku-item-background-color: @background-color;
@sku-icon-gray-color: @gray-4;
@sku-upload-mask-color: rgba(50, 50, 51, 0.8);
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: "./",
devServer: {
host: '0.0.0.0',
port: 8080,
open: false,
},
configureWebpack: {
externals: {
'BMap': 'BMap'
}
},
css: {
loaderOptions: {
less: {
// 若使用 less-loader@5,请移除 lessOptions 这一级,直接配置选项。
lessOptions: {
modifyVars: {
// 直接覆盖变量 优先级最高
// 'text-color': '#00a0e9',
// 'border-color': '#00ff00',
// 'nav-bar-background-color': '#00a0e9',
// 'nav-bar-icon-color': '#ffffff',
// 'nav-bar-text-color': ' #ffffff',
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
// hack: `true; @import "${resolve('./src/styles/resetVar.less')}";`,
},
},
},
},
},
}
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