fix:初始化天马流程代码,后续对接接口删掉不必要功能

parents
Showing with 4859 additions and 0 deletions
# 开发环境配置
VUE_APP_MODE = 'development'
# Jeeplus快速开发平台/开发环境
VUE_APP_BASE_API = '/api'
VUE_APP_SERVER_URL = 'http://rapidplatform.meiqicloud.com/'
# 生产环境配置
VUE_APP_MODE = 'pre'
VUE_APP_BASE_API = '/api'
#Jeeplus快速开发平台/后台地址
#VUE_APP_SERVER_URL = 'http://szpastest.tianma.cn/api'
VUE_APP_SERVER_URL = 'http://172.16.100.28/api'
# 生产环境配置
VUE_APP_MODE = 'production'
VUE_APP_BASE_API = '/api'
VUE_APP_SERVER_URL = ''http://172.16.100.29/api'
# 开发环境配置
VUE_APP_MODE = 'stage'
VUE_APP_BASE_API = '/api'
VUE_APP_SERVER_URL = 'https://sz-tianma-test.meiqicloud.com/api'
\ No newline at end of file
# 开发环境配置
VUE_APP_MODE = 'test'
VUE_APP_BASE_API = '/api'
VUE_APP_SERVER_URL = 'http://sz-tianma.meiqicloud.com/api'
.DS_Store
node_modules
dist
doc
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
node {
def remote1 = [:]
remote1.name = "test"
remote1.host = "192.168.0.77"
remote1.user = "root"
remote1.password = "HopdelDad@!Ldko%dlogA"
remote1.allowAnyHosts = true
remote1.project = "/home/group1_lzy/sz-tianma-server/workflow"
def remote2 = [:]
remote2.name = "uat"
remote2.host = "124.71.60.29"
//remote2.host = "192.168.0.29"
remote2.user = "root"
remote2.password = "makeit@888"
remote2.allowAnyHosts = true
remote2.project = "/home/tianma/workflow"
//配置项
def remoteList = [remote1, remote2]
//配置项
//def project = "/home/group1_lzy/sz-tianma-server/workflow"
//配置项
def profileList = ["build", "build:prod", "build:stage"]
def remoteNameList = []
for (def a in remoteList) {
remoteNameList += a.name;
}
def module = "."
properties([
parameters([
gitParameter(branch: "",
branchFilter: "origin/(.*)",
defaultValue: "master",
description: "",
name: "branch",
quickFilterEnabled: false,
selectedValue: "NONE",
sortMode: "NONE",
tagFilter: "*",
type: "PT_BRANCH"),
choice(name: "profile", choices: profileList),
choice(name: "server", choices: remoteNameList)
])
])
def branch = "${params.branch}"
def profile = "${params.profile}"
def server = "${params.server}"
echo branch
echo profile
echo server
stage("Preparation") {
checkout([$class : "GitSCM",
branches : [[name: "${params.branch}"]], // 传入分支
doGenerateSubmoduleConfigurations: false,
extensions : [],
gitTool : "Default",
submoduleCfg : [],
userRemoteConfigs : scm.userRemoteConfigs // !重要,复用我们在 Jenkins 上 SCM 配置,如凭据、仓库地址
])
}
stage("Build") {
echo "build"
nodejs("node"){
sh "npm install"
sh "npm run "+profile
}
}
stage("Deploy") {
def remote = null;
for (def a in remoteList) {
if (a.name == server) {
remote = a
}
}
def project = remote.project
sshPut remote: remote, from: "dist/", into: project+"/tmp"
sshCommand remote: remote, command: "rm -rf " + project + "/dist"
sshCommand remote: remote, command: "mv " + project + "/tmp/dist " + project + "/dist"
}
}
<p align="center">
<img src="https://pic.rmb.bdstatic.com/bjh/e2fe27dbed5b8c43bbd59374360c5763.png" width="100px">
</p>
<h1 align="center">wflow-pro 工作流</h1>
#### 📌 pro私有仓库禁止 直接fork,否则永久移出仓库,请遵循授权协议使用
#### 📢 严禁私下传播、倒卖等未经授权侵犯知识产权的使用行为
使用方式及文档参见官网 [wflow-pro](http://wflow.willianfu.top/docs/dev-pro/project.html)
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
/* "env"*/
],
/* plugins: [
"transform-vue-jsx"
]*/
}
image.png

72.2 KB

