Commit 74128f97 authored by 曾沂轮's avatar 曾沂轮

Feat: 添加模板

parents
node_modules
package-lock.json
\ No newline at end of file
# svi-cli smart-web-router Template
> 一个基于[SmartWeb](http://172.16.10.132:8010/smartweb2/document/)应该库支撑的路由应用模板,提供给svi-cli脚手架获取.
> 提供内部平台或项目使用的初始模板
## Usage / 用法
``` bash
$ npm install -g svi-cli # 如果已安装,请跳过
$ svi init smart-web-router my-project
$ cd my-project
$ npm install
$ npm run serve
```
module.exports = {
renderFiles: [
'package.json',
'README.md'
],
filters: {
},
prompts: {
name: {
type: 'string',
required: true,
message: 'Project name'
},
description: {
type: 'string',
required: false,
message: 'Project description',
default: 'A Smart Web project',
}
}
}
\ No newline at end of file
{
"name": "vue-app",
"version": "0.0.1",
"description": "a svi CLI vue-app template.",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"template"
],
"author": "zengyl@southzn.com",
"license": "MIT"
}
> 1%
last 2 versions
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
NODE_ENV=development
VUE_APP_BASEURL='//172.16.10.132:8091/smartwebservice'
VUE_APP_SERVICE_APP='http://172.16.10.132:8010'
\ No newline at end of file
NODE_ENV=production
VUE_APP_BASEURL='//www.south-smart.com/smartwebservice'
VUE_APP_SERVICE_APP='http://www.south-smart.com'
NODE_ENV=production
VUE_APP_BASEURL='//172.16.10.132:8091/smartwebservice'
VUE_APP_SERVICE_APP='http://172.16.10.132:8010'
\ No newline at end of file
node_modules
/dist
/lib
/build
\ No newline at end of file
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'@smart/standard'
],
plugins: [
'vue'
],
rules: {
'comma-dangle': ['error', {
'arrays': 'never',
'objects': 'ignore',
'imports': 'ignore',
'exports': 'ignore',
'functions': 'ignore'
}],
'no-multi-spaces': ['error', {
'ignoreEOLComments': true
}],
'no-unused-vars': [2, { 'args': 'none' }],
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
};
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# {{name}}
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
module.exports = {
presets: [
'@vue/app'
]
};
// 接口地址
const baseUrl = process.env.VUE_APP_BASEURL;
// 服务发布地址,主要作用第三方服务
const serviceUrl = process.env.VUE_APP_SERVICE_APP;
if (typeof window !== 'undefined') window.baseUrl = baseUrl;
export {
baseUrl,
serviceUrl
};
/* eslint-disable */
var http = require('http');
var https = require('https');
var url=require("url");
var pass = require('stream').PassThrough;
var getHeader = function (req) {
var ret = {};
for (var i in req.headers) {
if (!/^(host|connection|Access-|origin|referer|user-agent|user-doclever|path-doclever|url-doclever|method-doclever|headers-doclever|X-Requested-With)/i.test(i)) {
ret[i] = req.headers[i];
}
}
ret["accept"]="*/*";
var headers=req.headers["headers-doclever"];
if(headers)
{
headers=JSON.parse(headers);
for(var key in headers)
{
ret[key]=headers[key];
}
}
return ret
};
var filterResHeader = function (headers,res) {
var ret = {};
res.setHeader("Cache-Control", "no-cache,no-store");
res.setHeader("Pragrma", "no-cache");
res.setHeader("Expires", 0);
var resHeaders=res.getHeader("Access-Control-Expose-Headers")?res.getHeader("Access-Control-Expose-Headers").toLowerCase():"";
for (var i in headers) {
if (!/Access-/i.test(i)) {
if(/set-cookie/i.test(i))
{
for(let index=0;index<headers[i].length;index++)
{
headers[i][index]=headers[i][index].split(" ")[0];
}
ret[i]=headers[i];
}
else
{
ret[i] = headers[i];
}
}
if(!resHeaders)
{
res.setHeader("Access-Control-Expose-Headers",i);
}
else if(resHeaders.indexOf(i.toLowerCase()+",")==-1 && resHeaders.indexOf(","+i.toLowerCase())==-1)
{
res.setHeader("Access-Control-Expose-Headers",res.getHeader("Access-Control-Expose-Headers")+","+i);
}
}
return ret;
};
var getPath = function (req) {
var url = req.url;
if (url.substr(0, 7).toLowerCase() === 'http://') {
var i = url.indexOf('/', 7);
if (i !== -1) {
url = url.substr(i);
}
}
return url;
};
function getHost(req) {
var url=req.headers["url-doclever"];
url=url.replace(/^(http:\/\/|https:\/\/)/i,"");
var arr=url.split(":");
return arr[0];
}
function getPort(req) {
var url=req.headers["url-doclever"];
var defaultPort;
if(req.headers["url-doclever"].toLowerCase().startsWith("https://"))
{
defaultPort=443;
}
else
{
defaultPort=80;
}
url=url.replace(/^(http:\/\/|https:\/\/)/i,"");
var arr=url.split(":");
return arr.length>1?arr[1]:defaultPort;
}
var onProxy = function (req, res) {
handleHeader(req,res);
if(req.method=="OPTIONS")
{
return;
}
if(!req.headers["url-doclever"])
{
mock(req,res);
}
else
{
proxy(req,res);
}
};
function mock(req,res) {
var obj=url.parse(mockUrl);
var path=req.headers.path || url.parse(req.url).path;
var opt={
host: obj.hostname,
path: (obj.pathname=="/"?"":obj.pathname)+path,
method: req.method,
headers: getHeader(req),
port:obj.port?obj.port:80,
}
console.log("初次请求:method:"+opt.method+"host:"+opt.host+"port:"+opt.port+"path:"+opt.path)
if(opt.headers["content-length"])
{
delete opt.headers["content-length"]
}
var req2 = http.request(opt, function (res2) {
if(!realUrl || res2.headers["finish-doclever"]=="0")
{
console.log("接口开发中,返回mock数据");
res.writeHead(res2.statusCode, filterResHeader(res2.headers,res));
res2.pipe(res);
res2.on('end', function () {
});
}
else
{
if(res2.headers["finish-doclever"]=="1")
{
console.log("接口已完成,调用真实接口");
}
else
{
console.log("接口或者项目未找到,转调真实接口");
}
var headers=getHeader(req);
var objUrl=url.parse(realUrl);
var request1,opt1;
if(objUrl.protocol=="http:")
{
opt1={
host: objUrl.hostname,
path: (objUrl.pathname=="/"?"":objUrl.pathname)+path,
method: req.method,
port:objUrl.port?objUrl.port:80,
headers:headers
}
request1=http.request;
}
else
{
opt1={
host: objUrl.hostname,
path: (objUrl.pathname=="/"?"":objUrl.pathname)+path,
method: req.method,
port:objUrl.port?objUrl.port:443,
headers:headers,
rejectUnauthorized: false,
requestCert: true,
}
request1=https.request;
}
console.log("调用真实接口:method:"+opt1.method+", url:"+opt1.host+":"+opt1.port+opt1.path)
var req3=request1(opt1,function (res3) {
console.log("真实接口调用完成。status:"+res3.statusCode)
res.writeHead(res3.statusCode, filterResHeader(res3.headers,res));
res3.pipe(res);
res3.on('end', function () {
});
})
if (/POST|PUT/i.test(req.method)) {
stream.pipe(req3);
} else {
req3.end();
}
req3.on('error', function (err) {
res.end(err.stack);
});
}
});
var stream;
if (/POST|PUT|PATCH/i.test(req.method))
{
stream=new pass();
req.pipe(stream);
req.pipe(req2);
}
else
{
req2.end();
}
req2.on('error', function (err) {
res.end(err.stack);
});
}
function handleHeader(req,res) {
if(!req.headers.origin)
{
return;
}
res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE");
res.setHeader("Access-Control-Allow-Credentials","true");
if(req.headers["access-control-request-headers"])
{
res.setHeader("Access-Control-Allow-Headers",req.headers["access-control-request-headers"])
}
res.setHeader("Access-Control-Expose-Headers","connection,content-length,date,x-powered-by,content-encoding,server,etag,accept-ranges,allow,content-language,set-cookie,doclever-request");
if(req.method=="OPTIONS")
{
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();
return;
}
}
function redirect(res,bHttps,opt,location) {
var urlRedirect=location;
if(urlRedirect.startsWith("/"))
{
urlRedirect=(bHttps?"https://":"http://")+opt.host+":"+opt.port+urlRedirect;
}
var objUrl=url.parse(urlRedirect);
var request1,opt1;
if(objUrl.protocol=="http:")
{
opt1={
host: objUrl.hostname,
path: objUrl.path,
method: "GET",
port:objUrl.port?objUrl.port:80,
}
request1=http.request;
bHttps=false;
}
else
{
opt1={
host: objUrl.hostname,
path: objUrl.path,
method: "GET",
port:objUrl.port?objUrl.port:443,
rejectUnauthorized: false,
requestCert: true,
}
request1=https.request;
bHttps=true;
}
var req3=request1(opt1,function (res3) {
if(res3.statusCode==302)
{
redirect(res,bHttps,opt,res3.headers.location)
}
else
{
var resHeader=filterResHeader(res3.headers,res)
resHeader["doclever-request"]=JSON.stringify(handleSelfCookie(req3));
res.writeHead(res3.statusCode, resHeader);
res3.pipe(res);
res3.on('end', function () {
});
}
})
req3.end();
req3.on('error', function (err) {
res.end(err.stack);
});
}
function handleSelfCookie(req) {
var arr=req._headers;
arr["url"]=req.method+" "+req.path;
var cookie=arr["cookie"];
if(!cookie)
{
return arr;
}
var arrCookie=cookie.split(";");
var keys=["id","name","photo","qq","sex","company","phone","loginCount","age","email"];
arrCookie=arrCookie.filter(function (obj) {
obj=obj.trim();
for(let key of keys)
{
if(obj.startsWith(key+"="))
{
return false;
}
}
return true;
})
arr["cookie"]=arrCookie.join(";");
return arr;
}
function proxy(req,res) {
var bHttps=false;
if(req.headers["url-doclever"].toLowerCase().startsWith("https://"))
{
bHttps=true;
}
var opt,request;
if(bHttps)
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req),
rejectUnauthorized: false,
requestCert: true,
};
request=https.request;
}
else
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req)
};
request=http.request;
}
var req2 = request(opt, function (res2) {
if(res2.statusCode==302)
{
redirect(res,bHttps,opt,res2.headers.location)
}
else
{
var resHeader=filterResHeader(res2.headers,res)
resHeader["doclever-request"]=JSON.stringify(handleSelfCookie(req2));
res.writeHead(res2.statusCode, resHeader);
res2.pipe(res);
res2.on('end', function () {
});
}
});
if (/POST|PUT|PATCH/i.test(req.method)) {
req.pipe(req2);
} else {
req2.end();
}
req2.on('error', function (err) {
res.end(err.stack);
});
}
var args = process.argv.splice(2);
var mockUrl=args[0];
var realUrl=args[1];
var port=args[2]?args[2]:36742;
var server = http.createServer(onProxy);
server.listen(port);
console.log(args.length>0?("内网测试,Mock数据正监听端口:"+port):"正在运行中,请用DOClever的接口测试页面进行内网测试!");
<template>
<div id="formapp">
<form-view v-if="!pageId"></form-view>
<page-view v-else :id="pageId"></page-view>
</div>
</template>
<script>
import { getQueryString } from './utils/form';
import formView from './views/form.vue';
import pageView from './views/page.vue';
export default {
name: 'App',
components: {
formView,
pageView
},
data() {
return {
pageId: ''
};
},
created() {
this.pageId = getQueryString('pageId');
},
mounted() {
document.addEventListener('scroll', () => {
console.log(document.body.scrollTop);
});
}
};
</script>
import Vue from 'vue';
import axios from 'axios';
import qs from 'qs';
import './loginInterceptor';
import * as HTTP from '@config/http.config';
// 携带cookie信息
axios.defaults.withCredentials = true;
// 设置全局的请求次数,请求的间隙
axios.defaults.retry = 0;
axios.defaults.retryDelay = 1000;
// 请求超时拦截,重新请求
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
const config = err.config;
// If config does not exist or the retry option is not set, reject
if (!config || !config.retry) return Promise.reject(err);
// Set the variable for keeping track of the retry count
config.__retryCount = config.__retryCount || 0;
// Check if we've maxed out the total number of retries
if (config.__retryCount >= config.retry) {
// Reject with the error
return Promise.reject(err);
}
// Increase the retry count
config.__retryCount += 1;
// Create new promise to handle exponential backoff
const backoff = new Promise(function(resolve) {
setTimeout(function() {
resolve();
}, config.retryDelay || 1);
});
// Return the promise in which recalls axios to retry the request
return backoff.then(function() {
return axios(config);
});
});
// 为Vue注册$http
Vue.prototype.$http = axios;
const CancelToken = axios.CancelToken;
let cancel;
const baseUrl = HTTP.baseUrl;
window.baseUrl = baseUrl;
const config = {
baseUrl,
/**
* get获取数据,通用方法
* @param {String} url
* @param {Object} params
* @param {Object} options
*/
doGetPromise(url, params, options = {}) {
const { timeout = 30000, ...arg } = options;
return new Promise((resolve, reject) => {
axios
.get(url, {
timeout: timeout,
...arg,
params: {
...params,
t: new Date().getTime() // 解决IE上get请求缓存问题
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(response => {
resolve(response.data);
})
.catch(response => {
console.error('ajax error:', response);
reject(response);
});
});
},
/**
* FormData数据上传,文件上传必用
* @param {String} url
* @param {FormData} formData
*/
doPostPromiseForm(url, formData) {
return new Promise((resolve, reject) => {
axios
.post(url, formData, {
headers: {
'Content-type': 'multipart/form-data'
},
emulateJSON: false,
emulateHTTP: false,
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(res => {
resolve(res.data);
})
.catch(res => {
console.log('post error:', res);
reject(res);
});
});
},
/**
* 默认方式提交from表单数据json
* @param {String} url
* @param {Object} data
*/
doPostPromise(url, data) {
return new Promise((resolve, reject) => {
axios
.post(url, qs.stringify(data), {
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(res => {
resolve(res.data);
})
.catch(res => {
console.log('post error:', res);
reject(res);
});
});
},
/**
* 提交application/json方式
* @param {String} url
* @param {Object} data
*/
doPostPromiseJson(url, data) {
return new Promise((resolve, reject) => {
axios
.post(url, data, {
headers: {
'Content-type': 'application/json'
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(res => {
resolve(res.data);
})
.catch(res => {
console.log('post error:', res);
reject(res);
});
});
}
};
// 切换页面强行中断请求 router.beforeEach中用到
Vue.prototype.$cancelAjax = function(msg) {
if (cancel) {
cancel(msg || '手动中断请求');
}
};
export default config;
import config from './config';
const baseUrl = config.baseUrl;
const Api = {
...config,
login(data) {
return config.doPostPromise(baseUrl + '/index/login', data);
},
checkLogin() {
return config.doGetPromise(baseUrl + '/index/checkLogin', {}, { retry: 0 });
},
logout() {
return config.doGetPromise(baseUrl + '/index/logout', {});
},
/**
*
* @param {*} taskId
* @param {*} linkId
* @param {*} linkKey
*/
getBusinessStartForm(businessDefinitionId) {
return config.doGetPromise(
baseUrl + '/v1.1.0/workflow/workflowForm/getBusinessStartForm',
{
businessDefinitionId
}
);
},
/**
* 获取渲染的表单数据
* @param {String} taskId
* @param {String} linkId linkInstanceId
* @param {String} linkKey linkDefinitionKey
*/
renderFormByTaskId(taskId, linkId, linkKey) {
return config.doGetPromise(
baseUrl + '/v1.1.0/workflow/workflowForm/renderFormByTaskId',
{
taskId: taskId,
linkInstanceId: linkId,
linkDefinitionKey: linkKey
}
);
},
/**
* 办结工作渲染表单
* @param {String} processId
*/
renderFinishForm(processId) {
return config.doGetPromise(
baseUrl + '/v1.1.0/workflow/workflowForm/renderFinishForm',
{
historyProcessInstanceId: processId
}
);
},
/**
* 通过获取表单ID获取表单模板
* @param {string} formid 表单ID
*/
getForm(formid) {
return config.doGetPromise(baseUrl + '/v1.1.0/form/getForm', {
rid: formid
});
},
getAdminDivisionTree() {
return config.doGetPromise(
baseUrl + '/administrativeDivisions/getAdministrativeDivisionTree'
);
},
/**
* 获取用户权限下的系统模块功能
* @param {String} id 子系统Id
*/
getSystemAllModules(id) {
return config.doGetPromise(
baseUrl + '/systemModule/privilege/getUserModulesTreeBySystemId',
{ systemId: id }
);
},
/**
* 获取组织结构的树状信息
* @param {Number} type 类型,1:只返回部门岗位信息; 2:返回部门岗位与人员信息; 3:返回角色信息; 4:返回部门(无岗位);5:返回人员;其他:返回所有组织项信息
* @param {Number} valid 是否可用, -1:审核中 1:可用(第一次登录,需要修改密码) 2:可用(非第一次登录,不需要修改密码)
*/
getOrganTree(type, valid) {
return config.doGetPromise(baseUrl + '/organization/manager/getOrganTree', {
type: type,
valid: valid
});
},
// 获取代码字典
getChildItemByRootCode(data) {
return config.doGetPromise(
baseUrl + '/codeDict/getChildItemByRootCode',
data
);
},
/**
* 提交前检查是否有下个环节处理人
* @param {string} taskId
* @param {FormData} data 表单数据
*/
checkAndSubmitTaskByFormData(taskId, data) {
return config.doPostPromiseForm(
baseUrl +
'/v1.1.0/workflow/workflowForm/checkAndSubmitTaskByFormData/' +
taskId,
data
);
},
/**
* 获取转办人的信息
* @param {string} taskId 流程ID
*/
getTranformUser(taskId) {
return config.doGetPromise(
baseUrl + '/workflow/linkInstance/findLinkInstanceByTaskIdPassto',
{
taskId: taskId
}
);
},
/**
* 退回 - 获取退回对话框处理人树数据
* @param {string} currentTaskId
* @param {string} processDefinitionId
* @param {string} nextLinkKey
*/
getRerunPeople(currentTaskId, processDefinitionId, nextLinkKey) {
return config.doGetPromise(
baseUrl + '/workflow/workflowForm/getRerunPeople',
{
currentTaskId,
processDefinitionId,
nextLinkKey
}
);
},
/**
* 退回 - 根据任务id获取执行流id(第三步)
*/
findExecutionIdByTaskId(taskId) {
return config.doGetPromise(
baseUrl + '/workflow/execution/findExecutionIdByTaskId',
{
taskId
}
);
},
/**
* 退回 - 当前环节跳转到指定环节(第四步)
* @param {*} executionId
* @param {*} linkDefinitionKey
* @param {*} rerunReason
* @param {*} operationType
* @param {*} isSendbackOldLink
* @param {*} anotherAssignee
*/
sendReturnTaks(
executionId,
linkDefinitionKey,
rerunReason = '',
operationType = 'reRun',
isSendbackOldLink = 0,
anotherAssignee
) {
return config.doGetPromise(
baseUrl + '/v1.1.0/workflow/workflowForm/sendback',
{
executionId,
linkDefinitionKey,
rerunReason,
operationType,
isSendbackOldLink,
anotherAssignee
}
);
}
};
export default Api;
import axios from 'axios';
import store from '@/store';
import router from '@/router';
/* const filters = ['webgisService']
const handleFilter = (key) => {
if (Array.isArray(filters)) {
filters.map(item => {
if (item === key) {}
})
}
} */
/**
* 登录判断失效
* 在所有经过axios请求中,拦截到登录失效
*
* @param {Object} response
*/
function loginInterceptor(response) {
// console.log(response)
// 通过状态码判断登录已经失效
if (response.data && response.data.status === 9) {
store.dispatch('setUserInfo', {});
router.replace({
name: 'Logindialog'
});
// response.data = null
return response;
} else {
return response;
}
}
axios.interceptors.response.use(loginInterceptor);
import config from '../api/config';
const url = config.baseUrl;
export default [
{
name: 'guidance',
text: '办理指南',
icon: 'el-icon-info',
api: url + '/workflowWebService/getProcessManagementGuide'
},
{
name: 'save',
text: '保存',
icon: 'el-icon-tickets',
api: url + '/v1.1.0/workflow/workflowForm/saveFormData'
},
{
name: 'sign',
text: '接办',
icon: 'el-icon-tickets',
api: url + '/workflow/workflowForm/receiveTasks'
// api: url + '/workflowWebService/claimTask'
},
{
name: 'forceSign',
text: '强制接办',
icon: 'el-icon-tickets',
api: url + '/workflowWebService/forceClaimForm'
},
{
name: 'submit',
text: '提交',
icon: 'el-icon-check',
api: url + '/v1.1.0/workflow/workflowForm/submitTaskOnDialog'
},
{
name: 'isSendBack',
text: '提交退回',
icon: 'el-icon-check',
api: url + '/v1.1.0/workflow/workflowForm/submitSendbackTask/'
},
/* {
id: 'backSend',
name: 'backsend',
text: '跳转',
icon: 'el-icon-news',
api: ''
}, */
{
name: 'finish',
text: '结档',
icon: 'el-icon-edit-outline',
api: url + '/workflowWebService/finishProcessInstanceByTaskId'
},
{
name: 'refund',
text: '退件',
icon: 'el-icon-back',
api: url + '/workflow/workflowForm/refundTasks'
},
{
name: 'urge',
text: '催办',
icon: 'el-icon-share',
api: url + '/workflow/workflowForm/remindTasks'
},
{
name: 'turn',
text: '转办',
icon: 'el-icon-refresh',
api: url + '/workflow/workflowForm/passTasksToSb'
},
{
name: 'unsign',
text: '撤办',
icon: 'el-icon-remove-outline',
api: url + '/workflow/workflowForm/unclaimTasks'
},
{
name: 'apply',
text: '申请挂起',
icon: 'el-icon-document',
api: url + '/workflow/workflowForm/applySuspendTasks'
},
{
name: 'suspend',
text: '挂起',
icon: 'el-icon-goods',
api: url + '/workflow/workflowForm/suspendProcesses'
},
{
name: 'activeSuspend',
text: '解除挂起',
icon: 'el-icon-sold-out',
api: url + '/workflow/workflowForm/activateProcesses'
},
{
name: 'withdraw',
text: '收回',
icon: 'el-icon-arrow-left',
api: url + '/workflow/workflowForm/withdrawTasks'
},
{
name: 'rerun',
text: '退回',
icon: 'el-icon-d-arrow-left',
api: url + '/workflowWebService/prepareJumpTo'
},
{
name: 'getdraw',
text: '流转情况',
icon: 'el-icon-sort'
},
{
name: 'isBRule',
text: '查看限制消息',
icon: 'el-icon-view',
api: url + '/workflowWebService/getBusinessRuleResults'
}
];
<!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">
<link rel="shortcut icon" type="image/ico" href="<%= BASE_URL %>favicon.ico">
<title>表单渲染 - Smart Web</title>
<!-- <link rel="stylesheet" href="<%= BASE_URL %>iconfont/iconfont.css"> -->
<style type="text/css">
.maskbox {
border: 2px solid #ff0000;
background: #f8ecda;
opacity: 0.1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
}
</style>
</head>
<body>
<div id="formapp"></div>
<!-- built files will be auto injected -->
</body>
</html>
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
import './utils/init';
import ElemetUI from 'element-ui';
import 'element-ui/packages/theme-chalk/lib/index.css';
import VueProgressBar from 'vue-progressbar';
import SmartForm from 'smart-form';
import 'smart-form/lib/smartForm.css';
// import scss
import './styles/index.scss';
import './utils/expression';
Vue.config.productionTip = false;
Vue.use(ElemetUI, {
size: 'medium',
zIndex: 4000
});
Vue.use(SmartForm);
const vPopts = {
color: '#8fcdfc',
failedColor: '#874b4b',
thickness: '2px',
transition: {
speed: '0.1s',
opacity: '0.3s',
termination: 300
},
autoRevert: true,
location: 'top',
inverse: false,
autoFinish: true
};
Vue.use(VueProgressBar, vPopts);
/* eslint-disable no-new */
new Vue({
el: '#formapp',
components: {
App
},
template: '<App/>'
});
import Vuex from 'vuex';
const store = new Vuex.Store({
state: {
taskData: null
},
mutations: {
setTaskData(state, payload) {
state.taskData = payload;
}
},
actions: {
setTaskData({ commit }, payload) {
commit('setTaskData', payload);
}
}
});
export default store;
@import '@/styles/library.scss';
@import '@/styles/common/var.scss';
@import './mixins/mixins';
@import './reset';
.align-center {
text-align: center;
}
.fl {
float: left;
}
.flr {
float: right;
}
.clearfix {
clear: both;
&::after {
content: '';
display: block;
width: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
html, body {
height: 100%;
}
body {
overflow-x: auto;
}
#formapp {
width: 100%;
height: 100%;
padding: 0;
overflow: auto;
// min-height: 100%;
// position: relative;
.app-loading {
position: fixed;
z-index: 29;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
}
.form-header {
position: fixed;
top: 0;
left: 0;
z-index: 9;
width: 100%;
padding: 6px 12px;
background-color: #f2f2f2;
max-height: 44px;
overflow: auto;
}
.form-render {
padding-top: 28px;
width: 1000px;
margin: 0 auto;
}
.is-required {
.el-textarea__inner {
border-color: $--color-danger;
}
}
.page-view {
width: 100%;
height: 100%;
}
@include b(framework-tree) {
display: flex;
flex-direction: column;
width: 220px;
height: 100%;
padding-bottom: 10px;
border-right: $--border-base;
overflow: hidden;
background-color: rgba($color: mix($--color-black, $--color-primary-light-9), $alpha: 0.04);
@include e(header) {
padding: 0 4px 4px 4px;
}
@include e(wrapper) {
width: 100%;
height: 100%;
background-color: inherit;
overflow: auto;
@include b(custom-tree-node) {
flex: 1 1 auto;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.iconfont {
font-size: 16px;
margin-right: 4px;
}
@include b(tree-toolbar) {
display: none;
margin-right: 4px;
word-spacing: -5px;
.iconfont {
font-size: 16px;
margin-right: 0;
}
}
}
}
.el-tree-node__content {
font-size: 14px;
height: 30px;
&:hover {
background-color: rgba($color: mix($--color-black, $--color-primary-light-9), $alpha: 0.1);
.tree-toolbar {
display: block;
}
}
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: $--color-primary-light-8;
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
border-left: 4px solid $--color-primary-light-4;
}
}
}
// 提交弹窗
@include b(submit-dialog) {
.el-dialog__body {
padding-top: 10px;
padding-bottom: 10px;
}
@include e(wrapper) {
display: flex;
flex-direction: row;
}
@include e(sidebar) {
width: 160px;
border-right: $--border-base;
@include m(title) {
padding: 6px 5px;
background: $--background-color-base;
}
@include m(content) {
padding: 10px 10px;
.el-checkbox {
display: block;
margin-bottom: 10px;
}
.el-checkbox + .el-checkbox {
margin-left: 0 !important;
}
}
}
@include e(content) {
margin-left: 6px;
flex: 1 1 auto;
overflow: hidden;
.users {
height: 300px;
border: $--border-base;
overflow: auto;
.title {
display: inline-block;
padding: 4px 8px;
background: $--background-color-base;
}
.cate-title {
display: block;
background-color: $--color-primary-light-9;
color: $--color-primary;
font-weight: 600;
}
.normal-users {
margin-top: 10px;
padding-top: 10px;
border-top: $--border-base;
border-color: $--border-color-extra-light;
}
}
.el-tree-node__content {
height: auto;
padding: 4px 0;
}
.custom-tree-node {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
padding-right: 10px;
& > span {
flex: 1 1 auto;
padding-right: 5px;
line-height: 1.1;
word-wrap: break-word;
white-space: normal;
}
.flr {
font-size: 12px;
}
}
.submit-reason {
margin-top: 10px;
}
}
.submit-dialog__footer {
padding-top: 20px;
padding-bottom: 10px;
}
}
// 转办
@include b(transform-work) {
@include e(dialog) {
.el-dialog {
max-height: 96%;
min-height: 400px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.el-dialog__body {
flex: 1 1 auto;
// display: flex;
// flex-direction: column;
padding: 10px 12px;
overflow: auto;
}
.el-tabs {
// flex: 1 1 auto;
// display: flex;
// flex-direction: column;
margin-bottom: 10px;
overflow: hidden;
.el-tabs__header {
margin-bottom: 0;
}
.el-tabs__content {
// flex: 1 1 auto;
border: $--border-base;
border-top: 0 none;
overflow: auto;
}
}
.framework-tree {
// flex: 1 1 auto;
width: 100%;
max-height: 50vh;
overflow: auto;
}
}
}
// 退回
@include b(return-work) {
@include e(dialog) {
.el-dialog {
max-height: 96%;
min-height: 450px;
display: flex;
flex-direction: column;
}
.el-dialog__body {
flex: 1 1 auto;
display: flex;
flex-direction: column;
padding: 10px 12px;
}
.el-container {
border: $--border-base;
.el-aside {
border-right: $--border-base;
li {
padding: 8px 10px;
cursor: pointer;
&.is-active {
color: #ffffff;
background-color: $--color-primary-light-4;
}
}
}
header {
padding: 6px 12px;
background-color: $--background-color-base;
}
.el-main {
display: flex;
flex-direction: column;
}
.el-tabs {
flex: 1 1 auto;
}
}
.el-tree-node__content {
height: auto;
padding: 4px 0;
}
.custom-tree-node {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
padding-right: 10px;
& > span {
flex: 1 1 auto;
padding-right: 5px;
line-height: 1.1;
word-wrap: break-word;
white-space: normal;
}
.flr {
font-size: 12px;
}
}
.framework-tree {
width: 100%;
border-right: 0;
background-color: transparent;
}
.submit-reason {
margin-top: 10px;
}
}
}
\ No newline at end of file
$namespace: '';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';
@import "config";
/* BEM support Func
-------------------------- */
@function selectorToString($selector) {
$selector: inspect($selector);
$selector: str-slice($selector, 2, -2);
@return $selector;
}
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector, $modifier-separator) {
@return true;
} @else {
@return false;
}
}
@function containWhenFlag($selector) {
$selector: selectorToString($selector);
@if str-index($selector, '.' + $state-prefix) {
@return true
} @else {
@return false
}
}
@function containPseudoClass($selector) {
$selector: selectorToString($selector);
@if str-index($selector, ':') {
@return true
} @else {
@return false
}
}
@function hitAllSpecialNestRule($selector) {
@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}
@import "function";
/* BEM
-------------------------- */
@mixin b($block) {
$B: $block !global;
.#{$B} {
@content;
}
}
@mixin e($element) {
$E: $element !global;
$selector: &;
$currentSelector: "";
@each $unit in $element {
$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
}
@if hitAllSpecialNestRule($selector) {
@at-root {
#{$selector} {
#{$currentSelector} {
@content;
}
}
}
} @else {
@at-root {
#{$currentSelector} {
@content;
}
}
}
}
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
}
@at-root {
#{$currentSelector} {
@content;
}
}
}
@mixin configurable-m($modifier, $E-flag: false) {
$selector: &;
$interpolation: '';
@if $E-flag {
$interpolation: $element-separator + $E-flag;
}
@at-root {
#{$selector} {
.#{$B+$interpolation+$modifier-separator+$modifier} {
@content;
}
}
}
}
@mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B) {
$modifierCombo: '';
@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}
@at-root {
#{&}#{$specSelector}.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}
@mixin meb($modifier: false, $element: $E, $block: $B) {
$selector: &;
$modifierCombo: '';
@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}
@at-root {
#{$selector} {
.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}
}
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
@mixin extend-rule($name) {
@extend #{'%shared-'+$name};
}
@mixin share-rule($name) {
$rule-name: '%shared-'+$name;
@at-root #{$rule-name} {
@content
}
}
\ No newline at end of file
@mixin utils-user-select($value) {
-moz-user-select: $value;
-webkit-user-select: $value;
-ms-user-select: $value;
}
@mixin utils-clearfix {
$selector: &;
@at-root {
#{$selector}::before,
#{$selector}::after {
display: table;
content: "";
}
#{$selector}::after {
clear: both
}
}
}
@mixin utils-vertical-center {
$selector: &;
@at-root {
#{$selector}::after {
display: inline-block;
content: "";
height: 100%;
vertical-align: middle
}
}
}
@mixin utils-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
\ No newline at end of file
blockquote,body,button,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,hr,html,iframe,input,legend,li,ol,p,pre,td,textarea,th,ul{
margin:0;
padding:0;
}
html, body {
width: 100%;
}
body {
min-width: 1200px;
font-size: 1rem;
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;
color: #606266;
overflow: auto;
}
iframe {
width: 100%;
height: 100%;
border: 0;
outline: none;
}
a {
color: #0a6fe2;
text-decoration: none;
}
ul, ol, li {
list-style: none;
}
* {
scrollbar-base-color: #cecece;
scrollbar-3dlight-color: #eee;
scrollbar-highlight-color: #eee;
scrollbar-track-color: #f1f1f1;
// scrollbar-arrow-color: #000;
scrollbar-shadow-color: #eee;
// scrollbar-dark-shadow-color: #eee;
box-sizing: border-box;
}
*::-webkit-scrollbar {
width: 6px;
height: 6px;
}
*::-webkit-scrollbar-button {
display: none;
}
*::-webkit-scrollbar-track-piece {
background-color: #f2f2f2;
}
*::-webkit-scrollbar-thumb {
background-color: #C1C1C1;
border-radius: 6px;
}
\ No newline at end of file
const parentExpression = window.parent ? window.parent.$ : null;
const $ = {};
/**
* 引入平台表达式
* 扩展表单表达式
*/
// 合并父级表达式
if (parentExpression) {
Object.keys(parentExpression).forEach(function(key) {
$[key] = parentExpression[key];
});
}
/**
* @example
* $.form.xxx()
*/
$.form = {
/**
* 获取业务受理号
*/
getBusinessNumber() {
return window.taskData ? window.taskData.businessNumber : '';
},
/**
* 通过字段名获取表单的值
* @param {String} field 表单控件绑定字段,如JOB_YWB-RID
*/
getFormValue(field) {
const formData = window.formData;
if (formData) {
let value = null;
Object.keys(formData).forEach(key => {
if (key === field) value = formData[key];
});
return value;
} else {
return null;
}
},
/**
* 通过字段名设置表单的值
* @param {String} field 表单控件绑定字段,如JOB_YWB-RID
* @param {Any} value 传值
*/
setFormValue(field, value) {
const formData = window.formData;
if (formData) {
Object.keys(formData).forEach(key => {
if (key === field) formData[key] = value;
});
}
},
/**
* 获取任务ID
*/
getTaskId() {
return window.taskData ? window.taskData.taskId : '';
},
/**
* 获取环节ID
*/
getLinkId() {
return window.taskData ? window.taskData.linkId : '';
},
/**
* 获取环节KEY
*/
getLinkKey() {
return window.taskData ? window.taskData.linkKey : '';
},
/**
* 获取流程实例ID
*/
getProcessInstanceId() {
return window.taskData ? window.taskData.processInstanceId : '';
},
/**
* 获取流程定义ID
*/
getProcessDefinitionId() {
return window.taskData ? window.taskData.processDefinitionId : '';
}
};
window.$ = $;
import { Notification } from 'element-ui';
/**
* 处理数值,默认返回px单位
* @param {string|nubmer} val
* @returns {stirng}
*/
export const handleNumUnit = val => {
return isNaN(Number(val)) ? val : val + 'px';
};
/**
* 获取URL参数
* @param {string} name 参数名
*/
export function getQueryString(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
const r = window.location.search.substr(1).match(reg);
if (r !== null) return unescape(r[2]);
return null;
}
export function getBusinessDefinitionId() {
return getQueryString('businessDefinitionId');
}
export function getFormId() {
return getQueryString('formid');
}
export function getTaskId() {
return getQueryString('taskId');
}
export function getLinkId() {
return getQueryString('linkId');
}
export function getLinkKey() {
return getQueryString('linkKey');
}
export function getFinishForm() {
return getQueryString('historyProcessInstanceId');
}
/**
* 统一处理提示
* @param {string} type success warning error
* @param {string} message 提示文字
* @param {string} title 提示标题
*/
export function notification(type, message, title) {
// Message[type](message)
title = title || '';
if (!title) {
switch (type) {
case 'success':
title = '操作成功';
break;
case 'info':
title = '提示';
break;
case 'warning':
title = '操作失败';
break;
case 'error':
title = '操作错误';
break;
}
}
Notification({
type: type,
title: title,
message: message,
position: 'top-right'
});
}
/**
* 外部页面公共通知方法
* @param {Object} options 和element-ui Notification组件属性一样
*/
export function outerNotice(options) {
const parentWin = window.parent;
parentWin.notification && parentWin.notification(options);
}
/**
* 打开标签
* @param {Object} component 组件的对象,比如 {id:'', name:'组织构架管理', componentName:'frameworkManage'}
* @param {Object} param 参数
*/
export function openTab(component, param) {
const parentWin = window.parent;
parentWin.openTab && parentWin.openTab(component, param);
}
/**
* 关闭标签
*/
export function closeTab() {
const parentWin = window.parent;
const tabId = parentWin.currentNavigation.id || '';
if (tabId) parentWin.removeTab && parentWin.removeTab(tabId);
}
/**
* 刷新标签页
*/
export function refreshTab(tabId) {
const parentWin = window.parent;
tabId =
tabId ||
(parentWin.currentNavigation &&
parentWin.currentNavigation.param &&
parentWin.currentNavigation.param.parent);
if (tabId) parentWin.refreshTab && parentWin.refreshTab(tabId);
}
// 设置高级或某此控件需要【数组】、【对象】类型
// 比如upload_list, sign
const checkObjectJson = data => {
const widgets = ['upload_list', 'sign', 'select'];
if (widgets.includes(data.type)) {
return data.model;
} else {
return '';
}
};
/**
* 遍历表单模板数据,返回需要【数组】、【对象】类型控件的models数据
* @param {Object} formdata
* @returns {Array} models
*/
export const transformFormData = formdata => {
if (!formdata.list) return;
const arr = [];
const fn = data => {
data.map(item => {
// console.log(item)
if (item.type === 'grid') {
item.columns.map(col => {
fn(col.list);
});
} else if (item.type !== 'text' && item.type !== 'button') {
const model = checkObjectJson(item);
if (model) arr.push(model);
}
});
};
fn(formdata.list);
return arr;
};
const utils = {
/**
* 判断数据是否为空,一般数据是object/array
* @param {Object/Array}
*/
isEmptyData(data) {
if (data === null || data === undefined) return true;
if (data instanceof Object) {
let t;
for (t in data) {
return false;
}
return true;
} else if (data instanceof Array) {
if (data.length === 0) return true;
return false;
}
},
/**
* 深拷贝
* @param {Object|Array} p
* @param {Object|Array} c [] or {}
*/
deepCopy(p, c) {
c = c || {};
for (const i in p) {
if (typeof p[i] === 'object') {
c[i] = p[i] ? (p[i] && p[i].constructor === Array ? [] : {}) : p[i];
this.deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
},
/**
* 随机生成唯一 ID
* @param {Number}
*/
generateId(len = 4) {
return Number(
Math.random()
.toString()
.substr(3, len) + Date.now()
).toString(36);
},
/**
* 优化遍历,数组去重
* @param {Array} array
*/
uniq(array, key) {
const temp = [];
const index = [];
const l = array.length;
for (let i = 0; i < l; i++) {
for (let j = i + 1; j < l; j++) {
if (array[i][key] && array[i][key] === array[j][key]) {
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
return temp;
}
};
export default utils;
const $ = window.parent ? window.parent.$ : {};
/**
* 全局作用在表单库里内部读取window上的方法
*
* taskData 是请求表单数据后注册到window上的对象,
* 包含{taskId, linkId, linkKey, processDefinitionId, processDefinitionKey, processInstanceId, businessNumber}
*/
window.getUser = $.system.getUser;
window.getUserName = $.system.getUserName;
window.getBussinessId = function() {
return window.taskData ? window.taskData.businessNumber : '';
};
<template>
<el-dialog :visible.sync="dialogVisible" title="查看业务办理指南" fullscreen @closed="handleClosed">
<el-tabs tab-position="left">
<el-tab-pane label="操作指南" v-html="htmlContent.ManagementGuide"></el-tab-pane>
<el-tab-pane label="填写说明" v-html="htmlContent.LinkDefinitionDescription"></el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script>
import Api from '@form/api';
export default {
name: 'GuideDialog',
props: ['data'],
data() {
return {
dialogVisible: false,
htmlContent: {
ManagementGuide: '',
LinkDefinitionDescription: ''
}
};
},
mounted() {
this.dialogVisible = true;
this.init();
},
destroyed() {
this.dialogVisible = false;
},
methods: {
init() {
Api.doGetPromise(this.data.api, {
processDefinitionId: this.data.processDefinitionId,
taskKey: this.data.linkKey
}).then(res => {
this.htmlContent = res;
});
},
handleClosed() {
this.$emit('closed');
}
}
};
</script>
<template>
<div class="return-work">
<el-dialog
class="return-work__dialog"
:visible.sync="dialogVisible"
title="退回工作"
@closed="handleClosed"
>
<el-container>
<el-aside width="200px">
<header>选择退回环节</header>
<section>
<ul>
<li
v-for="item in linkEntity"
:key="item.definitionKey"
:class="{'is-active': item.definitionKey === currentKey}"
@click="handleLinkClick(item.definitionKey)"
>{{ item.definitionName }}</li>
</ul>
</section>
</el-aside>
<el-main v-loading="isLoadingPeople">
<el-tabs type="card" v-model="currentTab">
<el-tab-pane label="默认处理人" name="default">
<el-tree
ref="mainTree"
:data="currentData.defUsers"
:props="treeProps"
default-expand-all
show-checkbox
node-key="id"
check-on-click-node
:default-checked-keys="defChecked"
>
<div class="custom-tree-node" slot-scope="{node, data}">
<span>{{ node.label }}</span>
<div class="flr">
<span>
待处理任务:
<strong>{{ data.count ? data.count : 0 }}</strong>条,
在职状态:
<strong>{{ handleUserState(data.organInfo.status) }}</strong>
</span>
</div>
</div>
</el-tree>
</el-tab-pane>
<el-tab-pane label="另选处理人" name="another">
<div class="framework-tree">
<el-tree
class="framework-tree__wrapper"
ref="anotherTree"
:data="currentData.anoUsers"
:props="treeProps"
default-expand-all
node-key="id"
check-on-click-node
highlight-current
@current-change="handleAnoTreeCurrentChange"
>
<div class="custom-tree-node" slot-scope="{node, data}">
<span>{{ node.label }}</span>
<div class="flr">
<span>
待处理任务:
<strong>{{ data.count ? data.count : 0 }}</strong>条,
在职状态:
<strong>{{ handleUserState(data.organInfo.status) }}</strong>
</span>
</div>
</div>
</el-tree>
</div>
</el-tab-pane>
</el-tabs>
<div class="submit-reason">
<div class="title">退回原因:</div>
<el-tooltip effect="dark" placement="right" content="不能为空" :disabled="!!reason">
<el-input
type="textarea"
v-model="reason"
:class="{'is-required': !reason}"
:rows="3"
placeholder="原因必填"
></el-input>
</el-tooltip>
</div>
</el-main>
</el-container>
<div slot="footer">
<!-- <el-checkbox v-model="isUrgent" style="margin-right: 15px;">紧急</el-checkbox> -->
<span style="margin-right: 15px;">
退回环节处理完成后的操作:
<el-radio-group v-model="returnType">
<el-radio :label="0">按流程定义提交</el-radio>
<el-radio :label="1">提交到本环节</el-radio>
</el-radio-group>
</span>
<el-button
type="primary"
:disabled="!currentKey"
:loading="isSubmiting"
@click="submitTask"
>提交</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import Api from '@form/api';
import { notification } from '@form/utils/form';
export default {
name: 'returnTask',
props: ['data'],
data() {
return {
dialogVisible: false,
linkEntity: [], // 有下个环节的主体
isLoadingPeople: false, // 加载下个环节人
currentTab: 'default',
currentKey: '', // 选中当前环节的Key
currentData: {
defUsers: null,
anoUsers: null
},
treeProps: {
label: 'fullName',
children: 'children'
},
defChecked: [],
anoChecked: '',
reason: '',
returnType: 0,
isSubmiting: false
};
},
mounted() {
this.init();
},
methods: {
init() {
if (!this.data) return;
/* this.dialogVisible = true // 测试弹窗打开
this.linkEntity = [{
definitionKey: 'eq9jn2y97g0',
definitionName: '收件'
}] */
Api.doGetPromise(this.data.api, {
taskId: this.data.taskId,
opertionType: 1
})
.then(res => {
// console.log(res)
if (res.length === 0) {
notification(
'info',
res.message || '任务没有历史,不可执行退回操作!'
);
this.handleClosed();
} else {
if (res[0]) {
// 有历史的,可以执行退回
this.dialogVisible = true;
this.linkEntity = [];
res.map(item => {
this.linkEntity.push(item.linkDefinitionEntity);
});
} else {
notification('info', '任务没有历史,不可执行退回操作!');
this.handleClosed();
}
}
})
.catch(err => {
notification('error', err.message || '退回服务失败!');
this.handleClosed();
});
},
handleUserState(status) {
if (status === 1 || status === 2) return '在职';
return '离职';
},
// 另选处理人的选中监听
handleAnoTreeCurrentChange(data) {
this.anoChecked = data.id;
},
// 获取退回环节的人员
getRerunPeople(nextLink) {
this.isLoadingPeople = true;
// Api.getRerunPeople('110c73b6-54f5-11e9-ba9c-005056c00001', '9b498463-04bc-11e9-a8ab-005056c00001', 'eq9jn2y97g0')
Api.getRerunPeople(
this.data.taskId,
this.data.processDefinitionId,
nextLink
)
.then(res => {
this.isLoadingPeople = false;
// console.log('getRerunPeople: ', res)
if (res.status === 0) {
const defUsers = res.data.defaultUserInfos;
const anoUsers = res.data.anotherUserInfos;
this.currentData.defUsers = [];
this.currentData.anoUsers = [];
for (const key in defUsers) {
defUsers[key].disabled = true;
defUsers[key].id = key;
this.defChecked.push(key);
this.currentData.defUsers.push(defUsers[key]);
}
for (const key in anoUsers) {
anoUsers[key].id = key;
this.currentData.anoUsers.push(anoUsers[key]);
}
// this.currentData = res.data
} else {
notification('warning', res.message || '获取人员失败,请重试!');
}
})
.catch(err => {
this.isLoadingPeople = false;
notification('error', err.message || '网络有误,请重试!');
});
},
handleClosed() {
this.$emit('closed');
},
// 环节点击
handleLinkClick(key) {
this.currentKey = key;
this.getRerunPeople(key);
},
submitTask() {
if (this.currentTab === 'another' && !this.anoChecked) {
notification('warning', '请选择另选处理人!');
return;
}
if (!this.reason) {
notification('warning', '请填写退回原因!');
return;
}
this.isSubmiting = true;
// 提交前先获取执行流程ID
Api.findExecutionIdByTaskId(this.data.taskId)
.then(res => {
if (res.status === 0) {
// 第四步,发送
const another =
this.currentTab === 'another' ? this.anoChecked : '';
// console.log(res.data, this.data.linkKey, this.reason, undefined, this.returnType, another)
Api.sendReturnTaks(
res.data,
this.currentKey,
this.reason,
undefined,
this.returnType,
another
)
.then(res => {
this.isSubmiting = false;
if (res.status === 0) {
notification('success', '退回成功!');
this.$emit('done');
} else {
notification(
'warning',
res.message || '退回提交失败,请重试!'
);
}
})
.catch(err => {
this.isSubmiting = false;
notification('error', err.message || '退回提交失败,请重试!');
});
} else {
this.isSubmiting = false;
notification('warning', res.message || '退回提交失败,请重试!');
}
})
.catch(err => {
this.isSubmiting = false;
notification('error', err.message || '退回提交失败,请重试!');
});
}
}
};
</script>
<template>
<el-dialog
:visible.sync="submitDialogVisible"
top="5%"
width="750px"
class="submit-dialog"
:modal-append-to-body="false"
title="选择处理人"
:close-on-click-modal="false"
@closed="handleDialogClosed">
<div class="submit-dialog__wrapper">
<div class="submit-dialog__sidebar">
<div class="submit-dialog__sidebar--title">
<span>下一环节</span>
</div>
<div class="submit-dialog__sidebar--content">
<!-- <ul>
<li v-for="link in nextLinks" :key="link.definitionKey">
<el-radio v-model="currentLink" :label="link" border>{{ link.definitionName }}</el-radio>
</li>
</ul> -->
<el-checkbox-group v-model="checkedLink">
<el-checkbox v-for="link in nextLinks" :key="link.definitionKey" :label="link" @change="handleCrrentLink(link)">
<span @click.stop.prevent="handleCrrentLink(link)">{{ link.definitionName }}</span>
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div class="submit-dialog__content">
<div class="users">
<div class="main-users">
<span class="title cate-title">{{ currentLink.name }}</span>
<span class="title">主要处理人</span>
<el-tree
ref="mainTree"
:data="currentLink.masterMen"
:props="treeProps"
node-key="id"
default-expand-all
show-checkbox
check-on-click-node
:default-checked-keys="mainCheckedKeys"
@check-change="handleMainTreeCheckChange">
<div class="custom-tree-node" slot-scope="{node, data}">
<span>{{ node.label }}</span>
<div class="flr" >
<span>
待处理任务:<strong>{{ data.count ? data.count : 0 }}</strong>条,
在职状态:<strong>{{ handleUserState(data.organInfo.status) }}</strong>
</span>
</div>
</div>
</el-tree>
</div>
<div class="normal-users">
<span class="title">一般处理人</span>
<el-tree
ref="narmalTree"
:data="currentLink.normalMen"
:props="treeProps"
node-key="id"
default-expand-all
show-checkbox
check-on-click-node
:default-checked-keys="normalCheckedKeys"
@check-change="handleNorTreeCheckChange">
<div class="custom-tree-node" slot-scope="{node, data}">
<span>{{ node.label }}</span>
<div class="flr" >
<span>待处理任务:{{ data.count ? data.count : 0 }}条,在职状态:{{ handleUserState(data.organInfo.status) }}</span>
</div>
</div>
</el-tree>
</div>
</div>
<div class="submit-reason">
<span>提交原因:</span>
<div>
<el-input type="textarea" :rows="3" v-model="subReson"></el-input>
</div>
</div>
</div>
</div>
<div slot="footer" class="submit-dialog__footer">
<el-checkbox v-model="isUrgent" style="margin-right: 15px;">紧急</el-checkbox>
<el-button type="primary" :disabled="checkedLink.length === 0" :loading="isSubmiting" @click="saveTask">保存</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'SubmitTask',
props: {
data: Object,
nextLinks: {
type: Array,
default: () => []
},
nextLinkUsers: {
type: [Array, Object],
default: () => []
}
},
data() {
return {
submitDialogVisible: false,
currentLink: '', // 环节的选择
checkedLink: [],
userStack: [], // 存储环节用户栈
selectionLink: [],
treeProps: {
label: 'fullName',
children: 'children'
},
mainCheckedKeys: [],
normalCheckedKeys: [],
subReson: '',
isUrgent: false,
isSubmiting: false,
isCanceling: false, // 取消中。。。
closedAction: 'close'
};
},
watch: {
nextLinks: {
immediate: true,
deep: false,
handler(val) {
if (val.length === 0) {
this.currentLink = '';
this.userStack = [];
return;
}
// 初始时,先把数据整合好
this.nextLinks.forEach(link => {
const masterMen = [];
const normalMen = [];
for (const user in this.nextLinkUsers) {
if (link.masterMen.includes(user)) {
this.nextLinkUsers[user].id = this.nextLinkUsers[user].organInfo.rid;
masterMen.push(this.nextLinkUsers[user]);
}
if (link.normalMen.includes(user)) {
this.nextLinkUsers[user].id = this.nextLinkUsers[user].organInfo.rid;
normalMen.push(this.nextLinkUsers[user]);
}
}
this.userStack.push({
...link,
id: link.definitionKey,
name: link.definitionName,
masterMen: masterMen,
normalMen: normalMen
});
});
}
},
currentLink(val) { // 选中当前环节处理
if (!val) return;
this.mainCheckedKeys = [];
this.normalCheckedKeys = [];
this.currentLink.masterMen.forEach(user => {
this.$set(user, 'checked', true);
// 如果提交所有人,禁止状态,不能改变选中
if (val.completingToAll) this.$set(user, 'disabled', true) ;
this.mainCheckedKeys.push(user.organInfo.rid);
});
this.currentLink.normalMen.forEach(user => {
this.$set(user, 'checked', true);
// 如果提交所有人,禁止状态,不能改变选中
if (val.completingToAll) this.$set(user, 'disabled', true);
this.normalCheckedKeys.push(user.organInfo.rid);
});
},
checkedLink(val) { // 环节选择监听
this.handleCheckChange();
}
},
mounted() {
this.submitDialogVisible = true;
// 默认显示第一条
this.currentLink = this.userStack[0];
},
methods: {
handleCrrentLink(link) {
this.userStack.forEach(item => {
if (item.id === link.definitionKey) {
this.currentLink = item;
}
});
},
handleUserState(status) {
if (status === 1 || status === 2) return '在职';
return '离职';
},
handleMainTreeCheckChange(data, isCheck, isLeaf) {
data.checked = isCheck;
},
// 一般处理人选择改变
handleNorTreeCheckChange(data, isCheck) {
data.checked = isCheck;
},
// 下一环节选择
handleCheckChange() {
this.selectionLink = [];
this.checkedLink.forEach(link => {
this.userStack.forEach(stack => {
if (link.definitionKey === stack.id) {
this.selectionLink.push(stack);
}
});
});
},
saveTask() {
if (this.selectionLink.length === 0) return;
this.isSubmiting = true;
let data = [];
this.selectionLink.forEach(link => {
const masterMens = [];
const normalMens = [];
const obj = {};
link.masterMen.forEach(user => {
if (user.checked) masterMens.push(user.id);
});
link.normalMen.forEach(user => {
if (user.checked) normalMens.push(user.id);
});
obj[link.id] = {
masterMens: masterMens,
normalMens: normalMens,
resion: this.subReson,
emergencyLevel: this.isUrgent ? 1 : 0
};
data.push(JSON.stringify(obj));
});
data = data.join(',');
this.$emit('save', data);
},
handleDialogClosed() {
this.$emit('closed', this.closedAction);
}
}
};
</script>
<template>
<div class="transform-work">
<el-dialog
class="transform-work__dialog"
:visible.sync="showCheckPeople"
title="转办操作"
width="600px"
top="2%"
:modal-append-to-body="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
@opened="handleCheckOpened"
@closed="handleClosed"
>
<el-tabs type="card">
<el-tab-pane label="选择处理人">
<div class="framework-tree">
<el-tree
class="framework-tree__wrapper"
ref="frameTreeCheckFirst"
:data="framesFirstData"
:props="{
label: 'organName'
}"
node-key="treeNodeId"
empty-text="无选择处理人"
:expand-on-click-node="false"
default-expand-all
highlight-current
@current-change="handleCurrentFirstChange"
>
<span class="custom-tree-node" slot-scope="{node, data}">
<span>
<i :class="['iconfont', data.iconCls]"></i>
{{ node.label }}
</span>
</span>
</el-tree>
</div>
</el-tab-pane>
<el-tab-pane label="另选处理人">
<div class="framework-tree">
<div class="framework-tree__header">
<el-input
placeholder="输入名称进行过滤"
v-model="filterText"
size="small"
prefix-icon="el-icon-search"
clearable
></el-input>
</div>
<el-tree
class="framework-tree__wrapper"
ref="frameTreeCheck"
:data="framesData"
:props="treeProps"
node-key="treeNodeId"
empty-text="无另选处理人"
:expand-on-click-node="false"
default-expand-all
highlight-current
:filter-node-method="filterNode"
@current-change="handleCurrentFirstChange"
>
<span class="custom-tree-node" slot-scope="{node, data}">
<span>
<i :class="['iconfont', data.iconCls]"></i>
{{ node.label }}
</span>
</span>
</el-tree>
</div>
</el-tab-pane>
</el-tabs>
<div class="transform-reason">
<div class="title">转办原因:</div>
<el-tooltip effect="dark" placement="right" content="不能为空" :disabled="!!reason">
<el-input
type="textarea"
v-model="reason"
:class="{'is-required': !reason}"
:rows="3"
placeholder="原因必填"
></el-input>
</el-tooltip>
</div>
<div slot="footer" class="transform-work__dialog--btns">
<el-checkbox
v-model="isEmergency"
:true-label="1"
:false-label="0"
style="margin-right: 10px;"
>紧急</el-checkbox>
<el-button type="primary" :loading="isSubmiting" @click="handleSave">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import Api from '@form/api';
import { notification } from '@form/utils/form';
/**
* 转办
*/
export default {
name: 'transformWork',
props: ['data'],
data() {
return {
showCheckPeople: false,
filterText: '',
treeProps: {
label: 'text',
children: 'children'
},
framesFirstData: null,
framesData: null,
checkedUser: null,
reason: '',
isEmergency: 0,
isSubmiting: false
};
},
watch: {
filterText(val) {
this.$refs['frameTreeCheck'].filter(val);
}
},
mounted() {
this.init();
},
methods: {
init() {
this.getTansformUser();
this.getOrganTree();
this.showCheckPeople = true;
},
getTansformUser() {
Api.getTranformUser(this.data.taskId)
.then(res => {
// console.log(res)
if (res.status === 0) {
// this.framesData = res.data
const data = res.data;
if (data.userInfos) {
const _data = [];
for (const item in data.userInfos) {
_data.push(item.organInfo);
}
this.framesFirstData = _data;
} else {
this.framesFirstData = data;
}
} else {
notification('warning', res.message || '获取转办人失败,请重试');
}
})
.catch(err => {
notification('error', err.message || '获取转办人失败');
});
},
getOrganTree() {
Api.getOrganTree(2, 1).then(res => {
if (res.status === 0) {
this.framesData = res.data;
}
});
},
filterNode(value, data) {
if (!value) return true;
return data[this.treeProps.label].indexOf(value) !== -1;
},
handleCurrentFirstChange(data) {
this.checkedUser = data;
},
handleSave() {
if (!this.checkedUser || this.checkedUser.attributes.organType !== 10) {
this.$alert('请选择或只能选择处理人', '提示', {
type: 'warning'
});
return;
}
if (this.reason) {
this.submitTransform();
}
},
submitTransform() {
// console.log(this.checkedUser)
const submitData = [
{
taskId: this.data['taskId'],
assignee: this.checkedUser.id || this.checkedUser.rid,
passToReanson: this.reason,
emergencyLevel: this.isEmergency
}
];
this.isSubmiting = true;
Api.doPostPromiseJson(this.data.api, submitData)
.then(res => {
this.isSubmiting = false;
if (res.status === 0) {
notification('success', '转办成功!');
this.$emit('save', res);
} else {
notification('warning', res.message || '转办失败,请重试');
}
})
.catch(err => {
this.isSubmiting = false;
notification('error', '转办失败' + err.message);
});
},
handleCheckOpened() {
this.$refs['frameTreeCheck'].setCurrentKey(null);
this.reason = '';
},
handleClosed() {
this.$emit('closed');
}
}
};
</script>
<template>
<div class="form-app">
<div v-if="loadError" style="margin-top: 60px; text-align: center;">
<i class="el-icon-warning" style="color: red"></i> 表单获取失败
</div>
<div class="form-header">
<el-button
v-for="(item,index) in headBtnLists"
:key="item.id"
:id="item.id"
:icon="item.icon"
size="small"
@click="handleMethod(item, index)"
>{{item.text}}</el-button>
<!-- 自定义按钮 -->
<el-button
v-for="(item, index) in headCustomBtns"
:key="index"
size="small"
@click="handleCustomBtn(item)"
>{{ item.operationName }}</el-button>
</div>
<div class="form-render" v-if="isReRender">
<smart-form :data="formData" :value="values" ref="generateForm"></smart-form>
</div>
<template v-if="isLoading">
<div class="app-loading" v-loading="isLoading" element-loading-text="加载处理中..."></div>
</template>
<!-- 办理指南 -->
<guide-dialog
v-if="guideDialogVisible"
:data="childrenData"
@closed="guideDialogVisible = false"
></guide-dialog>
<!-- 提交弹窗选择环节处理人 -->
<submit-task
v-if="submitTaskDialogVisible"
:data="childrenData"
ref="submitTask"
:nextLinks="submitData.subTask"
:nextLinkUsers="submitData.userInfos"
@closed="submitTaskDialogVisible = false"
@save="handleSubmitTaskSave"
></submit-task>
<!-- 转办 -->
<transform-work
v-if="transformDialogVisible"
:data="childrenData"
@closed="transformDialogVisible = false"
@save="handleTransformTaskSave"
></transform-work>
<!-- 退回 -->
<return-task
v-if="returnTaskVisible"
:data="childrenData"
@closed="returnTaskVisible = false"
@done="handleReturnTaskDone"
></return-task>
</div>
</template>
<script>
import SubmitTask from './common/submitTask.vue';
import TransformWork from './common/transformWork.vue';
import GuideDialog from './common/guide.vue';
import ReturnTask from './common/returnTask.vue';
// import Utils from '@form/utils'
import {
transformFormData,
getBusinessDefinitionId,
getFormId,
getTaskId,
getLinkId,
getLinkKey,
getFinishForm,
notification,
outerNotice,
openTab,
closeTab,
refreshTab
} from '@form/utils/form';
import Api from '@form/api';
import btnsSourceMap from '@form/config/btnsSourceMap';
export default {
name: 'formView',
components: {
// generateForm
SubmitTask,
TransformWork,
GuideDialog,
ReturnTask
},
computed: {
loadError() {
return (
!this.isLoading &&
(!this.formData || Object.keys(this.formData).length === 0)
);
},
isSelect() {
return !!getFormId();
}
},
data() {
return {
apiFnName: '', // 加载API的方法名
isLoading: false, // 加载过渡
isReRender: true, // 重渲染
headBtnLists: [], // 头部的按钮列表
headCustomBtns: [], // 头部自定义按钮,一般包含表达式
formData: {},
values: {},
childrenData: {
taskId: getTaskId(),
linkId: getLinkId(),
linkKey: getLinkKey()
},
guideDialogVisible: false, // 办理指南dialog
submitTaskDialogVisible: false, // 提交dialog
submitData: {},
transformDialogVisible: false, // 转办dialog
returnTaskVisible: false // 退回dialog
};
},
created() {
this.init();
},
mounted() {
/* this.$refs['generateForm'].$on('form-item-click', (widget, isChecked) => {
console.log(widget, isChecked)
}) */
},
methods: {
init() {
this.fetch();
},
// 刷新
refresh() {
this.fetch();
},
handleResultHtml(data, key) {
try {
data = JSON.parse(data);
return data.data[key];
} catch (error) {
console.error(error);
return {};
}
},
fetch() {
let taskId = getTaskId() || this.childrenData.taskId;
const linkId = getLinkId() || this.childrenData.linkId;
const linkKey = getLinkKey() || this.childrenData.linkKey;
// console.log(taskId, linkId, linkKey)
let apiFn = 'renderFormByTaskId';
if (getBusinessDefinitionId()) {
// 创建时请求
taskId = getBusinessDefinitionId();
apiFn = 'getBusinessStartForm';
} else if (getFormId()) {
// 通过formid去获取表单值
taskId = getFormId();
apiFn = 'getForm';
} else if (getFinishForm()) {
taskId = getFinishForm();
apiFn = 'renderFinishForm';
}
this.isLoading = true;
Api[apiFn](taskId, linkId, linkKey)
.then(res => {
this.isLoading = false;
if (res.status === 0) {
// 判断是通过ID获取的模板渲染
if (getFormId()) {
const data = res.data.form;
this.formData = JSON.parse(data.templatejson) || {};
} else {
const detailMap = res.data.detailMap;
const ourselfOperationShow = detailMap.ourselfOperationShow;
const result = detailMap.result;
// 头部按钮初始化
if (ourselfOperationShow) {
const headBtnLists = [];
btnsSourceMap.forEach(item => {
if (ourselfOperationShow[item.name]) {
headBtnLists.push(item);
}
});
this.headBtnLists = headBtnLists;
// 自定义按钮
let operationConfigs;
try {
operationConfigs = JSON.parse(detailMap.operationConfigs);
} catch {
throw new Error('自定义按钮数据格式有误');
}
this.headCustomBtns = operationConfigs[0];
// console.log('header buttons: ', ourselfOperationShow, this.headCustomBtns)
}
// 其他属性赋值
this.childrenData['taskId'] = detailMap.taskId;
this.childrenData['linkId'] = detailMap.linkInstanceId;
this.childrenData['linkKey'] = detailMap.linkDefinitionKey;
this.childrenData['processDefinitionId'] =
detailMap.processDefinitionId;
this.childrenData['processDefinitionKey'] =
detailMap.processDefinitionKey;
this.childrenData['processInstanceId'] =
detailMap.processInstanceId;
this.childrenData['businessNumber'] = detailMap.businessNumber;
// window上注册 taskData 全局属性,主要表单内部使用
// this.$store.dispatch('setTaskData', this.childrenData)
window.taskData = this.childrenData;
if (result) {
const _data = this.handleResultHtml(
detailMap['result'],
'template'
);
this.formData = JSON.parse(_data) || {};
this.handleModels(
this.handleResultHtml(detailMap['result'], 'values')
);
}
}
} else {
this.$message({
type: 'warning',
message: res.message || '获取表单数据失败,请重试'
});
}
})
.catch(err => {
this.isLoading = false;
this.$message({
type: 'error',
message: err.message || '获取表单数据错误,服务连接错误'
});
});
},
// 绑定的models处理
handleModels(values) {
// console.log('handleModels:', values)
const obj = {};
// 表单数据处理,返回数据处理Array models
const models = transformFormData(this.formData);
// 主要处理JSON
Object.keys(values).forEach(key => {
// console.log(key, values[key])
if (models.indexOf(key) >= 0 && values[key] !== null) {
try {
obj[key] = JSON.parse(values[key]);
} catch {
obj[key] = values[key];
}
} else {
obj[key] = values[key];
}
});
this.values = obj;
// window上注册 formData 表单数据 全局属性
window.formData = this.values;
},
/**
* 统一处理data里的返回的错误
* 比如:data: [{status: 1, messaget: ''}]
*/
handleDataReturnErr(data, message) {
if (Array.isArray(data)) {
if (data[0].status === 0) {
notification('success', message);
// 刷新
this.refresh();
} else {
notification('warning', data[0].message);
}
} else {
notification('success', message);
}
},
// 头部按钮点击操作
handleMethod(item, index) {
this.childrenData.api = item.api;
switch (item.name) {
// 有一些操作不需要验证表单
case 'guidance':
this.openGuide(item.api);
break;
case 'save':
this.saveForm(item.api);
break;
case 'sign':
this.signTask(item.api);
break;
case 'forceSign':
this.forceSignTask(item.api);
break;
case 'finish':
this.finishTask(item.api);
break;
case 'refund':
this.refundTask(item.api);
break;
case 'urge':
this.remindTask(item.api);
break;
case 'turn':
this.transformTask(item.api);
break;
case 'unsign':
this.unclaimTask(item.api);
break;
case 'apply':
case 'suspend':
this.suspendTask(item.api, item.name);
break;
case 'activeSuspend':
this.activeSuspend(item.api);
break;
case 'withdraw':
this.withdrawTask(item.api);
break;
case 'rerun':
this.retrunTask(item.api);
break;
case 'getdraw':
this.checkTransfer();
break;
case 'isSendBack':
this.submitBackForm(item.api);
break;
case 'submit':
// this.submitForm(item.api)
this.handleValidate().then(valid => {
if (valid) this.submitForm(item.api);
});
break;
}
// console.log(this.$refs['generateForm'].getData())
},
/**
* 表单验证处理
*/
handleValidate() {
return new Promise((resolve, reject) => {
this.$refs['generateForm']
.validate()
.then(valid => {
if (valid) {
resolve(valid);
} else {
notification('warning', '表单未填写完整,请验证后再操作');
// reject(new Error('表单验证错误'))
}
})
.catch(err => {
notification('error', '表单未填写完整,请验证后再操作');
reject(err);
});
});
},
/**
* 处理表单数据,提交
*/
handleFormData() {
const formData = this.$refs['generateForm'].getData();
const fomrDataSub = new FormData();
Object.keys(formData).map(key => {
let value = formData[key];
// 转JSON字符串提交
if (typeof formData[key] === 'object' && formData[key] !== null) {
value = JSON.stringify(formData[key]);
}
fomrDataSub.append(key, value);
});
return fomrDataSub;
},
// 办理指南
openGuide(apiUrl) {
this.guideDialogVisible = true;
},
// 保存表单操作
saveForm(apiUrl) {
const fomrDataSub = this.handleFormData();
const taskId = getTaskId() || this.childrenData.taskId;
this.isLoading = true;
Api.doPostPromiseForm(apiUrl + '/' + taskId, fomrDataSub)
.then(res => {
this.isLoading = false;
// console.log(res)
if (res.status === 0) {
notification('success', '保存成功!');
} else {
notification('warning', res.message || '保存失败,请重试!');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '保存失败,请重试!');
});
},
// 提示表单操作
submitForm(apiUrl) {
const fomrDataSub = this.handleFormData();
this.isLoading = true;
// 先检查是否需要弹窗选择下一处理人
Api.checkAndSubmitTaskByFormData(
getTaskId() || this.childrenData.taskId,
fomrDataSub
)
.then(res => {
this.isLoading = false;
if (res.status === 0) {
const data = res.data;
if (data.submitStatus === 1) {
// 需要选择处理人,弹窗处理
this.submitData.subTask = data.subTask;
this.submitData.userInfos = data.userInfos;
this.submitTaskDialogVisible = true;
} else {
// 关闭和刷新标签页
setTimeout(() => {
refreshTab();
closeTab();
outerNotice({
type: 'success',
title: '提交成功',
message: res.message
});
}, 150);
}
} else {
notification('warning', res.message || '提交失败!');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '提交错误');
});
},
// 提交弹窗保存操作提交下一环节及处理人
handleSubmitTaskSave(data) {
Api.doPostPromise(this.childrenData.api, {
taskId: this.childrenData.taskId,
submitData: data
})
.then(res => {
if (this.$refs['submitTask']) {
this.$refs['submitTask'].$data.isSubmiting = false;
}
if (res.status === 0) {
this.submitTaskDialogVisible = false;
// 关闭标签
setTimeout(() => {
refreshTab();
closeTab();
outerNotice({
type: 'success',
title: '提交成功',
message: res.message
});
}, 150);
} else {
notification('warning', res.message || '提交失败!');
}
})
.catch(err => {
if (this.$refs['submitTask']) {
this.$refs['submitTask'].$data.isSubmiting = false;
}
notification('error', err.message || '提交错误');
});
},
// 提交返回操作
submitBackForm(apiUrl) {
notification('error', '功能暂时未开发');
},
// 接办
signTask(apiUrl) {
// console.log(apiUrl)
const submitData = [
{
taskId: getTaskId(),
jid: this.childrenData.businessNumber
}
];
this.isLoading = true;
this.isReRender = false;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
this.isReRender = true;
// console.log('signTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '接办成功');
// 刷新
this.refresh();
} else {
notification('warning', res.message || '接办失败,请重试');
}
})
.catch(err => {
this.isLoading = false;
this.isReRender = true;
notification('error', err.message || '接办失败!');
});
},
// 撤办
unclaimTask(apiUrl) {
const submitData = [
{
taskId: getTaskId(),
jid: this.childrenData.businessNumber
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '撤办成功');
} else {
notification('warning', res.message || '撤办失败,请重试');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '撤办失败!');
});
},
// 强制接办
forceSignTask(apiUrl) {
notification('error', '功能暂时未开发');
},
// 结档
finishTask(apiUrl) {
notification('error', '功能暂时未开发');
},
// 退件
refundTask(apiUrl) {
this.$prompt('请输入退件原因', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValidator: function(value) {
if (!value) return false;
return true;
},
inputErrorMessage: '原因不能空!'
}).then(({ value }) => {
const submitData = [
{
taskId: getTaskId(),
refundReason: value,
jid: this.childrenData.businessNumber
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '退件成功');
} else {
notification('warning', res.message || '退件失败,请重试');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '退件失败!');
});
});
},
// 催办
remindTask(apiUrl) {
this.$prompt('请输入催办信息', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValidator: function(value) {
if (!value) return false;
return true;
},
inputErrorMessage: '信息不能空!'
}).then(({ value }) => {
const submitData = [
{
taskId: getTaskId(),
message: value,
jid: this.childrenData.businessNumber
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '催办成功');
} else {
notification('warning', res.message || '催办失败,请重试');
}
})
.catch(err => {
notification('error', err.message || '催办失败!');
});
});
},
// 转办
transformTask(apiUrl) {
this.transformDialogVisible = true;
},
// 转办成功
handleTransformTaskSave(res) {
this.transformDialogVisible = false;
// 关闭和刷新
refreshTab();
closeTab();
// 外部提示通知
outerNotice({
type: 'success',
title: '转办成功',
message: res.message
});
},
// 申请挂起、挂起
suspendTask(apiUrl, type) {
const text = type === 'apply' ? '申请挂起' : '挂起';
this.$prompt(`请输入${text}原因`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValidator: function(value) {
if (!value) return false;
return true;
},
inputErrorMessage: '原因不能空!'
}).then(({ value }) => {
const submitData = [
{
taskId: getTaskId(),
suspendReason: value
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, `${text}成功'`);
} else {
notification('warning', res.message || `${text}失败,请重试`);
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || `${text}失败!`);
});
});
},
// 解除挂起
activeSuspend(apiUrl) {
const submitData = [
{
taskId: getTaskId()
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '解除挂起成功');
} else {
notification('warning', res.message || '解除挂起失败,请重试');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '解除挂起失败!');
});
},
// 收回
withdrawTask(apiUrl) {
const submitData = [
{
processDefinitionId: this.childrenData.processDefinitionId,
processInstanceId: this.childrenData.processInstanceId,
// taskId: getTaskId(),
linkDefinitionKey: this.childrenData.linkKey
}
];
this.isLoading = true;
Api.doPostPromiseJson(apiUrl, submitData)
.then(res => {
this.isLoading = false;
// console.log('receiveTasks', res)
if (res.status === 0) {
this.handleDataReturnErr(res.data, '收回成功');
} else {
notification('warning', res.message || '收回失败,请重试');
}
})
.catch(err => {
this.isLoading = false;
notification('error', err.message || '收回失败!');
});
},
// 退回
retrunTask(apiUrl) {
this.returnTaskVisible = true;
},
// 退回成功操作提交
handleReturnTaskDone() {
this.returnTaskVisible = false;
// 刷新
this.refresh();
},
// 查看流转
checkTransfer() {
const component = {
id:
this.childrenData.taskId + '_' + this.childrenData.processInstanceId,
name: '查看流程窗口',
componentName: 'checkProcess'
};
const param = {
processInstanceId: this.childrenData.processInstanceId
};
openTab(component, param);
},
// 自定义按钮点击
handleCustomBtn(item) {
// console.log(item)
if (item.operation) {
/* eslint-disable no-eval */
eval(item.operation);
}
}
}
};
</script>
<template>
<div class="page-view">
<div v-if="loadError" style="margin-top: 60px; text-align: center;">
<i class="el-icon-warning" style="color: red"></i> 配置页获取失败
</div>
<template v-if="isLoading">
<div class="app-loading" v-loading="isLoading" element-loading-text="加载处理中..."></div>
</template>
<smart-page :data="templateData" :page-info="pageInfo"></smart-page>
</div>
</template>
<script>
/**
* 渲染快速功能配置页
* smart-page
*/
import { getQueryString } from '@form/utils/form';
import config from '@form/api/config';
export default {
name: 'PageView',
props: {
id: String
},
data() {
return {
isLoading: true,
loadError: false,
templateData: null,
pageInfo: null
};
},
mounted() {
if (!this.id) return;
this.getTemplate();
this.getAuthories();
},
methods: {
getTemplate() {
this.isLoading = true;
config.doGetPromise('/v1.1.0/report/searchTemplate', { rid: this.id }).then(res => {
this.isLoading = false;
if (res.status === 0) {
const data = res.data.reportInfo;
this.templateData = JSON.parse(data.templatejson);
delete data.templatejson;
this.pageInfo = { ...this.pageInfo, ...data };
} else {
this.$message.warning(res.message || '获取页面模板数据有误!');
this.loadError = true;
}
}).catch(err => {
this.$message.error(err.message || '获取页面模板数据有误!');
this.isLoading = false;
this.loadError = true;
});
},
// 获取模块权限,赋值到pageInfo
getAuthories() {
const systemInfo = window.$ ? window.$.system.getSystemInfo() : null;
const systemId = systemInfo ? systemInfo.systemId : '';
const moduleId = getQueryString('moduleId');
config.doGetPromise('/authorityManage/queryUserSysAuthorizeInfoList', {
systemId,
moduleId
}).then(res => {
if (res.status === 0) {
if (!this.pageInfo) this.pageInfo = {};
this.pageInfo.authorities = res.data.sysAuthorizeList;
} else {
this.$message.warning(res.message || '获取权限异常!');
}
});
}
}
};
</script>
{
"name": "smart-web",
"description": "{{description}}",
"version": "1.0.0",
"author": "zengyl@southzn.com",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"core-js": "^2.6.5",
"smart-web": "^2.2.1",
"vue": "^2.6.10",
"vue-router": "^3.1.3"
},
"devDependencies": {
"@smart/eslint-config-standard": "^0.1.0",
"@vue/cli-plugin-babel": "^3.10.0",
"@vue/cli-plugin-eslint": "^3.10.0",
"@vue/cli-plugin-unit-mocha": "^3.10.0",
"@vue/cli-service": "^3.10.0",
"@vue/test-utils": "1.0.0-beta.29",
"babel-eslint": "^10.0.1",
"chai": "^4.1.2",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.0",
"vue-template-compiler": "^2.6.10"
}
}
module.exports = {
plugins: {
autoprefixer: {}
}
};
<!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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>smart web tabs sample.</title>
</head>
<body>
<noscript>
<strong>We're sorry but smart-web-tabs 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>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
};
</script>
import Vue from 'vue';
import axios from 'axios';
import qs from 'qs';
import store from '../store';
import * as _config from '@config/http.config';
import { Message } from 'element-ui';
// 携带cookie信息
axios.defaults.withCredentials = true;
// 设置全局的请求次数,请求的间隙
axios.defaults.retry = 1;
axios.defaults.retryDelay = 1000;
// 设置defaults.baseURL
axios.defaults.baseURL = _config.baseUrl;
// 请求超时拦截,重新请求
axios.interceptors.response.use(function(response) {
const status = response.status;
// const data = response.data;
if (status !== 200) {
Message({
type: 'error',
message: '请求服务好像出错了,' + status
});
return Promise.reject(response);
}/* else if (data.status === 2) {
Message({
type: 'error',
message: '请求服务后台处理出现了错误'
});
} else if (data.status === 1) {
Message({
type: 'warning',
message: '请求服务处理出现了异常,' + data.message
});
} */
return Promise.resolve(response);
}, function axiosRetryInterceptor(err) {
const config = err.config;
// If config does not exist or the retry option is not set, reject
if (!config || !config.retry) return Promise.reject(err);
// Set the variable for keeping track of the retry count
config.__retryCount = config.__retryCount || 0;
// Check if we've maxed out the total number of retries
if (config.__retryCount >= config.retry) {
const status = err.response.status;
Message({
type: 'error',
message: `请求服务好像出错了,状态码:${status}`
});
// Reject with the error
return Promise.reject(err);
}
// Increase the retry count
config.__retryCount += 1;
// Create new promise to handle exponential backoff
const backoff = new Promise(function(resolve) {
setTimeout(function() {
resolve();
}, config.retryDelay || 1);
});
// Return the promise in which recalls axios to retry the request
return backoff.then(function() {
return axios(config);
});
});
const CancelToken = axios.CancelToken;
let cancel;
const config = {
/**
* get获取数据,通用方法
* @param {String} url
* @param {Object} params
* @param {Object} options
*/
doGetPromise(url, params, options = {}) {
const { timeout = 30000, ...arg } = options;
return new Promise((resolve, reject) => {
axios.get(url, {
timeout: timeout,
...arg,
params: {
systemId: store.state.platformInfo.systemId, // 全面接口添加systemId字段
...params,
t: new Date().getTime() // 解决IE上get请求缓存问题
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
}).then(response => {
resolve(response.data);
}).catch(response => {
// console.error('ajax error:', response)
reject(response);
});
});
},
/**
* FormData数据上传,文件上传必用
* @param {String} url
* @param {FormData} formData
*/
doPostPromiseForm(url, formData) {
return new Promise((resolve, reject) => {
// 全面接口添加systemId字段
if (formData.has) { // ie FormData没有has方法
if (formData.has('systemId')) formData.append('systemId', store.state.platformInfo.systemId);
}
axios.post(url, formData, {
headers: {
'Content-type': 'multipart/form-data'
},
emulateJSON: false,
emulateHTTP: false,
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
}).then(res => {
resolve(res.data);
}).catch(res => {
console.log('post error:', res);
reject(res);
});
});
},
/**
* 默认方式提交from表单数据
* @param {String} url
* @param {Object} data
*/
doPostPromise(url, data) {
return new Promise((resolve, reject) => {
// 全面接口添加systemId字段
if (!data.hasOwnProperty('systemId')) data.systemId = store.state.platformInfo.systemId;
axios.post(url, qs.stringify(data), {
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
}).then(res => {
resolve(res.data);
}).catch(res => {
// console.log('post error:', res)
reject(res);
});
});
},
/**
* 默认方式提交json数据
* @param {String} url
* @param {Object} data
*/
doPostPromiseJson(url, data) {
return new Promise((resolve, reject) => {
// 全面接口添加systemId字段
if (!data.hasOwnProperty('systemId')) data.systemId = store.state.platformInfo.systemId;
axios.post(url, data, {
headers: {
'Content-type': 'application/json'
},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
}).then(res => {
resolve(res.data);
}).catch(res => {
console.log('post error:', res);
reject(res);
});
});
}
};
// 切换页面强行中断请求 router.beforeEach中用到
Vue.prototype.$cancelAjax = function(msg) {
if (cancel) {
cancel(msg || '手动中断请求');
}
};
export default config;
import config from './config';
const Api = {
/**
* 获取系统信息
* @param {String} sysCode 系统code
*/
getSystemInfo(sysCode) {
return config.doGetPromise('/index/getSystemCfgBeforeLogin', {sysCode});
},
login(data) {
return config.doPostPromise('/index/login', data);
},
checkLogin() {
return config.doGetPromise('/index/checkLogin', {}, { retry: 0 });
},
logout() {
return config.doGetPromise('/index/logout', {});
},
getAdminDivisionTree() {
return config.doGetPromise('/administrativeDivisions/getAdministrativeDivisionTree');
},
/**
* 获取用户权限下的系统模块功能
* @param {String} systemId 子系统Id
* @param {type} 类型:0-菜单,1-功能点
*/
getUserModulesTreeBySystemId(systemId, type = 0) {
return config.doGetPromise('/systemModule/getUserModulesTree', {
systemId,
type
});
},
/**
* 获取系统模块功能
* @param {String} id 子系统Id
* @param {Number(0,1)} 类型:0-菜单,1-功能点,默认是0
*/
getSystemAllModules(id, type = 0) {
return config.doGetPromise('/systemModule/getSystemAllModulesTree', {
systemId: id,
type
});
},
/**
* 获取组织结构的树状信息
* @param {Number} type 类型,1:只返回部门岗位信息; 2:返回部门岗位与人员信息; 3:返回角色信息; 4:返回部门(无岗位);5:返回人员;其他:返回所有组织项信息
* @param {Number} valid 是否可用, -1:审核中 1:可用(第一次登录,需要修改密码) 2:可用(非第一次登录,不需要修改密码)
*/
getOrganTree(type, valid) {
return config.doGetPromise('/organization/manager/getOrganTree', {
type: type,
valid: valid
});
},
// 获取代码字典
getChildItemByRootCode(data) {
return config.doGetPromise('/codeDict/getChildItemByRootCode', data);
},
/**
* 获取用户拥有的业务
* @param {String} userId
*/
getBusinessTree(userId) {
return config.doGetPromise('/business/system/businessDefTreeByUserId', {
userId: userId
});
},
/**
* 获取个人配置
* @param {String} type 配置信息类型;其中1:个人配置 ,2:业务配置,3:功能配置,4:主题配置
*/
getUserConfigTheme(type = 4) {
return config.doGetPromise('/personalConfigure/listAllInfo', {
infoType: type
});
},
/**
* 根据模块查询用户的权限
*/
getUserAuthories(moduleId) {
return config.doGetPromise('/authorityManage/queryUserSysAuthorizeInfoList', {
moduleId
});
}
};
export default Api;
import axios from 'axios';
import store from '@/store';
import router from '@/router';
import MessageBox from 'element-ui/lib/message-box';
/* const filters = ['webgisService']
const handleFilter = (key) => {
if (Array.isArray(filters)) {
filters.map(item => {
if (item === key) {}
})
}
} */
/**
* 登录判断失效
* 在所有经过axios请求中,拦截到登录失效
*
* @param {Object} response
*/
let isOtherLogin = false;
function loginInterceptor(response) {
// 9: 此账号在其他地方登陆
// 8: 账号登录已经失效
if (response.data && response.data.status === 8) {
if (!isOtherLogin) {
store.dispatch('setUserInfo', {});
router.replace({
name: 'LoginDialog',
query: router.currentRoute.query
});
isOtherLogin = false;
// response.data = null
}
return response;
} else if (response.data && response.data.status === 9) {
if (!isOtherLogin) {
isOtherLogin = true;
store.dispatch('setUserInfo', {});
MessageBox.alert('该账号在别的地方登录了,请重新登录', '提示', {
type: 'warning',
confirmButtonText: '登录',
callback: action => {
isOtherLogin = false;
if (action === 'confirm') {
router.replace({
name: 'LoginDialog',
query: router.currentRoute.query
});
}
}
});
}
return response;
} else {
return response;
}
}
axios.interceptors.response.use(loginInterceptor);
<template>
<div class="errorPage">
<p class="num">404</p>
<div class="des">
<h4>您的页面或组件找不到!</h4>
<p>1. 您的路由设置不正确</p>
<p>2. 您的组件未注册</p>
</div>
</div>
</template>
<template>
<div class="errorPage">
<p class="num">403</p>
<div class="des">
<h4>您的系统查找不到或无访问权限!!!</h4>
<h4>请检查您的系统代码或ID是否正确</h4>
</div>
</div>
</template>
import STabPane from '../tabs/src/tab-pane.vue';
/* istanbul ignore next */
STabPane.install = function(Vue) {
Vue.component(STabPane.name, STabPane);
};
export default STabPane;
import STabs from './src/tabs';
/* istanbul ignore next */
STabs.install = function(Vue) {
Vue.component(STabs.name, STabs);
};
export default STabs;
<template>
<div class="s-tabs__active-bar" :class="`is-${ rootTabs.tabPosition }`" :style="barStyle"></div>
</template>
<script>
export default {
name: 'TabBar',
props: {
tabs: Array
},
inject: ['rootTabs'],
computed: {
barStyle: {
cache: false,
get() {
if (!this.$parent.$refs.tabs) return {};
const style = {};
let offset = 0;
let tabSize = 0;
const sizeName = ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'width' : 'height';
const sizeDir = sizeName === 'width' ? 'x' : 'y';
const firstUpperCase = str => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
};
this.tabs.every((tab, index) => {
const $el = this.$parent.$refs.tabs[index];
if (!$el) { return false; }
if (!tab.active) {
offset += $el[`client${firstUpperCase(sizeName)}`];
return true;
} else {
tabSize = $el[`client${firstUpperCase(sizeName)}`];
if (sizeName === 'width' && this.tabs.length > 1) {
tabSize -= (index === 0 || index === this.tabs.length - 1) ? 20 : 40;
}
return false;
}
});
if (sizeName === 'width' && offset !== 0) {
offset += 20;
}
const transform = `translate${firstUpperCase(sizeDir)}(${offset}px)`;
style[sizeName] = tabSize + 'px';
style.transform = transform;
style.msTransform = transform;
style.webkitTransform = transform;
return style;
}
}
}
};
</script>
<script>
import TabBar from './tab-bar';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
function noop() {}
const firstUpperCase = str => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
};
export default {
name: 'TabNav',
components: {
TabBar
},
inject: ['rootTabs'],
props: {
panes: Array,
currentName: String,
editable: Boolean,
onTabClick: {
type: Function,
default: noop
},
onTabRemove: {
type: Function,
default: noop
},
onTabOtherRemove: {
type: Function,
default: noop
},
onTabAllRemove: {
type: Function,
default: noop
},
type: String,
stretch: Boolean,
navContextmenu: Boolean
},
data() {
return {
scrollable: false,
navOffset: 0,
isFocus: false,
focusable: true
};
},
computed: {
navStyle() {
const dir = ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'X' : 'Y';
return {
transform: `translate${dir}(-${this.navOffset}px)`
};
},
sizeName() {
return ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'width' : 'height';
}
},
methods: {
scrollPrev() {
const containerSize = this.$refs.navScroll[`offset${ firstUpperCase(this.sizeName) }`];
const currentOffset = this.navOffset;
if (!currentOffset) return;
const newOffset = currentOffset > containerSize
? currentOffset - containerSize
: 0;
this.navOffset = newOffset;
},
scrollNext() {
const navSize = this.$refs.nav[`offset${ firstUpperCase(this.sizeName) }`];
const containerSize = this.$refs.navScroll[`offset${ firstUpperCase(this.sizeName) }`];
const currentOffset = this.navOffset;
if (navSize - currentOffset <= containerSize) return;
const newOffset = navSize - currentOffset > containerSize * 2
? currentOffset + containerSize
: (navSize - containerSize);
this.navOffset = newOffset;
},
scrollToActiveTab() {
if (!this.scrollable) return;
const nav = this.$refs.nav;
const activeTab = this.$el.querySelector('.is-active');
if (!activeTab) return;
const navScroll = this.$refs.navScroll;
const activeTabBounding = activeTab.getBoundingClientRect();
const navScrollBounding = navScroll.getBoundingClientRect();
const maxOffset = nav.offsetWidth - navScrollBounding.width;
const currentOffset = this.navOffset;
let newOffset = currentOffset;
if (activeTabBounding.left < navScrollBounding.left) {
newOffset = currentOffset - (navScrollBounding.left - activeTabBounding.left);
}
if (activeTabBounding.right > navScrollBounding.right) {
newOffset = currentOffset + activeTabBounding.right - navScrollBounding.right;
}
newOffset = Math.max(newOffset, 0);
this.navOffset = Math.min(newOffset, maxOffset);
},
update() {
if (!this.$refs.nav) return;
const sizeName = this.sizeName;
const navSize = this.$refs.nav[`offset${ firstUpperCase(sizeName) }`];
const containerSize = this.$refs.navScroll[`offset${ firstUpperCase(sizeName) }`];
const currentOffset = this.navOffset;
if (containerSize < navSize) {
const currentOffset = this.navOffset;
this.scrollable = this.scrollable || {};
this.scrollable.prev = currentOffset;
this.scrollable.next = currentOffset + containerSize < navSize;
if (navSize - currentOffset < containerSize) {
this.navOffset = navSize - containerSize;
}
} else {
this.scrollable = false;
if (currentOffset > 0) {
this.navOffset = 0;
}
}
},
changeTab(e) {
const keyCode = e.keyCode;
let nextIndex;
let currentIndex, tabList;
if ([37, 38, 39, 40].indexOf(keyCode) !== -1) { // 左右上下键更换tab
tabList = e.currentTarget.querySelectorAll('[role=tab]');
currentIndex = Array.prototype.indexOf.call(tabList, e.target);
} else {
return;
}
if (keyCode === 37 || keyCode === 38) { // left
if (currentIndex === 0) { // first
nextIndex = tabList.length - 1;
} else {
nextIndex = currentIndex - 1;
}
} else { // right
if (currentIndex < tabList.length - 1) { // not last
nextIndex = currentIndex + 1;
} else {
nextIndex = 0;
}
}
tabList[nextIndex].focus(); // 改变焦点元素
tabList[nextIndex].click(); // 选中下一个tab
this.setFocus();
},
setFocus() {
if (this.focusable) {
this.isFocus = true;
}
},
removeFocus() {
this.isFocus = false;
},
visibilityChangeHandler() {
const visibility = document.visibilityState;
if (visibility === 'hidden') {
this.focusable = false;
} else if (visibility === 'visible') {
setTimeout(() => {
this.focusable = true;
}, 50);
}
},
windowBlurHandler() {
this.focusable = false;
},
windowFocusHandler() {
setTimeout(() => {
this.focusable = true;
}, 50);
},
onMousewheel(e) {
e.stopPropagation();
// console.log('mousewheel', e)
const delta = event.wheelDelta || event.detail;
const navSize = this.$refs.nav[`offset${ firstUpperCase(this.sizeName) }`];
const containerSize = this.$refs.navScroll[`offset${ firstUpperCase(this.sizeName) }`];
const currentOffset = this.navOffset;
// console.log(delta, delta < 0, currentOffset, containerSize, navSize)
let newOffset = 0;
if (delta < 0) {
if (navSize - currentOffset <= containerSize) return;
newOffset = navSize - currentOffset > containerSize * 2
? currentOffset + containerSize
: (navSize - containerSize);
} else {
if (!currentOffset) return;
newOffset = currentOffset > containerSize
? currentOffset - containerSize
: 0;
}
this.navOffset = newOffset;
},
onContextmenuClick(pane, type, e) {
// console.log('onclick', pane, e)
switch (type) {
case '关闭该标签页':
this.onTabRemove(pane, e);
break;
case '关闭其他标签页':
this.onTabOtherRemove(pane, e);
break;
case '关闭全部':
this.onTabAllRemove(e);
break;
}
if (document.getElementById('sTabsContextmenu')) {
const node = document.getElementById('sTabsContextmenu');
node.parentNode.removeChild(node);
}
},
onContextmenu(pane, e) {
if (!this.navContextmenu) return;
e.preventDefault();
e.stopPropagation();
if (pane.isClosable) {
if (document.getElementById('sTabsContextmenu')) {
const node = document.getElementById('sTabsContextmenu');
node.parentNode.removeChild(node);
}
const node = document.createElement('ul');
node.className = 's-tabs__contextmenu';
node.id = 'sTabsContextmenu';
const list = ['关闭该标签页', '关闭其他标签页', '关闭全部'];
list.map(item => {
const liNode = document.createElement('li');
liNode.className = 's-tabs__contextmenu--item';
liNode.addEventListener('click', (e) => {
this.onContextmenuClick(pane, item, e);
});
liNode.innerText = item;
node.appendChild(liNode);
});
document.body.appendChild(node);
node.style.top = e.clientY + 'px';
node.style.left = e.clientX + 'px';
node.style.display = 'block';
document.body.addEventListener('mousedown', () => {
node.style.display = 'none';
});
node.addEventListener('mousedown', (e) => {
e.stopPropagation();
});
}
},
onMouseup(pane, e) {
// mouse middle click
if (e.button === 1) {
if (pane.isClosable) this.onTabRemove(pane, e);
}
}
},
updated() {
this.update();
},
render(h) {
const {
type,
panes,
editable,
stretch,
onTabClick,
onTabRemove,
navStyle,
scrollable,
scrollNext,
scrollPrev,
changeTab,
setFocus,
removeFocus,
onMousewheel,
onContextmenu,
onMouseup
} = this;
const scrollBtn = scrollable
? [
<span class={['s-tabs__nav-prev', scrollable.prev ? '' : 'is-disabled']} on-click={scrollPrev}><i class="el-icon-arrow-left"></i></span>,
<span class={['s-tabs__nav-next', scrollable.next ? '' : 'is-disabled']} on-click={scrollNext}><i class="el-icon-arrow-right"></i></span>
] : null;
const tabs = this._l(panes, (pane, index) => {
const tabName = pane.name || pane.index || index;
const closable = pane.isClosable || editable;
pane.index = `${index}`;
const btnClose = closable
? <span class="el-icon-close" on-click={(ev) => { onTabRemove(pane, ev); }}></span>
: null;
const tabLabelContent = pane.$slots.label || pane.label;
// const tabindex = pane.active ? 0 : -1
return (
<div
class={{
's-tabs__item': true,
[`is-${ this.rootTabs.tabPosition }`]: true,
'is-active': pane.active,
'is-disabled': pane.disabled,
'is-closable': closable,
'is-focus': this.isFocus
}}
id={`tab-${tabName}`}
aria-controls={`pane-${tabName}`}
role="tab"
aria-selected={ pane.active }
ref="tabs"
// tabindex={tabindex}
refInFor
on-focus={() => { setFocus(); }}
on-blur ={() => { removeFocus(); }}
on-click={(ev) => { removeFocus(); onTabClick(pane, tabName, ev); }}
on-keydown={(ev) => { if (closable && (ev.keyCode === 46 || ev.keyCode === 8)) { onTabRemove(pane, ev); } }}
on-contextmenu={(ev) => onContextmenu(pane, ev)}
on-mouseup={(ev) => onMouseup(pane, ev)}
>
{tabLabelContent}
{btnClose}
</div>
);
});
return (
<div class={['s-tabs__nav-wrap', scrollable ? 'is-scrollable' : '', `is-${ this.rootTabs.tabPosition }`]}>
{scrollBtn}
<div class={['s-tabs__nav-scroll']} ref="navScroll" on-mousewheel={ onMousewheel }>
<div
class={['s-tabs__nav', `is-${ this.rootTabs.tabPosition }`, stretch && ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'is-stretch' : '']}
ref="nav"
style={navStyle}
role="tablist"
on-keydown={ changeTab }
>
{!type ? <tab-bar tabs={panes}></tab-bar> : null}
{tabs}
</div>
</div>
</div>
);
},
mounted() {
addResizeListener(this.$el, this.update);
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
window.addEventListener('blur', this.windowBlurHandler);
window.addEventListener('focus', this.windowFocusHandler);
if (document.getElementById('sTabsContextmenu')) {
const node = document.getElementById('sTabsContextmenu');
node.parentNode.removeChild(node);
}
},
beforeDestroy() {
if (this.$el && this.update) removeResizeListener(this.$el, this.update);
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
window.removeEventListener('blur', this.windowBlurHandler);
window.removeEventListener('focus', this.windowFocusHandler);
if (document.getElementById('sTabsContextmenu')) {
const node = document.getElementById('sTabsContextmenu');
node.parentNode.removeChild(node);
}
}
};
</script>
<template>
<div
class="s-tab-pane"
v-if="(!lazy || loaded) || active"
v-show="active"
role="tabpanel"
:aria-hidden="!active"
:id="`pane-${paneName}`"
:aria-labelledby="`tab-${paneName}`"
>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'STabPane',
componentName: 'STabPane',
props: {
label: String,
labelContent: Function,
name: String,
closable: Boolean,
disabled: Boolean,
lazy: Boolean
},
data() {
return {
index: null,
loaded: false
};
},
computed: {
isClosable() {
return this.closable || this.$parent.closable;
},
active() {
const active = this.$parent.currentName === (this.name || this.index);
return active;
},
paneName() {
return this.name || this.index;
}
},
watch: {
label() {
this.$parent.$forceUpdate();
},
active(val) {
if (val) {
this.loaded = true;
}
}
}
};
</script>
<script>
import TabNav from './tab-nav';
export default {
name: 'STabs',
components: {
TabNav
},
props: {
type: String,
activeName: String,
closable: Boolean,
addable: Boolean,
value: {},
editable: Boolean,
tabPosition: {
type: String,
default: 'top'
},
beforeLeave: Function,
stretch: Boolean,
navContextmenu: {
default: true
}
},
provide() {
return {
rootTabs: this
};
},
data() {
return {
currentName: this.value || this.activeName,
panes: []
};
},
watch: {
activeName(value) {
this.setCurrentName(value);
},
value(value) {
this.setCurrentName(value);
},
currentName(value) {
if (this.$refs.nav) {
this.$nextTick(() => {
this.$refs.nav.$nextTick(_ => {
this.$refs.nav.scrollToActiveTab();
});
});
}
}
},
methods: {
calcPaneInstances() {
if (this.$slots.default) {
const paneSlots = this.$slots.default.filter(vnode => vnode.tag &&
vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'STabPane');
// update indeed
const panes = paneSlots.map(({ componentInstance }) => componentInstance);
if (!(panes.length === this.panes.length && panes.every((pane, index) => pane === this.panes[index]))) {
this.panes = panes;
}
}
},
handleTabClick(tab, tabName, event) {
if (tab.disabled) return;
this.setCurrentName(tabName);
this.$emit('tab-click', tab, event);
},
handleTabRemove(pane, ev) {
if (pane.disabled) return;
ev.stopPropagation();
this.$emit('edit', pane.name, 'remove');
this.$emit('tab-remove', pane.name);
},
handleTabOtherRemove(pane, ev) {
ev.stopPropagation();
this.panes.map(item => {
if (item.name !== pane.name && item.isClosable) {
this.handleTabRemove(item, ev);
}
});
this.setCurrentName(pane.name);
},
handleTabALLRemove(ev) {
this.panes.map(item => {
if (item.isClosable) {
this.handleTabRemove(item, ev);
} else {
this.setCurrentName(item.name);
}
});
},
handleTabAdd() {
this.$emit('edit', null, 'add');
this.$emit('tab-add');
},
setCurrentName(value) {
const changeCurrentName = () => {
this.currentName = value;
this.$emit('input', value);
};
if (this.currentName !== value && this.beforeLeave) {
const before = this.beforeLeave(value, this.currentName);
if (before && before.then) {
before.then(() => {
changeCurrentName();
this.$refs.nav && this.$refs.nav.removeFocus();
});
} else if (before !== false) {
changeCurrentName();
}
} else {
changeCurrentName();
}
}
},
render(h) {
const {
type,
handleTabClick,
handleTabRemove,
handleTabOtherRemove,
handleTabALLRemove,
handleTabAdd,
currentName,
panes,
editable,
addable,
tabPosition,
stretch,
navContextmenu
} = this;
const newButton = editable || addable
? (
<span
class="s-tabs__new-tab"
on-click={ handleTabAdd }
tabindex="0"
on-keydown={ (ev) => { if (ev.keyCode === 13) { handleTabAdd(); } }}
>
<i class="el-icon-plus"></i>
</span>
)
: null;
const headerSlot = this.$slots.header ? <div class="s-tabs__header--slot">{this.$slots.header}</div> : null;
const navData = {
props: {
currentName,
onTabClick: handleTabClick,
onTabRemove: handleTabRemove,
onTabOtherRemove: handleTabOtherRemove,
onTabAllRemove: handleTabALLRemove,
editable,
type,
panes,
stretch,
navContextmenu
},
ref: 'nav'
};
const header = (
<div class={['s-tabs__header', `is-${ tabPosition }`]}>
{newButton}
<tab-nav { ...navData }></tab-nav>
{headerSlot}
</div>
);
const panels = (
<div class="s-tabs__content">
{this.$slots.default}
</div>
);
return (
<div class={{
's-tabs': true,
's-tabs--card': type === 'card',
[`s-tabs--${tabPosition}`]: true,
's-tabs--border-card': type === 'border-card'
}}>
{ tabPosition !== 'bottom' ? [header, panels] : [panels, header] }
</div>
);
},
created() {
if (!this.currentName) {
this.setCurrentName('0');
}
},
mounted() {
this.calcPaneInstances();
},
updated() {
this.calcPaneInstances();
}
};
</script>
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store';
import ElemetUI from 'element-ui';
import SmartWeb from 'smart-web';
import VueProgressBar from 'vue-progressbar';
import './styles/app.scss';
// import 'smart-web/packages/styles/lib/index.css';
import './plugins/registComponents';
import asyncComponents from './plugins/asyncComponents';
import './utils/appinit';
import './utils/window';
import './utils/expression';
import './api/loginInterceptor';
Vue.config.productionTip = false;
Vue.use(ElemetUI, { size: 'medium', zIndex: 4000 });
Vue.use(SmartWeb, {
baseUrl: process.env.VUE_APP_BASEURL,
systemId: '00000000-0000-0015-0001-000000000001'
});
Vue.use(asyncComponents);
const vPopts = {
color: '#8fcdfc',
failedColor: '#874b4b',
thickness: '2px',
transition: {
speed: '0.1s',
opacity: '0.3s',
termination: 300
},
autoRevert: true,
location: 'top',
inverse: false,
autoFinish: true
};
Vue.use(VueProgressBar, vPopts);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: {
App
},
template: '<App/>'
});
import { extend, cb } from './extend';
import appHome from '@/views/common/appHome';
import errorPage from '@/components/404.vue';
/**
* 动态异步加载组件,除了必须组件(HOME, 404)
*/
export const asyncComponents = {
appHome,
errorPage,
appMessage: () => import('@/views/common/message').then(cb),
appIframe: () => import('@/views/common/AppIframe.vue'),
configurePage: () => import('@/views/common/ConfigurePage.vue').then(cb)
};
/**
* 注册routes文件夹的路由组件
*/
const files = require.context('./routes', false, /\.js$/);
files.keys().forEach(key => {
if (typeof files(key).default === 'object') {
const _obj = files(key).default;
for (const routeName in _obj) {
asyncComponents[routeName] = _obj[routeName];
}
}
});
const install = (Vue, opts = {}) => {
Object.keys(asyncComponents).map(key => {
if (typeof asyncComponents[key] === 'object') {
asyncComponents[key].extends = extend;
}
Vue.component(key, asyncComponents[key]);
});
};
/**
* 判断异步组件是否已经注册
* @param {String} str 判断的组件名称
* @returns Boolean
*/
export const checkAsyncComponents = (str) => {
let flag = false;
for (const key in asyncComponents) {
if (str === key) {
flag = true;
break;
}
}
return flag;
};
export const getComponentsName = () => {
const componentsNames = [];
for (const key in asyncComponents) {
componentsNames.push(key);
}
return componentsNames;
};
export default install;
import store from '@/store';
// tab页面混入渲染成功后tab-mounted监听
export const extend = {
computed: {
$SMTab() {
return store.state.currentNavigation;
}
},
watch: {
'$SMTab.param.reload': function(val, oldVal) {
if (val && oldVal !== val) {
this.refresh && this.refresh();
}
}
},
mounted() {
this.$emit('tab-mounted');
}
};
export const cb = (comp) => {
comp.default.extends = extend;
return comp;
};
export default extend;
import Vue from 'vue';
import Tabs from '@/components/tabs';
import Tabpane from '@/components/tab-pane';
/**
* 注册加载组件
*/
export const registComponents = {
Tabs,
Tabpane
};
Object.keys(registComponents).map(key => {
if (registComponents[key].type === 'prototype') {
Object.keys(registComponents[key]).map(item => {
Vue.prototype[item] = registComponents[key][item];
});
} else {
Vue.use(registComponents[key]);
}
});
import { cb } from '../extend';
export default {
businessConfiguration: () => import('@/views/businessConfig/businessConfiguration').then(cb)
};
import { cb } from '../extend';
export default {
mapConfig: () => import('@/views/mapConfig/mapConfig').then(cb),
layerManage: () => import('@/views/mapConfig/layerManage').then(cb),
mapSearchConfig: () => import('@/views/mapConfig/mapSearchConfig').then(cb),
serviceRegister: () => import('@/views/mapConfig/serviceRegister').then(cb),
catalogManagement: () => import('@/views/mapConfig/catalogManagement').then(cb)
};
import { cb } from '../extend';
export default {
createWork: () => import('@/views/myWork/createWork').then(cb),
checkProcess: () => import('@/views/myWork/checkProcess').then(cb),
doingWork: () => import('@/views/myWork/doingWork').then(cb),
handledWork: () => import('@/views/myWork/handledWork').then(cb),
suspendWork: () => import('@/views/myWork/suspendWork').then(cb),
finishedWork: () => import('@/views/myWork/finishedWork').then(cb),
returnBox: () => import('@/views/myWork/returnBox').then(cb),
deleteBox: () => import('@/views/myWork/deleteBox').then(cb),
monitorWork: () => import('@/views/myWork/monitorWork').then(cb),
settingColumn: () => import('@/views/myWork/settingColumn').then(cb)
};
import { cb } from '../extend';
export default {
interface: () => import('@/views/personalConfig/interface').then(cb),
accountSetting: () => import('@/views/personalConfig/accountSetting').then(cb)
};
import { cb } from '../extend';
export default {
frameworkManage: () => import('@/views/systemSetup/frameworkManage').then(cb),
childSystemManage: () => import('@/views/systemSetup/childSystemManage').then(cb),
modulesManage: () => import('@/views/systemSetup/modulesManage').then(cb),
functionModulesManage: () => import('@/views/systemSetup/functionModulesManage').then(cb),
authorityManage: () => import('@/views/systemSetup/authorityManage').then(cb),
codeDictionary: () => import('@/views/systemSetup/codeDictionary').then(cb),
workflowDesign: () => import('@/views/systemSetup/workflowDesign').then(cb),
editProcess: () => import('@/views/systemSetup/editProcess').then(cb),
SNamingManagement: () => import('@/views/systemSetup/SNamingManagement').then(cb),
stampdefManage: () => import('@/views/systemSetup/stampdefManage').then(cb),
myComWord: () => import('@/views/systemSetup/myComWord').then(cb),
compInformation: () => import('@/views/systemSetup/compInformation').then(cb),
snBuilder: () => import('@/views/systemSetup/snBuilder').then(cb),
operationLog: () => import('@/views/systemSetup/operationLog').then(cb),
holidayManagement: () => import('@/views/systemSetup/holidayManagement').then(cb),
businessDefManager: () => import('@/views/systemSetup/businessDefManager').then(cb),
checkExpression: () => import('@/views/systemSetup/checkExpression').then(cb),
adminDivision: () => import('@/views/systemSetup/adminDivision').then(cb),
iconView: () => import('@/views/common/iconView').then(cb),
environmentConfig: () => import('@/views/systemSetup/environmentConfig').then(cb),
taskScheduling: () => import('@/views/systemSetup/taskScheduling').then(cb)
};
import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';
import Api from '../api';
import store from '../store';
import { removeLoading, getSystemInfo } from '../utils/global';
Vue.use(Router);
function nextLogin(to, from, next) {
next({
name: 'Login',
replace: true,
query: to.query
});
}
function filterRouteLogin(route) {
return ['Login', 'LoginDialog'].indexOf(route.name) >= 0;
}
// 判断是否存在用户
/* function isExistUser () {
return store.state.userInfo && store.state.userInfo.userId
}
// 判断是否存在平台信息
function isExistPlatform () {
return store.state.platformInfo && store.state.platformInfo.systemId
} */
const router = new Router({
// mode: 'history',
routes
});
router.beforeEach((to, from, next) => {
if (to.name === '404' || to.name === 'Unfound') {
removeLoading();
next();
return;
}
function checkLogin() {
// 检查登录
Api.checkLogin().then(res => {
if (res.status === 0) {
const data = res.data;
// vuex store
const userState = {
...data.loginInfo,
userId: data.userId
};
// 设置vuex userInfo
store.dispatch('setUserInfo', userState);
// 路由跳转
if (filterRouteLogin(to)) {
next({
name: 'Main'
});
} else {
next();
}
} else {
store.dispatch('setUserInfo', {});
nextLogin(to, from, next);
}
}).catch(() => {
store.dispatch('setUserInfo', {});
nextLogin(to, from, next);
});
}
// 获取系统信息
getSystemInfo(to.query.sysCode).then(_ => {
if (from.meta.igonreLogin) {
next();
return;
}
if (to.name === 'Main') {
checkLogin();
} else {
next();
}
}).catch(err => {
if (err.status === 1 || err.status === 2) {
// 获取系统信息错误
next({
name: 'Unfound',
replace: true,
query: to.query
});
} else {
nextLogin(to, from, next);
}
});
});
export default router;
import Main from '@/views/Main';
import Login from '@/views/login/Login';
import LoginDialog from '@/views/login/LoginDialog';
import ErrorPage from '@/components/404';
import UnfoundSys from '@/components/UnfoundSys';
import store from '@/store';
import Api from '@/api';
function checkLogin() {
return new Promise((resolve, reject) => {
Api.checkLogin().then(res => {
if (res.status === 0) {
const data = res.data;
// vuex store
const userState = {
...data.loginInfo,
userId: data.userId
};
// 设置vuex userInfo
store.dispatch('setUserInfo', userState);
// 路由跳转
resolve();
} else {
store.dispatch('setUserInfo', {});
reject(res);
}
}).catch((err) => {
store.dispatch('setUserInfo', {});
reject(err);
});
});
}
export default [
{
path: '/',
name: 'Main',
component: Main,
// redirect: '/home',
props: (route) => ({ sysId: route.query.sysId }),
children: [{
path: 'logindialog',
name: 'LoginDialog',
component: LoginDialog,
meta: {
igonreLogin: true
}/* ,
beforeEnter: (to, from, next) => {
checkLogin().then(_ => {
next({
name: 'Main',
query: to.query
})
}).catch(_ => {
next()
})
} */
}]
}, {
path: '/login',
name: 'Login',
component: Login,
meta: {
igonreLogin: true
},
beforeEnter: (to, from, next) => {
checkLogin().then(_ => {
next({
name: 'Main',
query: to.query
});
}).catch(_ => {
next();
});
}
}, {
path: '/unfound',
name: 'Unfound',
component: UnfoundSys
}, {
path: '*',
name: '404',
component: ErrorPage
}
];
import Vue from 'vue';
import Vuex from 'vuex';
const packageConfig = require('../../../package.json');
Vue.use(Vuex);
const modules = {};
const files = require.context('./modules', false, /\.js$/);
files.keys().forEach(key => {
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default;
});
const store = new Vuex.Store({
namespaced: true,
modules,
state: {
platformInfo: {
moduleId: '#',
systemId: ''/* '00000000-0000-0015-0001-000000000001' */,
name: 'Smart Web 平台',
// name: '国土测绘院政务系统',
disabled: true,
version: packageConfig.version || ''
},
unreadMessage: 0, // 未读消息
userInfo: {
userId: '',
SysId: '',
OrganName: '',
RealName: ''
},
userIdentity: 'none', // 用户身份,admin, none
theme: {
format: 'left-right',
themeColor: 'deep'
},
currentNavigation: { // 当前页面信息
name: '首页',
id: 'home',
componentName: 'appHome'
},
navigationList: []
},
mutations: {
setUserInfo(state, payload) {
state.userInfo = payload;
},
setUserIdentity(state, payload) {
state.userIdentity = payload;
},
setTheme(state, payload) {
state.theme = payload;
},
setNavigation(state, payload) {
state.currentNavigation = payload;
let flag = true;
state.navigationList.map(item => {
if (item.name === payload.name) {
flag = false;
}
});
// 判断是否新标签页插入
if (flag) state.navigationList.push(payload);
},
removeNavigation(state, name) {
const len = state.navigationList.length;
for (let i = len - 1; i >= 0; i--) {
if (state.navigationList[i].id === name) {
state.navigationList.splice(i, 1);
}
}
},
initNavigation(state) {
state.currentNavigation = {
name: '首页',
id: 'home',
componentName: 'appHome'
};
state.navigationList = [{
name: '首页',
id: 'home',
componentName: 'appHome'
}];
},
setCurrentNavigation(state, name) {
for (const nav of state.navigationList) {
if (nav.componentName === 'settingColumn') {
nav.name = name;
}
}
},
setUnreadMessage(state, count) {
state.unreadMessage = count;
}
},
actions: {
setUserInfo(context, payload) {
context.commit('setUserInfo', payload);
if (payload && payload.Qua === 99) {
context.commit('setUserIdentity', 'admin');
} else {
context.commit('setUserIdentity', 'none');
}
},
setTheme({ commit }, payload) {
commit('setTheme', payload);
},
setNavigation(context, payload) {
if (context.state.currentNavigation.id === payload.id) return;
const len = context.state.navigationList.length;
for (let i = 0; i < len; i++) {
if (context.state.navigationList[i].id === payload.id && !payload.param) { // 存在在List,并且没带有param
payload = context.state.navigationList[i];
break;
} else if (context.state.navigationList[i].id === payload.id && payload.param) { // 存在在List,并且带有param
context.state.navigationList[i].param = payload.param;
break;
}
}
context.commit('setNavigation', payload);
},
removeNavigation(context, name) {
context.commit('removeNavigation', name);
},
initNavigation(context) {
context.commit('initNavigation');
},
setCurrentNavigation(context, name) {
context.commit('setCurrentNavigation', name);
},
setUnreadMessage(context, count) {
context.commit('setUnreadMessage', count);
}
}
});
export default store;
/**
* 菜单存储,菜单权限
*/
export default {
namespaced: true,
state: {
menuList: []
},
getters: {
menuList: state => {
return state.menuList;
}
},
mutations: {
setMenuList(state, payload) {
state.menuList = payload;
}
},
actions: {
setMenuList({ commit }, payload) {
commit('setMenuList', payload);
}
}
};
@import "./common/var";
@import './mixins/mixins';
@import './library';
@import './common/main';
@import './common/other/theme';
%placehodler {
width: 100%;
height: 100%;
}
#app, .app-main {
@extend %placehodler;
}
.app-main {
display: flex;
flex-direction: row;
}
.app-wrapper {
display: flex;
flex-direction: row;
flex: 1 1 0%;
width: 100%;
height: 100%;
}
.app-container {
flex: 1 1 0%;
overflow: hidden;
}
.app-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0 0.6em;
width: 100%;
height: $--header-height;
// line-height: $--height-header;
color: $--header-color;
background-color: $--header-background-color;
// box-shadow: 0 1px 3px rgba($color: $--header-box-shadow-color, $alpha: 0.1);
border-bottom: 1px solid $--header-border-color;
a {
color: $--header-color;
&:hover {
opacity: 0.75;
}
}
.app-header--right {
// margin-left: 2em;
flex: 1 1 auto;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.app-header--function {
display: inline-block;
padding: 0 20px;
margin-right: 20px;
// border-right: 1px solid rgba($color: $--header-background-color, $alpha: 0.5);
& > * {
margin-left: 20px;
}
}
}
.app-header__userinfo {
// margin-left: 1em;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
.gutter {
margin: 0 0.6em;
}
.message {
position: relative;
display: inline-block;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
&:hover {
background-color: mix($--color-black, $--header-background-color, 10%);
}
.iconfont {
font-size: $--font-size-large;
}
.tips {
position: absolute;
right: 2px;
top: 2px;
width: 10px;
height: 10px;
text-indent: -999px;
background-color: $--color-danger;
border: 1px solid mix($--color-white, $--color-danger, 20%);
border-radius: 10px;
color: $--color-white;
font-size: $--font-size-mini;
overflow: hidden;
}
}
.user-name {
& > i {
margin-right: 4px;
}
span {
font-size: $--header-font-size;
font-weight: 600;
}
&:hover {
opacity: .75;
}
}
.quit-user {
&:hover {
opacity: .75;
}
}
}
.app-logo {
display: flex;
align-items: center;
height: $--header-height;
color: $--color-white;
background-color: $--color-primary;
.menu {
display: flex;
width: $--header-height;
height: $--header-height;
align-items: center;
justify-content: center;
}
.img {
width: 28px;
height: 28px;
display: inline-block;
vertical-align: middle;
background-image: url('../assets/img/logo-white.png');
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
}
.app-title {
display: inline-block;
margin-left: 4px;
font-size: 20px;
font-weight: 500;
}
.app-navigation {
display: flex;
flex-direction: column;
position: relative;
width: 240px;
height: 100%;
background-color: $--nav-background-color-light;
transition: width .3s ease-in-out;
::-webkit-scrollbar {
width: 4px;
}
::-webkit-scrollbar-track-piece {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
background-color: mix($--color-black, $--nav-background-color-light, 15%);
border-radius: 6px;
}
&.is-collapse {
width: 64px;
.app-logo {
justify-content: center;
}
.app-title {
display: none;
}
}
.app-navigation--menu {
flex: 1 1 auto;
border-right: 0 none;
background-color: $--nav-background-color-light;
overflow: auto;
.el-menu {
background-color: $--color-white;
}
.el-menu-item, .el-submenu__title {
color: $--nav-font-color;
}
.el-menu-item:hover, .el-menu-item:focus, .el-submenu__title:hover {
background-color: $--color-primary-light-8;
}
}
/* .el-menu {
border-right: 0 none;
background-color: $--nav-background-color;
} */
.navigation-controll {
position: absolute;
z-index: 2999;
top: 50%;
right: -14px;
transform: translateY(-30px);
width: 14px;
height: 60px;
line-height: 60px;
text-align: center;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
background-color: $--nav-background-color-light;
cursor: pointer;
.iconfont {
font-size: $--font-size-mini;
}
}
}
.app-container--main {
display: flex;
flex-direction: column;
flex: 1 1 auto;
width: 100%;
height: 100%;
overflow: hidden;
/* .app_tabs {
height: $--app-tabs-height;
background-color: $--app-tabs-background-color;
} */
.s-tabs__nav.is-top {
border-top: 0;
}
.s-tabs__header {
padding-left: 10px;
height: $--app-tabs-height;
background-color: $--app-tabs-background-color;
border-bottom-color: $--app-tabs-border-color;
margin-bottom: 0;
}
.s-tabs__item {
border-left-color: $--app-tabs-border-color !important;
color: $--app-tabs-text-color;
outline: none;
&.is-active {
color: $--color-primary;
background-color: $--app-tabs-active-color;
}
&.is-closable, &.is-closable:hover {
padding-left: 16px !important;
padding-right: 14px !important;
}
.el-icon-close {
margin-left: 10px;
font-size: 16px !important;
width: 18px !important;
height: 18px !important;
text-align: center;
line-height: 18px !important;
&:hover {
border-radius: 50%;
background-color: $--app-tabs-background-color;
}
}
}
.s-tabs__content {
flex: 1 1 0;
overflow: hidden;
.s-tab-pane {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
& > div {
width: 100%;
height: 100%;
overflow: auto;
}
}
}
}
.el-menu--collapse .el-menu-item span,
.el-menu--collapse .el-submenu > .el-submenu__title span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
.el-menu--collapse .el-menu-item .el-submenu__icon-arrow,
.el-menu--collapse .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
display: none;
}
.el-menu .iconfont {
font-size: $--font-size-large;
}
/* login css */
.login__wrapper {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
// background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0) 60%, #232a38),
// linear-gradient(70deg, #303b41 32%, #333d52);
// background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0) 60%, #223a86),
// linear-gradient(70deg, #4e89e2 32%, #9ee6c2);
// background-color: #333d52;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -2;
background: url('../assets/img/login_bg.jpg') center center no-repeat;
background-size: cover;
filter: blur(8px);
}
&::after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0) 60%, #768edb),
linear-gradient(70deg, #55667e 32%, #5ca397);
background-color: #333d52;
opacity: 0.35;
}
.login-form {
width: 450px;
}
.login-logo {
position: absolute;
top: 1rem;
left: 1rem;
color: #ffffff;
}
.login-logo__icon {
display: inline-block;
width: 40px;
height: 40px;
margin-right: 0.2rem;
background: url('../assets/img/logo-white.png') no-repeat;
background-size: contain;
vertical-align: middle;
}
.login-logo__title {
font-size: 28px;
vertical-align: middle;
}
}
.login-form {
width: 400px;
.login-form__close {
float: right;
color: $--color-info;
font-size: 16px;
cursor: pointer;
&:hover {
color: $--color-primary;
}
}
.submitBtn {
width: 100px;
}
}
.login-dialog__wrapper {
/* position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%; */
.el-dialog__header, .el-dialog__body {
padding: 0;
}
}
/* login css end */
/* loading spinner custom */
.loading-spinner {
display: block;
text-align: center;
}
.loading-spinner .el-icon-loading {
font-size: 20px;
}
.loading-spinner .circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.loading-spinner .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: $--color-primary;
stroke-linecap: round;
}
.loading-spinner .text {
margin-top: 4px;
font-size: $--font-size-small;
}
@keyframes loading-rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
/* loading spinner custom end */
@import './var';
@import '../mixins/mixins';
@import './other/reset';
@import '../component/index';
/* error page css */
.errorPage {
width: 100%;
height: 100%;
padding-top: 20vh;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0) 60%, #ffffff),
linear-gradient(60deg,#f0f8f6 32%,#f6f7ef);
.num {
font-size: 8rem;
color: $--color-primary;
font-family: 'Courier New', Courier, monospace;
}
.des {
text-align: left;
p {
font-size: $--font-size-small;
color: $--color-info;
}
h4 {
color: inherit;
font-weight: 500;
margin-bottom: 4px;
}
}
}
/* error page css end */
\ No newline at end of file
@import '../var.scss';
blockquote,body,button,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,hr,html,iframe,input,legend,li,ol,p,pre,td,textarea,th,ul{
margin:0;
padding:0;
}
html, body {
width: 100%;
height: 100%;
}
body {
min-width: 1200px;
min-height: 540px;
font-size: 1rem;
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;
color: $--color-text-regular;
overflow: auto;
}
input, textarea {
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif;
}
iframe {
width: 100%;
height: 100%;
border: 0;
outline: none;
}
a {
color: $--color-primary;
text-decoration: none;
}
ul, ol, li {
list-style: none;
}
* {
scrollbar-base-color: #cecece;
scrollbar-3dlight-color: #eee;
scrollbar-highlight-color: #eee;
scrollbar-track-color: #f1f1f1;
scrollbar-arrow-color: #000;
scrollbar-shadow-color: #eee;
// scrollbar-dark-shadow-color: #eee;
box-sizing: border-box;
}
*::-webkit-scrollbar {
width: 6px;
height: 10px;
}
*::-webkit-scrollbar-button {
display: none;
}
*::-webkit-scrollbar-track-piece {
background-color: #f2f2f2;
}
*::-webkit-scrollbar-thumb {
background-color: #C1C1C1;
border-radius: 6px;
}
code {
font-family: Verdana, Geneva, Tahoma, Helvetica, sans-serif;
padding: 1px 4px;
color: $--color-danger;
background-color: rgba($color: $--color-warning, $alpha: 0.2);
}
pre {
font-family: 'Source Code Pro', Monaco, Consolas, Verdana, Geneva, Tahoma, Helvetica, sans-serif;
}
\ No newline at end of file
@import '../../mixins/mixins';
@import '../var';
@include b(app-main) {
display: flex;
position: relative;
&.left-right {
flex-direction: row;
}
&.top-bottom {
flex-direction: column;
@include b(app-header) {
@include when(light) {
color: $--color-white;
background-color: $--color-primary;
a, .el-button--text {
color:$--color-white;
}
.message .tips {
border-color: $--color-white;
}
}
@include when(deep) {
color: $--color-white;
background-color: mix($--color-black, $--nav-background-color, 5%);
a, .el-button--text {
color: mix($--color-white, $--nav-background-color, 85%);
}
.app-logo {
background-color: transparent;
}
}
}
}
}
@include b(app-navigation) {
@include when(light) {
background-color: $--nav-background-color-light;
.app-logo {
display: flex;
align-items: center;
height: $--header-height;
background-color: $--color-primary;
color: $--color-white;
}
.app-navigation--menu {
background-color: $--nav-background-color-light;
border-right: $--border-base;
.el-menu {
background-color: $--color-white;
}
.el-menu-item, .el-submenu__title {
color: $--nav-font-color;
}
.el-menu-item:hover, .el-menu-item:focus, .el-submenu__title:hover {
background-color: $--color-primary-light-8;
}
}
.navigation-controll {
color: mix($--color-white, $--color-primary, 45%);
background-color: $--nav-background-color-light;
&:hover {
background-color: mix($--color-black, $--nav-background-color-light, 5%);
.iconfont {
color: $--color-primary;
}
}
}
}
@include when(deep) {
background-color: $--nav-background-color;
.app-logo {
display: flex;
align-items: center;
height: $--header-height;
background-color: $--color-primary;
color: $--color-white;
}
::-webkit-scrollbar-thumb {
background-color: mix($--color-white, $--nav-background-color, 35%);
}
.app-navigation--menu {
background-color: $--nav-background-color;
.el-tree {
color: $--color-primary-light-6;
i.iconfont {
color: $--color-primary-light-6;
}
.el-tree-node__content {
&:hover, &:focus {
background-color: mix($--color-white, $--nav-background-color, 8%);
}
}
&.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: mix($--color-white, $--nav-background-color, 8%);
}
}
.el-menu {
background-color: mix($--color-white, $--nav-background-color, 10%);
}
.el-menu-item, .el-submenu__title {
color: $--color-primary-light-6;
i {
color: $--color-primary-light-6;
}
}
.el-menu-item:hover, .el-menu-item:focus,
.el-submenu__title:hover, .el-submenu__title:focus {
background-color: mix($--color-white, $--nav-background-color, 5%);
}
}
.navigation-controll {
background-color: mix($--color-black, $--nav-background-color, 10%);
color: mix($--color-white, $--nav-background-color, 45%);
&:hover {
background-color: mix($--color-black, $--nav-background-color, 20%);
.iconfont {
color: $--color-primary;
}
}
}
}
}
body {
&.is-light {
& > .el-menu--vertical {
background-color: $--nav-background-color-light;
max-height: 100%;
overflow: auto;
.el-menu {
background-color: $--nav-background-color-light;
}
.el-menu-item, .el-submenu__title {
color: $--nav-font-color;
}
.el-menu-item:hover, .el-menu-item:focus, .el-submenu__title:hover {
background-color: $--color-primary-light-8;
}
}
}
&.is-deep {
& > .el-menu--vertical {
background-color: $--nav-background-color;
max-height: 100%;
overflow: auto;
.el-menu {
background-color: $--nav-background-color;
}
.el-menu-item, .el-submenu__title {
color: $--color-primary-light-6;
i {
color: $--color-primary-light-6;
}
}
.el-menu-item:hover, .el-menu-item:focus, .el-submenu__title:hover {
background-color: mix($--color-white, $--nav-background-color, 20%);
}
}
}
}
\ No newline at end of file
@import '~smart-web/packages/styles/src/common/var';
\ No newline at end of file
@import './tabs.scss';
@import './progress.scss';
\ No newline at end of file
@import "../mixins/mixins";
@import "../mixins/utils";
@import '../common/var';
@include b(sm-progress) {
position: relative;
line-height: 1;
@include e(text) {
font-size:14px;
color: $--color-text-regular;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
line-height: 1;
i {
vertical-align: middle;
display: block;
}
}
@include m(circle) {
display: inline-block;
.sm-progress__text {
position: absolute;
top: 50%;
left: 0;
width: 100%;
text-align: center;
margin: 0;
transform: translate(0, -50%);
i {
vertical-align: middle;
display: inline-block;
}
}
}
@include m(without-text) {
.sm-progress__text {
display: none;
}
.sm-progress-bar {
padding-right: 0;
margin-right: 0;
display: block;
}
}
@include m(text-inside) {
.sm-progress-bar {
padding-right: 0;
margin-right: 0;
}
}
@include when(success) {
.sm-progress-bar__inner {
background-color: $--color-success;
}
.sm-progress__text {
color: $--color-success;
}
}
@include when(exception) {
.sm-progress-bar__inner {
background-color: $--color-danger;
}
.sm-progress__text {
color: $--color-danger;
}
}
}
@include b(sm-progress-bar) {
padding-right: 50px;
display: inline-block;
vertical-align: middle;
width: 100%;
margin-right: -55px;
box-sizing: border-box;
@include e(outer) {
height: 6px;
border-radius: 100px;
background-color: $--border-color-lighter;
overflow: hidden;
position: relative;
vertical-align: middle;
}
@include e(inner) {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: $--color-primary;
text-align: right;
border-radius: 100px;
line-height: 1;
white-space: nowrap;
@include utils-vertical-center;
@include when(animate) {
transition: width .4s ease;
&::before {
content: '';
position: absolute;
display: block;
width: 100%;
height: 100%;
background-image: linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);
background-size: 40px 40px;
animation: reverse progress-bar-stripes 0.50s linear infinite, animate-positive 2s;
}
}
}
@include e(innerText) {
display: inline-block;
vertical-align: middle;
color: $--color-white;
font-size: 12px;
margin: 0 5px;
}
}
@keyframes progress {
0% {
background-position: 0 0;
}
100% {
background-position: 32px 0;
}
}
@keyframes progress-bar-stripes{
from {
background-position: 40px 0;
}
to {
background-position: 0 0;
}
}
@keyframes animate-positive {
0% { width: 0; }
}
\ No newline at end of file
@import "../mixins/mixins";
@import '../common/var';
@include b(s-tabs) {
@include e(header) {
display: flex;
flex-direction: row;
padding: 0;
position: relative;
margin: 0 0 15px;
}
@include e(active-bar) {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
background-color: $--color-primary;
z-index: 1;
transition: transform .3s cubic-bezier(.645,.045,.355,1);
list-style: none;
}
@include e(new-tab) {
float: right;
border: 1px solid #d3dce6;
height: 18px;
width: 18px;
line-height: 18px;
margin: 12px 0 9px 10px;
border-radius: 3px;
text-align: center;
font-size: 12px;
color: #d3dce6;
cursor: pointer;
transition: all .15s;
.s-icon-plus {
transform: scale(0.8, 0.8);
}
&:hover {
color: $--color-primary;
}
}
@include e(nav-wrap) {
flex: 1 1 0%;
overflow: hidden;
margin-bottom: -1px;
position: relative;
&::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 2px;
background-color: $--border-color-light;
z-index: $--index-normal;
}
@include when(scrollable) {
padding: 0 20px;
box-sizing: border-box;
}
}
@include e(nav-scroll) {
overflow: hidden;
}
@include e((nav-next, nav-prev)) {
position: absolute;
cursor: pointer;
line-height: 44px;
font-size: 12px;
color: $--color-text-secondary;
}
@include e(nav-next) {
right: 0;
}
@include e(nav-prev) {
left: 0;
}
@include e(nav) {
white-space: nowrap;
position: relative;
transition: transform .3s;
float: left;
z-index: #{$--index-normal + 1};
@include when(stretch) {
min-width: 100%;
display: flex;
& > * {
flex: 1 1 0%;
text-align: center;
}
}
}
@include e(item) {
padding: 0 20px;
height: $--stabs-header-height;
box-sizing: border-box;
line-height: $--stabs-header-height;
display: inline-block;
list-style: none;
font-size: 14px;
font-weight: 500;
color: $--color-text-primary;
position: relative;
&:focus, &:focus:active {
outline: none;
}
&:focus.is-active.is-focus:not(:active) {
box-shadow: 0 0 2px 2px #409eff inset;
border-radius: 3px;
}
& .s-icon-close {
border-radius: 50%;
text-align: center;
transition: all .3s cubic-bezier(.645,.045,.355,1);
margin-left: 5px;
&:before {
transform: scale(.9);
display: inline-block;
}
&:hover {
background-color: $--color-text-placeholder;
color: $--color-white;
}
}
@include when(active) {
color: $--color-primary;
}
&:hover {
color: $--color-primary;
cursor: pointer;
}
@include when(disabled) {
color: $--disabled-color-base;
cursor: default;
}
}
@include e(content) {
overflow: hidden;
position: relative;
}
@include m(card) {
> .s-tabs__header {
border-bottom: 1px solid $--border-color-light;
}
> .s-tabs__header .s-tabs__nav-wrap::after {
content: none;
}
> .s-tabs__header .s-tabs__nav {
border: 1px solid $--border-color-light;
border-bottom: none;
border-radius: 4px 4px 0 0;
box-sizing: border-box;
}
> .s-tabs__header .s-tabs__active-bar {
display: none;
}
> .s-tabs__header .s-tabs__item .s-icon-close {
position: relative;
font-size: 12px;
width: 0;
height: 14px;
vertical-align: middle;
line-height: 15px;
overflow: hidden;
top: -1px;
right: -2px;
transform-origin: 100% 50%;
}
> .s-tabs__header .s-tabs__item {
border-bottom: 1px solid transparent;
border-left: 1px solid $--border-color-light;
transition: color .3s cubic-bezier(.645,.045,.355,1), padding .3s cubic-bezier(.645,.045,.355,1);
&:first-child {
border-left: none;
}
&.is-closable {
&:hover {
padding-left: 13px;
padding-right: 13px;
& .s-icon-close {
width: 14px;
}
}
}
&.is-active {
border-bottom-color: $--color-white;
&.is-closable {
padding-left: 20px;
padding-right: 20px;
.s-icon-close {
width: 14px;
}
}
}
}
}
@include m(border-card) {
background: $--color-white;
border: 1px solid $--border-color-base;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.12), 0 0 6px 0 rgba(0,0,0,0.04);
>.s-tabs__content {
padding: 15px;
}
>.s-tabs__header {
background-color: $--background-color-base;
border-bottom: 1px solid $--border-color-light;
margin: 0;
}
> .s-tabs__header .s-tabs__nav-wrap::after {
content: none;
}
>.s-tabs__header .s-tabs__item {
transition: all .3s cubic-bezier(.645,.045,.355,1);
border: 1px solid transparent;
margin: -1px -1px 0;
color: $--color-text-secondary;
&.is-active {
color: $--color-primary;
background-color: $--color-white;
border-right-color: $--border-color-base;
border-left-color: $--border-color-base;
}
&:not(.is-disabled):hover {
color: $--color-primary;
}
&.is-disabled {
color: $--disabled-color-base;
}
}
}
@include m((top, bottom)) {
.s-tabs__item.is-top:nth-child(2),
.s-tabs__item.is-bottom:nth-child(2) {
padding-left: 0;
}
.s-tabs__item.is-top:last-child,
.s-tabs__item.is-bottom:last-child {
padding-right: 0;
}
&.s-tabs--border-card, &.s-tabs--card,
.s-tabs--left, .s-tabs--right {
.s-tabs__item:nth-child(2) {
padding-left: 20px;
}
.s-tabs__item:last-child {
padding-right: 20px;
}
}
}
@include m(bottom) {
.s-tabs__header.is-bottom {
margin-bottom: 0;
margin-top: 10px;
}
&.s-tabs--border-card {
.s-tabs__header.is-bottom {
border-bottom: 0;
border-top: 1px solid $--border-color-base;
}
.s-tabs__nav-wrap.is-bottom {
margin-top: -1px;
margin-bottom: 0;
}
.s-tabs__item.is-bottom:not(.is-active) {
border: 1px solid transparent;
}
.s-tabs__item.is-bottom {
margin: 0 -1px -1px -1px;
}
}
}
@include m((left, right)) {
overflow: hidden;
.s-tabs__header.is-left,
.s-tabs__header.is-right {
flex-direction: column;
}
.s-tabs__header.is-left,
.s-tabs__header.is-right,
.s-tabs__nav-wrap.is-left,
.s-tabs__nav-wrap.is-right,
.s-tabs__nav-scroll {
height: 100%;
}
.s-tabs__active-bar.is-left,
.s-tabs__active-bar.is-right {
top: 0;
bottom: auto;
width: 2px;
height: auto;
}
.s-tabs__nav-wrap.is-left,
.s-tabs__nav-wrap.is-right {
margin-bottom: 0;
> .s-tabs__nav-prev,
> .s-tabs__nav-next {
height: 30px;
line-height: 30px;
width: 100%;
text-align: center;
cursor: pointer;
i {
transform: rotateZ(90deg);
}
}
> .s-tabs__nav-prev {
left: auto;
top: 0;
}
> .s-tabs__nav-next {
right: auto;
bottom: 0;
}
&.is-scrollable {
padding: 30px 0;
}
&::after {
height: 100%;
width: 2px;
bottom: auto;
top: 0;
}
}
.s-tabs__nav.is-left,
.s-tabs__nav.is-right {
float: none;
}
.s-tabs__item.is-left,
.s-tabs__item.is-right {
display: block;
}
}
@include m(left) {
.s-tabs__header.is-left {
float: left;
margin-bottom: 0;
margin-right: 10px;
}
.s-tabs__nav-wrap.is-left {
margin-right: -1px;
&::after {
left: auto;
right: 0;
}
}
.s-tabs__active-bar.is-left {
right: 0;
left: auto;
}
.s-tabs__item.is-left {
text-align: right;
}
&.s-tabs--card {
.s-tabs__active-bar.is-left {
display: none;
}
.s-tabs__item.is-left {
border-left: none;
border-right: 1px solid $--border-color-light;
border-bottom: none;
border-top: 1px solid $--border-color-light;
}
.s-tabs__item.is-left:first-child {
border-right: 1px solid $--border-color-light;
border-top: none;
}
.s-tabs__item.is-left.is-active {
border: 1px solid $--border-color-light;
border-right-color: #fff;
border-left: none;
border-bottom: none;
&:first-child {
border-top: none;
}
&:last-child {
border-bottom: none;
}
}
.s-tabs__nav {
border-radius: 4px 0 0 4px;
border-bottom: 1px solid $--border-color-light;
border-right: none;
}
.s-tabs__new-tab {
float: none;
}
}
&.s-tabs--border-card {
.s-tabs__header.is-left {
border-right: 1px solid #dfe4ed;
}
.s-tabs__item.is-left {
border: 1px solid transparent;
margin: -1px 0 -1px -1px;
&.is-active {
border-color: transparent;
border-top-color: rgb(209, 219, 229);
border-bottom-color: rgb(209, 219, 229);
}
}
}
}
@include m(right) {
.s-tabs__header.is-right {
float: right;
margin-bottom: 0;
margin-left: 10px;
}
.s-tabs__nav-wrap.is-right {
margin-left: -1px;
&::after {
left: 0;
right: auto;
}
}
.s-tabs__active-bar.is-right {
left: 0;
}
&.s-tabs--card {
.s-tabs__active-bar.is-right {
display: none;
}
.s-tabs__item.is-right {
border-bottom: none;
border-top: 1px solid $--border-color-light;
}
.s-tabs__item.is-right:first-child {
border-left: 1px solid $--border-color-light;
border-top: none;
}
.s-tabs__item.is-right.is-active {
border: 1px solid $--border-color-light;
border-left-color: #fff;
border-right: none;
border-bottom: none;
&:first-child {
border-top: none;
}
&:last-child {
border-bottom: none;
}
}
.s-tabs__nav {
border-radius: 0 4px 4px 0;
border-bottom: 1px solid $--border-color-light;
border-left: none;
}
}
&.s-tabs--border-card {
.s-tabs__header.is-right {
border-left: 1px solid #dfe4ed;
}
.s-tabs__item.is-right {
border: 1px solid transparent;
margin: -1px -1px -1px 0;
&.is-active {
border-color: transparent;
border-top-color: rgb(209, 219, 229);
border-bottom-color: rgb(209, 219, 229);
}
}
}
}
@include e(contextmenu) {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 2000;
padding: 6px 0;
font-size: 14px;
background-color: #fff;
box-shadow: $--select-dropdown-shadow;
@include m(item) {
padding: 10px 16px;
color: $--color-text-regular;
cursor: pointer;
&:hover {
background-color: $--select-option-hover-background;
}
}
}
}
.slideInRight-transition,
.slideInLeft-transition {
display: inline-block;
}
.slideInRight-enter {
animation: slideInRight-enter .3s;
}
.slideInRight-leave {
position: absolute;
left: 0;
right: 0;
animation: slideInRight-leave .3s;
}
.slideInLeft-enter {
animation: slideInLeft-enter .3s;
}
.slideInLeft-leave {
position: absolute;
left: 0;
right: 0;
animation: slideInLeft-leave .3s;
}
@keyframes slideInRight-enter {
0% {
opacity: 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(100%);
transform: translateX(100%)
}
to {
opacity: 1;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(0);
transform: translateX(0)
}
}
@keyframes slideInRight-leave {
0% {
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1
}
100% {
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(100%);
transform: translateX(100%);
opacity: 0
}
}
@keyframes slideInLeft-enter {
0% {
opacity: 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(-100%);
transform: translateX(-100%)
}
to {
opacity: 1;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(0);
transform: translateX(0)
}
}
@keyframes slideInLeft-leave {
0% {
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1
}
100% {
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
opacity: 0
}
}
@import "./common/var";
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index.scss";
@import "~smart-web/packages/styles/src/index.scss";
\ No newline at end of file
$namespace: '';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';
@import "config";
/* BEM support Func
-------------------------- */
@function selectorToString($selector) {
$selector: inspect($selector);
$selector: str-slice($selector, 2, -2);
@return $selector;
}
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector, $modifier-separator) {
@return true;
} @else {
@return false;
}
}
@function containWhenFlag($selector) {
$selector: selectorToString($selector);
@if str-index($selector, '.' + $state-prefix) {
@return true
} @else {
@return false
}
}
@function containPseudoClass($selector) {
$selector: selectorToString($selector);
@if str-index($selector, ':') {
@return true
} @else {
@return false
}
}
@function hitAllSpecialNestRule($selector) {
@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}
@import "function";
/* BEM
-------------------------- */
@mixin b($block) {
$B: $block !global;
.#{$B} {
@content;
}
}
@mixin e($element) {
$E: $element !global;
$selector: &;
$currentSelector: "";
@each $unit in $element {
$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
}
@if hitAllSpecialNestRule($selector) {
@at-root {
#{$selector} {
#{$currentSelector} {
@content;
}
}
}
} @else {
@at-root {
#{$currentSelector} {
@content;
}
}
}
}
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
}
@at-root {
#{$currentSelector} {
@content;
}
}
}
@mixin configurable-m($modifier, $E-flag: false) {
$selector: &;
$interpolation: '';
@if $E-flag {
$interpolation: $element-separator + $E-flag;
}
@at-root {
#{$selector} {
.#{$B+$interpolation+$modifier-separator+$modifier} {
@content;
}
}
}
}
@mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B) {
$modifierCombo: '';
@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}
@at-root {
#{&}#{$specSelector}.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}
@mixin meb($modifier: false, $element: $E, $block: $B) {
$selector: &;
$modifierCombo: '';
@if $modifier {
$modifierCombo: $modifier-separator + $modifier;
}
@at-root {
#{$selector} {
.#{$block+$element-separator+$element+$modifierCombo} {
@content
}
}
}
}
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
@mixin extend-rule($name) {
@extend #{'%shared-'+$name};
}
@mixin share-rule($name) {
$rule-name: '%shared-'+$name;
@at-root #{$rule-name} {
@content
}
}
\ No newline at end of file
@mixin utils-user-select($value) {
-moz-user-select: $value;
-webkit-user-select: $value;
-ms-user-select: $value;
}
@mixin utils-clearfix {
$selector: &;
@at-root {
#{$selector}::before,
#{$selector}::after {
display: table;
content: "";
}
#{$selector}::after {
clear: both
}
}
}
@mixin utils-vertical-center {
$selector: &;
@at-root {
#{$selector}::after {
display: inline-block;
content: "";
height: 100%;
vertical-align: middle
}
}
}
@mixin utils-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
\ No newline at end of file
import Vue from 'vue';
import store from '@/store';
import Utils from '@/utils';
import { getTheme, changeTheme } from '@/utils/global';
const vm = new Vue();
/**
* 应用初始化的一个配置操作
* 比如检查登录、获取皮肤配置,其他配置等
*/
// 加载用户主题
if (localStorage.getItem('themeValue')) {
const val = JSON.parse(localStorage.getItem('themeValue'));
changeTheme(val);
} else {
const val = {format: 'left-right', themeColor: 'deep'};
changeTheme(val);
}
// 监听用户改变
vm.$watch(function() {
return store.state.userInfo;
}, function(val) {
if (!Utils.isEmptyData(val)) {
// 获取皮肤
getTheme();
}
});
import menu from './modules/menu';
import system from './modules/system';
/**
* 全局平台表达式
* @example
* $.menu.xxx()
* $.system.xxx()
* $.form.xxx() // 扩展表单, 表单页面调用才有效
*/
const SWE = {
menu,
system
};
window.$ = SWE;
export default SWE;
import store from '@/store';
import Utils from '@/utils';
import { checkAsyncComponents } from '@/plugins/asyncComponents';
/**
* 菜单表达式函数
* 操作标签页
*/
export default {
/**
* 全局打开新标签页方法
* 利用的是store, id作为唯一性检查,没有id就会自动生成id
* @param {Object} data 组件的对象,比如 {id:'', name:'组织构架管理', componentName:'frameworkManage'}
* @param {Any} param 绑定到数据里的param
*/
openTab(data, param) {
if (!data.id) data.id = Utils.generateId();
let componentName = data.componentName || data.router;
// 判断是否为http开头的外链
if (componentName.indexOf('http') === 0) {
param = {
url: componentName
};
componentName = 'appIframe';
} else {
// 判断是否异步注册该组件
const isRegistered = checkAsyncComponents(componentName);
if (!isRegistered) {
componentName = 'errorPage';
}
}
// 菜单模块ID赋值,权限通过模块ID获取的
if (!data.moduleId) {
const menuList = store.getters['menu/menuList'];
if (menuList.length > 0) {
let menu;
const fn = (data) => {
const len = data.length;
for (let i = 0; i < len; i++) {
// console.log(data[i].router, componentName)
if (data[i].router === componentName) {
menu = data[i];
break;
} else {
if (data[i].children && data[i].children.length > 0) {
fn(data[i].children);
}
}
}
};
fn(menuList);
// 模块id赋值
if (menu) data.moduleId = menu.moduleId;
}
}
data.componentName = componentName;
if (param) data.param = param;
store.dispatch('setNavigation', data);
},
/**
* 打开一个外部链接的标签
* @param {String} name 标签名称
* @param {String} url 外部URL
* @param {Boolean|String} only 布尔值为true时,是固定使用externalLinkTab---1打开页面,当是string字符串时,自定义打开固定标签页
*/
openExternalLinkTab(name, url, only) {
const id = (typeof only === 'boolean' && only)
? 'externalLinkTab---1'
: (typeof only === 'string' && only)
? only : '';
this.openTab({
id,
name,
componentName: url
});
},
/**
* 关闭/移除标签页
* @param {String} id tab标签的唯一标识
*/
removeTab(id) {
window.removeTab(id); // 用的是Main.vue里的tab标签移除方法
},
/**
* 刷新标签页
* @param {String} id tab标签的唯一标识
*/
refreshTab(id) {
store.state.navigationList.map(item => {
if (item.id === id) {
item.param = {
reload: new Date()
};
}
});
},
// 获取当前打开的标签页
getCurrentTab() {
return store.state.currentNavigation;
}
};
import store from '@/store';
import { Notification } from 'element-ui';
/**
* 系统表达式函数
* 获取系统,用户, 全局通知等信息
*/
export default {
/**
* 获取用户信息
* @returns {Object | null}
*/
getUser() {
return store.state.userInfo || null;
},
/**
* 获取用户身份
* @returns {String}
*/
getUserName() {
return store.state.userInfo ? store.state.userInfo.RealName : '';
},
/**
* 获取系统信息
* @returns {Object}
*/
getSystemInfo() {
return store.state.platformInfo || null;
},
/**
* 获取用户身份
* @returns {String} admin | none
*/
getUserIdentity() {
return store.state.userIdentity || '';
},
/**
* 公共提示方法,一般用于组件内保存提交时提示
* @param {object} options 和element-ui Notification组件属性一样
* 例如:object = {type: 'success', title: '操作成功', message: '页面保存成功'}
*/
notification(options) {
const {
customClass = 'custom-notification',
position = 'bottom-right',
...opts
} = options;
const _opts = {
customClass,
position,
...opts
};
Notification(_opts);
}
};
### WEB平台前端表达式
```js
window.$ = {expression}
```
`$` 是 Smart Web Expression 的缩写
> 主要使用于表单工作流上设计,也可以用于某些组件内,但不建议,建议还是使用模块化引用开发
> 绑定在`window`全局上
\ No newline at end of file
import store from '../store';
import router from '../router';
import Api from '../api';
import Utils from './index';
import $ from './expression';
// 获取URL参数
export const getQueryString = (name) => {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
const r = window.location.search.substr(1).match(reg); // 查询?后面的参数,并匹配正则
if (r != null) return unescape(r[2]);
const param = getHashParameters();
// console.log(param)
if (param[name]) return param[name];
return null;
};
function getHashParameters() {
const arr = (location.hash || '').replace(/^#\/[a-zA-Z0-9]*\?/, '').split('&');
const params = {};
for (let i = 0; i < arr.length; i++) {
const data = arr[i].split('=');
if (data.length === 2) {
params[data[0]] = data[1];
}
}
return params;
}
// 改变初始化加载提示文字
const appLoadingSub = document.getElementById('app-loading-subtitle');
if (appLoadingSub) appLoadingSub.innerHTML = '正在获取系统信息中...';
// 移除加载页
export function removeLoading() {
const el = document.getElementById('app-loading');
if (el) {
el.className = 'app-loading app-loading-leave';
setTimeout(() => { el.parentNode && el.parentNode.removeChild(el); }, 251);
}
}
// 获取系统信息
export function getSystemInfo(sysCode) {
sysCode = sysCode || getQueryString('sysCode');
console.log('系统code:', sysCode);
return new Promise((resolve, reject) => {
Api.getSystemInfo(sysCode).then(res => {
removeLoading();
if (res.status === 0) {
// console.log(res.data)
store.state.platformInfo.systemId = res.data.systemId;
store.state.platformInfo.name = res.data.sysMainTitle;
resolve();
} else {
reject(res);
}
}).catch(err => {
removeLoading();
// 获取系统信息错误
router.replace({
name: 'Unfound'
});
reject(err);
});
});
}
/**
* 获取用户信息
*/
export const getUser = $.system.getUser;
/**
* 获取用户名
*/
export const getUserName = $.system.getUserName;
/**
* 全局打开新标签页方法
* 利用的是store, id作为唯一性检查,没有id就会自动生成id
* @param {Object} data 组件的对象,比如 {id:'', name:'组织构架管理', componentName:'frameworkManage'}
* @param {Any} param 绑定到数据里的param
*/
export const openTab = $.menu.openTab;
/**
* 关闭/移除tab
* @param {String} id tab标签的唯一标识
*/
export const removeTab = $.menu.removeTab;
/**
* 刷新tab页
* @param {String} id tab标签的唯一标识
*/
export const refreshTab = $.menu.refreshTab;
/**
* 公共提示方法,一般用于组件内保存提交时提示
* @param {object} options 和element-ui Notification组件属性一样
*/
export const notification = $.system.notification;
/**
* 改变皮肤的方法
* 为body添加is-class
* @param {Object} theme
*/
export const changeTheme = (theme) => {
document.body.className = theme.format + ' is-' + theme.themeColor;
store.dispatch('setTheme', theme);
localStorage.setItem('themeValue', JSON.stringify(theme));
};
/**
* 获取个人界面皮肤配置
*/
export const getTheme = () => {
Api.getUserConfigTheme().then(res => {
if (res.status === 0) {
const data = res.data;
if (!Utils.isEmptyData(data)) {
changeTheme(data);
}
}
});
};
/**
* 日期转成方法,注册到原型链上
* @param {Stirng} fmt yyyy-MM-dd hh:mm:ss
*/
/* eslint no-extend-native: "off" */
Date.prototype.format = function(fmt) {
const o = {
'M+': this.getMonth() + 1, // 月份
'd+': this.getDate(), // 日
'h+': this.getHours(), // 小时
'm+': this.getMinutes(), // 分
's+': this.getSeconds(), // 秒
'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
'S': this.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
}
}
return fmt;
};
const utils = {
/**
* 判断数据是否为空,一般数据是object/array
* @param {Object/Array}
*/
isEmptyData(data) {
if (data === null || data === undefined) return true;
if (data instanceof Object) {
let t;
for (t in data) {
return false;
}
return true;
} else if (data instanceof Array) {
if (data.length === 0) return true;
return false;
}
},
/**
* 深拷贝
* @param {Object|Array} p
* @param {Object|Array} c [] or {}
*/
deepCopy(p, c) {
c = c || {};
for (const i in p) {
if (typeof p[i] === 'object') {
c[i] = p[i]
? (p[i] && p[i].constructor === Array) ? [] : {}
: p[i];
this.deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
},
/**
* 随机生成唯一 ID
* @param {Number}
*/
generateId(len = 4) {
return Number(Math.random().toString().substr(3, len) + Date.now()).toString(36);
},
/**
* 优化遍历,数组去重
* @param {Array} array
*/
uniq(array, key) {
const temp = [];
const index = [];
const l = array.length;
for (let i = 0; i < l; i++) {
for (let j = i + 1; j < l; j++) {
if (array[i][key] && array[i][key] === array[j][key]) {
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
return temp;
}
};
export default utils;
import permissionMixin from '../permissionMixin';
/**
* 系统设置一般公共性权限
*/
export default {
mixins: [permissionMixin]
};
import Api from '@/api';
/**
* 组件混入统一权限
* data注入userAuthories存储接口或者管理权限
* userAuthories = {
* identity: 'admin', // 或者无
* defaultAuthority: '2', // 2-只读,4-操作,8-管理(后台约束)
* expandAuthorities: [] // 扩展的权限列表
* }
*/
export default {
computed: {
$SMTab() {
return this.$store.state.currentNavigation;
},
userInfo() {
return this.$store.state.userInfo;
},
defaultAuthority() {
return this.userAuthories ? this.userAuthories.defaultAuthority : '';
},
expandAuthorities() {
return this.userAuthories ? this.userAuthories.expandAuthorities : [];
}
},
data() {
return {
userAuthories: null
};
},
watch: {
userInfo: {
deep: true,
handler(val) {
if (val && val.userId) {
this.initPermission();
}
}
},
userAuthories: {
deep: true,
handler(val) {
this.hanldePermission && this.hanldePermission(val);
}
}
},
created() {
this.initPermission();
},
methods: {
initPermission() {
// 超级管理员特殊处理
if (this.$store.state.userIdentity === 'admin') {
this.userAuthories = {
defaultAuthority: 8,
expandAuthorities: []
};
return;
}
/**
* 一些模块的控件过滤
* 例如:没有存在的菜单的项的路由组件,不作权限控件
*/
if (this.$SMTab &&
[].indexOf(this.$SMTab.componentName) >= 0
) {
return;
}
// 判断是否有moduleId,一般首页没有
if (!this.$SMTab || !this.$SMTab.moduleId) return;
Api.getUserAuthories(this.$SMTab.moduleId).then(res => {
if (res.status === 0) {
this.userAuthories = {
defaultAuthority: res.data.defaultSysAuthorize,
expandAuthorities: res.data.sysAuthorizeList
};
}
});
}
},
};
import permissionMixin from '../permissionMixin';
/**
* 系统设置一般公共性权限
*/
export default {
mixins: [permissionMixin]
};
import { getUser, getUserName, openTab, removeTab, refreshTab, notification } from './global';
// 配置全局,可以在iframe等地方使用
window.openTab = openTab;
window.removeTab = removeTab;
window.refreshTab = refreshTab;
window.notification = notification;
window.getUser = getUser;
window.getUserName = getUserName;
<template>
<div :class="['app-main', theme.format]">
<app-header v-if="theme.format === 'top-bottom'" :class="themeClrCls"></app-header>
<div class="app-wrapper">
<app-navigation></app-navigation>
<div class="app-container" ref="appContainer">
<!-- <div class="app_container-main">
<app-tabs></app-tabs>
<router-view></router-view>
</div> -->
<s-tabs class="app-container--main" v-model="currentTab" type="card" @tab-remove="removeTab">
<template slot="header" v-if="theme.format === 'left-right'">
<app-header></app-header>
</template>
<s-tab-pane
v-for="item in tabsData"
:key="item.id"
:label="item.name"
:name="item.id"
:closable="hasOwnProperty(item, 'closable') ? item.closable : true"
>
<vue-progress-bar style="position:absolute;"></vue-progress-bar>
<component :is="item.componentName" @tab-mounted="handleComponentMounted"></component>
</s-tab-pane>
</s-tabs>
</div>
</div>
<router-view></router-view>
</div>
</template>
<script>
import AppHeader from './common/Header';
import AppNavigation from './Navigation';
import Utils from '@/utils';
import { changeTheme } from '@/utils/global';
export default {
name: 'Main',
components: {
AppHeader,
AppNavigation
},
computed: {
theme() {
return this.$store.state.theme;
},
themeClrCls() {
return 'is-' + this.theme.themeColor;
},
currentNavigation() {
return this.$store.state.currentNavigation;
},
navigationList() {
return this.$store.state.navigationList;
}
},
data() {
return {
currentTab: 'home',
oldNavigation: null,
tabsData: [
{
name: '首页',
id: 'home',
style: '',
closable: false,
componentName: 'appHome'
}/* , {
name: 'frameworkManage',
title: '组织架构管理',
style: '',
componentName: 'frameworkManage'
} */
]
};
},
watch: {
theme: {
immediate: true,
handler(val) {
changeTheme(val);
}
},
currentNavigation(newVal, oldVal) {
this.oldNavigation = oldVal;
if (!Utils.isEmptyData(newVal)) {
let flag = true;
const len = this.tabsData.length;
for (let i = 0; i < len; i++) {
if (this.tabsData[i].id === newVal.id) {
this.currentTab = this.tabsData[i].id;
flag = false;
break;
}
}
if (!flag) return;
let index = 0;
this.tabsData.map((tab, idx) => {
if (!Utils.isEmptyData(oldVal) && oldVal.id === tab.id) {
index = idx;
}
});
// 判断去追加,在是在后面追加
if (!index) {
this.tabsData.push(newVal);
} else {
this.tabsData.splice(index + 1, 0, newVal);
}
this.currentTab = newVal.id;
// 新打开tab
this.$Progress.start();
}
},
navigationList(newVal) {
if (newVal.length > 0) {
}
},
currentTab() {
const len = this.tabsData.length;
for (let i = 0; i < len; i++) {
if (this.tabsData[i].id === this.currentTab) {
this.$store.dispatch('setNavigation', this.tabsData[i]);
break;
}
}
}
},
mounted() {
this.init();
// 注册到全局
window.removeTab = this.removeTab;
},
methods: {
init() {
this.currentTab = 'home';
this.$store.dispatch('initNavigation');
},
hasOwnProperty(obj, key) {
return obj.hasOwnProperty(key);
},
removeTab(targetName) {
const tabs = this.tabsData;
let activeName = this.currentTab;
if (activeName === targetName) {
for (let i = 0; i < tabs.length; i++) {
// 判断是否跳到上一个访问过标签页
if (!Utils.isEmptyData(this.oldNavigation) && tabs[i].id === this.oldNavigation.id) {
activeName = this.oldNavigation.id;
break;
} else if (tabs[i].id === targetName) {
const nextTab = tabs[i + 1] || tabs[i - 1];
if (nextTab) {
activeName = nextTab.id;
}
}
}
}
this.currentTab = activeName;
this.tabsData = tabs.filter(tab => tab.id !== targetName);
this.$store.dispatch('removeNavigation', targetName);
},
handleComponentMounted() {
// console.log('handleComponentMounted')
this.$Progress.finish();
}
}
};
</script>
<template>
<div :class="['app-navigation', {'is-collapse': isCollapse}, themeClrCls]" @mouseover="isShowControll = true" @mouseout="isShowControll = false">
<logo v-if="theme.format === 'left-right'" />
<span v-if="isLoading" style="text-align: center; color: #abb9d1;"><i class="el-icon-loading"></i></span>
<el-menu
:default-active="defaultActive"
class="app-navigation--menu"
:collapse="isCollapse"
:unique-opened="true">
<template v-for="subItem in navDatas">
<el-submenu
:key="subItem.moduleId"
v-if="subItem.children && subItem.children.length > 0"
:index="subItem.moduleId"
:disabled="subItem.disabled">
<template slot="title">
<i v-if="subItem.icon && !hasImage(subItem.icon)" :class="['iconfont', subItem.icon]"></i>
<img v-else-if="hasImage(subItem.icon)" class="imgIcon" :src="subItem.icon" width="16" height="16">
<span class="text">{{ subItem.name }}</span>
</template>
<el-menu-item
v-for="item in subItem.children"
:key="item.moduleId"
:index="item.moduleId"
:disabled="item.disabled"
@click.native="handleSelect(item)">
<i v-if="item.icon && !hasImage(item.icon)" :class="['iconfont', item.icon]"></i>
<img v-else-if="hasImage(item.icon)" class="imgIcon" :src="item.icon" width="16" height="16">
<span class="text">{{ item.name }}</span>
</el-menu-item>
</el-submenu>
<el-menu-item
v-else
:key="subItem.moduleId"
:index="subItem.moduleId"
:disabled="subItem.disabled"
@click.native="handleSelect(subItem)">
<i v-if="subItem.icon && !hasImage(subItem.icon)" :class="['iconfont', subItem.icon]"></i>
<img v-else-if="hasImage(subItem.icon)" class="imgIcon" :src="subItem.icon" width="16" height="16">
<span class="text">{{ subItem.name }}</span>
</el-menu-item>
</template>
</el-menu>
<!-- <div class="app-navigation--menu">
<el-tree
:data="navDatas"
:props="defaultProps"
empty-text="暂无或未取到系统模块"
node-key="moduleId"
highlight-current
@current-change="handleSelect">
<span class="nav-tree-node" slot-scope="{ node, data }">
<span>
<i v-if="data.icon && !hasImage(data.icon)" :class="['iconfont', data.icon]"></i>
<span v-else-if="hasImage(data.icon)" class="imgIcon">
<img :src="data.icon" width="18" height="18">
</span>
{{ node.label }}
</span>
</span>
</el-tree>
</div> -->
<div class="navigation-controll" v-show="isShowControll" @click="isCollapse = !isCollapse">
<i class="iconfont" :class="controllIcon"></i>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex';
import Utils from '@/utils';
import { openTab } from '@/utils/global';
import Api from '@/api';
import Logo from './common/Logo.vue';
export default {
name: 'Navigation',
components: {
Logo
},
computed: {
...mapState(['theme', 'platformInfo', 'userInfo']),
themeClrCls() {
return 'is-' + this.theme.themeColor;
},
controllIcon() {
return this.isCollapse ? 'icon-right' : 'icon-left';
}
},
data() {
return {
isLoading: false,
defaultProps: {
children: 'children',
label: 'name'
},
defaultActive: '',
isCollapse: false,
isShowControll: false,
navDatas: [/*
{
title: '我的工作',
name: 'myWork',
icon: 'iconfont icon-riqi',
router: '',
children: [
{
title: '收文管理',
name: 'receiptManage',
icon: 'iconfont icon-bumen',
router: 'receiptManage'
}, {
title: '创建工作',
name: 'createWork',
icon: 'iconfont icon-zuhe',
router: 'createWork'
}
]
}, {
title: '统计分析',
name: 'statisAnalysis',
icon: 'iconfont icon-shipin',
router: 'statisAnalysis'
}, {
title: '系统设置',
name: 'systemSetup',
icon: 'iconfont icon-shezhi',
router: 'systemSetup',
children: [
{
title: '模块管理',
name: 'modulesManage',
router: 'modulesManage'
}, {
title: '组织结构管理',
name: 'frameworkManage',
router: 'frameworkManage'
}, {
title: '权限管理',
name: 'authorityManage',
router: 'authorityManage'
}, {
title: '行政区划管理',
name: 'districtManage',
router: 'districtManage'
}, {
title: '子系统管理',
name: 'childSystemManage',
router: 'childSystemManage'
}, {
title: '业务定义',
name: 'businessDefine',
router: 'businessDefine'
}, {
title: '代码字典',
name: 'codeDictionary',
router: 'codeDictionary'
}, {
title: '工作流设计',
name: 'workflowDesign',
router: 'workflowDesign'
}, {
title: '电子印章管理',
name: 'stampdefManage',
router: 'stampdefManage'
}, {
title: '编号公式管理',
name: 'formulaManage',
router: 'formulaManage'
}, {
title: '节假日管理',
name: 'holidayManage',
router: 'holidayManage'
}, {
title: '单位信息',
name: 'companyInfomation',
router: 'companyInfomation'
}
]
}, {
title: 'WebGis',
name: 'webGis',
icon: 'iconfont icon-wang',
router: 'webGis'
}
*/]
};
},
watch: {
userInfo(val) {
this.fecthData();
}
},
mounted() {
this.fecthData();
},
methods: {
...mapActions({
dispatchMenuList: 'menu/setMenuList'
}),
hasImage(val) {
return val && /(.jpg|.png|.jpeg|.ico|.gif)$/g.test(val.toString());
},
fecthData() {
if (Utils.isEmptyData(this.userInfo)) return;
this.isLoading = true;
Api.getUserModulesTreeBySystemId(this.platformInfo.systemId).then(res => {
this.isLoading = false;
// console.log(res)
if (res.status === 0) {
this.navDatas = res.data;
this.dispatchMenuList(this.navDatas);
} else {
this.$message({
type: 'warning',
message: '获取模块树失败,请重试'
});
}
}).catch(err => {
this.isLoading = false;
this.$message({
type: 'warning',
message: err.message || '获取模块树失败,请重试'
});
});
},
handleSelect(item) {
if (!item.router) {
this.$message({
type: 'warning',
message: '没有配置到路由',
duration: 2000
});
return;
}
this.defaultActive = item.moduleId;
const obj = {
id: item.pageId || item.router,
moduleId: item.moduleId,
pageId: item.pageId,
name: item.name,
componentName: item.router
};
openTab(obj);
}
}/* ,
render (h) {
let menuItem = ''
this.navDatas.map(item => {
if (item.children && item.children.length > 0) {
menuItem += `<el-submenu index="${item.router}">`
}
})
} */
};
</script>
<template>
<sw-business-configuration></sw-business-configuration>
</template>
<script>
export default {
name: 'businessConfiguration',
};
</script>
<template>
<div class="app-iframe" style="overflow: hidden;">
<error-page v-if="!url"></error-page>
<ss-iframe v-else :url="url" :name="name" @load="handleFrameLoaded"></ss-iframe>
</div>
</template>
<script>
export default {
name: 'AppIframe',
computed: {
currentNavigation() {
return this.$store.state.currentNavigation;
}
},
data() {
return {
navigation: null,
url: '',
name: '',
};
},
/* watch: {
currentNavigation: {
deep: true,
handler (val) {
if (val) {
if (val.componentName === 'appIframe' && val.param) {
this.navigation = val
}
}
}
},
'navigation.param' () {
this.init()
}
}, */
mounted() {
window.currentNavigation = this.currentNavigation;
this.navigation = this.currentNavigation;
this.init();
},
methods: {
init() {
this.$Progress.start();
this.url = this.currentNavigation && this.currentNavigation.param ? this.currentNavigation.param.url : '';
this.name = this.currentNavigation.id;
},
handleFrameLoaded() {
console.log('----------------------handleFrameLoaded');
this.$Progress.finish();
}
}
};
</script>
<template>
<ss-iframe :url="url"></ss-iframe>
</template>
<script>
/**
* 渲染快速功能配置页
* smart-page
*/
export default {
name: 'ConfigurePage',
data() {
return {
url: ''
};
},
mounted() {
const tab = this.$store.state.currentNavigation;
this.url = `./form.html?pageId=${tab.pageId}&moduleId=${tab.moduleId}`;
}
};
</script>
<template>
<div class="app-header">
<logo v-if="theme.format === 'top-bottom'" />
<div class="app-header--right">
<div class="app-header__userinfo">
<!-- <a href="javascript:;" class="message gutter" @click="handleMessage">
<i class="iconfont icon-tongzhi"></i>
<div class="tips">9</div>
</a>-->
<div class="app-header--function">
<a class="el-button el-button--text"
:href="`${serviceUrl}/smartcharts`" target="_blank">
<span>图表设计器</span>
</a>
<a class="el-button el-button--text"
:href="`${serviceUrl}/smartform`" target="_blank">
<span>表单设计器</span>
</a>
</div>
<el-badge :value="unreadMessage"
:hidden="unreadMessage === 0 || unreadMessage === '0'"
style="margin-right: 10px;cursor: pointer;"
:max="99"
@click.native="handleMessage">
<i class="iconfont icon-tongzhi"></i>
</el-badge>
<a href="javascript:;" class="user-name gutter">
<i class="iconfont icon-touxiang"></i>
<span v-if="userInfo.RealName" @click="handleUserClick">{{ userInfo.RealName }}</span>
<span v-else @click="handleRelogin">登录</span>
</a>
<!-- <a href="javascript:;" class="quit-user gutter" @click="logout">
<i class="iconfont icon-tuichu"></i>
<span>退出</span>
</a> -->
<el-button v-if="userInfo.RealName" class="quit-user gutter" type="text"
size="small" icon="iconfont icon-tuichu" :loading="isLoadingout" @click="logout">
退出
</el-button>
</div>
</div>
</div>
</template>
<script>
import Api from '@/api';
import { baseUrl, serviceUrl } from '@config/http.config';
import Logo from './Logo.vue';
import { openTab } from '@/utils/global';
export default {
name: 'AppHeader',
components: {
Logo
},
computed: {
theme() {
return this.$store.state.theme;
},
themeClrCls() {
return 'is-' + this.theme.themeColor;
},
userInfo() {
return this.$store.state.userInfo;
},
organName() {
return this.userInfo.OrganName ? this.userInfo.OrganName : '无部门';
},
unreadMessage() {
return this.$store.state.unreadMessage || 0;
}
},
data() {
return {
serviceUrl,
isLoadingout: false,
websocket: null
};
},
watch: {
userInfo(val) {
if (val) {
this.init();
} else {
window.WebSocket && this.websocket && this.websocket.close();
}
}
},
mounted() {
this.init();
},
beforeDestroy() {
window.WebSocket && this.websocket && this.websocket.close();
},
methods: {
init() {
if (this.userInfo && this.userInfo.userId && window.WebSocket) {
this.websocket = new WebSocket(`ws:${baseUrl}/MessageWebsocket?userId=${this.userInfo.userId}`);
this.websocket.onopen = function(event) {
// console.log(event)
};
this.websocket.onclose = function(event) {
// console.log(event)
};
this.websocket.onmessage = (event) => {
// state.unreadMessage = event.data
// this.unreadMessage = event.data;
this.$store.dispatch('setUnreadMessage', event.data);
};
this.websocket.onerror = function(event) {
// console.log(event)
};
}
},
/**
* 查看消息
*/
handleMessage() {
openTab({
id: 'appMessage',
name: '我的消息',
componentName: 'appMessage'
});
},
handleRelogin() {
this.$router.push('/loginDialog');
},
handleUserClick() {
openTab({
id: 'accountSetting',
name: '账户设置',
componentName: 'accountSetting'
});
},
logout() {
this.$confirm('是否要退出账户?', '退出', {
type: 'warning'
}).then(_ => {
this.isLoadingout = true;
Api.logout().then(res => {
this.isLoadingout = false;
if (res.status === 0) {
this.$message({
type: 'success',
message: '账户退出成功'
});
this.$router.replace({
path: '/login',
query: this.$route.query
});
} else {
this.$message({
type: 'warning',
message: res.message
});
}
}).catch(err => {
this.isLoadingout = false;
this.$message({
type: 'error',
message: err.message
});
});
}).catch(_ => {});
}
}
};
</script>
<template>
<div class="home-config">
</div>
</template>
<script>
export default {
name: 'HomeConfig'
};
</script>
<template>
<div class="app-logo" href="#">
<a class="menu" href="javascript:;" :title="platformInfo.name"><span class="img"></span></a>
<h2 class="app-title" :style="appTilteStl">{{ platformInfo.name }}</h2>
</div>
</template>
<script>
export default {
name: 'Logo',
computed: {
theme() {
return this.$store.state.theme;
},
platformInfo() {
return this.$store.state.platformInfo;
},
appTilteStl() {
if (this.theme.format === 'top-bottom') return { fontSize: '22px' };
let fontSize = '20px';
const getStrLen = (str) => {
if (str == null) return 0;
if (typeof str !== 'string') {
str += '';
}
/* eslint-disable */
return str.replace(/[^\x00-\xff]/g, '01').length
}
let len = getStrLen(this.platformInfo.name)
// console.log(len)
len >= 20 ? fontSize = '16px' : fontSize = '20px'
return { fontSize }
}
}
}
</script>
\ No newline at end of file
<template>
<sw-home
@statis-item-click="handleStatisClick"
@open-doing-work="handleOpenDoingWork"
@open-doing-work-more="handleDoingWorkMore">
</sw-home>
</template>
<script>
import {openTab} from '@/utils/global';
export default {
name: 'AppHome',
methods: {
handleStatisClick(item) {
openTab({
id: item.router,
name: item.text,
componentName: item.router
});
},
handleOpenDoingWork(row) {
openTab({
id: 'doingWork',
name: '在办工作',
componentName: 'doingWork',
param: {
jid: row['job_base-jid']
}
});
},
handleDoingWorkMore() {
openTab({
id: 'doingWork',
name: '在办工作',
componentName: 'doingWork'
});
}
}
};
</script>
<template>
<div class="function-module">
<div class="title">已有模块</div>
<div class="content">
<span class="module-item" v-for="module in componentsNames" :key="module">{{ module }}</span>
</div>
</div>
</template>
<script>
import { getComponentsName } from '@/plugins/asyncComponents';
export default {
name: 'functionModule',
data() {
return {
componentsNames: null
};
},
mounted() {
this.componentsNames = getComponentsName();
}
};
</script>
<template>
<sw-icon></sw-icon>
</template>
<script>
export default {
name: 'iconView',
};
</script>
<template>
<sw-message
:user-info="userInfo"
@unread-message-change="handleUnreadMessageChange">
</sw-message>
</template>
<script>
export default {
name: 'AppMessage',
computed: {
userInfo() {
return this.$store.state.userInfo;
}
},
methods: {
handleUnreadMessageChange(val) {
this.$store.dispatch('setUnreadMessage', val);
}
}
};
</script>
<template>
<div class="login__wrapper" id="loginView">
<div class="login-logo">
<span class="login-logo__icon"></span>
<span class="login-logo__title">{{ systemTitle }}</span>
</div>
<login-form @submit="handleSubmited"></login-form>
</div>
</template>
<script>
import LoginForm from './LoginForm.vue';
export default {
name: 'Login',
components: {
LoginForm
},
computed: {
systemTitle() {
return this.$store.state.platformInfo.name;
}
},
methods: {
handleSubmited(userInfo) {
console.log(userInfo);
}
}
};
</script>
<template>
<div class="login-dialog__wrapper">
<el-dialog
:visible.sync="dialogVisible"
width="400px"
:close-on-click-modal="false"
:close-on-press-escape="false"
@open="handleOpened"
@close="handleClose">
<span slot="title"></span>
<login-form @submit="handleSubmited"></login-form>
</el-dialog>
</div>
</template>
<script>
import LoginForm from './LoginForm';
// import { checkLogin } from '@/utils/global'
export default {
name: 'LoginDialog',
components: {
LoginForm
},
data() {
return {
dialogVisible: false
};
},
mounted() {
setTimeout(() => {
this.open();
}, 4);
},
methods: {
open() {
this.dialogVisible = true;
},
handleOpened() {
this.$nextTick(() => {
this.$message({
message: '账户登录已失效,请重新登录',
type: 'warning',
duration: 4000
});
});
},
handleClose() {
this.$router.replace('/');
},
handleSubmited(userInfo) {
// console.log(userInfo)
this.$message.closeAll();
}
}
};
</script>
<template>
<div class="login-form">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span style="line-height: 36px;font-size:20px;">登录</span>
<span v-if="showClose" class="login-form__close" @click.stop="handleClose"><i class="el-icon-close"></i></span>
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="rules"
label-width="100px"
@submit.native.prevent>
<el-form-item label="账户:" prop="name">
<el-input v-model="loginForm.name" placeholder="输入登录用户名" autofocus @change="handleInputChange"></el-input>
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input type="password"
v-model="loginForm.password"
placeholder="请输入密码"
@keyup.native.enter="onSubmit('loginForm')"
@change="handleInputChange"></el-input>
</el-form-item>
<el-form-item>
<el-checkbox label="记住账户" v-model="loginForm.remember"></el-checkbox>
</el-form-item>
<el-form-item class="buttons">
<el-button
type="primary"
size="large"
class="submitBtn"
:loading="loginForm.loading"
@click="onSubmit()" >
{{ loginForm.submitText }}
</el-button>
<el-button type="text" @click="resetFields()">重置</el-button>
</el-form-item>
<el-form-item v-if="loginForm.isSubmit" style="margin-bottom: 0;">
<el-alert type="error" :title="loginForm.errorText" :closable="true" style="line-height: 1.2;" @close="loginForm.isSubmit = false"></el-alert>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import sha1 from 'js-sha1';
import Api from '@/api';
export default {
name: 'LoginForm',
props: {
showClose: Boolean
},
data() {
return {
loginForm: {
name: '',
password: '',
remember: false,
loading: false,
isSubmit: false,
errorText: '用户名或密码错误',
submitText: '登录'
},
rules: {
name: [
{required: true, message: '请输入账户名称', trigger: 'change'}/* ,
{ min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' } */
],
password: [
{required: true, message: '请输入密码', trigger: 'change'}/* ,
{ min: 3, max: 18, message: '长度在 3 到 18 个字符', trigger: 'blur' } */
]
}
};
},
mounted() {
this.init();
},
methods: {
init() {
if (window.localStorage) {
const rname = localStorage.getItem('rememberName');
this.loginForm.name = rname;
this.loginForm.remember = true;
}
},
handleInputChange() {
this.loginForm.isSubmit = false;
},
onSubmit() {
this.$refs['loginForm'].validate((valid) => {
this.loginForm.isSubmit = false;
if (valid) {
this.loginForm.loading = true;
const psw = sha1(this.loginForm.password).toUpperCase();
const uName = this.loginForm.name.replace(/\s/g, '');
Api.login({
username: uName,
password: psw
}).then(res => {
this.loginForm.loading = false;
const data = res.data;
if (res.status === 0) {
// 本地存储
if (this.loginForm.remember) {
localStorage.setItem('rememberName', uName);
}
// vuex store
const userState = {
...data.loginInfo,
userId: data.userId
};
this.$store.dispatch('setUserInfo', userState);
// notify
const message = '欢迎您,' + userState.RealName;
this.$notify({
title: '登录成功',
message: message,
type: 'success'
});
this.$emit('submit', userState);
this.$router.replace({
path: '/',
query: this.$route.query
});
} else {
this.loginForm.errorText = res.message || '用户名或密码错误';
this.loginForm.isSubmit = true;
}
}).catch(err => {
this.loginForm.loading = false;
this.loginForm.isSubmit = true;
this.loginForm.errorText = '提交失败,服务有误! ' + err.message;
});
} else {
console.log('error submit!!');
return false;
}
});
},
resetFields() {
this.$refs['loginForm'].resetFields();
},
handleClose() {
this.$emit('close');
}
}
};
</script>
<template>
<sw-catalog-management></sw-catalog-management>
</template>
<script>
export default {
name: 'catalogManagement',
};
</script>
<template>
<sw-layer-manage></sw-layer-manage>
</template>
<script>
export default {
name: 'layerManage',
};
</script>
<template>
<sw-map-config></sw-map-config>
</template>
<script>
export default {
name: 'mapConfig',
};
</script>
<template>
<sw-map-search></sw-map-search>
</template>
<script>
export default {
name: 'mapSearchConfig',
};
</script>
<template>
<sw-service-register></sw-service-register>
</template>
<script>
export default {
name: 'serviceRegister',
};
</script>
<template>
<sw-check-process
:user-authority="userAuthories"
:process-instance-id="processInstanceId">
</sw-check-process>
</template>
<script>
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'checkProcess',
mixins: [permission],
data() {
return {
processInstanceId: ''
};
},
computed: {
currentNavigation() {
return this.$store.state.currentNavigation;
}
},
created() {
this.init();
},
methods: {
init() {
this.processInstanceId = this.currentNavigation.param.processInstanceId;
},
}
};
</script>
<template>
<sw-create-work
ref="createWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@create-work="handleCreateWork"
@setting-column="handleSetColumn">
</sw-create-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'CreateWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.createWork.refresh();
},
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}`,
parent: 'createWork'
}
});
},
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
handleCreateWork(id) {
openTab({
name: '创建工作窗口',
componentName: 'appIframe',
param: {
url: `./form.html?businessDefinitionId=${id}`
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'create_list'
}
});
}
}
};
</script>
<template>
<sw-delete-box
ref="deleteBox"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-delete-box>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'DeleteBox',
mixins: [permission],
methods: {
refresh() {
this.$refs.deleteBox.refresh();
},
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey,
historyProcessInstanceId
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}&historyProcessInstanceId=${historyProcessInstanceId}`,
parent: 'deleteBox'
}
});
},
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'delete_list'
}
});
}
}
};
</script>
<template>
<sw-doing-work
ref="doingWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-doing-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'DoingWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.doingWork.refresh();
},
// 打开
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}`,
parent: 'doingWork'
}
});
},
// 查看流转情况,流程
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'run_list'
}
});
}
}
};
</script>
<template>
<sw-finished-work
ref="finishedWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-finished-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'FinishedWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.finishedWork.refresh();
},
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}`,
parent: 'finishedWork'
}
});
},
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'finish_list'
}
});
}
}
};
</script>
<template>
<sw-handled-work
ref="handledWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-handled-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'HandledWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.handledWork.refresh();
},
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}`,
parent: 'handledWork'
}
});
},
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'handled_list'
}
});
}
}
};
</script>
<template>
<sw-monitor-work
ref="monitorWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-monitor-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'MonitorWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.monitorWork.refresh();
},
// 打开
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey,
historyProcessInstanceId
} = data;
openTab({
name: businessId || '查看工作',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}&historyProcessInstanceId=${historyProcessInstanceId}`,
parent: 'monitorWork'
}
});
},
// 查看流转情况,流程
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'monitor_run_list'
}
});
}
}
};
</script>
<template>
<sw-return-box
ref="returnBox"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-return-box>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'ReturnBox',
mixins: [permission],
methods: {
refresh() {
this.$refs.returnBox.refresh();
},
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey,
historyProcessInstanceId
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}&historyProcessInstanceId=${historyProcessInstanceId}`,
parent: 'returnBox'
}
});
},
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'sendback_list'
}
});
}
}
};
</script>
<template>
<sw-setting-column
ref="settingColumn"
:user-authority="userAuthories"
:type="workType"></sw-setting-column>
</template>
<script>
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'SettingColumn',
mixins: [permission],
computed: {
$SMTab() {
return this.$store.state.currentNavigation;
}
},
data() {
return {
workType: ''
};
},
watch: {
$SMTab(value) {
if (value.componentName === 'settingColumn' && value.param.workType !== this.workType) {
// this.$store.dispatch('setCurrentNavigation', value.name)
this.refresh();
}
}
},
created() {
this.workType = this.$SMTab.param.workType;
},
methods: {
refresh() {
this.workType = this.$SMTab.param.workType;
this.$refs.settingColumn.refresh();
},
}
};
</script>
<template>
<sw-suspend-work
ref="suspendWork"
:user-authority="userAuthories"
@open-work="handleOpenWork"
@check-process="handleCheckProcess"
@setting-column="handleSetColumn"></sw-suspend-work>
</template>
<script>
import { openTab } from '@/utils/global';
import permission from '@/utils/mixins/myWork/permission';
export default {
name: 'suspendWork',
mixins: [permission],
methods: {
refresh() {
this.$refs.suspendWork.refresh();
},
// 打开
handleOpenWork(data) {
const {
businessId,
taskId,
linkInstanceId,
linkDefinitionKey
} = data;
openTab({
name: businessId || '查看环节',
id: businessId,
componentName: 'appIframe',
param: {
url: `./form.html?taskId=${taskId}&linkInstanceId=${linkInstanceId}&linkDefinitionKey=${linkDefinitionKey}`,
parent: 'suspendWork'
}
});
},
// 查看流转情况,流程
handleCheckProcess(data) {
const {
businessId,
processInstanceId,
taskId
} = data;
openTab({
id: '', // 不设置,可以多打开
name: businessId ? `${businessId} - 流程` : '查看流程',
componentName: 'checkProcess',
param: {
processInstanceId: processInstanceId,
taskId: taskId
}
});
},
// 设置列
handleSetColumn() {
openTab({
id: 'settingColumn',
name: `${this.$parent.label}-设置列`,
componentName: 'settingColumn',
param: {
workType: 'suspend_list'
}
});
}
}
};
</script>
<template>
<sw-account @user-change="handleUserChange"></sw-account>
</template>
<script>
export default {
name: 'accountSetting',
methods: {
handleUserChange(userInfo) {
this.$store.state.userInfo.RealName = userInfo.realName;
}
}
};
</script>
<template>
<sw-interface
:theme="theme"
@theme-change="handleThemeChange"></sw-interface>
</template>
<script>
import { changeTheme } from '@/utils/global';
export default {
name: 'interface',
computed: {
theme() {
return this.$store.state.theme;
}
},
methods: {
handleThemeChange(form) {
changeTheme(form);
}
}
};
</script>
<template>
<sw-sql-naming :authories="userAuthories"></sw-sql-naming>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'SNamingManagement',
mixins: [permission],
};
</script>
<template>
<sw-district :authories="userAuthories"></sw-district>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'adminDivision',
mixins: [permission],
};
</script>
<template>
<sw-authority
:authories="userAuthories"
:sysName="sysName"
:childSysId="childSysId">
</sw-authority>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'AuthorityManage',
mixins: [permission],
data() {
return {
sysName: '', // 系统名称
childSysId: '' // 系统ID
};
},
created() {
this._initData();
},
methods: {
// 初始化数据
_initData() { // 平台tab传值替换
if (this.$SMTab && this.$SMTab.hasOwnProperty('param') && this.$SMTab.param.hasOwnProperty('childSysId')) {
this.sysName = this.$SMTab.param.sysName;
this.childSysId = this.$SMTab.param.childSysId;
}
}
}
};
</script>
<template>
<sw-business-definition :authories="userAuthories" @check-expression="checkExpresion">
</sw-business-definition>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
import { openTab } from '@/utils/global';
export default {
name: 'BusinessDefManager',
mixins: [permission],
methods: {
checkExpresion(node) {
const param = {
currentNode: node || null
};
const data = {
id: 'checkExpression',
componentName: 'checkExpression',
name: '检查表达式'
};
openTab(data, param);
},
}
};
</script>
<template>
<sw-check-expression
:authories="userAuthories"
:business-node="businessNode"></sw-check-expression>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
import Utils from '@/utils';
export default {
name: 'CheckExpression',
mixins: [permission],
data() {
return {
businessNode: null
};
},
computed: {
currentNavigation() {
return this.$store.state.currentNavigation;
}
},
watch: {
'currentNavigation.param': {
immediate: true,
deep: true,
handler(val, oldVal) {
if (!Utils.isEmptyData(val) && oldVal !== val) {
this.handleRouteParam();
}
}
},
},
methods: {
// 初始和改变时处理拿到的页面传参
handleRouteParam() {
this.businessNode = this.currentNavigation.param.currentNode;
}
}
};
</script>
<template>
<sw-child-system
:authories="userAuthories"
@check-system="handleCheckSystem"
@modules-manage="handleModulesManage"
@funtion-modules-manage="handleChildFunctions"
@authority-manage="handleChildAuthority"></sw-child-system>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
import { openTab } from '@/utils/global';
export default {
name: 'ChildSystemManage',
mixins: [permission],
methods: {
handleCheckSystem(system) {
let url = system.visitUrl;
if (!url) url = location.protocol + '//' + location.host + location.pathname + (location.hash ? '#/' : '') + '?sysCode=' + system.sysCode;
window.open(url);
},
/**
* 子系统模块管理
*/
handleModulesManage(childSysId, sysName) {
openTab({
id: '', // 不设置,可以多打开
name: sysName + '模块管理',
componentName: 'modulesManage',
param: {
childSysId,
sysName
}
});
},
/**
* 子系统功能点管理
*/
handleChildFunctions(childSysId, sysName) {
openTab({
id: '', // 不设置,可以多打开
name: sysName + '功能点管理',
componentName: 'functionModulesManage',
param: {
childSysId,
sysName
}
});
},
/**
* 子系统权限管理
*/
handleChildAuthority(childSysId, sysName) {
openTab({
id: '', // 不设置,可以多打开
name: sysName + '子权限管理',
componentName: 'authorityManage',
param: {
childSysId,
sysName
}
});
},
}
};
</script>
<template>
<sw-code-dictionary :authories="userAuthories"></sw-code-dictionary>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'CodeDictionary',
mixins: [permission],
};
</script>
<template>
<sw-company :authories="userAuthories"></sw-company>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'compInformation',
mixins: [permission],
};
</script>
<template>
<sw-edit-process
:url="url"
@before-load="init"
@loaded="handleFrameLoaded">
<error-page slot="error"></error-page>
</sw-edit-process>
</template>
<script>
export default {
name: 'EditProcess',
computed: {
currentNavigation() {
return this.$store.state.currentNavigation;
}
},
data() {
return {
navigation: null,
url: ''
};
},
watch: {
currentNavigation: {
deep: true,
handler(val) {
if (val) {
if (val.componentName === 'EditProcess' && val.param) {
this.navigation = val;
}
}
}
},
'navigation.param'() {
this.init();
}
},
mounted() {
this.navigation = this.currentNavigation;
},
methods: {
init() {
this.$Progress.start();
this.$Progress.increase(10);
this.url = this.navigation && this.navigation.param ? this.navigation.param.url : '';
},
handleFrameLoaded() {
this.$Progress.finish();
}
}
};
</script>
<template>
<sw-environment :authories="userAuthories"></sw-environment>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'EnvironmentConfig',
mixins: [permission],
};
</script>
<template>
<sw-framework :authories="userAuthories"></sw-framework>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'FrameworkManage',
mixins: [permission]
};
</script>
<template>
<sw-function-modules
:authories="userAuthories"
:childInfo="childInfo"
:platformInfo="platformInfo"
/>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'FunctoinModulesManage',
mixins: [permission],
computed: {
$SMTab() {
return this.$store.state.currentNavigation;
},
platformInfo() {
return this.$store.state.platformInfo;
}
},
data() {
return {
childInfo: null, // 子系统信息
};
},
created() {
this._initData();
},
methods: {
// 初始化数据
_initData() {
if (this.$SMTab.param) {
this.childInfo = {
systemId: this.$SMTab.param.childSysId,
name: this.$SMTab.param.sysName
};
} else {
this.childInfo = null;
}
},
}
};
</script>
<template>
<sw-holiday :authories="userAuthories"></sw-holiday>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'HolidayManagement',
mixins: [permission],
};
</script>
<template>
<sw-modules
:authories="userAuthories"
:childInfo="childInfo"
:platformInfo="platformInfo"
@check-icon="handleCheckMoreIcon">
<function-modules slot="modulesList"></function-modules>
</sw-modules>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
import FunctionModules from '@/views/common/functionModule';
import { openTab } from '@/utils/global';
export default {
name: 'ModulesManage',
mixins: [permission],
components: {
FunctionModules
},
computed: {
$SMTab() {
return this.$store.state.currentNavigation;
},
platformInfo() {
return this.$store.state.platformInfo;
}
},
data() {
return {
childInfo: null, // 子系统信息
};
},
created() {
this._initData();
},
methods: {
_initData() {
if (this.$SMTab.param) {
this.childInfo = {
systemId: this.$SMTab.param.childSysId,
name: this.$SMTab.param.sysName
};
} else {
this.childInfo = null;
}
},
handleCheckMoreIcon() {
openTab({
id: 'iconView',
name: '图标',
componentName: 'iconView'
});
},
}
};
</script>
<template>
<sw-common-words :authories="userAuthories"></sw-common-words>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'myComWord',
mixins: [permission],
};
</script>
<template>
<sw-operation-log :authories="userAuthories"></sw-operation-log>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'operationLog',
mixins: [permission],
};
</script>
<template>
<sw-number-formula :authories="userAuthories"></sw-number-formula>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'snBuilder',
mixins: [permission],
};
</script>
<template>
<sw-stamp :authories="userAuthories"></sw-stamp>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'StampdefManage',
mixins: [permission],
};
</script>
<template>
<sw-task-scheduling :authories="userAuthories"></sw-task-scheduling>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
export default {
name: 'taskScheduling',
mixins: [permission],
};
</script>
<template>
<sw-workflow
:authories="userAuthories"
@create-workflow="handleCreateProcess"
@edit-workflow="handleEditProcess"
></sw-workflow>
</template>
<script>
import permission from '@/utils/mixins/systemSetup/permission';
import { openTab } from '@/utils/global';
import { baseUrl } from '@config/http.config';
export default {
name: 'WorkflowDesign',
mixins: [permission],
methods: {
handleCreateProcess(modelId) {
const data = {
id: '',
name: '新建流程',
componentName: 'appIframe'
};
const url = baseUrl + '/modeler.html?modelId=' + modelId;
openTab(data, { url: url });
},
handleEditProcess(modelId) {
const data = {
id: 'edit-process',
name: '编辑流程',
componentName: 'editProcess'
};
const url = baseUrl + '/modeler.html?modelId=' + modelId;
// let url = process.env.NODE_ENV === 'development' ? serviceUrl + '/smartweb2' : '.'
// url += '/workflow-designer/index.html?modelId=' + this.currentNode.id
openTab(data, { url: url, reload: true });
},
}
};
</script>
module.exports = {
env: {
mocha: true
}
};
import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message';
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
});
expect(wrapper.text()).to.include(msg);
});
});
const webpack = require('webpack');
const path = require('path');
function resolve(dir) {
return path.join(__dirname, dir);
}
const pages = {
app: {
// page 的入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-commons', 'element-ui', 'app']
},
form: {
entry: 'form/main.js',
template: 'form/form.html',
filename: 'form.html',
chunks: ['chunk-vendors', 'chunk-commons', 'element-ui', 'smart-form', 'form']
}
};
module.exports = {
publicPath: './',
runtimeCompiler: true,
devServer: {
host: '0.0.0.0',
port: '8022'
},
productionSourceMap: false,
pages: pages,
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
const configs = {};
configs.optimization = {
splitChunks: {
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // 只打包初始时依赖的第三方
},
elementUI: {
name: 'element-ui', // 单独将 elementUI 拆包
priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
test: /[\\/]node_modules[\\/]element-ui[\\/]/
},
smartForm: {
name: 'smart-form', // 单独将拆包
priority: 21, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
test: /[\\/]node_modules[\\/]smart-form[\\/]/
}/* ,
commons: {
name: 'chunk-comomns',
test: resolve('src/components'), // 可自定义拓展你的规则
minChunks: 2, // 最小共用次数
priority: 5,
reuseExistingChunk: true
} */
}
}
};
return configs;
}
},
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('src'))
.set('@form', resolve('form'))
.set('@config', resolve('config'));
const arr = ['app', 'form'];
// TODO: Remove this workaround once https://github.com/vuejs/vue-cli/issues/2463 is fixed
// Remove preload plugins for multi-page build to prevent infinite recursion
arr.forEach(page => {
config.plugins.delete(`preload-${page}`);
config.plugins.delete(`prefetch-${page}`);
});
config.plugin('ignore')
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
},
// IE兼容
transpileDependencies: ['element-ui/src', 'element-ui/packages']
};
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