This diff could not be displayed because it is too large.
{
"name": "client",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --mode test",
"build:test": "vue-cli-service build --mode test",
"build:stage": "vue-cli-service build --mode stage",
"build:pre": "vue-cli-service build --mode pre",
"build:prod": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint",
"test": "vue-cli-service inspect"
},
"dependencies": {
"@tinymce/tinymce-vue": "2.1.0",
"@vant/area-data": "^1.3.1",
"@zxing/library": "^0.19.1",
"axios": "^0.20.0",
"clipboard": "^2.0.6",
"core-js": "^3.6.5",
"element-ui": "^2.15.8",
"less": "^3.12.2",
"less-loader": "^7.0.1",
"moment": "^2.29.4",
"monaco-editor": "0.30.0",
"qrcodejs2": "0.0.2",
"signature_pad": "^3.0.0-beta.4",
"tinymce": "5.4.1",
"vant": "^2.12.48",
"vue": "^2.6.11",
"vue-amap": "^0.5.10",
"vue-router": "^3.4.3",
"vuedraggable": "^2.24.1",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-preset-env": "^1.7.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"monaco-editor-webpack-plugin": "6.0.0",
"style-resources-loader": "^1.3.2",
"vue-cli-plugin-style-resources-loader": "^0.1.4",
"vue-template-compiler": "^2.6.11",
"vuepress": "^1.9.9"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
This diff could not be displayed because it is too large.
No preview for this file type
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<style type="text/css">
body{
margin: 0;
}
.loadingSeven{
/* background: #1989fa; */
color: #000;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.loadingSeven span{
display: inline-block;
width: 8px;
height: 100%;
border-radius: 4px;
background: white;
-webkit-animation: loadsaven 1.04s ease infinite;
}
@-webkit-keyframes loadsaven{
0%,100%{
height: 10px;
background: white;
}
50%{
height: 30px;
margin-top: -20px;
background: white;
}
}
.loadingSeven span:nth-child(2){
-webkit-animation-delay:0.13s;
}
.loadingSeven span:nth-child(3){
-webkit-animation-delay:0.26s;
}
.loadingSeven span:nth-child(4){
-webkit-animation-delay:0.39s;
}
.loadingSeven span:nth-child(5){
-webkit-animation-delay:0.52s;
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<div id="loading" class="loadingSeven">
加载中...
</div>
<!-- <div id="loading" class="loadingSeven">
<div style="text-align: center">
<div>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div style="font-size: 12px; margin-top: 5px;">
wflow-pro
<div style="font-size: 14px">正在努力加载中...</div>
</div>
</div>
</div> -->
</div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<transition name="router-fade" mode="out-in">
<router-view v-if="!$route.meta.keepAlive" />
</transition>
</div>
</template>
<script>
//import layout from './components/layout'
export default {
components: {},
data() {
return {};
},
mounted() {
if (
sessionStorage.getItem("path") &&
sessionStorage.getItem("path") !== "undefined"
) {
this.$router.push(sessionStorage.getItem("path"));
}
},
methods: {},
};
</script>
<style lang="less">
:focus {
outline: -webkit-focus-ring-color auto 0px;
}
body {
margin: 0;
min-width: 300px;
// background-color: #f5f6f6;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
body,
html {
margin: 0;
height: 100%;
}
ul {
padding: 0;
margin: 0;
li {
list-style-type: none;
}
}
.item-desc {
font-size: small;
color: #5e5e5e;
}
.max-fill {
width: 100% !important;
}
::-webkit-scrollbar {
width: 0;
height: 10px;
background-color: white;
}
::-webkit-scrollbar-thumb {
width: 0;
height: 10px;
border-radius: 16px;
background-color: #d9d9d9;
}
/*/deep/ .el-message {
background: white !important;
padding: 5px !important;
}*/
</style>
import request from './request.js'
// 物料
export function matLedgerPage(params) {
return request({
url: `/mat/material/page`,
method: 'post',
data: params
})
}
// 产品分页
export function productPage(params) {
return request({
url: `/base/product/page`,
method: 'post',
data: params
})
}
// 站点
export function stationPage(params) {
return request({
url: `/base/station/post/page`,
method: 'post',
data: params
})
}
//异常分类
export function categoryPage(params) {
return request({
url: `/ams/category/page`,
method: 'post',
data: params
})
}
//工序段
export function procedureSectionPage(params) {
return request({
url: `/ams/procedure-section/page`,
method: 'post',
data: params
})
}
//工序
export function procedurePage(params) {
return request({
url: `/ams/procedure/page`,
method: 'post',
data: params
})
}
// 不良项目
export function undesirableItemPage(params) {
return request({
url: `/ams/undesirable-item/page`,
method: 'post',
data: params
})
}
// 原材料异常分类
export function incomeMaterialPage(params) {
const url = `/ams/income-material/page`
return request({
url: url,
method: 'post',
data: params
})
}
// 异常等级
export function gradePage(params) {
return request({
url: `/ams/grade/page`,
method: 'post',
data: params
})
}
// 异常单-编辑
export function billEdit(data) {
const url = `/ams/bill/edit`
return request({
url: url,
method: 'post',
data: data
})
}
// 异常单详情
export function billView(data) {
const url = `/ams/bill/view`
return request({
url: url,
method: 'post',
data: data
})
}
//异常内容-分页列表
export function exContentPage(data) {
const url = `/ams/content/page`
return request({
url: url,
method: 'post',
data: data
})
}
import request from '@/api/request.js'
// 查询表单组
export function getFormGroups(param) {
return request({
url: 'admin/form/group',
method: 'get',
params: param
})
}
// 表单排序
export function groupItemsSort(param) {
return request({
url: 'admin/form/group/sort',
method: 'put',
data: param
})
}
// 更新表单组
export function updateGroup(param, method) {
return request({
url: 'admin/form/group',
method: method,
params: param
})
}
// 获取表单分组
export function getGroup() {
return request({
url: 'admin/form/group/list',
method: 'get'
})
}
// 更新表单
export function updateForm(param) {
return request({
url: 'admin/form',
method: 'put',
params: param
})
}
export function createForm(param){
return request({
url: 'admin/form',
method: 'post',
data: param
})
}
// 查询表单详情
export function getFormDetail(id) {
return request({
url: 'admin/form/detail/' + id,
method: 'get'
})
}
// 更新表单详情
export function updateFormDetail(param) {
return request({
url: 'admin/form/detail',
method: 'put',
data: param
})
}
export default {
getFormGroups, groupItemsSort, createForm, getFormDetail,
updateGroup, getGroup, updateForm, updateFormDetail
}
import request from '@/api/request.js'
// 查询表单及分组
export function getGroupModels(param) {
return request({
url: 'wflow/model/group/list',
method: 'get',
params: param
})
}
// 查询表单及分组
export function getGroupModelsByUser(param) {
return request({
url: 'wflow/model/list/byUser',
method: 'get',
params: param
})
}
// 查询所有模型分组
export function getModelGroups(param) {
return request({
url: '/wflow/model-group/list',
method: 'post',
data: param
})
}
// 表单分组排序
export function modelGroupsSort(param) {
return request({
url: 'wflow/model/group/sort',
method: 'put',
data: param
})
}
// 表单排序
export function modelsSort(groupId, param) {
return request({
url: `wflow/model/sort/${groupId}`,
method: 'put',
data: param
})
}
// 修改分组
export function updateModelGroupName(groupId, param) {
return request({
url: `wflow/model/group/${groupId}`,
method: 'put',
params: param
})
}
// 新增模型分组
export function createModelGroup(param) {
return request({
url: `/wflow/model-group/add`,
method: 'post',
data: param
})
}
// 删除分组
export function deleteModelGroup(groupId) {
return request({
url: `wflow/model/group/${groupId}`,
method: 'delete'
})
}
// 删除模型
export function deleteModel(modelId) {
return request({
url: `wflow/model/${modelId}`,
method: 'delete'
})
}
// 获取模型
export function getModelById(modelId) {
return request({
url: `wflow/model/detail/${modelId}`,
method: 'get'
})
}
// 获取模型
export function getModelByDefId(defId) {
return request({
url: `wflow/model/detail/def/${defId}`,
method: 'get'
})
}
// 修改分组
export function modelMoveToGroup(modelId, groupId) {
return request({
url: `wflow/model/${modelId}/move/${groupId}`,
method: 'put'
})
}
// 启用或停用流程
export function enOrDisModel(modelId, type) {
return request({
url: `wflow/model/${modelId}/active/${type}`,
method: 'put'
})
}
// 获取抄送我的流程
export function getCcMeList(params) {
return request({
url: `wflow/process/ccMe`,
method: 'get',
params: params
})
}
// 获取控制台统计数据
export function getProcessCountData() {
return request({
url: `wflow/process/instance/count`,
method: 'get'
})
}
export default {
createModelGroup, updateModelGroupName, modelGroupsSort,
modelsSort, getGroupModels, getModelGroups, modelMoveToGroup,
deleteModelGroup, deleteModel, getModelById, getModelByDefId,
enOrDisModel, getCcMeList, getProcessCountData, getGroupModelsByUser
}
import request from '@/api/request.js'
//获取用户通知
export function getUserNotify(params){
return request({
url: `wflow/notify`,
method: 'get',
params: params
})
}
//已读通知
export function readNotify(params){
return request({
url: `wflow/notify`,
method: 'put',
data: params
})
}
export default {
getUserNotify, readNotify
}
import request from '@/api/request.js'
// 查询组织架构树
export function getOrgTree(param) {
return request({
url: 'oa/org/tree',
method: 'get',
params: param
})
}
// 查询系统角色
export function getRole() {
return request({
url: 'oa/org/role',
method: 'get'
})
}
// 搜索人员
export function getUserByName(param) {
return request({
url: 'oa/org/tree/user/search',
method: 'get',
params: param
})
}
// 搜索人员
export function getUserDepts(userId) {
return request({
url: `oa/org/user/${userId}/dept`,
method: 'get'
})
}
// 获取审批代理人
export function getUserAgent() {
return request({
url: `oa/org/user/agent`,
method: 'get'
})
}
// 获取审批代理人
export function setUserAgent(params) {
return request({
url: `oa/org/user/agent`,
method: 'put',
data: params
})
}
// 获取审批代理人
export function cancelUserAgent() {
return request({
url: `oa/org/user/agent`,
method: 'delete'
})
}
export default {
getOrgTree, getUserByName, getRole,
getUserDepts, getUserAgent, setUserAgent, cancelUserAgent
}
import request from '@/api/request.js'
import {syncRequest} from './request.js'
/**
*
* 查询当前用户的指定级别领导
* @param level 指定级别
* @param deptId 部门ID
* @param skipEmpty 是否跳过空部门
* @returns {Promise<unknown>}
*/
export function getUserLeader(level, deptId, skipEmpty){
return request({
url: `wflow/process/step/leader/level`,
method: 'get',
params: {level: level, deptId: deptId, skipEmpty: skipEmpty}
})
}
/**
* 查询当前用户的指定级别下的所有领导
* @param maxLevel 截至级别,为空则直到顶级
* @param deptId 部门ID
* @param skipEmpty 是否跳过空部门
*/
export function getUserLeaders(maxLevel, deptId, skipEmpty){
return request({
url: `wflow/process/step/leader/to/level`,
method: 'get',
params: {maxLevel: maxLevel, deptId: deptId, skipEmpty: skipEmpty}
})
}
/**
* 获取指定系统角色的所有人员
* @param roles
*/
export function getUsersByRoles(roles){
return request({
url: `wflow/process/step/userByRoles`,
method: 'post',
data: roles
})
}
/**
* 查询所有部门主管
* @param deptIds 部门ID
*/
export function getLeaderByDepts(deptIds){
return request({
url: `wflow/process/step/deptLeader`,
method: 'post',
data: deptIds
})
}
/**
* 获取指定人员是否属于某部门
* @param userId 该人员ID
* @param depts 部门 List
*/
export function userInDepts(userId, depts){
let result = false
syncRequest({
url: `/wflow/process/step/user/${userId}/belong/depts`,
method: 'POST',
data: depts,
type: 'json',
success: res => {
result = res
}
})
return result
}
export function getNewVerProcess(code){
return request({
url: `wflow/process/model/${code}`,
method: 'get'
})
}
export function saveProcess(params){
return request({
url: `wflow/process/model/save/`,
method: 'post',
data: params
})
}
export function deployProcess(code){
return request({
url: `wflow/process/model/deploy/${code}`,
method: 'post'
})
}
export function getCustomPrintConfig(instanceId){
return request({
url: `wflow/process/model/customPrint/${instanceId}`,
method: 'get'
})
}
export function delProcessInst(instanceId){
return request({
url: `wflow/process/instance/${instanceId}`,
method: 'delete'
})
}
export function startProcess(code, params){
return request({
url: `wflow/process/start/${code}`,
method: 'post',
data: params
})
}
export default {
getUserLeader, getUserLeaders, getUsersByRoles, userInDepts,
deployProcess, saveProcess, getNewVerProcess, getCustomPrintConfig,
getLeaderByDepts, delProcessInst
}
import request from './request.js'
//获取用户待办
export function getUserTodoList(params) {
return request({
url: `wflow/process/task/todoList`,
method: 'get',
params: params
})
}
//获取用户发起的实例
export function getUserSubmittedList(params) {
return request({
url: `wflow/process/mySubmitted`,
method: 'get',
params: params
})
}
//获取所有发起的实例
export function getSubmittedList(params) {
return request({
url: `wflow/process/submittedList`,
method: 'get',
params: params
})
}
//获取我已处理的所有审批实例
export function getIdoList(params) {
return request({
url: `wflow/process/task/idoList`,
method: 'get',
params: params
})
}
//查询流程进度及表单
export function getFormAndProcessProgress(instanceId, nodeId) {
return request({
url: `wflow/process/progress/${instanceId}/${nodeId}`,
method: 'get'
})
}
//处理任务
export function approvalTask(params) {
return request({
url: `wflow/process/task/handler`,
method: 'post',
data: params
})
}
//获取流程实例表单数据
export function getInstanceFormData(instanceId) {
return request({
url: `wflow/process/form/data/by/${instanceId}`,
method: 'get'
})
}
export function getWflowDataView(params) {
//
return request({
url: `/mobile/wflow/data/view`,
method: 'post',
data: params
})
}
//获取可回退的节点
export function getEnableRecallNodes(instanceId, taskId) {
return request({
url: `wflow/process/task/recall/nodes`,
method: 'get',
params: { instanceId: instanceId, taskId: taskId }
})
}
export default {
getUserTodoList, getUserSubmittedList, getSubmittedList,
getFormAndProcessProgress, approvalTask, getInstanceFormData,
getEnableRecallNodes, getIdoList
}
import Vue from "vue";
import axios from "axios";
import qs from "qs";
import { Message, MessageBox, Loading } from "element-ui";
import store from "@/store";
import router from "@/router";
// 超时时间
axios.defaults.timeout = 300000;
// 跨域请求,允许保存cookie
axios.defaults.withCredentials = true;
axios.defaults.headers = { "Content-Type": "application/json; charset=utf-8" };
// axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
// 非生产环境 && 开启代理, 接口前缀统一使用[/api]前缀做代理拦截!
const BASE_URL =
["development"].includes(process.env.VUE_APP_MODE)
? process.env.VUE_APP_BASE_API
: process.env.VUE_APP_SERVER_URL;
// 对面暴露的基础请求路径
axios.defaults.baseURL = BASE_URL;
function getQueryString(name) {
const url_string = window.location.href//"https://www.baidu.com/t.html?name=mick&age=20"; //
const url = new URL(url_string);
return url.searchParams.get(name);
}
/**
* 请求拦截
*/
axios.interceptors.request.use(
(config) => {
let token = getQueryString('token') //sessionStorage.getItem("token");
let factoryId = localStorage.getItem("factoryId");
if (token || token != "undefined") {
config.headers.factoryId = factoryId;
config.headers.token = token;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
/**
* 响应拦截
*/
axios.interceptors.response.use(
(response) => {
let { code } = response.data;
if (code === 501) {
window.parent.postMessage(
{ text: "子页面发消息给父页面", type: "token-past-due" },
"*"
);
return;
} else {
return response.data;
}
// return response
},
(error) => {
if (!error.response) return Promise.reject(error);
const { status, data, config } = error.response;
switch (status) {
// 需要重新登录
case 401: {
break;
}
// 路径找不到
case 403: {
break;
}
// 路径找不到
case 404: {
break;
}
case 503: {
break;
}
case 504: {
break;
}
default: {
return Promise.reject(e);
}
}
return Promise.reject(error);
}
);
export function syncRequest(config) {
let ajax = new XMLHttpRequest();
ajax.withCredentials = true;
//ajax.responseType = 'json'
ajax.open(config.method, baseURL + config.url, false);
ajax.onload = function (e) {
if (ajax.readyState === 4) {
if (ajax.status === 200 && config.success) {
config.success(ajax.responseText);
} else if (config.fail) {
config.fail(ajax.responseText);
}
}
};
ajax.onerror = function (e) {
if (config.fail) {
config.fail(ajax.responseText);
}
};
if (config.data) {
if (config.type === "json") {
ajax.setRequestHeader("Content-type", "application/json");
ajax.send(JSON.stringify(config.data));
} else {
ajax.setRequestHeader(
"Content-type",
"application/x-www-form-urlencoded"
);
let form = new FormData();
for (const key in config.data) {
form.set(key, config.data[key]);
}
ajax.send(form);
}
} else {
ajax.send(null);
}
}
export default axios;
import request from './request.js'
// 获取表单分组
export function login(userId) {
return request({
url: `sys/auth/login/ignore/${userId}`,
method: 'get'
})
}
// 用户 分页信息
export function userPage(params) {
return request({
url: `/sys/user/page`,
method: 'post',
data: params
})
}
// 用户组
export function userGroupPage(params) {
return request({
url: `/base/user-group/page`,
method: 'post',
data: params
})
}
\ No newline at end of file
.el-icon {
font-size: 15px;
}
.el-main {
--el-main-padding: 10px;
}
.el-breadcrumb {
font-size: 13px;
}
.el-table {
--el-table-header-bg-color: #f7f8fa !important;
--el-table-header-text-color: var(--el-text-color-regular) !important;
.cell {
line-height: 20px;
}
}
.el-dialog {
--el-dialog-padding-primary: 10px !important;
}
.el-dialog__body {
padding: var(--el-dialog-padding-primary)
calc(var(--el-dialog-padding-primary) + 10px) !important;
}
.el-button + .el-button {
margin-left: var(--p-base);
}
.el-card {
--el-card-padding: 10px !important;
--el-card-border-radius: 0 !important;
}
table {
.el-form-item {
margin-bottom: 0;
&.is-error {
margin-bottom: 18px;
}
}
}
.el-step.is-center .el-step__description {
margin-top: 3px;
}
.el-tag + .el-tag {
margin-left: var(--p-base);
}
.el-drawer__header {
margin-bottom: 0 !important;
}
.el-button--mini {
padding: 5px 11px !important
}
.el-input__inner{
height: 22px !important;
line-height: 22px !important;
}
// 覆盖element-plus scss变量
$--colors: (
'primary': (
'base': #1d50a3,
),
);
$--menu: (
'item-height': 50px,
'bg-color': #18202e,
'active-color': #ffffff,
'hover-bg-color': #434a50,
'icon-width': 20px,
'base-level-padding': 10px,
'level-padding': 10px,
);
$--header: (
'height': 40px,
'padding': 0,
);
$--font-size: (
'extra-large': 18px,
'large': 16px,
'medium': 15px,
'base': 12px,
'small': 12px,
'extra-small': 11px,
'mini':12px
);
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: $--colors,
$menu: $--menu,
$header: $--header,
$font-size: $--font-size,
$border-radius: (
'base': 0,
)
);
*{
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
body{
margin: 0;
padding: 0;
}
/*路由切换动画*/
.router-fade-enter-active {
transition: all 0.3s cubic-bezier(0.6, 0.5, 0.3, 0.1);
}
.router-fade-leave-active {
transition: all 0.3s cubic-bezier(0.5, 0.5, 0.5, 0.5);
}
.router-fade-enter {
transform: translateX(0px);
opacity: 0;
}
.router-fade-leave-to {
transform: translateX(50px);
opacity: 0;
}
.fl {
float: left;
}
.fr {
float: right;
}
.tl{
text-align: left;
}
.tr{
text-align: right;
}
.card-page-box{
background: #fff;
height: 100vh;
}
\ No newline at end of file
@font-face {
font-family: "iconfont"; /* Project id 3538338 */
src: url('iconfont.woff2?t=1663221768308') format('woff2'),
url('iconfont.woff?t=1663221768308') format('woff'),
url('iconfont.ttf?t=1663221768308') format('truetype');
}
[class^="iconfont"],[class*="iconfont"]{
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-mn_xiuxi:before {
content: "\e60a";
}
.icon-cooperation-full:before {
content: "\e85d";
}
.icon-yanfa:before {
content: "\e8e9";
}
.icon-yanfaguanli-yangpinjianyan:before {
content: "\e63f";
}
.icon-tsm_0108:before {
content: "\e621";
}
.icon-dengdaishenhe:before {
content: "\e61f";
}
.icon-dengdaizhongbeifen:before {
content: "\e60f";
}
.icon-zhuanyi:before {
content: "\e686";
}
.icon-quxiao:before {
content: "\e67a";
}
.icon-yitongguo:before {
content: "\e601";
}
.icon-yijujue:before {
content: "\e602";
}
.icon-yiquxiao:before {
content: "\e608";
}
.icon-yichexiao:before {
content: "\e609";
}
.icon-fanhui-chehui-06:before {
content: "\e81d";
}
.icon-zhuanyi-16:before {
content: "\e870";
}
.icon-iconfontdianzishu:before {
content: "\e605";
}
.icon-iconfontchuzu:before {
content: "\e624";
}
.icon-iconfontzhitongche:before {
content: "\e625";
}
.icon-iconfontgongjiao:before {
content: "\e626";
}
.icon-iconfonttehuijingxuan:before {
content: "\e631";
}
.icon-iconfontwifi1:before {
content: "\e632";
}
.icon-iconfonterweima:before {
content: "\e60e";
}
.icon-iconfontunie64e:before {
content: "\e617";
}
.icon-iconfonticon3:before {
content: "\e61d";
}
.icon-iconfonticonfontsetting:before {
content: "\e735";
}
.icon-iconfontbucket:before {
content: "\e618";
}
.icon-iconfontyoujian:before {
content: "\e645";
}
.icon-iconfontkafei:before {
content: "\e61e";
}
.icon-iconfontihou:before {
content: "\e630";
}
.icon-iconfontgift:before {
content: "\e604";
}
.icon-iconfontdianying:before {
content: "\e606";
}
.icon-iconfontrenmentuijian:before {
content: "\e633";
}
.icon-iconfont3:before {
content: "\e607";
}
.icon-xiaoxi:before {
content: "\e62b";
}
.icon-fangzi:before {
content: "\e646";
}
.icon-BBDanquan:before {
content: "\e656";
}
.icon-iconfont-jiaoyi:before {
content: "\e68d";
}
.icon-iconfonticon-dianyu:before {
content: "\e635";
}
.icon-iconfonticon-gaojin:before {
content: "\e638";
}
.icon-iconfonticon-nengha:before {
content: "\e63c";
}
.icon-iconfonticon-xitong:before {
content: "\e641";
}
.icon-iconfontkefu:before {
content: "\e61c";
}
.icon-mima:before {
content: "\e648";
}
.icon-renlishebao:before {
content: "\e636";
}
.icon-bumen:before {
content: "\e758";
}
.icon-charutupian:before {
content: "\ec7f";
}
.icon-kaoqinguanli:before {
content: "\e610";
}
.icon-shenfenzheng:before {
content: "\e614";
}
.icon-weizhi:before {
content: "\e64b";
}
.icon-24gf-phoneBubble:before {
content: "\e966";
}
.icon-kaoqin:before {
content: "\e643";
}
.icon-huiyi:before {
content: "\e61b";
}
.icon-jiaban:before {
content: "\e637";
}
.icon-biaoge:before {
content: "\e665";
}
.icon-shiyongwendang:before {
content: "\eb66";
}
.icon-duoxuankuang:before {
content: "\e62e";
}
.icon-danxuan:before {
content: "\e751";
}
.icon-chuzu:before {
content: "\e600";
}
.icon-zhaopin:before {
content: "\e647";
}
.icon-caiwu:before {
content: "\e67d";
}
.icon-caigou:before {
content: "\e887";
}
.icon-zhufangbutie:before {
content: "\e68e";
}
.icon-wodechanpin:before {
content: "\e679";
}
.icon-fapiaoguanli:before {
content: "\e63b";
}
.icon-gongzi:before {
content: "\e7e9";
}
.icon-zhufangbutiezhanghu:before {
content: "\e60c";
}
.icon-weixiu:before {
content: "\e613";
}
.icon-yuangonglizhi:before {
content: "\e615";
}
.icon-zhaopinguanli:before {
content: "\e616";
}
.icon-caiwu1:before {
content: "\e603";
}
.icon-qingjiashenqing:before {
content: "\e60d";
}
.icon-ziyuan207:before {
content: "\e722";
}
.icon-yongcanjiucan:before {
content: "\e67e";
}
.icon-map-site:before {
content: "\ea00";
}
.icon-hetong:before {
content: "\e68a";
}
.icon-buka:before {
content: "\e6ca";
}
.icon-chucha:before {
content: "\e6c7";
}
.icon-baoxiaoshenqing-feiyongbaoxiaoshenqing-02:before {
content: "\e726";
}
.icon-a-11Cfenzuzuzhishu:before {
content: "\e676";
}
No preview for this file type
No preview for this file type
No preview for this file type
@bg-color: #ebecf0;
@bg-light-color: #f7f8fa;
@bg-grey-back: #ebecf0;
@color-default: #8c8c8c;
@p-base: 8px;
//主题定制
@theme-primary: #1989fa; //主题色,应当与element-ui一致
@theme-danger: #f56c6c; //主题色,应当与element-ui一致
@theme-success: #35b881;
@theme-warning: #f78f5f;
@theme-aside-bgc: #f7f7f9;
@theme-desc-color: #a2a4a8; //辅助文字颜色
//审批流程节点配色
@node-root: #576a95; //发起人
@node-condition: #15bca3; //条件
@node-cc: #3296fa; //抄送
@node-concurrent: #718dff; //并行
@node-approval: #ff943e; //审批
@node-delay: #f25643; //延时
@node-trigger: #47bc82; //触发器
//移动端Vant Less覆盖
@font-size-xs: 12px;
@font-size-sm: 14px;
@font-size-md: 16px;
@font-size-lg: 18px;
@font-weight-bold: 500;
@line-height-xs: 16px;
@line-height-sm: 20px;
@line-height-md: 22px;
@line-height-lg: 24px;
//通用类
.w-desc-text{
color: @theme-desc-color;
}
.w-row-text{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.w-t-center{
text-align: left;
}
.w-t-left{
left: 0;
text-align: left;
}
.w-t-right{
right: 0;
text-align: left;
}
.w-h-center{
display: flex;
align-items: center;
}
No preview for this file type
No preview for this file type
This diff could not be displayed because it is too large.
<template>
<div class="search-form">
<el-form
inline
:label-width="inline ? undefined : undefined"
label-suffix=":"
>
<slot />
<el-form-item :label-width="btnLabelWidth || '0'">
<template #label>
<div />
</template>
<el-button type="primary" @click="onSearch">查询</el-button>
<el-button @click="onReset">重置</el-button>
<slot name="btn" />
</el-form-item>
</el-form>
</div>
</template>
<script>
import { deepClone } from "@/utils/common.js";
export default {
name: "SearchForm",
props: {
value: Object,
inline: Boolean,
labelWidth: { type: String, default: "100px" },
btnLabelWidth: String,
},
emits: ["input", "search"],
methods: {
onSearch() {
this.$emit("search");
},
onReset() {
this.$emit("input", deepClone(this.$copy));
this.$emit("search", true); // true 重置
},
},
mounted() {
this.$copy = deepClone(this.value);
},
};
</script>
<style lang="less" scoped>
.search-form {
background: @bg-light-color;
padding: 8px 8px 0 8px;
margin-bottom: 8px;
// font-size: 12px;
/deep/ .el-form-item__label {
padding: 0 5px 0 0;
}
/deep/ .el-form--inline .el-form-item {
margin-bottom: 8px;
margin-right: 10px;
}
.el-form-item--default {
margin-bottom: 15px;
}
.el-select {
width: 100%;
}
&-btns {
// width: auto !important;
// margin-bottom: 0 !important;
.el-form-item__content > * {
margin-left: 8px;
}
}
}
</style>
<template>
<popup
v-model="visible"
:style="popupStyle"
position="left"
lazy-render
safe-area-inset-bottom
v-if="visible"
>
<div style="background: #fff">
<nav-bar
:title="title"
left-text="返回"
right-text="确定"
left-arrow
@click-left="close"
@click-right="doSubmit"
/>
<div>
<search
v-model="formInline.name"
show-action
placeholder="搜索人员姓名"
@search="onSearch"
>
<template #action>
<div @click="onSearch">搜索</div>
</template>
</search>
<checkbox
shape="square"
@change="handleCheckAllChange"
v-model="checkAll"
style="margin: 10px 10px"
>
全选
<span style="margin: 0 10px; color: #8c8c8c">
已选 [ {{ currentSelect.length }} ]
</span>
<span
v-show="currentSelect.length > 0 && multiple"
style="color: #3971f8"
@click.stop="clearSelected"
>
清空
</span>
</checkbox>
</div>
<div class="list-box">
<list
v-model="loading"
:finished="finished"
@load="onLoad"
finished-text="没有更多了"
>
<div class="item-box" v-for="item in tableList" :key="item.id">
<checkbox v-model="item.selected">
{{ item.name }}
</checkbox>
</div>
</list>
</div>
</div>
</popup>
</template>
<script>
import {
Popup,
List,
Cell,
NavBar,
Radio,
Checkbox,
Dialog,
Toast,
Search,
} from "vant";
import { userPage } from "@/api/sys";
export default {
name: "OrgPicker",
components: { Popup, List, NavBar, Checkbox, Search },
props: {
pcMode: {
default: true,
type: Boolean,
},
title: {
default: "请选择",
type: String,
},
type: {
default: "org", //org选择部门/人员 user-选人 dept-选部门 role-选角色
type: String,
},
multiple: {
//是否多选
default: false,
type: Boolean,
},
limit: {
type: Number,
default: 999,
},
selected: {
default: () => {
return [];
},
type: Array,
},
},
data() {
return {
visible: false,
loading: false,
checkAll: false,
nowDeptId: null,
isIndeterminate: false,
searchUsers: [],
nodes: [],
select: [],
deptStack: [],
popupStyle: {
height: "100%",
width: "100%",
background: "#fff",
},
finished: false,
refreshing: false,
tableList: [],
formInline: {
name: "",
},
page: {
size: 20,
current: 0,
total: 0,
},
currentSelect: [],
searchText: "",
activity: null,
params: {},
};
},
watch: {
tableList: {
handler() {
this.currentSelect = [];
this.tableList.map((item) => {
if (item.selected) {
this.currentSelect.push({ id: item.id, name: item.name });
}
});
},
deep: true,
},
},
methods: {
open(params, selectList) {
this.tableList = [];
this.$nextTick(() => {
this.params = params;
this.visible = true;
// 已选数组
this.currentSelect = [...selectList];
// this.getList();
});
},
onSearch() {
this.finished = false;
this.tableList = [];
this.page.current = 1;
this.getList();
},
clearSelected() {},
onLoad() {
this.page.current++;
this.getList();
},
getList() {
if (this.finished) return;
userPage({
page: this.page.current,
limit: this.page.size,
data: {
name: this.formInline.name,
},
}).then((res) => {
if (res.code === 200) {
this.tableList = this.tableList.concat(
res.data.list.map((item) => {
return {
...item,
selected: this.currentSelect.find((it) => {
return it.id === item.id;
})
? true
: false,
};
})
);
this.page.total = res.data.total;
this.loading = false;
// 动态加载的重点
if (this.tableList.length < this.page.total) {
this.finished = false; // 数据未加载完
} else {
this.finished = true; // 数据加载完
}
}
});
},
handleCheckAllChange() {
this.$nextTick(() => {
this.tableList = this.tableList.map((item) => {
return {
...item,
selected: this.checkAll,
};
});
});
},
close() {
this.visible = false;
this.finished = false;
this.tableList = [];
this.page.current = 0;
this.loading = false;
this.formInline = {
name: "",
};
},
doSubmit() {
if (this.currentSelect.length > this.limit && this.limit !== 99999999) {
this.$message.warning(`最多选择${this.limit}人已超出!`);
} else {
this.$emit("ok", this.currentSelect);
this.close();
}
},
},
};
</script>
<style lang="less" scoped>
.list-box {
height: calc(100vh - 150px);
overflow-y: scroll;
padding: 0 10px;
}
.item-box {
height: 40px;
display: flex;
align-items: center;
justify-content: flex-start;
}
</style>
<template>
<div :class="{avatar: true, 'show-y': showY}">
<div class="a-img">
<template v-if="type === 'user'">
<el-avatar v-if="src" :size="size" :src="src"/>
<div v-else :style="{'--bgc': bgc, '--size': size + 'px',}">
<span>{{ alisa }}</span>
</div>
</template>
<el-avatar v-else-if="type === 'dept'" style="background: #f78f5f" icon="iconfont icon-map-site" :size="size"/>
<el-avatar v-else icon="el-icon-user-solid" style="background: #576a95" :size="size"/>
<i class="close el-icon-close" v-if="closeable" @click="$emit('close')"></i>
<i :class="['status', statusIcon]" v-show="status"></i>
</div>
<div class="name" v-if="!showY && showName">{{ name }}</div>
<ellipsis hoverTip class="name" v-show="showName" :style="{width: (size + 10) + 'px'}" :content="name" v-else/>
</div>
</template>
<script>
export default {
name: "Avatar",
install(Vue){
Vue.component('avatar', this)
},
components: {},
props: {
type: {
type: String,
default: 'user'
},
name: {
type: String,
default: '未知'
},
size: {
type: Number,
default: 40
},
src: {
type: String,
default: undefined
},
bgc: {
type: String,
default: '#1989fa'
},
square:{
type: Boolean,
default: false
},
showY: {
type: Boolean,
default: false
},
showName:{
type: Boolean,
default: true
},
closeable:{
type: Boolean,
default: false
},
status:{
type: String
}
},
computed: {
alisa() {
return this.name.length > 2 ? this.name.substring(this.name.length - 2, this.name.length) : this.name
},
statusIcon(){
switch (this.status){
case 'error': return 'error el-icon-error';
case 'pending': return 'pending iconfont icon-dengdaizhongbeifen';
case 'success': return 'success el-icon-success';
case 'cc': return 'cc el-icon-s-promotion';
case 'comment': return 'comment iconfont icon-xiaoxi';
case 'transfer': return 'transfer iconfont icon-zhuanyi';
case 'cancel': return 'cancel iconfont icon-fanhui-chehui-06';
case 'recall': return 'recall iconfont icon-quxiao';
case 'leader': return 'leader el-icon-user-solid';
default: return null
}
}
},
data() {
return {}
},
methods: {}
}
</script>
<style lang="less" scoped>
.show-y{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column !important;
.name{
margin-left: 0 !important;
}
}
.close{
position: absolute;
top: 0;
right: 0;
color: white;
cursor: pointer;
border-radius: 50%;
background: black;
}
.avatar {
display: flex;
flex-direction: row;
position: relative;
align-items: center;
.a-img{
display: flex;
border-radius: 50%;
flex-direction: column;
justify-content: center;
background: white;
position: relative;
& > div {
display: inline-block;
text-align: center;
background: var(--bgc);
color: white;
border-radius: 50%;
width: var(--size);
height: var(--size);
line-height: var(--size);
font-size: 14px;
}
}
/deep/ .el-avatar{
background: white;
}
.name{
text-align: center;
color: #19191a;
font-size: 14px;
margin-left: 10px;
}
}
.status{
position: absolute;
bottom: -4px;
right: -8px;
border-radius: 50%;
font-size: 15px;
background: white;
border: 2px solid white;
}
.error{
color: @theme-danger;
}
.leader{
font-size: 12px;
color: @theme-warning;
}
.pending{
color: @theme-warning;
}
.success{
color: @theme-success;
}
.transfer{
color: white;
background: #7a939d;
font-size: 12px;
padding: 1px;
}
.comment{
color: @theme-primary;
}
.cc{
color: white;
font-size: 12px;
padding: 1px;
background: @theme-primary;
}
.cancel{
color: #838383;
}
.recall{
color: #f56c6c;
}
</style>
<template>
<div ref="editor" :style="{width: '100%', 'height': height}"></div>
</template>
<script>
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
export default {
name: 'CodeEditor',
components: {},
inheritAttrs: false,
props: {
options: {
type: Object,
default: () => {
return {
theme: "vs",
selectOnLineNumbers: true,
roundedSelection: false,
readOnly: false,
automaticLayout: true,
glyphMargin: true,
showFoldingControls: "always",
formatOnPaste: true,
formatOnType: true,
folding: true
}
}
},
lang: {
type: String,
default: 'javascript'
},
height: {
type: String,
default: '300px'
},
value: {
type: String,
default: ''
},
defaultValue: {
type: String,
default: ''
}
},
data() {
return {
editor: null,
randomKey: '',
code: ''
}
},
mounted() {
this.init();
},
beforeDestroy() {
// 销毁之前把monaco的实例也销毁了,不然会多次注册
if (this.editor) {
this.editor.dispose();
}
},
methods: {
init() {
this.editor = monaco.editor.create(this.$refs.editor, {
theme: "vs", // 主题
value: this.value, // 默认显示的值
language: this.lang,
folding: true, // 是否折叠
foldingHighlight: true, // 折叠等高线
foldingStrategy: "indentation", // 折叠方式 auto | indentation
showFoldingControls: "always", // 是否一直显示折叠 always | mouseover
disableLayerHinting: true, // 等宽优化
emptySelectionClipboard: false, // 空选择剪切板
selectionClipboard: false, // 选择剪切板
automaticLayout: true, // 自动布局
codeLens: false, // 代码镜头
scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
colorDecorators: true, // 颜色装饰器
accessibilitySupport: "off", // 辅助功能支持 "auto" | "off" | "on"
lineNumbers: "on", // 行号 取值: "on" | "off" | "relative" | "interval" | function
lineNumbersMinChars: 5, // 行号最小字符 number
enableSplitViewResizing: false,
readOnly: false, //是否只读 取值 true | false
});
this.editor.onDidChangeModelContent((event) => {
this.$emit('input', this.editor.getValue())
})
this.loadVal()
},
reloadCode(value){
this.editor.setValue(value || this.value)
this.loadVal()
},
loadVal(){
if (!this.$isNotEmpty(this.value)){
this.$emit('input', this.defaultValue)
}
}
},
}
</script>
<style lang="less" scoped>
.code-editor-wrapper {
height: 100%;
text-align: left;
overflow: auto;
/deep/ .CodeMirror {
height: 100%;
}
}
</style>
<template>
<vue-editor v-model="_value" :init="init" :disabled="readonly"></vue-editor>
</template>
<script>
import tinymce from "tinymce/tinymce";
import axios from "axios";
import vueEditor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver/theme";
import "tinymce/icons/default";
import "tinymce/skins/ui/oxide/skin.css";
import "tinymce/plugins/print";
import "tinymce/plugins/preview";
import "tinymce/plugins/autolink";
import "tinymce/plugins/directionality";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/image";
import "tinymce/plugins/link";
import "tinymce/plugins/template";
import "tinymce/plugins/code";
import "tinymce/plugins/table";
import "tinymce/plugins/charmap";
import "tinymce/plugins/pagebreak";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/advlist";
import "tinymce/plugins/lists";
import "tinymce/plugins/imagetools";
import "tinymce/plugins/textpattern";
import "tinymce/plugins/help";
import "tinymce/plugins/autoresize";
export default {
components: { vueEditor },
props: {
value: {
type: String,
required: false,
},
height: {
type: Number,
default: 800,
},
readonly: {
type: Boolean,
default: false,
},
plugins: {
type: [String, Array],
default:
"print preview autolink directionality visualblocks visualchars fullscreen image link template code table charmap pagebreak nonbreaking insertdatetime advlist lists imagetools textpattern help autoresize",
},
toolbar: {
type: [String, Array],
default:
"code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link | a\
lignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat |\
table image charmap emoticons hr pagebreak insertdatetime | \
styleselect formatselect fontselect fontsizeselect | \
| bdmap indent2em lineheight formatpainter axupimgs | print preview | fullscreen",
branding: false,
},
},
data() {
return {
//初始化配置
editor: null,
init: {
language_url: "/editor/js/zh_CN.js",
language: "zh_CN",
skin_url: "/editor/skins/lightgray",
height: this.height,
inline: false,
plugins: this.plugins,
toolbar: this.toolbar,
branding: false,
menubar: true,
toolbar_drawer: false,
toolbar_sticky: true,
convert_urls: false,
images_upload_handler: (blobInfo, success) => {
let formData = new FormData();
formData.append("file", blobInfo.blob(), blobInfo.filename());
formData.append("isImg", true);
axios
.post(this.uploadUrl, formData, {
"Content-type": "multipart/form-data",
})
.then(
(res) => {
this.$message.success("上传成功");
success(this.$getRes(res.data.url));
},
(err) => {
this.$message.error("上传失败");
console.log(err);
}
);
},
setup: (editor) => {
editor.on("init", (e) => {
console.log("编辑器初始化完成...", editor);
this.editor = editor;
editor.dom.doc.ondrop = this.dropElOnEditor;
});
},
},
reloading: false,
};
},
computed: {
uploadUrl() {
let mode = sessionStorage.getItem("mode");
if (process.env.VUE_APP_MODE === "development") {
if (mode !== "PC") {
return "/wflow/res";
} else {
return process.env.VUE_APP_BASE_API + "/wflow/res";
}
} else {
if (mode !== "PC") {
return "/wflow/res";
} else {
return process.env.VUE_APP_SERVER_URL + "/wflow/res";
}
}
},
_value: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
},
},
},
mounted() {},
methods: {
dropElOnEditor(ev) {
tinymce.activeEditor.focus();
const text = ev.dataTransfer.getData("text");
ev.dataTransfer.clearData();
console.log(text, ev);
const cp = JSON.parse(text);
//this.setCursor(ev.target, 1)
if (cp.name && cp.name === "TableList") {
this.insertDom(this.createTable(cp));
} else {
this.insertText("${" + cp.id + "}");
}
ev.preventDefault();
},
insertText(text) {
this.editor.execCommand("mceInsertContent", false, text);
},
autoFocus(x, y) {
let evt = document.createEvent("MouseEvents");
evt.initMouseEvent(
"click",
true,
true,
window,
0,
0,
0,
x,
y,
false,
false,
false,
false,
0,
null
);
document.body.dispatchEvent(evt);
},
//移动游标到指定位置,这里需要计算下移动多少
setCursor(target, offset) {
tinymce.activeEditor.selection.setCursorLocation(target, offset);
//this.editor.setCursorLocation(target, 2)
},
insertDom(dom) {
this.insertText(dom.innerHTML);
},
createTable(field) {
//const height = 40;
const table = document.createElement("table");
const tbody = document.createElement("tbody");
const trh = document.createElement("tr");
const trd = document.createElement("tr");
table.setAttribute("class", field.id);
table.setAttribute(
"style",
"border-collapse: collapse; width: 99.8363%; height: 74px;"
);
table.setAttribute("border", "1");
table.appendChild(tbody);
trh.setAttribute("style", "height: 40px;");
trd.setAttribute("style", "height: 40px;");
tbody.appendChild(trh);
tbody.appendChild(trd);
//构造表格行
field.props.columns.forEach((col) => {
const tdh = document.createElement("td");
const style = `width: ${(100 / field.props.columns.length).toFixed(
3
)}%; height: 40px;`;
tdh.setAttribute("style", style);
tdh.innerText = col.title;
trh.appendChild(tdh);
const tdd = document.createElement("td");
tdd.setAttribute("style", style);
tdd.innerText = "${" + col.id + "}";
trd.appendChild(tdd);
});
const tableDom = document.createElement("span");
tableDom.appendChild(table);
return tableDom;
},
reload() {
this.reloading = true;
this.$nextTick(() => (this.reloading = false));
},
},
};
</script>
<style scoped></style>
<template>
<div :class="{'line': row === 1, 'lines': row > 1}"
:title="hoverTip ? content: null"
:style="{'--row':row}">
<slot name="pre"></slot>
{{content}}
<slot name="aft"></slot>
</div>
</template>
<script>
//超出指定行数自动隐藏文字
export default {
name: "Ellipsis",
install(Vue){
Vue.component('ellipsis', this)
},
components: {},
props:{
row: {
type: Number,
default: 1
},
hoverTip:{
type: Boolean,
default: false
},
content:{
type: String,
default: ''
}
},
data() {
return {}
},
methods: {}
}
</script>
<style lang="less" scoped>
.line{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.lines{
display: -webkit-box;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: var(--row);
-webkit-box-orient: vertical;
}
</style>
<template>
<div class="m-form-item">
<div class="m-form-item_title">
<span class="title-required" v-if="required || rule.length > 0">* </span>
<span>{{label}}</span>
</div>
<div class="m-form-item_content">
<slot ref="item"></slot>
</div>
<div v-if="showError && rule.length > 0" class="valid-error">
{{rule[0].message || '请完善'}}
</div>
</div>
</template>
<script>
export default {
name: "FormItem",
components: {},
props:{
label: {
type: String,
default: ''
},
rule: {
type: Array,
default: () => {
return []
}
},
prop:{
type: String,
default: ''
},
model:{
type: Object,
default: () => {
return {}
}
},
required: {
type: Boolean,
default: false
}
},
data() {
return {
showError: false
}
},
methods: {
isError(){
return this.showError
},
validate(call){
if (this.rule.length > 0 ){
if (this.rule[0].type === 'array'){
this.showError = !(Array.isArray(this.model[this.prop]) && this.model[this.prop].length > 0)
}else {
this.showError = !this.$isNotEmpty(this.model[this.prop])
}
}
if (!this.showError){
}
if (call){
call(!this.showError)
}
}
}
}
</script>
<style lang="less" scoped>
.m-form-item{
position: relative;
padding: 10px 10px 20px 10px;
background: white;
//margin-top: 5px;
margin-bottom: 10px;
& > div:first-child{
margin-bottom: 8px;
font-size: 1.2rem;
color: #545456;
}
& > div:last-child{
//padding: 0 5px;
}
.title-required{
color: @theme-danger;
}
.valid-error{
color: @theme-danger;
position: absolute;
font-size: 0.85rem;
}
}
</style>
<template>
<div>
<el-input placeholder="请输入URL地址" v-model="value.url">
<el-select
v-model="value.method"
style="width: 85px"
slot="prepend"
placeholder="方法"
>
<el-option label="GET" value="GET"></el-option>
<el-option label="POST" value="POST"></el-option>
<el-option label="PUT" value="PUT"></el-option>
<el-option label="DELETE" value="DELETE"></el-option>
</el-select>
</el-input>
<el-tabs v-model="active">
<el-tab-pane label="header头" name="header">
<div
v-for="(header, index) in value.headers"
:key="header.name + index"
>
<el-input
v-model="header.name"
placeholder="header名"
style="width: 30%"
></el-input>
<span class="w-space"></span>
<el-input
v-model="header.value"
placeholder="header值"
style="width: 50%"
></el-input>
<i
class="el-icon-delete"
@click="value.headers.splice(index, 1)"
circle
></i>
</div>
</el-tab-pane>
<el-tab-pane
v-if="value.method === 'POST' || value.method === 'DELETE'"
label="body参数"
name="body"
></el-tab-pane>
<el-tab-pane label="前置处理" name="pre">
<code-editor
style="border: 1px solid #e5e7ec"
v-model="value.pre"
:default-value="preDefault"
/>
</el-tab-pane>
<el-tab-pane label="后置处理" name="aft">
<code-editor
style="border: 1px solid #e5e7ec"
v-model="value.aft"
:default-value="aftDefault"
/>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: "HttpReq",
components: {
CodeEditor: () => import("./CodeEditor.vue"),
},
props: {
value: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
active: "body",
preDefault: "function preHandler(ctx){\n\t//发起请求前做一些处理\n\t\n}",
aftDefault:
"function aftHandler(rsp){\n\t//获取到结果后做一些处理\n\t\n}",
};
},
methods: {},
};
</script>
<style scoped lang="less">
.w-space {
margin: 0 5px;
color: @theme-desc-color;
}
</style>
<template>
<div v-if="!isTask">
<el-tag type="primary" :size="size" v-if="instance.status === 'RUNNING'"
>进行中</el-tag
>
<el-tag
type="danger"
:size="size"
v-else-if="instance.result === 'refuse-end'"
>审批驳回</el-tag
>
<el-tag
type="info"
:size="size"
v-else-if="instance.result === 'cancel-end'"
>已撤销</el-tag
>
<el-tag type="success" :size="size" v-else>审批通过</el-tag>
</div>
<el-tag v-else :type="(taskStatus[instance.taskResult] || {}).type">{{
(taskStatus[instance.taskResult] || {}).text
}}</el-tag>
</template>
<script>
export default {
name: "ProcessStatus",
components: {},
props: {
instance: {
type: Object,
default: () => {
return {};
},
},
size: {
type: String,
default: "medium",
},
isTask: {
type: Boolean,
default: false,
},
},
data() {
return {
taskStatus: {
agree: { type: "success", text: "已同意" },
refuse: { type: "danger", text: "已拒绝" },
recall: { type: "warning", text: "已退回" },
transfer: { type: "primary", text: "已转交" },
},
};
},
methods: {},
};
</script>
<style scoped>
</style>
<template>
<w-dialog v-model="_value" closeFree title="扫码录入" width="500px" :showFooter="false" @closed="closeScan" @opened="openScan" v-if="pcMode">
<div class="scan-video" v-if="_value">
<video ref="video" style="width: 100%;" id="video" autoplay></video>
</div>
<p style="color:#656363; text-align: center">{{tipMsg}}</p>
</w-dialog>
<popup v-else v-model="_value" :style="popupStyle" @closed="closeScan" @opened="openScan" position="left" lazy-render closeable safe-area-inset-bottom>
<div class="scan-cancel" @click="_value = false">取消</div>
<div class="m-scan-video" v-if="_value">
<video ref="video" id="video" autoplay></video>
</div>
<p style="color:white; text-align: center">{{tipMsg}}</p>
</popup>
</template>
<script>
import { Popup } from 'vant'
import { BrowserMultiFormatReader } from '@zxing/library';
export default {
name: "ScanCode",
components: {Popup},
props:{
value: {
type: Boolean,
default: false
},
pcMode:{
type: Boolean,
default: false
}
},
data() {
return {
tipMsg: '',
codeReader: null,
popupStyle: {
height: '100%',
width: '100%',
background: 'black',
opacity: '0.8',
}
}
},
computed: {
_value: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
}
}
},
destroyed(){
this.closeScan()
},
methods: {
closeScan(){
if (this.codeReader){
this.codeReader.reset();
this.codeReader = null
}
},
async openScan() {
if (!this.codeReader){
this.codeReader = new BrowserMultiFormatReader();
}
this.codeReader.getVideoInputDevices().then((videoInputDevices) => {
this.tipMsg = '正在打开摄像头...';
console.log('videoInputDevices', videoInputDevices);
// 默认获取第一个摄像头设备id
let firstDeviceId = videoInputDevices[0].deviceId;
// 获取第一个摄像头设备的名称
const videoInputDeviceslablestr = JSON.stringify(videoInputDevices[0].label);
if (videoInputDevices.length > 1) {
// 判断是否后置摄像头
if (videoInputDeviceslablestr.indexOf('back') > -1) {
firstDeviceId = videoInputDevices[0].deviceId;
} else {
firstDeviceId = videoInputDevices[1].deviceId;
}
}
this.decodeFromInputVideoFunc(firstDeviceId);
}).catch(err => {
this.tipMsg = '发生错误: ' + JSON.stringify(err);
});
},
decodeFromInputVideoFunc(firstDeviceId) {
this.codeReader.reset(); // 重置
this.codeReader.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {
this.tipMsg = '请将摄像头对准条形码/二维码...';
if (result) {
if (result.text) {
this.$emit('ok', result.text)
this._value = false
}
}
if (err && !(err)) {
this.tipMsg = '识别失败: ' + JSON.stringify(err);;
}
});
}
}
}
</script>
<style lang="less" scoped>
.scan-cancel{
position: fixed;
top: 20px;
left: 20px;
color: white;
cursor: pointer;
font-size: 1.1rem;
opacity: 1
}
.m-scan-video{
width: 100%;
text-align: center;
margin-top: 40%;
video {
width: 80%;
}
}
</style>
<template>
<el-tooltip :effect="isDark ? 'dark':'light'" :content="content" placement="top-start">
<span>
<slot></slot>
<i class="el-icon-question" style="cursor: pointer"></i>
</span>
</el-tooltip>
</template>
<script>
export default {
install(Vue) {
Vue.component('Tip', this)
},
name: "Tip",
components: {},
props:{
isDark:{
type: Boolean,
default: true
},
content:{
type: String,
default: ''
}
},
data() {
return {}
},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<el-dialog
custom-class="custom-dialog"
:class="{ border: true, fullscreen: fullscreen }"
:width="width"
:title="title"
append-to-body
:close-on-click-modal="clickClose"
@opened="$emit('opened')"
@closed="$emit('closed')"
:destroy-on-close="closeFree"
:visible.sync="_value"
>
<slot name="title" slot="title"></slot>
<slot></slot>
<div slot="footer" v-if="showFooter">
<el-button
@click="
_value = false;
$emit('cancel');
"
>{{ cancelText }}</el-button
>
<el-button type="primary" @click="$emit('ok')">{{ okText }}</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "WDialog",
install(Vue) {
Vue.component("WDialog", this);
},
components: {},
props: {
title: {
type: String,
default: "",
},
width: {
type: String,
default: "50%",
},
fullscreen: {
type: Boolean,
default: false,
},
noPadding: {
type: Boolean,
default: false,
},
value: {
type: Boolean,
default: false,
},
clickClose: {
type: Boolean,
default: false,
},
closeFree: {
type: Boolean,
default: false,
},
showFooter: {
type: Boolean,
default: true,
},
cancelText: {
type: String,
default: "取 消",
},
okText: {
type: String,
default: "确 定",
},
border: {
type: Boolean,
default: true,
},
},
computed: {
_value: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
},
},
},
data() {
return {};
},
methods: {},
};
</script>
<style lang="less" scoped>
/deep/ .custom-dialog {
.el-dialog__header {
padding: 10px 20px;
.el-dialog__title {
font-size: 17px;
}
.el-dialog__headerbtn {
top: 15px;
.i {
font-size: large;
}
}
}
.el-dialog__footer {
padding: 10px 20px;
}
}
.border {
/deep/ .el-dialog__header {
border-bottom: 1px solid #e8e8e8;
}
/deep/ .el-dialog__footer {
border-top: 1px solid #e8e8e8;
}
}
.fullscreen {
overflow: hidden;
/deep/ .el-dialog {
margin-top: 0 !important;
width: 100% !important;
.el-dialog__body {
padding: 0;
height: calc(100vh - 94px);
}
}
}
</style>
<template>
<el-dialog
title="请选择用户组"
width="800px"
:close-on-click-modal="false"
:append-to-body="true"
:visible.sync="visible"
:before-close="onCancel"
v-if="visible"
>
<div id="show">
<div class="userDialog">
<div>
<search-form v-model="formInline" @search="getList" ref="form">
<el-form-item label="用户组名称">
<el-input
v-model="formInline.name"
placeholder="请输入姓名"
></el-input>
</el-form-item>
</search-form>
</div>
<div>
<div class="flex-title">
<div>可选项</div>
<div></div>
</div>
<!-- 选修课课程表 -->
<el-table
border
ref="multipleTable"
:data="tableList"
@select="select"
@select-all="selectAll"
style="margin: 10px 0"
v-loading="loading"
>
<el-table-column type="selection" width="50" align="center">
</el-table-column>
<el-table-column prop="type" label="业务类型">
<template #default="{ row }">
{{ getDictName("base.userGroup.type", row.type) }}
</template>
</el-table-column>
<el-table-column
prop="name"
label="用户组名称"
show-overflow-tooltip
/>
<el-table-column
prop="description"
label="用户组描述"
show-overflow-tooltip
/>
</el-table>
<div class="flex-end">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="page.current"
:page-size="page.size"
layout="total, sizes, prev, pager, next"
:total="page.total"
:page-sizes="[10, 20, 30, 40, 50, 100]"
:pager-count="5"
>
</el-pagination>
</div>
</div>
<div>
<el-divider content-position="left">
已选项 {{ currentSelect.length }}条</el-divider
>
<div class="tag-box">
<el-tag
style="margin: 0 6px 6px 0"
v-for="(item, index) in currentSelect"
:key="item.id"
closable
@close="onDelete(item, index)"
>
{{ item.name }}
</el-tag>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="onCancel" icon="el-icon-circle-close">关闭</el-button>
<el-button type="primary" icon="el-icon-circle-check" @click="doSubmit()"
>确定</el-button
>
</span>
</el-dialog>
</template>
<script>
import SearchForm from "@/components/SearchForm/index.vue";
import { userGroupPage } from "@/api/sys";
import { getDictName } from "@/utils/dict";
export default {
components: { SearchForm },
data() {
return {
loading: false,
visible: false,
tableList: [],
selectList: [],
formInline: {
name: "",
},
page: {
size: 10,
current: 1,
total: 0,
},
currentSelect: [],
searchText: "",
activity: null,
params: {},
};
},
props: {
selectData: {
type: Object,
default: () => {
return {};
},
},
// 限制只能选几个
limit: {
type: Number,
default: 99999999,
},
},
methods: {
getDictName,
open(params, selectList) {
this.tableList = [];
this.$nextTick(() => {
this.params = params;
this.visible = true;
// 已选数组
this.currentSelect = [...selectList];
this.getList();
});
},
onSearch() {
this.page.current = 1;
this.getList();
},
getList() {
this.loading = true;
userGroupPage({
page: this.page.current,
limit: this.page.size,
data: {
...this.formInline,
...this.params,
...this.selectData,
},
})
.then((res) => {
if (res.code === 200) {
this.tableList = res.data.list;
this.page.total = res.data.total;
this.$nextTick(() => {
this.currentSelect.map((item1) => {
this.tableList.map((item2) => {
if (item1.id === item2.id) {
this.$refs.multipleTable.toggleRowSelection(item2, true);
}
});
});
this.loading = false;
});
}
})
.catch((err) => {
console.error(err);
});
},
handleSelectionChange(val) {
this.currentSelect = this.currentSelect.concat(val);
},
handleSizeChange(val) {
this.page.size = val;
this.getList();
},
handleCurrentChange(val) {
this.page.current = val;
this.getList();
},
// 复选框中选中时,存储数据
select(selection, row) {
const _tempList = this.currentSelect;
const index = _tempList.findIndex((it) => {
return it.id === row.id;
});
if (index > -1) {
this.currentSelect.splice(index, 1);
} else {
this.currentSelect = this.currentSelect.concat(row);
}
},
pageChange({ page }) {
this.queryParams.pageNum = page;
this.getList();
},
onCancel() {
this.formInline = {
name: "",
};
this.visible = false;
},
selectAll(list) {
if (list.length > 0) {
list.map((item) => {
const index = this.currentSelect.findIndex((it) => {
return item.id === it.id;
});
if (index < 0) {
this.currentSelect.push(item);
}
});
} else {
this.tableList.map((item) => {
const index = this.currentSelect.findIndex((it) => {
return item.id === it.id;
});
if (index > -1) {
this.currentSelect.splice(index, 1);
}
});
}
},
doSubmit() {
if (this.currentSelect.length > this.limit && this.limit !== 99999999) {
this.$message.warning(`最多选择${this.limit}人已超出!`);
} else {
this.$emit("ok", this.currentSelect, {
type: this.formInline.type,
});
this.visible = false;
this.formInline = {
name: "",
};
}
},
allDelete() {
this.currentSelect = [];
this.tableList.map((item2) => {
this.$refs.multipleTable.toggleRowSelection(item2, false);
});
},
onSubmit() {
this.page.current = 1;
this.getList();
},
onReset() {
this.formInline = {
name: "",
};
this.getList();
},
onDelete(item) {
let currentSelect = this.$deepCopy(this.currentSelect);
currentSelect.map((it, index) => {
if (item.id === it.id) {
this.currentSelect.splice(index, 1);
}
});
this.tableList.map((it, index) => {
if (item.id === it.id) {
this.$refs.multipleTable.toggleRowSelection(it, false);
}
});
},
},
};
</script>
<style lang="less" scoped>
.memberType {
padding-bottom: 10px;
margin-bottom: 25px;
border-bottom: 1px solid #e1e0e0;
}
.flex-start {
display: flex;
justify-content: flex-start;
}
.flex-title {
margin: 0 0;
font-weight: bold;
}
.flex-end {
display: flex;
align-items: center;
justify-content: flex-end;
}
.tag-box {
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
margin-top: 30px;
}
.userDialog {
}
/deep/ .el-dialog__body {
// margin-bottom: 10px;
padding: 20px 20px;
}
</style>
<template>
<el-dialog
title="请选择人员"
width="800px"
:close-on-click-modal="false"
:append-to-body="true"
:visible.sync="visible"
:before-close="onCancel"
v-if="visible"
>
<div id="show">
<div class="userDialog">
<div>
<search-form v-model="formInline" @search="onSubmit" ref="form">
<el-form-item label="姓名">
<el-input
v-model="formInline.name"
placeholder="请输入姓名"
></el-input>
</el-form-item>
<!-- <el-form-item label="性别">
<el-select v-model="formInline.sex" placeholder="请选择性别">
<el-option label="男" value="1"> </el-option>
<el-option label="女" value="2"> </el-option>
<el-option label="全部" value=""> </el-option>
</el-select>
</el-form-item> -->
</search-form>
</div>
<div>
<div class="flex-title">
<div>可选项</div>
<div></div>
</div>
<!-- 选修课课程表 -->
<el-table
border
ref="multipleTable"
:data="tableList"
@select="select"
@select-all="selectAll"
style="margin: 10px 0"
v-loading="loading"
>
<el-table-column type="selection" width="50" align="center">
</el-table-column>
<el-table-column label="姓名" prop="name" show-overflow-tooltip>
</el-table-column>
<el-table-column
label="手机号"
prop="mobile"
width="120px"
show-overflow-tooltip
>
</el-table-column>
<!-- <el-table-column
label="性别"
prop="sex"
align="center"
width="80px"
>
<template slot-scope="scope">
<span v-if="scope.row.sex === 1"></span>
<span v-else-if="scope.row.sex === 2"></span>
<span v-else-if="scope.row.sex === 3">其他</span>
</template>
</el-table-column> -->
<el-table-column
label="部门"
prop="deptIdPathName"
show-overflow-tooltip
>
</el-table-column>
<el-table-column label="人员状态" width="100">
<template slot-scope="scope">
<span v-if="scope.row.status === '1'">启用</span>
<span v-else-if="scope.row.status === '0'">禁用</span>
</template>
</el-table-column>
</el-table>
<div class="flex-end">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="page.current"
:page-size="page.size"
layout="total, sizes, prev, pager, next"
:total="page.total"
:page-sizes="[10, 20, 30, 40, 50, 100]"
:pager-count="5"
>
</el-pagination>
</div>
</div>
<div>
<el-divider content-position="left">
已选项 {{ currentSelect.length }}条
</el-divider>
<div class="tag-box">
<el-tag
style="margin: 0 6px 6px 0"
v-for="(item, index) in currentSelect"
:key="item.id"
closable
@close="onDelete(item, index)"
>
{{ item.name }}
</el-tag>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="onCancel" icon="el-icon-circle-close">关闭</el-button>
<el-button type="primary" icon="el-icon-circle-check" @click="doSubmit()"
>确定</el-button
>
</span>
</el-dialog>
</template>
<script>
import { userPage } from "@/api/sys";
import SearchForm from "@/components/SearchForm/index.vue";
export default {
components: { SearchForm },
data() {
return {
loading: false,
visible: false,
tableList: [],
selectList: [],
formInline: {
name: "",
deptName: "",
sex: "",
},
page: {
size: 10,
current: 1,
total: 0,
},
currentSelect: [],
searchText: "",
activity: null,
params: {},
};
},
props: {
selectData: {
type: Object,
default: () => {
return {};
},
},
// 限制只能选几个
limit: {
type: Number,
default: 99999999,
},
},
methods: {
open(params, selectList) {
this.tableList = [];
this.$nextTick(() => {
this.params = params;
this.visible = true;
// 已选数组
this.currentSelect = [...selectList];
this.getList();
});
},
onSearch() {
this.page.current = 1;
this.getList();
},
getList() {
this.loading = true;
userPage({
page: this.page.current,
limit: this.page.size,
data: {
...this.formInline,
...this.params,
...this.selectData,
},
})
.then((res) => {
if (res.code === 200) {
this.tableList = res.data.list;
this.page.total = res.data.total;
this.$nextTick(() => {
this.currentSelect.map((item1) => {
this.tableList.map((item2) => {
if (item1.id === item2.id) {
this.$refs.multipleTable.toggleRowSelection(item2, true);
}
});
});
this.loading = false;
});
}
})
.catch((err) => {
console.error(err);
});
},
handleSelectionChange(val) {
this.currentSelect = this.currentSelect.concat(val);
},
handleSizeChange(val) {
this.page.size = val;
this.getList();
},
handleCurrentChange(val) {
this.page.current = val;
this.getList();
},
// 复选框中选中时,存储数据
select(selection, row) {
const _tempList = this.currentSelect;
const index = _tempList.findIndex((it) => {
return it.id === row.id;
});
if (index > -1) {
this.currentSelect.splice(index, 1);
} else {
this.currentSelect = this.currentSelect.concat(row);
}
},
pageChange({ page }) {
this.queryParams.pageNum = page;
this.getList();
},
onCancel() {
this.formInline = {
name: "",
deptName: "",
sex: "",
};
this.visible = false;
},
selectAll(list) {
if (list.length > 0) {
list.map((item) => {
const index = this.currentSelect.findIndex((it) => {
return item.id === it.id;
});
if (index < 0) {
this.currentSelect.push(item);
}
});
} else {
this.tableList.map((item) => {
const index = this.currentSelect.findIndex((it) => {
return item.id === it.id;
});
if (index > -1) {
this.currentSelect.splice(index, 1);
}
});
}
},
doSubmit() {
if (this.currentSelect.length > this.limit && this.limit !== 99999999) {
this.$message.warning(`最多选择${this.limit}人已超出!`);
} else {
this.$emit("ok", this.currentSelect, {
type: this.formInline.type,
});
this.visible = false;
this.formInline = {
name: "",
deptName: "",
sex: "",
};
}
},
allDelete() {
this.currentSelect = [];
this.tableList.map((item2) => {
this.$refs.multipleTable.toggleRowSelection(item2, false);
});
},
onSubmit() {
this.page.current = 1;
this.getList();
},
onReset() {
this.formInline = {
name: "",
deptName: "",
sex: "",
};
if (params.permissionType !== "00") {
this.getList();
}
},
onDelete(item) {
let currentSelect = this.$deepCopy(this.currentSelect);
currentSelect.map((it, index) => {
if (item.id === it.id) {
this.currentSelect.splice(index, 1);
}
});
this.tableList.map((it, index) => {
if (item.id === it.id) {
this.$refs.multipleTable.toggleRowSelection(it, false);
}
});
},
},
};
</script>
<style lang="less" scoped>
.memberType {
padding-bottom: 10px;
margin-bottom: 25px;
border-bottom: 1px solid #e1e0e0;
}
.flex-start {
display: flex;
justify-content: flex-start;
}
.flex-title {
margin: 0 0;
font-weight: bold;
}
.flex-end {
display: flex;
align-items: center;
justify-content: flex-end;
}
.tag-box {
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
margin-top: 30px;
}
.userDialog {
}
/deep/ .el-dialog__body {
// margin-bottom: 10px;
padding: 20px 20px;
}
</style>
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
require("@/utils/Injection");
/*import tinymce from 'tinymce'
Vue.prototype.$tinymce = tinymce*/
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/display.css";
import "element-ui/lib/theme-chalk/index.css";
import "vant/lib/index.css";
import "vant/lib/index.less";
import "@/assets/theme/index.css";
import "@/assets/global.css";
import "@/assets/iconfont/iconfont.css";
import Ellipsis from "@/components/common/Ellipsis";
import WDialog from "@/components/common/WDialog";
import Tip from "@/components/common/Tip";
import Avatar from "@/components/common/Avatar";
Vue.use(ElementUI, { size: "mini", zIndex: 3000 });
Vue.use(Ellipsis);
Vue.use(WDialog);
Vue.use(Tip);
Vue.use(Avatar);
Vue.config.productionTip = false;
// import VueAMap from "vue-amap";
// Vue.use(VueAMap);
// /*高德地图组件初始化*/
// VueAMap.initAMapApiLoader({
// key: "ebb9f6fb9beaec43fddcb22ab7406386",
// uiVersion: "1.0",
// plugin: [
// "AMap.Autocomplete",
// "AMap.ElasticMarker",
// "AMap.PlaceSearch",
// "AMap.MapType",
// "AMap.Geocoder",
// "AMap.Geolocation",
// ],
// v: "1.4.4",
// });
window.addEventListener("message", function (e) {
if (e.data.break) return
console.log(e.origin, e.data, e.data.userInfo); //子页面接收参数
localStorage.setItem("token", e.data.token || "");
localStorage.setItem("factoryId", e.data.factoryId || "");
localStorage.setItem("userInfo", e.data.userInfo);
localStorage.setItem("loginUser", e.data.userInfo);
localStorage.setItem("dictionary", e.data.dictionary);
store.commit(
"setLoginUser",
e.data.userInfo ? JSON.parse(e.data.userInfo) : null
);
// 跳转的页面路由
sessionStorage.setItem("path", e.data.path || "");
// 提交流程用的参数
sessionStorage.setItem("formId", e.data.formId || "");
// 审核流程用的参数
sessionStorage.setItem("selectInstance", e.data.selectInstance);
// 从父级页面来,要回到父级页面
sessionStorage.setItem("from", e.data.from);
//表单类型
sessionStorage.setItem("mode", e.data.mode || "PC");
store.commit("setMode", e.data.mode || "PC");
//表单按钮类型 btnType
sessionStorage.setItem("btnType", e.data.btnType || "");
//表单是否禁用
sessionStorage.setItem("formDisabled", e.data.disabled || "");
// 获取实例化表单数据id
sessionStorage.setItem("instanceId", e.data.instanceId || "");
// 暂存后的id
sessionStorage.setItem("id", e.data.id || "");
// 表单状态
sessionStorage.setItem("status", e.data.status || "");
// 流程
sessionStorage.setItem("nodeId", e.data.nodeId || "");
// 是否安卓环境
sessionStorage.setItem("isAndroid", e.data.isAndroid || "0");
//发起人
sessionStorage.setItem("initiator", e.data.initiator || "");
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
});
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
const viewport = {
content: "width=device-width, initial-scale=1.0, user-scalable=no",
};
const router = new Router({
routes: [
// {
// path: '/',
// redirect: '/approveManage'
// },
{
path: "/approveManage",
name: "approveManage",
component: () => import("@/views/admin/approveManage/index.vue"),
meta: { title: "审批管理", viewport: viewport },
},
// 只有表单的用法
{
path: "/formRender",
name: "formRender",
component: () => import("@/views/admin/approveManage/formRender.vue"),
meta: { title: "表单", viewport: viewport },
},
// 用于只有流程就行
{
path: "/process",
name: "process",
component: () => import("@/views/admin/approveManage/process.vue"),
meta: { title: "审核流程", viewport: viewport },
},
{
path: "/approvalDetails",
name: "approvalDetails",
component: () =>
import("@/views/admin/approveManage/approvalDetails.vue"),
meta: { title: "审批详情", viewport: viewport },
},
// 表单加流程的提交
{
path: "/form-process",
name: "form-process",
component: () => import("@/views/admin/approveManage/form-process.vue"),
meta: { title: "", viewport: viewport },
},
{
path: "/form-process-detail",
name: "form-process-detail",
component: () =>
import("@/views/admin/approveManage/form-process-detail.vue"),
meta: { title: "", viewport: viewport },
},
// {
// path: "/cc",
// name: "cc",
// component: () => import("@/views/workspace/oa/CcMe.vue"),
// meta: { title: "wflow-pro | 抄送我的", viewport: viewport },
// },
// {
// path: "/unfinished",
// name: "unfinished",
// component: () => import("@/views/workspace/oa/UnFinished.vue"),
// meta: { title: "wflow-pro | 未完成的", viewport: viewport },
// },
// {
// path: "/finished",
// name: "finished",
// component: () => import("@/views/workspace/oa/Finished.vue"),
// meta: { title: "wflow-pro | 未完成的", viewport: viewport },
// },
// {
// path: "/instances",
// name: "instances",
// component: () => import("@/views/admin/ProcessInstanceManage.vue"),
// meta: { title: "wflow-pro | 数据管理", viewport: viewport },
// },
// {
// path: "/formsPanel",
// name: "formsPanel",
// component: () => import("@/views/admin/FormsPanel.vue"),
// meta: { title: "wflow-pro | 表单列表", viewport: viewport },
// },
// 移动端异常流程
{
path: "/formMobile",
name: "formMobile",
component: () =>
import("@/views/admin/approveManageMobile/formMobile.vue"),
meta: { title: "", viewport: viewport },
},
{
path: "/formProcess",
name: "formProcess",
component: () =>
import("@/views/admin/approveManageMobile/formProcess.vue"),
meta: { title: "", viewport: viewport },
},
{
path: "/workspace",
name: "workspace",
component: () => import("@/views/workspace/WorkSpace.vue"),
children: [
{
path: "forms",
name: "forms",
component: () => import("@/views/workspace/oa/FromsApp.vue"),
meta: { title: "wflow-pro | OA审批", viewport: viewport },
},
{
path: "submit",
name: "submit",
component: () => import("@/views/workspace/oa/MySubmit.vue"),
meta: { title: "wflow-pro | 我发起的", viewport: viewport },
},
{
path: "cc",
name: "cc",
component: () => import("@/views/workspace/oa/CcMe.vue"),
meta: { title: "wflow-pro | 抄送我的", viewport: viewport },
},
{
path: "unfinished",
name: "unfinished",
component: () => import("@/views/workspace/oa/UnFinished.vue"),
meta: { title: "wflow-pro | 未完成的", viewport: viewport },
},
{
path: "finished",
name: "finished",
component: () => import("@/views/workspace/oa/Finished.vue"),
meta: { title: "wflow-pro | 未完成的", viewport: viewport },
},
{
path: "instances",
name: "instances",
component: () => import("@/views/admin/ProcessInstanceManage.vue"),
meta: { title: "wflow-pro | 数据管理", viewport: viewport },
},
{
path: "formsPanel",
name: "formsPanel",
component: () => import("@/views/admin/FormsPanel.vue"),
meta: { title: "wflow-pro | 表单列表", viewport: viewport },
},
],
},
{
path: "/mbinitiate",
name: "mbinitiate",
component: () => import("@/views/workspace/MbInitiateProcess.vue"),
meta: { title: "wflow-pro | 发起审批", viewport: viewport },
},
{
path: "/admin/design",
name: "design",
component: () => import("@/views/admin/FormProcessDesign.vue"),
meta: { title: "wflow-pro | 表单流程设计", viewport: viewport },
},
],
});
router.beforeEach((to, from, next) => {
if (to.meta.title) {
document.title = to.meta.title;
}
if (to.meta.content) {
let head = document.getElementByTagName("head");
let meta = document.createElemnet("meta");
meta.name = "viewport";
meta.content = "width=device-width, initial-scale=1.0, user-scalable=no";
head[0].appendChild(meta);
}
next();
sessionStorage.setItem("router-path", to.path);
});
export default router;
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
nodeMap: new Map(),
formItemMap: new Map(),
isEdit: null,
loginUser: {},
selectedNode: {},
selectFormItem: null,
design: {
business: "10",
formConfig: {},
groupId: "",
isStop: "0",
},
validComponents: [],
validOptions: [],
token: "",
factoryId: "",
userInfo: null,
mode: localStorage.getItem("mode") || "PC",
},
mutations: {
selectedNode(state, val) {
state.selectedNode = val;
},
loadForm(state, val) {
state.design = val;
},
validComponents(state, val) {
state.validComponents = val;
},
validOptions(state, val) {
state.validOptions = val;
},
setIsEdit(state, val) {
state.isEdit = val;
},
setToken(state, val) {
state.token = val;
},
setFactoryId(state, val) {
state.factoryId = val;
},
setUserInfo(state, val) {
state.userInfo = val;
},
setLoginUser(state, val) {
state.loginUser = val;
},
setMode(state, val) {
state.mode = val;
},
},
getters: {
getToken: () => {
return state.token;
},
getFactoryId: () => {
return state.factoryId;
},
getUserInfo: () => {
return state.userInfo;
},
},
actions: {},
modules: {},
});
import Vue from 'vue'
import moment from "moment";
import { Toast } from "vant";
//api后端接口地址 http://workflow.meiqicloud.com/api/
Vue.prototype.BASE_URL = process.env.VUE_APP_MODE === 'development' ? 'http://localhost:8080/api' : process.env.VUE_APP_SERVER_URL
//文件资源前缀,用来拼接URL
Vue.prototype.RES_FILE_PRE = Vue.prototype.BASE_URL
/**
* 解析资源地址
* @param url 资源url
* @returns {string}
*/
Vue.prototype.$getRes = function (url) {
const reg = /^(http:|https:).*/gi
return reg.test(url) ? url : this.RES_FILE_PRE + url
}
/**
* 判空函数,对象或字符串
* @param obj
* @returns {boolean}
*/
Vue.prototype.$isNotEmpty = function (obj) {
return (obj !== undefined && obj !== null && obj !== '' && obj !== 'null')
}
//判断是否设备为移动端
Vue.prototype.$isMobile = function () {
return window.screen.width < 450
}
//弹错误信息
Vue.prototype.$showError = function (err) {
if (Vue.prototype.$isMobile()) {
Toast.fail(err)
} else {
Vue.prototype.$message.error(err)
}
}
/**
* 从对象获取一个key的值,如果咩有就返回默认值
* @param obj 对象
* @param key key字段
* @param df 默认值
* @returns {*}
*/
Vue.prototype.$getDefalut = function (obj, key, df) {
return (obj === undefined || key === undefined || !this.$isNotEmpty(obj[key])) ? df : obj[key];
}
/**
* 对对象进行序列化深拷贝
* @param obj
* @returns {any}
*/
Vue.prototype.$deepCopy = function (obj) {
return JSON.parse(JSON.stringify(obj))
}
/**
* axios API 的请求错误结果提醒
* @param err 错误信息
* @param def 默认信息
*/
Vue.prototype.$err = (err, def) => {
try {
Vue.prototype.$message.error(err.message)
} catch (e) {
Vue.prototype.$message.error(def)
}
}
/**
* axios API 的请求成功结果提醒
* @param rsp 错误信息
* @param def 默认信息
*/
Vue.prototype.$ok = (rsp, def) => {
return Vue.prototype.$message.success(rsp.data ? rsp.data : def)
}
/**
* 时间段转换时长文字描述
* @param s 开始时间
* @param e 结束时间
* @returns {string}
*/
Vue.prototype.$timeCoverStr = function (s, e) {
if (s === e) {
return '0'
}
let start = moment(s);
let end = moment(e)
let years = end.diff(s, 'years')
let months = end.diff(s, 'months')
let days = end.diff(s, 'days')
let hours = end.diff(s, 'hours')
let minutes = end.diff(s, 'minutes')
let second = end.diff(s, 'seconds')
second = second % 60
minutes = minutes % 60
hours = hours % 24
months = months % 12
//因为每月天不固定,所以天要特殊动态处理
if (start.date() < end.date()) {
days = end.date() - start.date()
if (minutes > 0 || hours > 0) {
days--;
}
}
//处理超过俩月且天超过31
if (days > 31 && end.month() - start.month() >= 2) {
//将日期推至上月求差
days = end.diff(start.add(end.month() - start.month() - 1, 'month'), 'days')
}
return `${years > 0 ? years + '年 ' : ''}${months > 0 ? months + '个月 ' : ''}
${days > 0 ? days + '天 ' : ''}${hours > 0 ? hours + '小时 ' : ''}
${minutes > 0 ? minutes + '分钟 ' : ''}${second > 0 ? second + '秒' : ''}`
}
/**
* 移除一个数组值
* @param value 需要移除得值
* @returns {number}
*/
Array.prototype.remove = function (value) {
let index = this.indexOf(value)
if (index > -1) {
this.splice(index, 1)
}
return index
}
/**
* 根据key 移除数组里面一个指定值的对象,匹配唯一key
* @param key key
* @param val key对应的值
* @returns {number}
*/
Array.prototype.removeByKey = function (key, val) {
let index = this.findIndex(value => value[key] === val)
if (index > -1) {
this.splice(index, 1)
}
return index
}
//对象数组转map
Array.prototype.toMap = function (key) {
let map = new Map()
this.forEach(v => map.set(v[key], v))
return map
}
//判断是否为主要业务节点
export function isPrimaryNode(node){
return node &&
(node.type === 'ROOT' || node.type === 'APPROVAL'
|| node.type === 'CC' || node.type === 'DELAY'
|| node.type === 'TRIGGER');
}
export function isBranchNode(node){
return node && (node.type === 'CONDITIONS' || node.type === 'CONCURRENTS');
}
export function isEmptyNode(node){
return node && (node.type === 'EMPTY')
}
//是分支节点
export function isConditionNode(node){
return node.type === 'CONDITIONS';
}
//是分支节点
export function isBranchSubNode(node){
return node && (node.type === 'CONDITION' || node.type === 'CONCURRENT');
}
export function isConcurrentNode(node){
return node.type === 'CONCURRENTS'
}
export function forEachNode(node, callback){
if (isBranchNode(node)){
if (callback(node)){return}
node.branchs.map(branchNode => {
if (callback(branchNode)){return}
forEachNode(branchNode.children, callback)
})
forEachNode(node.children, callback)
}else if (isPrimaryNode(node) || isEmptyNode(node) || isBranchSubNode(node)){
if (callback(node)){return}
forEachNode(node.children, callback)
}
}
export default {
forEachNode, isPrimaryNode, isBranchNode, isEmptyNode,
isConditionNode, isBranchSubNode, isConcurrentNode
}
import router from '@/router'
/**
* 对象深拷贝
*/
export function deepClone(data) {
var type = getObjType(data)
var obj
if (type === 'array') {
obj = []
} else if (type === 'object') {
obj = {}
} else {
// 不再具有下一层次
return data
}
if (type === 'array') {
for (var i = 0, len = data.length; i < len; i++) {
data[i] = (function () {
if (data[i] === 0) {
return data[i]
}
return data[i]
}())
delete data[i].$parent
obj.push(deepClone(data[i]))
}
} else if (type === 'object') {
for (var key in data) {
delete data.$parent
obj[key] = deepClone(data[key])
}
}
return obj
}
export function getObjType(obj) {
var toString = Object.prototype.toString
var map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
}
if (obj instanceof Element) {
return 'element'
}
return map[toString.call(obj)]
}
export function goBack() {
let from = sessionStorage.getItem("from");
console.log('from', from)
if (from && from !== "null") {
sessionStorage.removeItem("from");
// type==="back" 关闭弹窗
window.parent.postMessage(
{ text: "子页面发消息给父页面", type: "back", from: from },
"*"
);
} else {
router.go(-1);
}
}
\ No newline at end of file
export const businessList = [
{
type: "10",
name: "治具流程",
hasForm: '0',
hasFlow: '1',
},
{
type: "20",
name: "点检管理记录表",
hasForm: '1',
hasFlow: '0',
},
{
type: "30",
name: "变化点流程",
hasForm: '0',
hasFlow: '1',
},
{
type: "40",
name: "异常处理表单流程",
hasForm: '1',
hasFlow: '1',
},
{
type: "50",
name: "设备流程",
hasForm: '0',
hasFlow: '1',
},
]
export function getBusinessName(business) {
let item = businessList.find((item) => {
return item.type === business
})
return item ? item.name : ''
}
export function getBusinessItem(business) {
let item = businessList.find((item) => {
return item.type === business
})
return item
}
export const receiveUpgrade = [
{
id: '0',
name: '0',
},
{
id: '1',
name: '1(+)',
},
{
id: '2',
name: '2(++)',
},
{
id: '3',
name: '3(+++)',
},
]
export const handleUpgrade = [
{
id: '0',
name: '0',
},
{
id: '1',
name: '1(+)',
},
{
id: '2',
name: '2(++)',
},
{
id: '3',
name: '3(+++)',
},
]
export function getReceiveUpgradeName(id) {
let item = receiveUpgrade.find((item) => {
return item.id === id
})
return item ? item.name : ''
}
export function getHandleUpgradeName(id) {
let item = handleUpgrade.find((item) => {
return item.id === id
})
return item ? item.name : ''
}
\ No newline at end of file
// import { useDictStore } from '@/store/modules/dict.js'
/**
* 转化数据字典的格式
* @param {Array} data 接口返回的数据结构
* @return {Array} 转化的数据结构[{list:[],value1:{},code1:{},value2:{},code2:{}}]
*/
export function transform(data) {
const result = Object.create(null)
if (!data) return result
return data.reduce((map, group) => {
// 处理dictionaryList为空的兼容
group.dictionaryList = group.dictionaryList || []
const project = { list: group.dictionaryList }
project.json = group
group.dictionaryList.forEach((dict) => {
if (project[dict.value]) {
console.warn(
`字典value重复:${group.name}(${group.code})下有重复${dict.value} `
)
} else {
project[dict.value] = dict
project[dict.code] = dict
}
})
map[group.code] = project
return map
}, result)
}
/**
* 根据字典分组code获取字典分组对象
* @param {string} groupCode
* @return {unknown}
*/
export function getGroupDictionary(groupCode) {
const dictionary = localStorage.getItem('dictionary') ? JSON.parse(localStorage.getItem('dictionary')) : {}
const dictList = dictionary
return dictList[groupCode]
}
/**
* 根据字典code获取字典数据的列表
* @param {String} groupCode 字典分组code
* @return {Array} 字典对应code的list
*/
export function getDictList(groupCode) {
const data = getGroupDictionary(groupCode)
return data ? data.list : []
}
/**
* 根据字典code获取字典对象
* @param {String} groupCode 字典分类code
* @param {String} code 字典code
* @param {boolean} [autoAddPrefix] 是否将code自动拼接在groupCode以获取子级code
* @return {{name: string, value: string}|undefined} 字典对象
*/
export function getDict(groupCode, code, autoAddPrefix = true) {
const data = getGroupDictionary(groupCode)
if (!data) return
if (autoAddPrefix) {
code = groupCode + '.' + code
}
return data[code]
}
/**
* 根据字典code对应的value获取对应code
* @param {String} groupCode 字典code
* @param {String} code 字典对应code的其中一个code
* @param {boolean} [autoAddPrefix] 字典对应code的其中一个code
* @return {String} 字典对应value对应的code
*/
export function getDictVal(groupCode, code, autoAddPrefix = true) {
const dict = getDict(groupCode, code, autoAddPrefix)
return dict && dict.value
}
/**
* 根据字典code对应的value获取对应value
* @param {String} groupCode 字典分组code
* @param {String[]} codes 子级code数组
* @param {boolean} [autoAddPrefix] 是否将code自动拼接在groupCode以获取子级code
* @return {String[]} 字典value数组,按codes的顺序排序
*/
export function getDictValList(groupCode, codes, autoAddPrefix = true) {
const data = getGroupDictionary(groupCode)
if (!data) return []
return codes.map(code => {
if (autoAddPrefix) {
code = groupCode + '.' + code
}
const dict = data[code]
return dict ? dict.value : ''
})
}
/**
* 根据字典code对应的value获取对应name
* @param {String} groupCode 字典code
* @param {String} val 字典对应code的其中一个value
* @return {String} 字典对应value对应的name
*/
export function getDictName(groupCode, val) {
const data = getGroupDictionary(groupCode)
if (!data) return
const dict = data[val]
return dict && dict.name
}
/**
* 根据字典code获取字典名称
* @param {String} groupCode 字典code
* @param {String} code 字典对应code的其中一个code
* @param {boolean} [autoAddPrefix] 是否将code自动拼接在groupCode以获取子级code
* @return {String} 字典名称
*/
export function getDictNameByCode(groupCode, code, autoAddPrefix = true) {
const data = getGroupDictionary(groupCode)
if (!data) return ''
if (autoAddPrefix) {
code = groupCode + '.' + code
}
const dict = data[code]
return dict && dict.name ? dict.name : ''
}
/**
* 图片转base64并压缩指定大小
* @param self
* @param size
*/
export function imgFileZip(self, size, call) {
//创建一个读取文件的对象
let reader = new FileReader();
//读取文件,转码
reader.readAsDataURL(self.files[0]);
reader.onload = function (e) {
let base64 = e.target.result; //转码过后的base64编码
console.log("压缩前", base64.length / 1024 + 'KB');
//创建一个图片
let newImage = new Image();
let quality = 0.6; //压缩系数0-1之间,压缩到0.9以上会有bug,注意!(可以自行设置)
newImage.src = base64;
newImage.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
let imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
//给生成图片设置一个默认的宽度(可以自行设置)
let myWidth = 50;
//准备在画布上绘制图片
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
//判断上传的图片的宽高是否超过设置的默认宽度以及设置同比例的高
if (Math.max(imgWidth, imgHeight) > myWidth) {
if (imgWidth > imgHeight) {
canvas.width = myWidth;
canvas.height = myWidth * imgHeight / imgWidth;
} else {
canvas.height = myWidth;
canvas.width = myWidth * imgWidth / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
}
//清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
//开始绘制图片到画布上
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
let newBase64 = canvas.toDataURL("image/jpeg", quality);//压缩图片大小(重点代码)
// 获取到当前的图片的大小,然后调整成自己需要的大小,例如说需要200KB-500KB之间(可以自行设置)
while (newBase64.length > 1024 * size && quality > 0) {
quality -= 0.02;
newBase64 = canvas.toDataURL("image/jpeg", quality);
}
call(newBase64);
console.log("压缩后", newBase64.length / 1024 + 'KB')
}
};
}
export function imgZip(path, obj, callback) {
var img = new Image();
img.src = path;
img.onload = function () {
var that = this;
// 默认按比例压缩
var w = that.width, h = that.height, scale = w / h;
w = (obj.width || w) / 3;
h = (obj.height || (w / scale)) / 3;
var quality = 0.6; // 默认图片质量为0.7
// 生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 创建属性节点
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, w, h);
// 图像质量
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality;
}
// quality值越小,所绘制出的图像越模糊
var base64 = canvas.toDataURL('image/jpeg', quality);
// 回调函数返回base64的值
callback(base64);
}
}
export default {
imgFileZip, imgZip
}
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 sign in to comment