feat: 完善批量修改填写人、审核页面优化、人员管理等功能

- 批量修改填写人:添加左侧分类列表、折叠功能、暂存和重新分配
- 审核页面:添加折叠和分页功能
- 查询分析页面:添加单位列显示
- 人员管理:创建独立页面,支持搜索、分页、批量操作
- 修复各种UI和功能问题
This commit is contained in:
Zhou 2026-06-23 09:55:55 +08:00
parent 4e1bef2888
commit 46b01b4504
212 changed files with 96867 additions and 79912 deletions

4
.arts/settings.json Normal file
View File

@ -0,0 +1,4 @@
{
"clawMode.mode": "editor",
"workbench.activityBar.location": "default"
}

View File

@ -1,3 +1,3 @@
> 1%
last 2 versions
> 1%
last 2 versions
not ie <= 9

View File

@ -1,62 +1,62 @@
/*
* @Author: DevinShi
* @Date: 2020-02-03 09:01:16
* @LastEditors: DevinShi
* @LastEditTime: 2020-02-03 09:08:38
* @Description: file content description
*/
"use strict";
module.exports = {
types: [
{ value: "feat", name: "功能: 一个新的功能" },
{ value: "fix", name: "修复: 修复一个Bug" },
{ value: "docs", name: "文档: 变更的只有文档" },
{ value: "style", name: "格式: 空格, 分号等格式修复" },
{ value: "refactor", name: "重构: 代码重构,注意和特性、修复区分开" },
{ value: "perf", name: "性能: 提升性能" },
{ value: "test", name: "测试: 添加一个测试" },
{ value: "chore", name: "工具: 开发工具变动(构建、脚手架工具等)" },
{ value: "revert", name: "回滚: 代码回退" }
],
// scopes: [
// {name: '模块1'},
// {name: '模块2'},
// {name: '模块3'},
// {name: '模块4'}
// ],
// it needs to match the value for field type. Eg.: 'fix'
scopeOverrides: {
fix: [
{ name: "功能" },
{ name: "样式" },
{ name: "e2e测试" },
{ name: "单元测试" }
],
chore: [{
name: '依赖修改',
}, {
name: '打包工具'
}]
},
// override the messages, defaults are as follows
messages: {
type: "选择一种你的提交类型:",
scope: "选择一个scope (可选):",
// used if allowCustomScopes is true
customScope: "自定义一个scope用于这次提交:",
subject: "短说明:\n",
body: '长说明,使用"|"换行(可选)\n',
breaking: "非兼容性说明 (可选):\n",
footer: "关联关闭的issue例如#31, #34(可选):\n",
confirmCommit: "确定提交说明?"
},
allowCustomScopes: true,
allowBreakingChanges: ["feat", "fix"],
// limit subject length
subjectLimit: 100
};
/*
* @Author: DevinShi
* @Date: 2020-02-03 09:01:16
* @LastEditors: DevinShi
* @LastEditTime: 2020-02-03 09:08:38
* @Description: file content description
*/
"use strict";
module.exports = {
types: [
{ value: "feat", name: "功能: 一个新的功能" },
{ value: "fix", name: "修复: 修复一个Bug" },
{ value: "docs", name: "文档: 变更的只有文档" },
{ value: "style", name: "格式: 空格, 分号等格式修复" },
{ value: "refactor", name: "重构: 代码重构,注意和特性、修复区分开" },
{ value: "perf", name: "性能: 提升性能" },
{ value: "test", name: "测试: 添加一个测试" },
{ value: "chore", name: "工具: 开发工具变动(构建、脚手架工具等)" },
{ value: "revert", name: "回滚: 代码回退" }
],
// scopes: [
// {name: '模块1'},
// {name: '模块2'},
// {name: '模块3'},
// {name: '模块4'}
// ],
// it needs to match the value for field type. Eg.: 'fix'
scopeOverrides: {
fix: [
{ name: "功能" },
{ name: "样式" },
{ name: "e2e测试" },
{ name: "单元测试" }
],
chore: [{
name: '依赖修改',
}, {
name: '打包工具'
}]
},
// override the messages, defaults are as follows
messages: {
type: "选择一种你的提交类型:",
scope: "选择一个scope (可选):",
// used if allowCustomScopes is true
customScope: "自定义一个scope用于这次提交:",
subject: "短说明:\n",
body: '长说明,使用"|"换行(可选)\n',
breaking: "非兼容性说明 (可选):\n",
footer: "关联关闭的issue例如#31, #34(可选):\n",
confirmCommit: "确定提交说明?"
},
allowCustomScopes: true,
allowBreakingChanges: ["feat", "fix"],
// limit subject length
subjectLimit: 100
};

View File

@ -1,20 +1,20 @@
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=false
indent_style=space
indent_size=2
[{.eslintrc,.babelrc,.stylelintrc,*.json}]
indent_style=space
indent_size=2
[*.less]
indent_style=space
indent_size=2
[*.{js,jsx,ts,tsx,vue,html}]
indent_style=space
indent_size=2
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=false
indent_style=space
indent_size=2
[{.eslintrc,.babelrc,.stylelintrc,*.json}]
indent_style=space
indent_size=2
[*.less]
indent_style=space
indent_size=2
[*.{js,jsx,ts,tsx,vue,html}]
indent_style=space
indent_size=2

6
.env
View File

@ -1,3 +1,3 @@
VUE_APP_BASE_DOMAIN=http://dcloud-demo.definesys.cn:31213
VUE_APP_TENANT_ID=254638499280453633
VUE_APP_PUBLIC_PATH=/app/
VUE_APP_BASE_DOMAIN=http://dcloud-demo.definesys.cn:31213
VUE_APP_TENANT_ID=254638499280453633
VUE_APP_PUBLIC_PATH=/

View File

@ -1,17 +1,17 @@
*.sh
node_modules
lib
*.md
*.scss
*.woff
*.ttf
.vscode
.idea
/build/
/dist/
/public/
/script/
/config/
/docs
.vscode
*.sh
node_modules
lib
*.md
*.scss
*.woff
*.ttf
.vscode
.idea
/build/
/dist/
/public/
/script/
/config/
/docs
.vscode

View File

@ -1,31 +1,31 @@
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/recommended'],
rules: {
// 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'space-before-function-paren': 'off',
// 禁止在计算属性中对属性修改
'vue/no-side-effects-in-computed-properties': 'off',
// 属性空格
'vue/attribute-hyphenation': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/html-self-closing': 'off',
'vue/require-default-prop': 'off',
'vue/max-attributes-per-line': 'off'
},
parserOptions: {
parser: 'babel-eslint'
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)'],
env: {
jest: true
}
}
]
}
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/recommended'],
rules: {
// 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'space-before-function-paren': 'off',
// 禁止在计算属性中对属性修改
'vue/no-side-effects-in-computed-properties': 'off',
// 属性空格
'vue/attribute-hyphenation': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/html-self-closing': 'off',
'vue/require-default-prop': 'off',
'vue/max-attributes-per-line': 'off'
},
parserOptions: {
parser: 'babel-eslint'
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)'],
env: {
jest: true
}
}
]
}

62
.gitignore vendored
View File

@ -1,31 +1,31 @@
.DS_Store
node_modules
/dist
/tests/e2e/reports/
selenium-debug.log
chromedriver.log
geckodriver.log
# 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?
node_modules.zip
apaas-custom-mydemo.zip
apaas-custom-mydemo-1.zip
eslint-report.html
fix-echarts-install.bat
.DS_Store
node_modules
/dist
/tests/e2e/reports/
selenium-debug.log
chromedriver.log
geckodriver.log
# 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?
node_modules.zip
apaas-custom-mydemo.zip
apaas-custom-mydemo-1.zip
eslint-report.html
fix-echarts-install.bat

2
.npmrc
View File

@ -1 +1 @@
sass_binary_site=https://registry.npmmirror.com/-/binary/node-sass
sass_binary_site=https://registry.npmmirror.com/-/binary/node-sass

View File

@ -1,10 +1,10 @@
*.js
*.png
*.eot
*.ttf
*.woff
/dist/
/lib/
/public/
.output.js
*.js
*.png
*.eot
*.ttf
*.woff
/dist/
/lib/
/public/
.output.js

View File

@ -1,36 +0,0 @@
# yuchai
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@ -1,39 +0,0 @@
# yuchai
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,160 +1,167 @@
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-mydemo"],
"router": {
"apaas-custom-modalContorl":{
"name": "apaas-custom-modalContorl",
"path": "apaas-custom-modalContorl",
"meta": {
"title": "模板管理"
}
},
"apaas-custom-selfEnginedata":{
"name": "apaas-custom-selfEnginedata",
"path": "apaas-custom-selfEnginedata",
"meta": {
"title": "玉柴发动机数据"
}
},
"apaas-custom-otherEnginedata":{
"name": "apaas-custom-otherEnginedata",
"path": "apaas-custom-otherEnginedata",
"meta": {
"title": "竞品发动机数据"
}
},
"apaas-custom-checkData":{
"name": "apaas-custom-checkData",
"path": "apaas-custom-checkData",
"meta": {
"title": "数据检查"
}
},
"apaas-custom-report":{
"name": "apaas-custom-report",
"path": "apaas-custom-report",
"meta": {
"title": "对标报告"
}
},
"apaas-custom-reportList":{
"name": "apaas-custom-reportList",
"path": "apaas-custom-reportList",
"meta": {
"title": "报告列表"
}
},
"apaas-custom-reportDetail":{
"name": "apaas-custom-reportDetail",
"path": "apaas-custom-reportDetail",
"meta": {
"title": "报告详情"
}
},
"apaas-custom-reportCheck":{
"name": "apaas-custom-reportCheck",
"path": "apaas-custom-reportCheck",
"meta": {
"title": "报告检查"
}
},
"apaas-custom-modelDetail":{
"name": "apaas-custom-modelDetail",
"path": "apaas-custom-modelDetail",
"meta": {
"title": "系统参数管理"
}
},
"apaas-custom-engineDetail":{
"name": "apaas-custom-engineDetail",
"path": "apaas-custom-engineDetail",
"meta": {
"title": "发动机参数详情"
}
},
"apaas-custom-approvalManagement":{
"name": "apaas-custom-approvalManagement",
"path": "apaas-custom-approvalManagement",
"meta": {
"title": "模板审批管理"
}
},
"apaas-custom-toDoList":{
"name": "apaas-custom-toDoList",
"path": "apaas-custom-toDoList",
"meta": {
"title": "数据待办"
}
},
"apaas-custom-myDone":{
"name": "apaas-custom-myDone",
"path": "apaas-custom-myDone",
"meta": {
"title": "我的已办"
}
},
"apaas-custom-mySend":{
"name": "apaas-custom-mySend",
"path": "apaas-custom-mySend",
"meta": {
"title": "我发起的"
}
},
"apaas-custom-myDemo":{
"name": "apaas-custom-myDemo",
"path": "apaas-custom-myDemo",
"meta": {
"title": "我的测试"
}
},
"apaas-custom-selfEngineCheck":{
"name": "apaas-custom-selfEngineCheck",
"path": "apaas-custom-selfEngineCheck",
"meta": {
"title": "玉柴发动机审核"
}
},
"apaas-custom-otherEngineCheck":{
"name": "apaas-custom-otherEngineCheck",
"path": "apaas-custom-otherEngineCheck",
"meta": {
"title": "竞品发动机审核"
}
},
"apaas-custom-managerData":{
"name": "apaas-custom-managerData",
"path": "apaas-custom-managerData",
"meta": {
"title": "责任人管理"
}
},
"apaas-custom-fillerData":{
"name": "apaas-custom-fillerData",
"path": "apaas-custom-fillerData",
"meta": {
"title": "填写人管理"
}
},
"apaas-custom-permissionManagement":{
"name": "apaas-custom-permissionManagement",
"path": "apaas-custom-permissionManagement",
"meta": {
"title": "权限管理"
}
},
"apaas-custom-checkPersonPermission":{
"name": "apaas-custom-checkPersonPermission",
"path": "apaas-custom-checkPersonPermission",
"meta": {
"title": "权限检查"
}
}
},
"customWidgetList": [
{
"code": "mydemo",
"text": "mydemo"
}
],
"outputName": "apaas-custom-mydemo"
}
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-mydemo"],
"router": {
"apaas-custom-modalContorl":{
"name": "apaas-custom-modalContorl",
"path": "apaas-custom-modalContorl",
"meta": {
"title": "模板管理"
}
},
"apaas-custom-selfEnginedata":{
"name": "apaas-custom-selfEnginedata",
"path": "apaas-custom-selfEnginedata",
"meta": {
"title": "玉柴发动机数据"
}
},
"apaas-custom-otherEnginedata":{
"name": "apaas-custom-otherEnginedata",
"path": "apaas-custom-otherEnginedata",
"meta": {
"title": "竞品发动机数据"
}
},
"apaas-custom-checkData":{
"name": "apaas-custom-checkData",
"path": "apaas-custom-checkData",
"meta": {
"title": "数据检查"
}
},
"apaas-custom-report":{
"name": "apaas-custom-report",
"path": "apaas-custom-report",
"meta": {
"title": "对标报告"
}
},
"apaas-custom-reportList":{
"name": "apaas-custom-reportList",
"path": "apaas-custom-reportList",
"meta": {
"title": "报告列表"
}
},
"apaas-custom-reportDetail":{
"name": "apaas-custom-reportDetail",
"path": "apaas-custom-reportDetail",
"meta": {
"title": "报告详情"
}
},
"apaas-custom-reportCheck":{
"name": "apaas-custom-reportCheck",
"path": "apaas-custom-reportCheck",
"meta": {
"title": "报告检查"
}
},
"apaas-custom-modelDetail":{
"name": "apaas-custom-modelDetail",
"path": "apaas-custom-modelDetail",
"meta": {
"title": "系统参数管理"
}
},
"apaas-custom-engineDetail":{
"name": "apaas-custom-engineDetail",
"path": "apaas-custom-engineDetail",
"meta": {
"title": "发动机参数详情"
}
},
"apaas-custom-approvalManagement":{
"name": "apaas-custom-approvalManagement",
"path": "apaas-custom-approvalManagement",
"meta": {
"title": "模板审批管理"
}
},
"apaas-custom-toDoList":{
"name": "apaas-custom-toDoList",
"path": "apaas-custom-toDoList",
"meta": {
"title": "数据待办"
}
},
"apaas-custom-myDone":{
"name": "apaas-custom-myDone",
"path": "apaas-custom-myDone",
"meta": {
"title": "我的已办"
}
},
"apaas-custom-mySend":{
"name": "apaas-custom-mySend",
"path": "apaas-custom-mySend",
"meta": {
"title": "我发起的"
}
},
"apaas-custom-myDemo":{
"name": "apaas-custom-myDemo",
"path": "apaas-custom-myDemo",
"meta": {
"title": "我的测试"
}
},
"apaas-custom-selfEngineCheck":{
"name": "apaas-custom-selfEngineCheck",
"path": "apaas-custom-selfEngineCheck",
"meta": {
"title": "玉柴发动机审核"
}
},
"apaas-custom-otherEngineCheck":{
"name": "apaas-custom-otherEngineCheck",
"path": "apaas-custom-otherEngineCheck",
"meta": {
"title": "竞品发动机审核"
}
},
"apaas-custom-managerData":{
"name": "apaas-custom-managerData",
"path": "apaas-custom-managerData",
"meta": {
"title": "责任人管理"
}
},
"apaas-custom-fillerData":{
"name": "apaas-custom-fillerData",
"path": "apaas-custom-fillerData",
"meta": {
"title": "填写人管理"
}
},
"apaas-custom-permissionManagement":{
"name": "apaas-custom-permissionManagement",
"path": "apaas-custom-permissionManagement",
"meta": {
"title": "权限管理"
}
},
"apaas-custom-roleMemberManagement":{
"name": "apaas-custom-roleMemberManagement",
"path": "apaas-custom-roleMemberManagement",
"meta": {
"title": "人员管理"
}
},
"apaas-custom-checkPersonPermission":{
"name": "apaas-custom-checkPersonPermission",
"path": "apaas-custom-checkPersonPermission",
"meta": {
"title": "权限检查"
}
}
},
"customWidgetList": [
{
"code": "mydemo",
"text": "mydemo"
}
],
"outputName": "apaas-custom-mydemo"
}

View File

@ -1,55 +1,55 @@
/**
* Element UI 懒加载插件由于我们需要使用懒加载scss动态编译主题所以不使用
*/
// eslint-disable-next-line no-unused-vars
const elementUIComponentPlugin = [
'component',
{
libraryName: 'element-ui',
styleLibraryName: '../packages/theme-chalk/src',
ext: '.scss'
},
'element-ui'
]
const XLibComponentPlugin = [
'component',
{
libraryName: '@x-ui/x-dcloud-ui',
styleLibrary: {
base: false,
name: 'theme-chalk/theme'
},
ext: '.scss'
},
'@x-ui/x-dcloud-ui'
]
const XDcloudPageWebPlugin = [
'component',
{
libraryName: '@x-apaas/x-dcloud-page-web',
styleLibrary: {
base: false,
name: 'theme-chalk/theme'
},
ext: '.scss'
},
'@x-apaas/x-dcloud-page-web'
]
module.exports = {
presets: [
[
'@vue/cli-plugin-babel/preset',
{
useBuiltIns: 'entry'
}
]
],
plugins: [
elementUIComponentPlugin,
XLibComponentPlugin,
XDcloudPageWebPlugin
]
}
/**
* Element UI 懒加载插件由于我们需要使用懒加载scss动态编译主题所以不使用
*/
// eslint-disable-next-line no-unused-vars
const elementUIComponentPlugin = [
'component',
{
libraryName: 'element-ui',
styleLibraryName: '../packages/theme-chalk/src',
ext: '.scss'
},
'element-ui'
]
const XLibComponentPlugin = [
'component',
{
libraryName: '@x-ui/x-dcloud-ui',
styleLibrary: {
base: false,
name: 'theme-chalk/theme'
},
ext: '.scss'
},
'@x-ui/x-dcloud-ui'
]
const XDcloudPageWebPlugin = [
'component',
{
libraryName: '@x-apaas/x-dcloud-page-web',
styleLibrary: {
base: false,
name: 'theme-chalk/theme'
},
ext: '.scss'
},
'@x-apaas/x-dcloud-page-web'
]
module.exports = {
presets: [
[
'@vue/cli-plugin-babel/preset',
{
useBuiltIns: 'entry'
}
]
],
plugins: [
elementUIComponentPlugin,
XLibComponentPlugin,
XDcloudPageWebPlugin
]
}

View File

@ -1,125 +1,125 @@
const shell = require('shelljs')
const path = require('path')
const fs = require('fs')
const rimraf = require('rimraf')
const customs = fs.readdirSync(path.resolve(process.cwd(), 'src/custom'))
const all = customs.reduce((result, dir) => {
// ignore directories whose name starts without `apaas-custom-plugin-`
if (dir.indexOf('apaas-custom-plugin-')) return result
try {
const apaasJson = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), 'src', 'custom', dir, 'apaas.json')))
// match every plugins except those whose local.notAll is true
if (apaasJson && (!apaasJson.local || !apaasJson.local.notAll)) result.push(dir.slice(20))
} catch (e) {
} finally {
return result
}
}, [])
const help = `
插件打包入口
格式
1. node thisJs xx <params> <value> 用指定的参数和值打包xx插件
2. node thisJs xx 打包xx插件
3. node thisJs <params> <value> 用指定的参数和值打包xx插件notes: 必须要包含 -i 或者 -a 参数
参数
-i <plugin_name> 指定插件名优先级高于格式1和格式2指定的插件名
-b 采用批量打包模式批量打包默认的插件为上文中的 all 变量值指定的插件集合此参数将忽略 -i 指定的具体插件名
批量打包默认的插件: ${all.join(',')}
-c 加密命名插件打包后的文件夹或压缩文件使用 md5 加密插件 code 后的字符串命名
-Z 取消压缩默认会给每一个插件打包使用此命令则取消打包这一步
-A <plugins_str> 声明参与批量打包的所有插件用英文逗号分隔多个插件 oo,aa 表示打包oo和aa这两个插件需要 -b 参数才会实际生效
-a 使用异步打包模式
-h, --help 查看打包命令帮助
--clean, --rm 清除所有打包产生的文件
支持缩略形式的参数 -cZ 相当于 -c -Z其后需要跟变量的参数写在省略形式前的会读取其后的变量值并生效
-iA oo 表示指定打包oo插件-Ai oo,aa表示指定需要批量打包的插件为 oo aa
`
let crypto = 'noc'
let noZip = 'noz'
let batchMode = false
let plugin = ''
let async = false
const pickValue = function(a, i) {
return a && a[i] && !a[i].startsWith('-') && a[i]
}
const parseArgv = function(argv) {
const localArgv = [...argv]
for (let i = 0; i < localArgv.length; i++) {
if (localArgv[i].startsWith('--')) {
switch (localArgv[i]) {
case '--clean':
case '--rm':
rimraf(path.resolve(process.cwd(), 'crypto'))
rimraf(path.resolve(process.cwd(), 'PLUGIN_*'))
rimraf(path.resolve(process.cwd(), 'PLUGIN_*.zip'))
process.exit(0)
case '--help':
console.log(help)
process.exit(0)
default:
break
}
} else if (localArgv[i].startsWith('-')) {
const flag = localArgv[i].slice(0)
const flags = (flag && flag.split('')) || []
flags.forEach((f) => {
let a
switch (f) {
case 'c':
crypto = '-c'
break
case 'b':
batchMode = true
break
case 'a':
async = true
break
case 'A':
;(a = pickValue(localArgv, i + 1)) && a && ((all = a.split(',')), i++)
break
case 'Z':
noZip = '-Z'
break
case 'i':
;(a = pickValue(localArgv, i + 1)) && a && ((plugin = a), i++)
break
case 'h':
console.log(help)
process.exit(0)
default:
break
}
})
}
}
if (!batchMode && !plugin) {
val = process.argv.slice(2, 3)[0]
val && !val.startsWith('-') && (plugin = val)
if (!plugin) {
console.error('未指定插件名')
process.exit(0)
}
}
}
parseArgv(process.argv.slice(2))
const scriptPath = path.resolve(process.cwd(), 'build/build-plugins.js')
const doBuild = (item) => {
shell.exec(`node ${scriptPath} ${item} ${crypto} ${noZip}`, { async: async })
}
if (batchMode) {
all.forEach(doBuild)
} else {
doBuild(plugin)
}
const shell = require('shelljs')
const path = require('path')
const fs = require('fs')
const rimraf = require('rimraf')
const customs = fs.readdirSync(path.resolve(process.cwd(), 'src/custom'))
const all = customs.reduce((result, dir) => {
// ignore directories whose name starts without `apaas-custom-plugin-`
if (dir.indexOf('apaas-custom-plugin-')) return result
try {
const apaasJson = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), 'src', 'custom', dir, 'apaas.json')))
// match every plugins except those whose local.notAll is true
if (apaasJson && (!apaasJson.local || !apaasJson.local.notAll)) result.push(dir.slice(20))
} catch (e) {
} finally {
return result
}
}, [])
const help = `
插件打包入口
格式
1. node thisJs xx <params> <value> 用指定的参数和值打包xx插件
2. node thisJs xx 打包xx插件
3. node thisJs <params> <value> 用指定的参数和值打包xx插件notes: 必须要包含 -i 或者 -a 参数
参数
-i <plugin_name> 指定插件名优先级高于格式1和格式2指定的插件名
-b 采用批量打包模式批量打包默认的插件为上文中的 all 变量值指定的插件集合此参数将忽略 -i 指定的具体插件名
批量打包默认的插件: ${all.join(',')}
-c 加密命名插件打包后的文件夹或压缩文件使用 md5 加密插件 code 后的字符串命名
-Z 取消压缩默认会给每一个插件打包使用此命令则取消打包这一步
-A <plugins_str> 声明参与批量打包的所有插件用英文逗号分隔多个插件 oo,aa 表示打包oo和aa这两个插件需要 -b 参数才会实际生效
-a 使用异步打包模式
-h, --help 查看打包命令帮助
--clean, --rm 清除所有打包产生的文件
支持缩略形式的参数 -cZ 相当于 -c -Z其后需要跟变量的参数写在省略形式前的会读取其后的变量值并生效
-iA oo 表示指定打包oo插件-Ai oo,aa表示指定需要批量打包的插件为 oo aa
`
let crypto = 'noc'
let noZip = 'noz'
let batchMode = false
let plugin = ''
let async = false
const pickValue = function(a, i) {
return a && a[i] && !a[i].startsWith('-') && a[i]
}
const parseArgv = function(argv) {
const localArgv = [...argv]
for (let i = 0; i < localArgv.length; i++) {
if (localArgv[i].startsWith('--')) {
switch (localArgv[i]) {
case '--clean':
case '--rm':
rimraf(path.resolve(process.cwd(), 'crypto'))
rimraf(path.resolve(process.cwd(), 'PLUGIN_*'))
rimraf(path.resolve(process.cwd(), 'PLUGIN_*.zip'))
process.exit(0)
case '--help':
console.log(help)
process.exit(0)
default:
break
}
} else if (localArgv[i].startsWith('-')) {
const flag = localArgv[i].slice(0)
const flags = (flag && flag.split('')) || []
flags.forEach((f) => {
let a
switch (f) {
case 'c':
crypto = '-c'
break
case 'b':
batchMode = true
break
case 'a':
async = true
break
case 'A':
;(a = pickValue(localArgv, i + 1)) && a && ((all = a.split(',')), i++)
break
case 'Z':
noZip = '-Z'
break
case 'i':
;(a = pickValue(localArgv, i + 1)) && a && ((plugin = a), i++)
break
case 'h':
console.log(help)
process.exit(0)
default:
break
}
})
}
}
if (!batchMode && !plugin) {
val = process.argv.slice(2, 3)[0]
val && !val.startsWith('-') && (plugin = val)
if (!plugin) {
console.error('未指定插件名')
process.exit(0)
}
}
}
parseArgv(process.argv.slice(2))
const scriptPath = path.resolve(process.cwd(), 'build/build-plugins.js')
const doBuild = (item) => {
shell.exec(`node ${scriptPath} ${item} ${crypto} ${noZip}`, { async: async })
}
if (batchMode) {
all.forEach(doBuild)
} else {
doBuild(plugin)
}

View File

@ -1 +1 @@
["admin", "app", "mobile", "workbench", "workbenchm"]
["admin", "app", "mobile", "workbench", "workbenchm"]

View File

@ -1,181 +1,181 @@
const shell = require('shelljs')
const fs = require('fs')
const path = require('path')
const zipper = require('zip-local')
const colors = require('colors')
const envDefine = require('./build-en-define.json')
const md5 = require('md5')
const lib = async (cmd, program) => {
const customModule = cmd.custom
const crypto = cmd.crypto === '-c'
const noZip = cmd.noZip === '-Z'
// 获取指定 custom 目录下的apaas.json
const customModulePath = path.resolve(process.cwd(), 'src/custom', customModule)
const customModuleConfigPath = path.resolve(customModulePath, 'apaas.json')
if (!fs.existsSync(customModuleConfigPath)) {
console.log(`Error: 自开发模块 ${customModule} 下不存在需要的 apaas.json 文件`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const apaasConfig = JSON.parse(fs.readFileSync(customModuleConfigPath))
const buildArray = envDefine
.map((_) => {
if (!apaasConfig[_]) {
return
}
const newConfig = { ...apaasConfig }
delete newConfig[_]
newConfig.outputName = md5(apaasConfig.code)
return {
// 排第一,且不会被覆盖
entry: apaasConfig[_],
...newConfig,
entry: apaasConfig[_],
type: _
}
})
.filter((item) => item)
const result = buildArray.map((config) => doLib(config, customModulePath, crypto))
if (result === [-1, -1]) {
process.exit(0)
}
const cryptoPath = crypto ? 'crypto/' + md5(apaasConfig.code) : apaasConfig.code
writeApaasJson(cryptoPath, apaasConfig)
if (!noZip) {
zip(cryptoPath, cryptoPath)
}
}
/**
* @params apaasModuleConfig 源配置信息
* @params customModulePath 打包入口
*/
const doLib = (apaasModuleConfig, customModulePath, crypto) => {
const customModuleEntryPath = path.resolve(customModulePath, apaasModuleConfig.entry)
const moduleType = apaasModuleConfig.type
const outputName = (crypto ? 'crypto/' + md5(apaasModuleConfig.code) : apaasModuleConfig.code) + '/' + moduleType
if (!fs.existsSync(customModuleEntryPath)) {
console.log(`Error: apaas.json 指定的entry: ${apaasModuleConfig.entry} 的路径错误 `['red'])
console.log(`error path is ${customModuleEntryPath}`['red'])
return -1
}
const customCliPath = path.resolve(
process.cwd(),
'./node_modules/@vue/cli-service/bin/vue-cli-service.js'
)
// 使用vue build 打包,并生成文件
shell.exec(
`node ${customCliPath} build --target lib --name ${apaasModuleConfig.outputName} --dest ${outputName} ${customModuleEntryPath}`
)
const suffix = ['umd.js', 'umd.min.js', 'common.js', 'css']
suffix.forEach((item => {
shell.mv(path.resolve(process.cwd(), `${outputName}/${apaasModuleConfig.outputName}.${item}`), path.resolve(process.cwd(), `${outputName}/index.${item}`))
}))
// shell.cp('-R', customModuleConfigPath, `${outputPath}/`)
const newOutputConfig = { ...apaasModuleConfig }
envDefine.forEach((_) => {
delete newOutputConfig[_]
})
const outputPath = path.resolve(process.cwd(), outputName)
// 拷贝public文件到指定目录
apaasModuleConfig.copyAssets.forEach((copyAsset) => {
copyAssetSource = copyAsset + copyAsset.endsWith('/') ? moduleType : '/' + moduleType
const assetPath = path.resolve(process.cwd(), copyAssetSource)
if (fs.existsSync(assetPath)) {
const outputAsset = path.resolve(outputPath, copyAsset.replace('public/', 'static/'))
shell.mkdir('-p', outputAsset)
shell.cp('-R', `${assetPath}/*`, `${outputAsset}/`)
}
})
}
/**
* @params outputPath 目标文件夹命
* @params originJson 源配置信息
*/
const writeApaasJson = function (outputPath, originJson) {
const newOutputConfig = { ...originJson }
delete newOutputConfig.type
delete newOutputConfig.outputName
delete newOutputConfig.local
newOutputConfig.extraConfig = { ...newOutputConfig.extraConfig }
envDefine.forEach(item => {
if (newOutputConfig[item]) {
newOutputConfig.extraConfig[item] = true
delete newOutputConfig[item]
newOutputConfig.extraConfig[item + 'Css'] = fs.existsSync(path.resolve(process.cwd(), outputPath, item, 'index.css'))
}
})
fs.writeFile(`${outputPath}/apaas.json`, JSON.stringify(newOutputConfig, null, ' '), function (
error
) {
if (error) {
console.log(`配置信息写入失败\n${error}`['red'])
}
})
}
/**
* @params originPath 源文件夹名
* @params outputName 目标文件名
*/
const zip = function (originName, outputName) {
const originPath = path.resolve(process.cwd(), originName)
const outputZipPath = path.resolve(process.cwd(), `${outputName}.zip`)
if (fs.existsSync(outputZipPath)) {
shell.rm(outputZipPath)
}
// 生成zip并压缩
zipper.zip(originPath, function (error, zipped) {
if (!error) {
zipped.compress() // compress before exporting
var buff = zipped.memory() // get the zipped file as a Buffer
zipped.save(outputZipPath, function (error) {
if (!error) {
console.log(`zipped successfully !`['green'])
// 删除指定生成目录
// shell.rm('-r',originPath)
} else {
console.log(`write error: ${error}`['red'])
}
})
} else {
console.log(`read error: ${error}`['red'])
}
})
}
const argv = process.argv.splice(2, 1)[0]
if (!argv) {
console.log(`未指定插件名`['red'])
process.exit(0)
}
const crypto = process.argv.splice(2, 1)[0]
const noZip = process.argv.splice(2, 1)[0]
module.exports = lib(
{
custom: `apaas-custom-plugin-${argv}`,
crypto,
noZip,
},
{}
)
const shell = require('shelljs')
const fs = require('fs')
const path = require('path')
const zipper = require('zip-local')
const colors = require('colors')
const envDefine = require('./build-en-define.json')
const md5 = require('md5')
const lib = async (cmd, program) => {
const customModule = cmd.custom
const crypto = cmd.crypto === '-c'
const noZip = cmd.noZip === '-Z'
// 获取指定 custom 目录下的apaas.json
const customModulePath = path.resolve(process.cwd(), 'src/custom', customModule)
const customModuleConfigPath = path.resolve(customModulePath, 'apaas.json')
if (!fs.existsSync(customModuleConfigPath)) {
console.log(`Error: 自开发模块 ${customModule} 下不存在需要的 apaas.json 文件`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const apaasConfig = JSON.parse(fs.readFileSync(customModuleConfigPath))
const buildArray = envDefine
.map((_) => {
if (!apaasConfig[_]) {
return
}
const newConfig = { ...apaasConfig }
delete newConfig[_]
newConfig.outputName = md5(apaasConfig.code)
return {
// 排第一,且不会被覆盖
entry: apaasConfig[_],
...newConfig,
entry: apaasConfig[_],
type: _
}
})
.filter((item) => item)
const result = buildArray.map((config) => doLib(config, customModulePath, crypto))
if (result === [-1, -1]) {
process.exit(0)
}
const cryptoPath = crypto ? 'crypto/' + md5(apaasConfig.code) : apaasConfig.code
writeApaasJson(cryptoPath, apaasConfig)
if (!noZip) {
zip(cryptoPath, cryptoPath)
}
}
/**
* @params apaasModuleConfig 源配置信息
* @params customModulePath 打包入口
*/
const doLib = (apaasModuleConfig, customModulePath, crypto) => {
const customModuleEntryPath = path.resolve(customModulePath, apaasModuleConfig.entry)
const moduleType = apaasModuleConfig.type
const outputName = (crypto ? 'crypto/' + md5(apaasModuleConfig.code) : apaasModuleConfig.code) + '/' + moduleType
if (!fs.existsSync(customModuleEntryPath)) {
console.log(`Error: apaas.json 指定的entry: ${apaasModuleConfig.entry} 的路径错误 `['red'])
console.log(`error path is ${customModuleEntryPath}`['red'])
return -1
}
const customCliPath = path.resolve(
process.cwd(),
'./node_modules/@vue/cli-service/bin/vue-cli-service.js'
)
// 使用vue build 打包,并生成文件
shell.exec(
`node ${customCliPath} build --target lib --name ${apaasModuleConfig.outputName} --dest ${outputName} ${customModuleEntryPath}`
)
const suffix = ['umd.js', 'umd.min.js', 'common.js', 'css']
suffix.forEach((item => {
shell.mv(path.resolve(process.cwd(), `${outputName}/${apaasModuleConfig.outputName}.${item}`), path.resolve(process.cwd(), `${outputName}/index.${item}`))
}))
// shell.cp('-R', customModuleConfigPath, `${outputPath}/`)
const newOutputConfig = { ...apaasModuleConfig }
envDefine.forEach((_) => {
delete newOutputConfig[_]
})
const outputPath = path.resolve(process.cwd(), outputName)
// 拷贝public文件到指定目录
apaasModuleConfig.copyAssets.forEach((copyAsset) => {
copyAssetSource = copyAsset + copyAsset.endsWith('/') ? moduleType : '/' + moduleType
const assetPath = path.resolve(process.cwd(), copyAssetSource)
if (fs.existsSync(assetPath)) {
const outputAsset = path.resolve(outputPath, copyAsset.replace('public/', 'static/'))
shell.mkdir('-p', outputAsset)
shell.cp('-R', `${assetPath}/*`, `${outputAsset}/`)
}
})
}
/**
* @params outputPath 目标文件夹命
* @params originJson 源配置信息
*/
const writeApaasJson = function (outputPath, originJson) {
const newOutputConfig = { ...originJson }
delete newOutputConfig.type
delete newOutputConfig.outputName
delete newOutputConfig.local
newOutputConfig.extraConfig = { ...newOutputConfig.extraConfig }
envDefine.forEach(item => {
if (newOutputConfig[item]) {
newOutputConfig.extraConfig[item] = true
delete newOutputConfig[item]
newOutputConfig.extraConfig[item + 'Css'] = fs.existsSync(path.resolve(process.cwd(), outputPath, item, 'index.css'))
}
})
fs.writeFile(`${outputPath}/apaas.json`, JSON.stringify(newOutputConfig, null, ' '), function (
error
) {
if (error) {
console.log(`配置信息写入失败\n${error}`['red'])
}
})
}
/**
* @params originPath 源文件夹名
* @params outputName 目标文件名
*/
const zip = function (originName, outputName) {
const originPath = path.resolve(process.cwd(), originName)
const outputZipPath = path.resolve(process.cwd(), `${outputName}.zip`)
if (fs.existsSync(outputZipPath)) {
shell.rm(outputZipPath)
}
// 生成zip并压缩
zipper.zip(originPath, function (error, zipped) {
if (!error) {
zipped.compress() // compress before exporting
var buff = zipped.memory() // get the zipped file as a Buffer
zipped.save(outputZipPath, function (error) {
if (!error) {
console.log(`zipped successfully !`['green'])
// 删除指定生成目录
// shell.rm('-r',originPath)
} else {
console.log(`write error: ${error}`['red'])
}
})
} else {
console.log(`read error: ${error}`['red'])
}
})
}
const argv = process.argv.splice(2, 1)[0]
if (!argv) {
console.log(`未指定插件名`['red'])
process.exit(0)
}
const crypto = process.argv.splice(2, 1)[0]
const noZip = process.argv.splice(2, 1)[0]
module.exports = lib(
{
custom: `apaas-custom-plugin-${argv}`,
crypto,
noZip,
},
{}
)

View File

@ -1,73 +1,73 @@
const shell = require('shelljs');
const fs = require('fs')
const path = require('path')
const zipper = require("zip-local");
const colors = require('colors');
const lib = async (cmd, program) => {
const customModule = cmd.custom
// 获取指定 custom 目录下的apaas.json
const customModulePath = path.resolve(`${process.cwd()}`, 'src/custom', customModule)
const customModuleConfigPath = path.resolve(customModulePath, 'apaas.json')
if (!fs.existsSync(customModuleConfigPath)) {
console.log(`Error: 自开发模块 ${customModule} 下不存在需要的 apass.json 文件`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const apaasConfig = JSON.parse(fs.readFileSync(customModuleConfigPath))
const customModuleEntryPath = path.resolve(customModulePath, apaasConfig.entry)
if (!fs.existsSync(customModuleEntryPath)) {
console.log(`Error: apaas.json 指定的entry: ${apaasConfig.entry} 的路径错误 `['red'])
console.log(`error path is ${customModuleEntryPath}`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const customCliPath = path.resolve(`${process.cwd()}`, './node_modules/.bin/vue-cli-service')
const outputPath = path.resolve(`${process.cwd()}`, `${apaasConfig.outputName}`)
const outputZipPath = path.resolve(`${process.cwd()}`, `${apaasConfig.outputName}.zip`)
// 使用vue build 打包,并生成文件
shell.exec(`node ${customCliPath} build --target lib --name ${apaasConfig.outputName} --dest ${apaasConfig.outputName} ${customModuleEntryPath}`)
shell.cp('-R', customModuleConfigPath, `${outputPath}/`)
// 拷贝public文件到指定目录
apaasConfig.copyAssets.forEach(copyAsset => {
const assetPath = path.resolve(`${process.cwd()}`, copyAsset)
const outputAsset = path.resolve(outputPath, copyAsset.replace('public/', 'static/'))
shell.mkdir('-p', outputAsset)
shell.cp('-R', `${assetPath}/*`, `${outputAsset}/`)
});
if (fs.existsSync(outputZipPath)) {
shell.rm(outputZipPath)
}
// 生成zip并压缩
zipper.zip(outputPath, function(error, zipped) {
if(!error) {
zipped.compress(); // compress before exporting
var buff = zipped.memory(); // get the zipped file as a Buffer
zipped.save(`${outputZipPath}`, function(error) {
if(!error) {
console.log("saved successfully !");
// 删除指定生成目录
// shell.rm('-r',outputPath)
}
});
}
})
}
module.exports = lib({
custom: 'apaas-custom-{{moduleName}}'
const shell = require('shelljs');
const fs = require('fs')
const path = require('path')
const zipper = require("zip-local");
const colors = require('colors');
const lib = async (cmd, program) => {
const customModule = cmd.custom
// 获取指定 custom 目录下的apaas.json
const customModulePath = path.resolve(`${process.cwd()}`, 'src/custom', customModule)
const customModuleConfigPath = path.resolve(customModulePath, 'apaas.json')
if (!fs.existsSync(customModuleConfigPath)) {
console.log(`Error: 自开发模块 ${customModule} 下不存在需要的 apass.json 文件`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const apaasConfig = JSON.parse(fs.readFileSync(customModuleConfigPath))
const customModuleEntryPath = path.resolve(customModulePath, apaasConfig.entry)
if (!fs.existsSync(customModuleEntryPath)) {
console.log(`Error: apaas.json 指定的entry: ${apaasConfig.entry} 的路径错误 `['red'])
console.log(`error path is ${customModuleEntryPath}`['red'])
console.log(`exit`['red'])
process.exit(0)
}
const customCliPath = path.resolve(`${process.cwd()}`, './node_modules/.bin/vue-cli-service')
const outputPath = path.resolve(`${process.cwd()}`, `${apaasConfig.outputName}`)
const outputZipPath = path.resolve(`${process.cwd()}`, `${apaasConfig.outputName}.zip`)
// 使用vue build 打包,并生成文件
shell.exec(`node ${customCliPath} build --target lib --name ${apaasConfig.outputName} --dest ${apaasConfig.outputName} ${customModuleEntryPath}`)
shell.cp('-R', customModuleConfigPath, `${outputPath}/`)
// 拷贝public文件到指定目录
apaasConfig.copyAssets.forEach(copyAsset => {
const assetPath = path.resolve(`${process.cwd()}`, copyAsset)
const outputAsset = path.resolve(outputPath, copyAsset.replace('public/', 'static/'))
shell.mkdir('-p', outputAsset)
shell.cp('-R', `${assetPath}/*`, `${outputAsset}/`)
});
if (fs.existsSync(outputZipPath)) {
shell.rm(outputZipPath)
}
// 生成zip并压缩
zipper.zip(outputPath, function(error, zipped) {
if(!error) {
zipped.compress(); // compress before exporting
var buff = zipped.memory(); // get the zipped file as a Buffer
zipped.save(`${outputZipPath}`, function(error) {
if(!error) {
console.log("saved successfully !");
// 删除指定生成目录
// shell.rm('-r',outputPath)
}
});
}
})
}
module.exports = lib({
custom: 'apaas-custom-{{moduleName}}'
}, {})

View File

@ -1,75 +1,75 @@
const program = require('commander');
const shelljs = require('shelljs');
const userHome = require('user-home');
const fs = require('fs')
const path = require('path')
const colors = require('colors');
const init = (cmd, program) => {
const moduleName = cmd.moduleName
const projectPath = path.resolve(`${process.cwd()}`, `apaas-custom-${moduleName}`)
const customPath = path.resolve(projectPath, 'src/custom');
const staticPath = path.resolve(projectPath, 'public/custom');
//检查控制台是否以运行`git `开头的命令
if (!shelljs.which('git')) {
//在控制台输出内容
console.log('error 本机上没有git请检查git是否安装或相关环境变量是否正确'['red']);
shelljs.exit(1);
}
const version = 'v0.0.1'
const gitTemplateRepo = `${userHome}/.apaasCliRepo`
shelljs.rm('-rf', gitTemplateRepo)
shelljs.mkdir('-p', gitTemplateRepo)
shelljs.exec(`git clone --branch ${version} https://gitee.com/shiyutian/apaas-custom-vue-starter.git --depth=1 ${gitTemplateRepo}`);
shelljs.rm('-rf', path.resolve(`${gitTemplateRepo}`, '.git'))
if (fs.existsSync(projectPath)) {
// 当前路径已经在相关工程
console.log('error 当前路径已经存在工程,请检查相关目录设置'['red'])
shelljs.exit(1);
} else {
shelljs.mkdir('-p', `${process.cwd()}`)
}
shelljs.cp('-R', `${gitTemplateRepo}/.`, projectPath)
const demoCustomModuleName = 'hello'
const demoCustomModulePath = path.resolve(customPath, `apaas-custom-${demoCustomModuleName}`)
const writeAndReplaceFileSync = (filePath) => {
const stat = fs.lstatSync(filePath)
if (stat.isDirectory()) {
const customModuleFileNames = fs.readdirSync(filePath)
customModuleFileNames.forEach(fileName => {
const tempFilePath = path.join(filePath, fileName)
writeAndReplaceFileSync(tempFilePath)
})
} else {
let fileContent = fs.readFileSync(filePath, 'utf-8')
fileContent = fileContent.replace(/{{moduleName}}/g, moduleName)
fileContent = fileContent.replace(/{{ModuleName}}/g, moduleName.charAt(0).toUpperCase() + moduleName.slice(1))
fs.writeFileSync(filePath, fileContent)
}
}
writeAndReplaceFileSync(demoCustomModulePath)
fs.renameSync(demoCustomModulePath, path.resolve(customPath, `apaas-custom-${moduleName}`))
fs.renameSync(path.resolve(staticPath, `apaas-custom-${demoCustomModuleName}`), path.resolve(staticPath, `apaas-custom-${moduleName}`))
}
module.exports = init
const program = require('commander');
const shelljs = require('shelljs');
const userHome = require('user-home');
const fs = require('fs')
const path = require('path')
const colors = require('colors');
const init = (cmd, program) => {
const moduleName = cmd.moduleName
const projectPath = path.resolve(`${process.cwd()}`, `apaas-custom-${moduleName}`)
const customPath = path.resolve(projectPath, 'src/custom');
const staticPath = path.resolve(projectPath, 'public/custom');
//检查控制台是否以运行`git `开头的命令
if (!shelljs.which('git')) {
//在控制台输出内容
console.log('error 本机上没有git请检查git是否安装或相关环境变量是否正确'['red']);
shelljs.exit(1);
}
const version = 'v0.0.1'
const gitTemplateRepo = `${userHome}/.apaasCliRepo`
shelljs.rm('-rf', gitTemplateRepo)
shelljs.mkdir('-p', gitTemplateRepo)
shelljs.exec(`git clone --branch ${version} https://gitee.com/shiyutian/apaas-custom-vue-starter.git --depth=1 ${gitTemplateRepo}`);
shelljs.rm('-rf', path.resolve(`${gitTemplateRepo}`, '.git'))
if (fs.existsSync(projectPath)) {
// 当前路径已经在相关工程
console.log('error 当前路径已经存在工程,请检查相关目录设置'['red'])
shelljs.exit(1);
} else {
shelljs.mkdir('-p', `${process.cwd()}`)
}
shelljs.cp('-R', `${gitTemplateRepo}/.`, projectPath)
const demoCustomModuleName = 'hello'
const demoCustomModulePath = path.resolve(customPath, `apaas-custom-${demoCustomModuleName}`)
const writeAndReplaceFileSync = (filePath) => {
const stat = fs.lstatSync(filePath)
if (stat.isDirectory()) {
const customModuleFileNames = fs.readdirSync(filePath)
customModuleFileNames.forEach(fileName => {
const tempFilePath = path.join(filePath, fileName)
writeAndReplaceFileSync(tempFilePath)
})
} else {
let fileContent = fs.readFileSync(filePath, 'utf-8')
fileContent = fileContent.replace(/{{moduleName}}/g, moduleName)
fileContent = fileContent.replace(/{{ModuleName}}/g, moduleName.charAt(0).toUpperCase() + moduleName.slice(1))
fs.writeFileSync(filePath, fileContent)
}
}
writeAndReplaceFileSync(demoCustomModulePath)
fs.renameSync(demoCustomModulePath, path.resolve(customPath, `apaas-custom-${moduleName}`))
fs.renameSync(path.resolve(staticPath, `apaas-custom-${demoCustomModuleName}`), path.resolve(staticPath, `apaas-custom-${moduleName}`))
}
module.exports = init
init({ moduleName : 'nice' }, program)

View File

@ -1,3 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional']
}
module.exports = {
extends: ['@commitlint/config-conventional']
}

View File

@ -204,10 +204,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -213,10 +213,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -204,10 +204,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -213,10 +213,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -204,10 +204,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -213,10 +213,10 @@ if (typeof window !== 'undefined') {
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./src/custom/apaas-custom-plugin-rule-functions/custom-functions/cubic/cubic.js
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
/*
* cubic函数
* 求三次方
* 接收一个数字类型的参数并求其三次方并返回
*/
/* harmony default export */ var cubic = ({
// 函数名必须以custom开头否则无法被解析

View File

@ -1,9 +1,9 @@
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'^@examples/(.*)$': '<rootDir>/examples/$1',
'^@packages/(.*)$': '<rootDir>/packages/$1',
'\\.(css|less|sass)$': 'identity-obj-proxy'
}
}
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'^@examples/(.*)$': '<rootDir>/examples/$1',
'^@packages/(.*)$': '<rootDir>/packages/$1',
'\\.(css|less|sass)$': 'identity-obj-proxy'
}
}

63807
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,90 +1,89 @@
{
"name": "x-project-app",
"version": "0.0.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"inspect": "vue-cli-service inspect",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint --fix",
"build-rule": "node ./build/build-plugins.js rule-functions -c",
"cm": "git-cz"
},
"dependencies": {
"@x-apaas/x-apaas-cli": "0.0.17",
"@x-apaas/x-apaas-frontend-i18n": "rc",
"@x-apaas/x-dcloud-page-engine": "rc",
"@x-apaas/x-dcloud-page-web": "rc",
"@x-ui/x-dcloud-ui": "^0.2.1",
"core-js": "^3.6.4",
"dayjs": "^1.8.27",
"echarts": "^5.6.0",
"element-ui": "^2.13.2",
"js-file-download": "^0.4.12",
"lodash-es": "^4.17.21",
"md5": "^2.3.0",
"normalize.css": "^8.0.1",
"register-service-worker": "^1.7.1",
"vue": "^2.6.11",
"vue-router": "^3.1.6",
"vuex": "^3.1.3",
"vuex-persist": "^2.2.0",
"x-extension": "^0.2.2"
},
"devDependencies": {
"@babel/polyfill": "^7.8.7",
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@vue/cli-plugin-babel": "^4.3.0",
"@vue/cli-plugin-e2e-nightwatch": "^4.3.0",
"@vue/cli-plugin-eslint": "^4.3.0",
"@vue/cli-plugin-pwa": "^4.3.0",
"@vue/cli-plugin-router": "^4.3.0",
"@vue/cli-plugin-unit-jest": "^4.3.0",
"@vue/cli-plugin-vuex": "^4.3.0",
"@vue/cli-service": "^4.3.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/test-utils": "1.0.0-beta.31",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1",
"colors": "^1.4.0",
"commitizen": "^4.1.2",
"commitlint-config-cz": "^0.13.1",
"conventional-changelog-cli": "^2.0.34",
"cz-conventional-changelog": "^3.2.0",
"cz-customizable": "^6.2.0",
"eslint": "^6.7.2",
"eslint-html-reporter": "^0.7.4",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.2.2",
"husky": "^4.2.5",
"lint-staged": "^9.5.0",
"node-sass": "^4.12.0",
"path": "^0.12.7",
"prettier": "^1.19.1",
"progress-bar-webpack-plugin": "^2.1.0",
"sass-loader": "^8.0.2",
"sass-resources-loader": "^2.0.3",
"shelljs": "^0.8.4",
"svg-sprite-loader": "^5.0.0",
"vue-i18n": "^8.17.7",
"vue-template-compiler": "^2.6.11",
"webpack-bundle-analyzer": "^3.8.0",
"webpack-theme-color-replacer": "^1.3.13",
"zip-local": "^0.3.4"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint --fix",
"git add"
]
}
}
{
"name": "x-project-app",
"version": "0.0.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"inspect": "vue-cli-service inspect",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint --fix",
"build-rule": "node ./build/build-plugins.js rule-functions -c",
"cm": "git-cz"
},
"dependencies": {
"@x-apaas/x-apaas-cli": "0.0.17",
"@x-apaas/x-apaas-frontend-i18n": "rc",
"@x-apaas/x-dcloud-page-engine": "rc",
"@x-apaas/x-dcloud-page-web": "rc",
"@x-ui/x-dcloud-ui": "^0.2.1",
"core-js": "^3.6.4",
"dayjs": "^1.8.27",
"echarts": "^5.6.0",
"element-ui": "^2.13.2",
"js-file-download": "^0.4.12",
"lodash-es": "^4.17.21",
"md5": "^2.3.0",
"normalize.css": "^8.0.1",
"register-service-worker": "^1.7.1",
"vue": "^2.6.11",
"vue-router": "^3.1.6",
"vuex": "^3.1.3",
"vuex-persist": "^2.2.0",
"x-extension": "^0.2.2"
},
"devDependencies": {
"@babel/polyfill": "^7.8.7",
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@vue/cli-plugin-babel": "^4.3.0",
"@vue/cli-plugin-e2e-nightwatch": "^4.3.0",
"@vue/cli-plugin-eslint": "^4.3.0",
"@vue/cli-plugin-pwa": "^4.3.0",
"@vue/cli-plugin-router": "^4.3.0",
"@vue/cli-plugin-unit-jest": "^4.3.0",
"@vue/cli-plugin-vuex": "^4.3.0",
"@vue/cli-service": "^4.3.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/test-utils": "1.0.0-beta.31",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1",
"colors": "^1.4.0",
"commitizen": "^4.1.2",
"commitlint-config-cz": "^0.13.1",
"conventional-changelog-cli": "^2.0.34",
"cz-conventional-changelog": "^3.2.0",
"cz-customizable": "^6.2.0",
"eslint": "^6.7.2",
"eslint-html-reporter": "^0.7.4",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.2.2",
"husky": "^4.2.5",
"lint-staged": "^9.5.0",
"path": "^0.12.7",
"prettier": "^1.19.1",
"progress-bar-webpack-plugin": "^2.1.0",
"sass-loader": "^8.0.2",
"sass-resources-loader": "^2.0.3",
"shelljs": "^0.8.4",
"svg-sprite-loader": "^5.0.0",
"vue-i18n": "^8.17.7",
"vue-template-compiler": "^2.6.11",
"webpack-bundle-analyzer": "^3.8.0",
"webpack-theme-color-replacer": "^1.3.13",
"zip-local": "^0.3.4"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint --fix",
"git add"
]
}
}

View File

@ -1,5 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}
module.exports = {
plugins: {
autoprefixer: {}
}
}

View File

@ -1,13 +1,13 @@
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'always',
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'lf'
}
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'always',
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'lf'
}

View File

@ -1,2 +1,2 @@
User-agent: *
Disallow:
User-agent: *
Disallow:

View File

@ -1,78 +1,78 @@
<!--
* @Author: your name
* @Date: 2020-05-26 10:06:34
* @LastEditTime: 2020-05-26 17:05:42
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/App.vue
-->
<template>
<div id="app">
<component :is="layout">
<router-view />
</component>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { SET_USER_INFO } from '@/store/auth.store'
import { initUserRole } from '@/utils/userRole'
import BlackLayout from '@/layouts/black.layout'
import DefaultLayout from '@/layouts/default.layout'
import NoSidebarLayout from '@/layouts/no-sidebar.layout'
export default {
components: {
BlackLayout,
DefaultLayout,
NoSidebarLayout
},
data() {
return {
}
},
computed: {
layout() {
return this.$route.meta.layout || 'DefaultLayout'
}
},
created() {
this.setUserInfo({
'loginName': 'admin',
'id': '1',
'phone': '17729389320',
'email': '17728389320@163.com',
'enableStatus': 'ENABLED',
'headPortrait': null,
'userName': '赵站洋',
'credentialNo': '110101199003076675',
'gender': 'male'
})
// localStorage.setItem('logedUser', '100771325211655012352')
},
mounted() {
//
this.$nextTick(() => {
initUserRole(this).catch((err) => {
console.error('初始化用户角色信息失败:', err)
})
})
},
methods: {
...mapMutations('authModule', {
setUserInfo: SET_USER_INFO
})
}
}
</script>
<style lang="scss">
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: $--app-font-color;
background-color: $--app-bg-Color;
}
</style>
<!--
* @Author: your name
* @Date: 2020-05-26 10:06:34
* @LastEditTime: 2020-05-26 17:05:42
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/App.vue
-->
<template>
<div id="app">
<component :is="layout">
<router-view />
</component>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
import { SET_USER_INFO } from '@/store/auth.store'
import { initUserRole } from '@/utils/userRole'
import BlackLayout from '@/layouts/black.layout'
import DefaultLayout from '@/layouts/default.layout'
import NoSidebarLayout from '@/layouts/no-sidebar.layout'
export default {
components: {
BlackLayout,
DefaultLayout,
NoSidebarLayout
},
data() {
return {
}
},
computed: {
layout() {
return this.$route.meta.layout || 'DefaultLayout'
}
},
created() {
this.setUserInfo({
'loginName': 'admin',
'id': '1',
'phone': '17729389320',
'email': '17728389320@163.com',
'enableStatus': 'ENABLED',
'headPortrait': null,
'userName': '赵站洋',
'credentialNo': '110101199003076675',
'gender': 'male'
})
// localStorage.setItem('logedUser', '100771325211655012352')
},
mounted() {
//
this.$nextTick(() => {
initUserRole(this).catch((err) => {
console.error('初始化用户角色信息失败:', err)
})
})
},
methods: {
...mapMutations('authModule', {
setUserInfo: SET_USER_INFO
})
}
}
</script>
<style lang="scss">
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: $--app-font-color;
background-color: $--app-bg-Color;
}
</style>

View File

@ -1,46 +1,46 @@
/*
* @Author: your name
* @Date: 2020-05-30 16:05:14
* @LastEditTime: 2020-05-30 19:20:52
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/account/index.js
*/
export default {
'USER_LOGIN': { // 用户登录
url: '/xdap-admin/user/login',
method: 'post'
},
'USER_REGISTER': { // 用户注册
url: '/xdap-admin/user/register',
method: 'post'
},
'USER_MODIFY_PASSWORD_BY_PHONE': { // 通过手机号修改密码
url: '/xdap-admin/user/find/password',
method: 'post'
},
'CREATE_ORG': { // 创建组织
url: '/xdap-admin/tenant/add/newTenant',
method: 'post'
},
'JOIN_ORG': {
url: '/xdap-admin/tenant/join/tenant',
method: 'get'
},
'SING_OUT': {
url: '/xdap-admin/user/signOut',
method: 'get'
},
'UPDATE_USER_PHONE': {
url: '/xdap-admin/user/update/userPhone',
method: 'post'
},
'UPDATE_USER_EMAIL': {
url: '/xdap-admin/user/update/userEmail',
method: 'post'
},
'IS_BELONG_TO_TENANT': {
url: '/xdap-admin/tenant/query/isBelongToTenant',
method: 'get'
}
}
/*
* @Author: your name
* @Date: 2020-05-30 16:05:14
* @LastEditTime: 2020-05-30 19:20:52
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/account/index.js
*/
export default {
'USER_LOGIN': { // 用户登录
url: '/xdap-admin/user/login',
method: 'post'
},
'USER_REGISTER': { // 用户注册
url: '/xdap-admin/user/register',
method: 'post'
},
'USER_MODIFY_PASSWORD_BY_PHONE': { // 通过手机号修改密码
url: '/xdap-admin/user/find/password',
method: 'post'
},
'CREATE_ORG': { // 创建组织
url: '/xdap-admin/tenant/add/newTenant',
method: 'post'
},
'JOIN_ORG': {
url: '/xdap-admin/tenant/join/tenant',
method: 'get'
},
'SING_OUT': {
url: '/xdap-admin/user/signOut',
method: 'get'
},
'UPDATE_USER_PHONE': {
url: '/xdap-admin/user/update/userPhone',
method: 'post'
},
'UPDATE_USER_EMAIL': {
url: '/xdap-admin/user/update/userEmail',
method: 'post'
},
'IS_BELONG_TO_TENANT': {
url: '/xdap-admin/tenant/query/isBelongToTenant',
method: 'get'
}
}

View File

@ -1,167 +1,167 @@
export default {
// 获取组织列表
QUERY_ORG_LIST_BY_NAME: {
url: '/xdap-app/department/query/departmentListByName',
method: 'post',
disableSuccessMsg: true
},
// 组织树
QUERY_ORG_TREE: {
url: '/xdap-app/department/query/departmentTree',
method: 'post',
disableSuccessMsg: true
},
// 新增部门
ADD_AND_EDIT_ORG: {
url: '/xdap-app/department/edit/department',
method: 'post'
},
// 删除部门
DELETE_ORG: {
url: '/xdap-app/department/remove/department',
method: 'post'
},
// 根据节点查询成员
QUERY_MEMBER_BY_ORG_ID: {
url: '/xdap-app/department/query/departmentMembers',
method: 'post',
disableSuccessMsg: true
},
QUERY_ALL_MEMBER_BY_ORG_ID: {
url: '/xdap-app/department/queryAll/departmentMembers',
method: 'post',
disableSuccessMsg: true
},
// 上级部门值列表
QUERY_DEPARTMENT_LIST: {
url: '/xdap-app/department/query/departmentList',
method: 'post',
disableSuccessMsg: true
},
// 人员移出部门
REMOVE_USER_FORM_ORG: {
url: '/xdap-app/department/remove/departmentMember',
method: 'post'
},
// 批量移出zu
ALL_REMOVE_USER_FORM_ORG: {
url: '/xdap-app/department/batchRemove/departmentMember',
method: 'post'
},
// 人员移出组织
REMOVE_USER_FORM_TENANT: {
url: '/xdap-app/department/remove/tenantMember',
method: 'post'
},
// 批量移出组织
ALL_REMOVE_USER_FORM_TENANT: {
url: '/xdap-app/department/batchRemove/tenantMember',
method: 'post'
},
// 修改在职/离职
CHANGE_WORK_STATUS: {
url: '/xdap-app/department/update/memberWorkStatus',
method: 'post'
},
// 批量修改在职/离职
ALL_CHANGE_WORK_STATUS: {
url: '/xdap-app/department/batchUpdate/memberWorkStatus',
method: 'post'
},
// 邀请部分接口
QUERY_DATA_INVITE: {
url: '/xdap-app/invitation/get/invitationCodeInfo',
method: 'post',
disableSuccessMsg: true
},
// 重新生成邀请码
RELOAD_DATA_INVITE: {
url: '/xdap-app/invitation/generate/invitationCode',
method: 'post'
},
SAVE_INVITE_CONFIG: {
url: '/xdap-app/invitation/modify/invitationCode',
method: 'post',
disableSuccessMsg: true
},
// 设置是否启用邀请码
SHOW_INVITE_BY_STATUS: {
url: '/xdap-app/invitation/update/invitationCodeStatus',
method: 'post',
disableSuccessMsg: true
},
// 组织树拖拽
TREE_NODE_MOVE: {
url: '/xdap-app/department/queue/departmentTree',
method: 'post',
disableSuccessMsg: true
},
// 获取待审核条数
GET_AUDIT_COUNT: {
url: '/xdap-app/invitation/count/approvingUsers',
method: 'post',
disableSuccessMsg: true
},
// 获取待审核成员信息
QUERY_AUDIT_TABLE_DATA: {
url: '/xdap-app/invitation/query/approvingUsers',
method: 'post',
disableSuccessMsg: true
},
// 拒绝
REFUSE_ADD_USER: {
url: '/xdap-app/invitation/refuse/approvingUser',
method: 'post'
},
// 同意
AGREE_ADD_USER: {
url: '/xdap-app/invitation/agree/approvingUser',
method: 'post'
},
// 批量同意
ALL_AGREE_ADD_USER: {
url: '/xdap-app/invitation/batchAgree/approvingUser',
method: 'post'
},
// 批量拒绝
ALL_REFUSE_ADD_USER: {
url: '/xdap-app/invitation/batchRefuse/approvingUser',
method: 'post'
},
// 编辑成员信息
EDIT_USER_DATA: {
url: '/xdap-app/department/update/memberInfo',
method: 'post'
},
DEPARTMENT_ADD_USERS: {
url: '/xdap-app/department/add/departmentMember',
method: 'post'
},
// 查询短信条数
QUERY_SMS_DATA_LIST: {
url: '/xdap-app/noticeHistory/query/smsLogHistoryList',
method: 'post',
disableSuccessMsg: true
},
// 查询邮件发送记录
QUERY_EMAIL_DATA_LIST: {
url: '/xdap-app/noticeHistory/query/emailLogHistoryList',
method: 'post',
disableSuccessMsg: true
},
// 导出短信发送记录
EXPORT_LIST_SMS_DATA: {
url: '/xdap-app/noticeHistory/export/smsLogHistory',
method: 'get'
},
// 导出邮件发送记录
EXPORT_LIST_EMAIL_DATA: {
url: '/xdap-app/noticeHistory/export/emailLogHistory',
method: 'get'
},
// 员工工作的转交
TRANSFER_USER_WORK: {
url: '/xdap-app/work/update/workTransfer',
method: 'post'
}
}
export default {
// 获取组织列表
QUERY_ORG_LIST_BY_NAME: {
url: '/xdap-app/department/query/departmentListByName',
method: 'post',
disableSuccessMsg: true
},
// 组织树
QUERY_ORG_TREE: {
url: '/xdap-app/department/query/departmentTree',
method: 'post',
disableSuccessMsg: true
},
// 新增部门
ADD_AND_EDIT_ORG: {
url: '/xdap-app/department/edit/department',
method: 'post'
},
// 删除部门
DELETE_ORG: {
url: '/xdap-app/department/remove/department',
method: 'post'
},
// 根据节点查询成员
QUERY_MEMBER_BY_ORG_ID: {
url: '/xdap-app/department/query/departmentMembers',
method: 'post',
disableSuccessMsg: true
},
QUERY_ALL_MEMBER_BY_ORG_ID: {
url: '/xdap-app/department/queryAll/departmentMembers',
method: 'post',
disableSuccessMsg: true
},
// 上级部门值列表
QUERY_DEPARTMENT_LIST: {
url: '/xdap-app/department/query/departmentList',
method: 'post',
disableSuccessMsg: true
},
// 人员移出部门
REMOVE_USER_FORM_ORG: {
url: '/xdap-app/department/remove/departmentMember',
method: 'post'
},
// 批量移出zu
ALL_REMOVE_USER_FORM_ORG: {
url: '/xdap-app/department/batchRemove/departmentMember',
method: 'post'
},
// 人员移出组织
REMOVE_USER_FORM_TENANT: {
url: '/xdap-app/department/remove/tenantMember',
method: 'post'
},
// 批量移出组织
ALL_REMOVE_USER_FORM_TENANT: {
url: '/xdap-app/department/batchRemove/tenantMember',
method: 'post'
},
// 修改在职/离职
CHANGE_WORK_STATUS: {
url: '/xdap-app/department/update/memberWorkStatus',
method: 'post'
},
// 批量修改在职/离职
ALL_CHANGE_WORK_STATUS: {
url: '/xdap-app/department/batchUpdate/memberWorkStatus',
method: 'post'
},
// 邀请部分接口
QUERY_DATA_INVITE: {
url: '/xdap-app/invitation/get/invitationCodeInfo',
method: 'post',
disableSuccessMsg: true
},
// 重新生成邀请码
RELOAD_DATA_INVITE: {
url: '/xdap-app/invitation/generate/invitationCode',
method: 'post'
},
SAVE_INVITE_CONFIG: {
url: '/xdap-app/invitation/modify/invitationCode',
method: 'post',
disableSuccessMsg: true
},
// 设置是否启用邀请码
SHOW_INVITE_BY_STATUS: {
url: '/xdap-app/invitation/update/invitationCodeStatus',
method: 'post',
disableSuccessMsg: true
},
// 组织树拖拽
TREE_NODE_MOVE: {
url: '/xdap-app/department/queue/departmentTree',
method: 'post',
disableSuccessMsg: true
},
// 获取待审核条数
GET_AUDIT_COUNT: {
url: '/xdap-app/invitation/count/approvingUsers',
method: 'post',
disableSuccessMsg: true
},
// 获取待审核成员信息
QUERY_AUDIT_TABLE_DATA: {
url: '/xdap-app/invitation/query/approvingUsers',
method: 'post',
disableSuccessMsg: true
},
// 拒绝
REFUSE_ADD_USER: {
url: '/xdap-app/invitation/refuse/approvingUser',
method: 'post'
},
// 同意
AGREE_ADD_USER: {
url: '/xdap-app/invitation/agree/approvingUser',
method: 'post'
},
// 批量同意
ALL_AGREE_ADD_USER: {
url: '/xdap-app/invitation/batchAgree/approvingUser',
method: 'post'
},
// 批量拒绝
ALL_REFUSE_ADD_USER: {
url: '/xdap-app/invitation/batchRefuse/approvingUser',
method: 'post'
},
// 编辑成员信息
EDIT_USER_DATA: {
url: '/xdap-app/department/update/memberInfo',
method: 'post'
},
DEPARTMENT_ADD_USERS: {
url: '/xdap-app/department/add/departmentMember',
method: 'post'
},
// 查询短信条数
QUERY_SMS_DATA_LIST: {
url: '/xdap-app/noticeHistory/query/smsLogHistoryList',
method: 'post',
disableSuccessMsg: true
},
// 查询邮件发送记录
QUERY_EMAIL_DATA_LIST: {
url: '/xdap-app/noticeHistory/query/emailLogHistoryList',
method: 'post',
disableSuccessMsg: true
},
// 导出短信发送记录
EXPORT_LIST_SMS_DATA: {
url: '/xdap-app/noticeHistory/export/smsLogHistory',
method: 'get'
},
// 导出邮件发送记录
EXPORT_LIST_EMAIL_DATA: {
url: '/xdap-app/noticeHistory/export/emailLogHistory',
method: 'get'
},
// 员工工作的转交
TRANSFER_USER_WORK: {
url: '/xdap-app/work/update/workTransfer',
method: 'post'
}
}

View File

@ -1,151 +1,151 @@
/**
* @Author: your name
* @Date: 2020-06-12 12:19:21
* @LastEditTime: 2020-06-13 17:19:01
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-project-app/src/api/app-page/index.js
*/
export default {
QUERY_LIST_PAGE_CONFIG_BY_ID: {
url: '/xdap-app/form/query/listPageConfigById',
method: 'get',
disableSuccessMsg: true
},
QUERY_LIST_PAGE_CONFIG_BY_TAB_ID: {
url: '/xdap-app/form/query/listPageViewDetail',
method: 'get',
disableSuccessMsg: true
},
QUERY_LIST_BUSINESS_DATA: {
url: '/xdap-app/business/query/listPageBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_CALC_LIST_BUSINESS_DATA: {
url: '/xdap-app/business/query/virtualBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_LIST_PAGE_BUTTON: {
url: '/xdap-app/form/query/listPageButton',
method: 'get',
disableSuccessMsg: true
},
// 数据导出
EXPORT_LIST_TO_EXCEL: {
url: 'xdap-app/excel/export/excelData',
method: 'post',
disableSuccessMsg: true
},
// 统计接口
STATISTICAL_TABLE: {
url: '/xdap-app/business/query/calAggregate',
method: 'post',
disableSuccessMsg: true
},
// 数据导入下载模板接口
EXPORT_TEMPLATE_TO_EXCEL: {
url: '/xdap-app/excel/export/excelTemplate',
method: 'get',
disableSuccessMsg: true
},
// 数据导入上传接口
IMPORT_EXCEL_DATA: {
url: '/xdap-app/excel/importExcelData',
method: 'post',
disableSuccessMsg: true
},
// 异常数据查询
EXCEL_IMPORT_LOGS: {
url: '/xdap-app/excel/query/excelImportLogs',
method: 'get',
disableSuccessMsg: true
},
ADD_MENU_COLLECT: {
url: '/xdap-app/menu/add/star',
method: 'post'
},
REMOVE_MENU_COLLECT: {
url: '/xdap-app/menu/remove/star',
method: 'post'
},
HAS_MENU_COLLECT: {
url: '/xdap-app/menu/has/menuStar',
method: 'post',
disableSuccessMsg: true
},
// 批量删除接口
BATCH_DELETE_DATA: {
url: '/xdap-app/business/delete/batchDocument',
method: 'post',
timeout: 1000 * 60 * 1
},
// 批量同意接口
BATCH_AGREE_DATA: {
url: '/xdap-app/process/batch/approve',
method: 'post',
timeout: 1000 * 600 * 1
},
// 批量拒绝接口
BATCH_REJECT_DATA: {
url: '/xdap-app/process/batch/reject',
method: 'post',
timeout: 1000 * 600 * 1
},
QUERY_STATISTICS_VALUE_COLUME: {
url: '/xdap-app/business/query/dataStatisticValue',
method: 'post',
disableSuccessMsg: true
},
QUERY_TREE_VIEW_TREE_NODE: {
url: '/xdap-app/business/query/treeNodeBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_TREE_VIEW_TREE_TABLE_DATA: {
url: '/xdap-app/business/query/childNodeListBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_OPERATION_COLUMN: {
url: '/xdap-app/form/query/listButton',
method: 'post',
disableSuccessMsg: true
},
// 查询聚合表列表配置
QUERY_COMBINE_LIST_PAGE_VIEW: {
url: '/xdap-app/query/combineListPageView',
method: 'get',
disableSuccessMsg: true
},
// 聚合表查询数据接口
QUERY_COMBINE_LIST_BUSINESSDATA: {
url: '/xdap-app/query/queryCombineListBusinessData',
method: 'post',
disableSuccessMsg: true
},
// 查询聚合表组件
QUERY_COMBINE_COMPONENT: {
url: '/xdap-app/query/combineComponent',
method: 'post',
disableSuccessMsg: true
},
// 聚合表按钮查询
QUERY_COMBINE_LISTBUTTON: {
url: '/xdap-app/query/combineListButton',
method: 'get',
disableSuccessMsg: true
},
QUERY_ADVANCE_SEARCH: {
url: '/xdap-app/dataFilter/query/dataFilter',
method: 'get',
disableSuccessMsg: true
},
// * 新的表单字段查询接口
QUERY_FORM_FIELD_ALL_IN_ONE: {
url: '/xdap-app/form/query/formComponent',
method: 'post',
disableSuccessMsg: true
}
}
/**
* @Author: your name
* @Date: 2020-06-12 12:19:21
* @LastEditTime: 2020-06-13 17:19:01
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-project-app/src/api/app-page/index.js
*/
export default {
QUERY_LIST_PAGE_CONFIG_BY_ID: {
url: '/xdap-app/form/query/listPageConfigById',
method: 'get',
disableSuccessMsg: true
},
QUERY_LIST_PAGE_CONFIG_BY_TAB_ID: {
url: '/xdap-app/form/query/listPageViewDetail',
method: 'get',
disableSuccessMsg: true
},
QUERY_LIST_BUSINESS_DATA: {
url: '/xdap-app/business/query/listPageBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_CALC_LIST_BUSINESS_DATA: {
url: '/xdap-app/business/query/virtualBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_LIST_PAGE_BUTTON: {
url: '/xdap-app/form/query/listPageButton',
method: 'get',
disableSuccessMsg: true
},
// 数据导出
EXPORT_LIST_TO_EXCEL: {
url: 'xdap-app/excel/export/excelData',
method: 'post',
disableSuccessMsg: true
},
// 统计接口
STATISTICAL_TABLE: {
url: '/xdap-app/business/query/calAggregate',
method: 'post',
disableSuccessMsg: true
},
// 数据导入下载模板接口
EXPORT_TEMPLATE_TO_EXCEL: {
url: '/xdap-app/excel/export/excelTemplate',
method: 'get',
disableSuccessMsg: true
},
// 数据导入上传接口
IMPORT_EXCEL_DATA: {
url: '/xdap-app/excel/importExcelData',
method: 'post',
disableSuccessMsg: true
},
// 异常数据查询
EXCEL_IMPORT_LOGS: {
url: '/xdap-app/excel/query/excelImportLogs',
method: 'get',
disableSuccessMsg: true
},
ADD_MENU_COLLECT: {
url: '/xdap-app/menu/add/star',
method: 'post'
},
REMOVE_MENU_COLLECT: {
url: '/xdap-app/menu/remove/star',
method: 'post'
},
HAS_MENU_COLLECT: {
url: '/xdap-app/menu/has/menuStar',
method: 'post',
disableSuccessMsg: true
},
// 批量删除接口
BATCH_DELETE_DATA: {
url: '/xdap-app/business/delete/batchDocument',
method: 'post',
timeout: 1000 * 60 * 1
},
// 批量同意接口
BATCH_AGREE_DATA: {
url: '/xdap-app/process/batch/approve',
method: 'post',
timeout: 1000 * 600 * 1
},
// 批量拒绝接口
BATCH_REJECT_DATA: {
url: '/xdap-app/process/batch/reject',
method: 'post',
timeout: 1000 * 600 * 1
},
QUERY_STATISTICS_VALUE_COLUME: {
url: '/xdap-app/business/query/dataStatisticValue',
method: 'post',
disableSuccessMsg: true
},
QUERY_TREE_VIEW_TREE_NODE: {
url: '/xdap-app/business/query/treeNodeBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_TREE_VIEW_TREE_TABLE_DATA: {
url: '/xdap-app/business/query/childNodeListBusinessData',
method: 'post',
disableSuccessMsg: true
},
QUERY_OPERATION_COLUMN: {
url: '/xdap-app/form/query/listButton',
method: 'post',
disableSuccessMsg: true
},
// 查询聚合表列表配置
QUERY_COMBINE_LIST_PAGE_VIEW: {
url: '/xdap-app/query/combineListPageView',
method: 'get',
disableSuccessMsg: true
},
// 聚合表查询数据接口
QUERY_COMBINE_LIST_BUSINESSDATA: {
url: '/xdap-app/query/queryCombineListBusinessData',
method: 'post',
disableSuccessMsg: true
},
// 查询聚合表组件
QUERY_COMBINE_COMPONENT: {
url: '/xdap-app/query/combineComponent',
method: 'post',
disableSuccessMsg: true
},
// 聚合表按钮查询
QUERY_COMBINE_LISTBUTTON: {
url: '/xdap-app/query/combineListButton',
method: 'get',
disableSuccessMsg: true
},
QUERY_ADVANCE_SEARCH: {
url: '/xdap-app/dataFilter/query/dataFilter',
method: 'get',
disableSuccessMsg: true
},
// * 新的表单字段查询接口
QUERY_FORM_FIELD_ALL_IN_ONE: {
url: '/xdap-app/form/query/formComponent',
method: 'post',
disableSuccessMsg: true
}
}

View File

@ -1,24 +1,24 @@
/*
* @Author: your name
* @Date: 2020-05-30 16:05:14
* @LastEditTime: 2020-05-30 20:13:11
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/common.js
*/
export default {
'SEND_PHONE_CODE': { // 发送手机验证码
url: '/xdap-admin/user/send/smsCode',
method: 'post'
},
'SEND_EMAIL_CODE': { // 发送邮箱验证码
url: '/xdap-admin/user/send/emailCode',
method: 'post'
},
// 切换租户保存租户信息
'SAVE_ORG_ID_BY_CHANGE': {
url: '/xdap-admin/tenant/switch/tenant',
method: 'post',
disableSuccessMsg: true
}
}
/*
* @Author: your name
* @Date: 2020-05-30 16:05:14
* @LastEditTime: 2020-05-30 20:13:11
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/common.js
*/
export default {
'SEND_PHONE_CODE': { // 发送手机验证码
url: '/xdap-admin/user/send/smsCode',
method: 'post'
},
'SEND_EMAIL_CODE': { // 发送邮箱验证码
url: '/xdap-admin/user/send/emailCode',
method: 'post'
},
// 切换租户保存租户信息
'SAVE_ORG_ID_BY_CHANGE': {
url: '/xdap-admin/tenant/switch/tenant',
method: 'post',
disableSuccessMsg: true
}
}

View File

@ -1,52 +1,52 @@
export default {
ENGINE_CHECK_LIST: {
url: '/custom/activiti/showEngReview',
method: 'post'
},
START_ENGINE_CHECK: {
url: '/custom/activiti/startActiviti',
method: 'post'
},
HANDLE_ENGINE_CHECK: {
url: '/custom/activiti/handleApproval',
method: 'post'
},
// 撤回
RETURN_ENGINE_CHECK: {
url: '/custom/activiti/returnApproval',
method: 'get'
},
GET_ENGINE_CHECK_DETAIL: {
url: '/custom/activiti/showActiviti',
method: 'post'
},
CHANGE_ENGINE_DATA: {
url: '/custom/activiti/initiateApproval',
method: 'get'
},
// 审批相关接口
CHECK_DATA_CAN_RETURN: {
url: '/custom/activiti/getIsDirect',
method: 'get'
},
GET_DATA_APPROVAL_USERS: {
url: '/custom/activiti/getApprovalUsers',
method: 'get'
},
RESEND_DATA_APPROVAL: {
url: '/custom/activiti/directSendingApproval',
method: 'get'
},
GET_CAN_RETURN_DATA_NODE: {
url: '/custom/activiti/getReturnNodes',
method: 'get'
},
CAN_RETURN_DATA_NODE: {
url: '/custom/activiti/handleReturnToNode',
method: 'post'
},
RESTART_DATA_APPROVAL: {
url: '/custom/activiti/handleReturn',
method: 'post'
}
}
export default {
ENGINE_CHECK_LIST: {
url: '/custom/activiti/showEngReview',
method: 'post'
},
START_ENGINE_CHECK: {
url: '/custom/activiti/startActiviti',
method: 'post'
},
HANDLE_ENGINE_CHECK: {
url: '/custom/activiti/handleApproval',
method: 'post'
},
// 撤回
RETURN_ENGINE_CHECK: {
url: '/custom/activiti/returnApproval',
method: 'get'
},
GET_ENGINE_CHECK_DETAIL: {
url: '/custom/activiti/showActiviti',
method: 'post'
},
CHANGE_ENGINE_DATA: {
url: '/custom/activiti/initiateApproval',
method: 'get'
},
// 审批相关接口
CHECK_DATA_CAN_RETURN: {
url: '/custom/activiti/getIsDirect',
method: 'get'
},
GET_DATA_APPROVAL_USERS: {
url: '/custom/activiti/getApprovalUsers',
method: 'get'
},
RESEND_DATA_APPROVAL: {
url: '/custom/activiti/directSendingApproval',
method: 'get'
},
GET_CAN_RETURN_DATA_NODE: {
url: '/custom/activiti/getReturnNodes',
method: 'get'
},
CAN_RETURN_DATA_NODE: {
url: '/custom/activiti/handleReturnToNode',
method: 'post'
},
RESTART_DATA_APPROVAL: {
url: '/custom/activiti/handleReturn',
method: 'post'
}
}

View File

@ -1,138 +1,150 @@
export default {
// 添加模板
ADD_MODEL: {
url: '/custom/template/insertTemplate',
method: 'post'
},
// 模板管理列表
GET_MODEL_LIST: {
url: '/custom/template/getTemplateByCondition',
method: 'get'
},
// 导入模板
IMPORT_MODEL: {
url: '/custom/template/import',
method: 'post'
},
// 修改模板
EDIT_MODEL: {
url: '/custom/template/updateTemplate',
method: 'post'
},
// 查看版本
CHECK_MODEL_VERISON: {
url: '/custom/template/getTemplateVersion',
method: 'get'
},
// 下载
DOWNLODE_MODEL: {
url: '/custom/template/export',
method: 'get'
},
DOWNLODE_ALL_MODEL: {
url: '/custom/template/exportMultiple',
method: 'get'
},
// 获取部门
GET_DEPARTMENT: {
url: '/custom/template/getDept',
method: 'get'
},
// 查询详情
GET_MODEL_DETAIL: {
url: '/custom/parameter/getParameterByCondition',
method: 'get'
},
// 添加参数
ADD_MODEL_PARAM: {
url: '/custom/parameter/insertParameter',
method: 'post'
},
// 维护参数
EDIT_MODEL_PARAM: {
url: '/custom/parameter/maintenanceParameters',
method: 'post'
},
DELETE_MODEL_PARAM: {
url: '/custom/parameter/deleteParameter',
method: 'get'
},
START_APPROVAL: {
url: '/custom/approval/startApproval',
method: 'post'
},
GET_APPROVAL_LIST: {
url: '/custom/approval/getApprovalList',
method: 'get'
},
HANDLE_APPROVAL: {
url: '/custom/approval/handleApproval',
method: 'post'
},
// 获取审批详情
// GET_APPROVAL_DETAIL: {
// url: '/custom/approval/getApprovalDetail',
// method: 'get'
// },
// 获取所有人
GET_ALLUSERS: {
url: '/custom/approval/getUsersByCondition',
method: 'get'
},
// 获取审批变更
GET_APPROVAL_CHANGE: {
url: '/custom/approval/getTemplateChanges',
method: 'get'
},
// 获取审批所有
GET_PPROVAL_ALL: {
url: '/custom/approval/getApprovalProcess',
method: 'get'
},
GET_SUB_DEPT: {
url: '/custom/responsible/getSubDepartmentById',
method: 'get'
},
// 处理模板审批撤回
RETURN_APPROVAL: {
url: '/custom/approval/handleReturn',
method: 'post'
},
RETURN_MODEL_APPROVAL: {
url: '/custom/approval/handleReturnToNode',
method: 'post'
},
RESTART_MODEL_APPROVAL: {
url: '/custom/approval/directSendingApproval',
method: 'get'
},
GET_CAN_RETURN_NODE: {
url: '/custom/approval/getReturnNodes',
method: 'get'
},
GET_RETURN_APPROVAL: {
url: '/custom/approval/getApprovalUsers',
method: 'get'
},
GET_CAN_RESEND_APPROVAL: {
url: '/custom/approval/getIsDirect?',
method: 'get'
},
EDIT_APPROVAL_PROCESS_TITLE: {
url: '/custom/approval/updateFlowTitle',
method: 'get'
},
EDIT_APPROVAL_PROCESS: {
url: '/custom/approval/updateNode',
method: 'post'
},
CONTINUE_APPROVAL_PROCESS: {
url: '/custom/approval/continueApproval',
method: 'get'
},
GET_DEPT_OF_USER: {
url: '/custom/responsible/getResponsibleDepartment',
method: 'get'
}
}
export default {
// 添加模板
ADD_MODEL: {
url: '/custom/template/insertTemplate',
method: 'post'
},
// 模板管理列表
GET_MODEL_LIST: {
url: '/custom/template/getTemplateByCondition',
method: 'get'
},
// 导入模板
IMPORT_MODEL: {
url: '/custom/template/import',
method: 'post'
},
// 修改模板
EDIT_MODEL: {
url: '/custom/template/updateTemplate',
method: 'post'
},
// 查看版本
CHECK_MODEL_VERISON: {
url: '/custom/template/getTemplateVersion',
method: 'get'
},
// 下载
DOWNLODE_MODEL: {
url: '/custom/template/export',
method: 'get'
},
DOWNLODE_ALL_MODEL: {
url: '/custom/template/exportMultiple',
method: 'get'
},
// 获取部门
GET_DEPARTMENT: {
url: '/custom/template/getDept',
method: 'get'
},
// 查询详情
GET_MODEL_DETAIL: {
url: '/custom/parameter/getParameterByCondition',
method: 'get'
},
// 添加参数
ADD_MODEL_PARAM: {
url: '/custom/parameter/insertParameter',
method: 'post'
},
// 维护参数
EDIT_MODEL_PARAM: {
url: '/custom/parameter/maintenanceParameters',
method: 'post'
},
DELETE_MODEL_PARAM: {
url: '/custom/parameter/deleteParameter',
method: 'get'
},
START_APPROVAL: {
url: '/custom/approval/startApproval',
method: 'post'
},
GET_APPROVAL_LIST: {
url: '/custom/approval/getApprovalList',
method: 'get'
},
HANDLE_APPROVAL: {
url: '/custom/approval/handleApproval',
method: 'post'
},
// 获取审批详情
// GET_APPROVAL_DETAIL: {
// url: '/custom/approval/getApprovalDetail',
// method: 'get'
// },
// 获取所有人
GET_ALLUSERS: {
url: '/custom/approval/getUsersByCondition',
method: 'get'
},
// 获取审批变更
GET_APPROVAL_CHANGE: {
url: '/custom/approval/getTemplateChanges',
method: 'get'
},
// 获取审批所有
GET_PPROVAL_ALL: {
url: '/custom/approval/getApprovalProcess',
method: 'get'
},
GET_SUB_DEPT: {
url: '/custom/responsible/getSubDepartmentById',
method: 'get'
},
// 处理模板审批撤回
RETURN_APPROVAL: {
url: '/custom/approval/handleReturn',
method: 'post'
},
RETURN_MODEL_APPROVAL: {
url: '/custom/approval/handleReturnToNode',
method: 'post'
},
RESTART_MODEL_APPROVAL: {
url: '/custom/approval/directSendingApproval',
method: 'get'
},
GET_CAN_RETURN_NODE: {
url: '/custom/approval/getReturnNodes',
method: 'get'
},
GET_RETURN_APPROVAL: {
url: '/custom/approval/getApprovalUsers',
method: 'get'
},
GET_CAN_RESEND_APPROVAL: {
url: '/custom/approval/getIsDirect?',
method: 'get'
},
EDIT_APPROVAL_PROCESS_TITLE: {
url: '/custom/approval/updateFlowTitle',
method: 'get'
},
EDIT_APPROVAL_PROCESS: {
url: '/custom/approval/updateNode',
method: 'post'
},
CONTINUE_APPROVAL_PROCESS: {
url: '/custom/approval/continueApproval',
method: 'get'
},
GET_DEPT_OF_USER: {
url: '/custom/responsible/getResponsibleDepartment',
method: 'get'
},
UPDATE_TEMPLATE_ORDER: {
url: '/custom/template/batchUpdateTemplateOrder',
method: 'post'
},
BATCH_UPDATE_DEPARTMENT: {
url: '/custom/todoTaskPojo/batchUpdateDepartment',
method: 'post'
},
SAVE_FILLED_BY_TEMP: {
url: '/custom/engineParamDetailPojo/saveFilledByTemp',
method: 'post'
}
}

View File

@ -1,68 +1,83 @@
export default {
// 权限管理相关接口
// 获取权限管理列表
GET_PERMISSION_DATA: {
url: '/custom/permission/getUserRoleAndPermission',
method: 'get'
},
// 保存权限管理
SAVE_PERMISSION_DATA: {
url: '/custom/permission/insertRole',
method: 'post'
},
// 修改权限管理
EDIT_PERMISSION_DATA: {
url: '/custom/permission/updatePermission',
method: 'post'
},
// 删除权限管理
DELETE_PERMISSION_DATA: {
url: '/custom/permission/deletePermission',
method: 'get'
},
// 获取所有权限表
GET_ALL_PERMISSION_LIST: {
url: '/custom/permission/getAllPermission',
method: 'get'
},
DELETE_ROLE_DATA: {
url: '/custom/permission/deleteRole',
method: 'get'
},
CHECK_ROLE_USER_DEPT: {
url: '/custom/permission/selectUserOrDeptByRole',
method: 'get'
},
GET_NOW_USER_ROLE: {
url: '/custom/permission/selectPermByUserId',
method: 'get'
},
ADD_ROLE_PERMISSION: {
url: '/custom/permission/addRoles',
method: 'post'
},
GET_ROLE_PERMISSION: {
url: '/custom/permission/selectRoles',
method: 'get'
},
DELETE_ROLE_PERMISSION: {
url: '/custom/permission/removeRoles',
method: 'get'
},
GET_ROLE_PERMISSION_BING: {
url: '/custom/permission/userRoleBinding',
method: 'post'
},
GET_SUB_SYSTEM_DATA_LIST: {
url: '/custom/permission/getAllParameters',
method: 'get'
},
EDIT_ROLE_CONTROL_LIST: {
url: '/custom/permission/updatePerForRole',
method: 'post'
},
GET_ROLE_CONTROL_LIST: {
url: '/custom/permission/selectPersByRole',
method: 'get'
}
}
export default {
// 权限管理相关接口
// 获取权限管理列表
GET_PERMISSION_DATA: {
url: '/custom/permission/getUserRoleAndPermission',
method: 'get'
},
// 保存权限管理
SAVE_PERMISSION_DATA: {
url: '/custom/permission/insertRole',
method: 'post'
},
// 修改权限管理
EDIT_PERMISSION_DATA: {
url: '/custom/permission/updatePermission',
method: 'post'
},
// 删除权限管理
DELETE_PERMISSION_DATA: {
url: '/custom/permission/deletePermission',
method: 'get'
},
// 获取所有权限表
GET_ALL_PERMISSION_LIST: {
url: '/custom/permission/getAllPermission',
method: 'get'
},
DELETE_ROLE_DATA: {
url: '/custom/permission/deleteRole',
method: 'get'
},
CHECK_ROLE_USER_DEPT: {
url: '/custom/permission/selectUserOrDeptByRole',
method: 'get'
},
GET_NOW_USER_ROLE: {
url: '/custom/permission/selectPermByUserId',
method: 'get'
},
ADD_ROLE_PERMISSION: {
url: '/custom/permission/addRoles',
method: 'post'
},
GET_ROLE_PERMISSION: {
url: '/custom/permission/selectRoles',
method: 'get'
},
DELETE_ROLE_PERMISSION: {
url: '/custom/permission/removeRoles',
method: 'get'
},
GET_ROLE_PERMISSION_BING: {
url: '/custom/permission/userRoleBinding',
method: 'post'
},
GET_SUB_SYSTEM_DATA_LIST: {
url: '/custom/permission/getAllParameters',
method: 'get'
},
EDIT_ROLE_CONTROL_LIST: {
url: '/custom/permission/updatePerForRole',
method: 'post'
},
GET_ROLE_CONTROL_LIST: {
url: '/custom/permission/selectPersByRole',
method: 'get'
},
// 获取角色成员列表
GET_ROLE_MEMBERS: {
url: '/custom/permission/getRoleMembers',
method: 'get'
},
// 添加角色成员
ADD_ROLE_MEMBERS: {
url: '/custom/permission/addRoleMembers',
method: 'post'
},
// 删除角色成员
DELETE_ROLE_MEMBERS: {
url: '/custom/permission/deleteRoleMembers',
method: 'post'
}
}

View File

@ -1,70 +1,70 @@
export default {
GET_REPORT_LIST: {
url: '/custom/benchmark/getReportAndTodoByCondition',
method: 'post'
},
GET_REPORT_LIST_BY_CONDITION: {
url: '/custom/benchmark/getApprovalList',
method: 'post'
},
ADD_REPORT: {
url: '/custom/benchmark/startReportApproval',
method: 'post'
},
SAVE_REPORT: {
url: '/custom/benchmark/insertReport',
method: 'post'
},
EDIT_REPORT: {
url: '/custom/benchmark/updateReport',
method: 'post'
},
RESTART_REPORT_APPROVAL: {
url: '/custom/benchmark/restartReportApproval',
method: 'post'
},
START_REPORT_APPROVAL: {
url: '/custom/benchmark/handleReportApproval',
method: 'post'
},
GET_REPORT_DETAIL: {
url: '/custom/benchmark/getReportDetail',
method: 'get'
},
GET_REPORT_DETAIL_PROCESS: {
url: '/custom/benchmark/getReportProcess',
method: 'get'
},
DOWNLOAD_REPORT: {
url: '/custom/benchmark/downloadReport',
method: 'get'
},
DELETE_REPORT: {
url: '/custom/benchmark/deleteReport',
method: 'get'
},
RETURN_REPORT: {
url: '/custom/benchmark/handleReturn',
method: 'post'
},
RESTART_REPORT_TODO: {
url: '/custom/benchmark/restartApproval',
method: 'get'
},
RESEND_REPORT_APPROVAL: {
url: '/custom/benchmark/directSendingApproval',
method: 'get'
},
RETURN_REPORT_TODO: {
url: '/custom/benchmark/handleReturnToNode',
method: 'post'
},
GET_REPORT_APPROVAL_USERS: {
url: '/custom/benchmark/getApprovalUsers',
method: 'get'
},
CONTINUE_REPORT_APPROVAL: {
url: '/custom/benchmark/continueApproval',
method: 'get'
}
}
export default {
GET_REPORT_LIST: {
url: '/custom/benchmark/getReportAndTodoByCondition',
method: 'post'
},
GET_REPORT_LIST_BY_CONDITION: {
url: '/custom/benchmark/getApprovalList',
method: 'post'
},
ADD_REPORT: {
url: '/custom/benchmark/startReportApproval',
method: 'post'
},
SAVE_REPORT: {
url: '/custom/benchmark/insertReport',
method: 'post'
},
EDIT_REPORT: {
url: '/custom/benchmark/updateReport',
method: 'post'
},
RESTART_REPORT_APPROVAL: {
url: '/custom/benchmark/restartReportApproval',
method: 'post'
},
START_REPORT_APPROVAL: {
url: '/custom/benchmark/handleReportApproval',
method: 'post'
},
GET_REPORT_DETAIL: {
url: '/custom/benchmark/getReportDetail',
method: 'get'
},
GET_REPORT_DETAIL_PROCESS: {
url: '/custom/benchmark/getReportProcess',
method: 'get'
},
DOWNLOAD_REPORT: {
url: '/custom/benchmark/downloadReport',
method: 'get'
},
DELETE_REPORT: {
url: '/custom/benchmark/deleteReport',
method: 'get'
},
RETURN_REPORT: {
url: '/custom/benchmark/handleReturn',
method: 'post'
},
RESTART_REPORT_TODO: {
url: '/custom/benchmark/restartApproval',
method: 'get'
},
RESEND_REPORT_APPROVAL: {
url: '/custom/benchmark/directSendingApproval',
method: 'get'
},
RETURN_REPORT_TODO: {
url: '/custom/benchmark/handleReturnToNode',
method: 'post'
},
GET_REPORT_APPROVAL_USERS: {
url: '/custom/benchmark/getApprovalUsers',
method: 'get'
},
CONTINUE_REPORT_APPROVAL: {
url: '/custom/benchmark/continueApproval',
method: 'get'
}
}

View File

@ -1,35 +1,35 @@
/*
* @Author: your name
* @Date: 2020-05-30 09:41:36
* LastEditTime: 2020-09-18 10:10:08
* LastEditors: Mosuzi
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/index.js
*/
import CommonApi from './common'
import AccountApi from './account'
import AdminApi from './admin'
import PersonalApi from './personal'
import WorkbenchApi from './workbench'
import AppPage from './app-page'
import demoApi from './demo/index'
import dataApi from './demo/data'
import modelApi from './demo/model'
import reportApi from './demo/report'
import activitiApi from './demo/activiti'
import permissionApi from './demo/permission'
export default {
...CommonApi,
...AccountApi,
...AdminApi,
...PersonalApi,
...WorkbenchApi,
...AppPage,
...demoApi,
...dataApi,
...modelApi,
...reportApi,
...activitiApi,
...permissionApi
}
/*
* @Author: your name
* @Date: 2020-05-30 09:41:36
* LastEditTime: 2020-09-18 10:10:08
* LastEditors: Mosuzi
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/index.js
*/
import CommonApi from './common'
import AccountApi from './account'
import AdminApi from './admin'
import PersonalApi from './personal'
import WorkbenchApi from './workbench'
import AppPage from './app-page'
import demoApi from './demo/index'
import dataApi from './demo/data'
import modelApi from './demo/model'
import reportApi from './demo/report'
import activitiApi from './demo/activiti'
import permissionApi from './demo/permission'
export default {
...CommonApi,
...AccountApi,
...AdminApi,
...PersonalApi,
...WorkbenchApi,
...AppPage,
...demoApi,
...dataApi,
...modelApi,
...reportApi,
...activitiApi,
...permissionApi
}

View File

@ -1,53 +1,53 @@
/*
* @Author: your name
* @Date: 2020-05-30 10:07:21
* @LastEditTime: 2020-06-06 12:27:21
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/personal-center/index.js
*/
export default {
QUERY_USER_INFO: {
url: '/xdap-admin/user/query/userInfo',
method: 'post',
disableSuccessMsg: true
},
UPDATE_USER_INFO: {
url: '/xdap-admin/user/update/userInfo',
method: 'post'
},
QUERY_ACCOUNT_INFO: {
url: '/xdap-admin/user/query/accountInfo',
method: 'get',
disableSuccessMsg: true
},
// 查询用户绑定第三方账号信息
QUERY_ACCOUNT_BIND: {
url: '/xdap-admin/user/query/userBind',
method: 'get',
disableSuccessMsg: true
},
QUIT_TENANT: {
url: '/xdap-admin/tenant/quit/tenant',
method: 'post'
},
UPDATE_USER_PASSWORD: {
url: '/xdap-admin/user/update/userPassword',
method: 'post'
},
UPLOAD_USER_AVATAR: {
url: '/xdap-admin/user/upload/userAvatar',
method: 'post',
disableSuccessMsg: true
},
// 绑定微信
BIND_OPNE_WECHAT: {
url: '/xdap-admin/user/bind/openWechat',
method: 'post'
},
// 解绑第三方账号
UNBIND_THIRD_PLATFORM: {
url: '/xdap-admin/user/unbind/userThirdPlatform',
method: 'post'
}
}
/*
* @Author: your name
* @Date: 2020-05-30 10:07:21
* @LastEditTime: 2020-06-06 12:27:21
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/personal-center/index.js
*/
export default {
QUERY_USER_INFO: {
url: '/xdap-admin/user/query/userInfo',
method: 'post',
disableSuccessMsg: true
},
UPDATE_USER_INFO: {
url: '/xdap-admin/user/update/userInfo',
method: 'post'
},
QUERY_ACCOUNT_INFO: {
url: '/xdap-admin/user/query/accountInfo',
method: 'get',
disableSuccessMsg: true
},
// 查询用户绑定第三方账号信息
QUERY_ACCOUNT_BIND: {
url: '/xdap-admin/user/query/userBind',
method: 'get',
disableSuccessMsg: true
},
QUIT_TENANT: {
url: '/xdap-admin/tenant/quit/tenant',
method: 'post'
},
UPDATE_USER_PASSWORD: {
url: '/xdap-admin/user/update/userPassword',
method: 'post'
},
UPLOAD_USER_AVATAR: {
url: '/xdap-admin/user/upload/userAvatar',
method: 'post',
disableSuccessMsg: true
},
// 绑定微信
BIND_OPNE_WECHAT: {
url: '/xdap-admin/user/bind/openWechat',
method: 'post'
},
// 解绑第三方账号
UNBIND_THIRD_PLATFORM: {
url: '/xdap-admin/user/unbind/userThirdPlatform',
method: 'post'
}
}

View File

@ -1,36 +1,36 @@
/*
* @Author: your name
* @Date: 2020-05-30 16:15:05
* LastEditTime: 2020-09-22 11:11:01
* LastEditors: Mosuzi
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/workbench/index.js
*/
export default {
QUERY_MY_TENANT_LIST: {
url: '/xdap-admin/tenant/query/myTenantList',
method: 'get',
disableSuccessMsg: true
},
// 查询首页应用
QUERY_HOME_LIST: {
url: '/xdap-app/app/query/workspaceHome',
method: 'get',
disableSuccessMsg: true
},
QUERY_TENANT_LIST_BY_USER: {
url: '/xdap-admin/tenant/query/tenantListByUser',
method: 'get',
disableSuccessMsg: true
},
QUERY_USER_TENANT_INFO: {
url: '/xdap-admin/tenant/query/userTenantInfo',
method: 'get',
disableSuccessMsg: true
},
USER_APP_CONFIG_UPDATE: {
url: '/xdap-app/user/config/update',
method: 'post',
disableSuccessMsg: true
}
}
/*
* @Author: your name
* @Date: 2020-05-30 16:15:05
* LastEditTime: 2020-09-22 11:11:01
* LastEditors: Mosuzi
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/api/workbench/index.js
*/
export default {
QUERY_MY_TENANT_LIST: {
url: '/xdap-admin/tenant/query/myTenantList',
method: 'get',
disableSuccessMsg: true
},
// 查询首页应用
QUERY_HOME_LIST: {
url: '/xdap-app/app/query/workspaceHome',
method: 'get',
disableSuccessMsg: true
},
QUERY_TENANT_LIST_BY_USER: {
url: '/xdap-admin/tenant/query/tenantListByUser',
method: 'get',
disableSuccessMsg: true
},
QUERY_USER_TENANT_INFO: {
url: '/xdap-admin/tenant/query/userTenantInfo',
method: 'get',
disableSuccessMsg: true
},
USER_APP_CONFIG_UPDATE: {
url: '/xdap-app/user/config/update',
method: 'post',
disableSuccessMsg: true
}
}

View File

@ -1,17 +1,17 @@
export default {
requireAllSvg: function() {
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
const req = require.context('./assets/icon', true, /\.svg$/)
requireAll(req)
},
/**
* 支持App应用动态导入图标
* @param { require.context('./assets/icon', true, /\.svg$/) }
*/
requireAppSvg: function(reqContext) {
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
const req = reqContext
requireAll(req)
}
}
export default {
requireAllSvg: function() {
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
const req = require.context('./assets/icon', true, /\.svg$/)
requireAll(req)
},
/**
* 支持App应用动态导入图标
* @param { require.context('./assets/icon', true, /\.svg$/) }
*/
requireAppSvg: function(reqContext) {
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
const req = reqContext
requireAll(req)
}
}

View File

@ -1,2 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590564441419" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3571" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M448.170667 273.706667a59.477333 59.477333 0 1 0 118.954666 0 59.477333 59.477333 0 0 0-118.954666 0zM448.170667 510.293333a59.221333 59.221333 0 1 0 118.442666 0 59.221333 59.221333 0 0 0-118.442666 0zM448.682667 747.221333a59.221333 59.221333 0 1 0 118.442666 0 59.221333 59.221333 0 0 0-118.442666 0z" p-id="3572"></path></svg>

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 709 B

View File

@ -1,322 +1,322 @@
'use strict'
var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (obj) { return typeof obj } : function (obj) { return obj && typeof Symbol === 'function' && obj.constructor === Symbol ? 'symbol' : typeof obj };
(function () {
// var canvasRef = ''
var opts = {
imgurl: '',
cw: 60,
ch: 60,
precision: 5,
onSuccess: null,
onError: null,
successText: '',
failText: '',
eventinfo: {
flag: false,
left: 0,
clipleft: 0,
currentX: 0
}
}
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]'
}
function createCaptchaBox(canvas) {
var captchaBox = document.createElement('div')
captchaBox.className = 'captcha-box'
captchaBox.style.width = canvas.width + 'px'
var dragBox = document.createElement('div')
dragBox.className = 'drag-box'
dragBox.id = 'drag-box'
var canvasBox = document.createElement('div')
canvasBox.className = 'canvas-box'
canvasBox.appendChild(canvas.cloneNode(true))
canvasBox.appendChild(createResult())
captchaBox.appendChild(canvasBox)
captchaBox.appendChild(createDragBar())
canvas.parentNode.replaceChild(captchaBox, canvas)
captchaBox.appendChild(dragBox)
return captchaBox
}
function createDragBar() {
var dragbar = document.createElement('div')
dragbar.className = 'captcha-dragbar'
dragbar.innerHTML = '\n <div class="drag-option-bg">\n <div class="drag-option">\n <div class="drag-track"></div>\n <div id="drag-slider" class="drag-slider"></div>\n <div class="drag-btn">\n <i id="drag-btn-refresh" class="refresh"></i>\n </div>\n </div>\n </div>\n '
return dragbar
}
function createResult() {
var result = document.createElement('div')
result.id = 'captcha-result'
result.className = 'captcha-result'
return result
}
function createCanvas(w, h) {
var canvas = document.createElement('canvas')
canvas.width = w
canvas.height = h
return canvas
}
function clipPath(ctx, startx, starty) {
startx = startx + 0.2
starty = starty + 0.2
var subw = parseInt((opts.cw - 1) / 6)
var subh = parseInt((opts.ch - 1) / 6)
var radius = Math.min(subw, subh)
var clipw = subw * 5 + 0.5
var cliph = subh * 5 + 0.5
ctx.beginPath()
ctx.moveTo(startx, starty)
ctx.lineTo(startx + clipw, starty)
ctx.lineTo(startx + clipw, starty + parseInt(cliph / 2) - radius)
ctx.arc(startx + clipw, starty + parseInt(cliph / 2), radius, -Math.PI / 2, Math.PI / 2, false)
ctx.lineTo(startx + clipw, starty + cliph)
ctx.lineTo(startx + clipw - (parseInt(clipw / 2) - radius), starty + cliph)
ctx.arc(startx + parseInt(clipw / 2), starty + cliph, radius, 0, Math.PI, false)
ctx.lineTo(startx, starty + cliph)
ctx.lineTo(startx, starty)
ctx.closePath()
}
function fillClip(canvas, startx, starty, alpha) {
var ctx = canvas.getContext('2d')
clipPath(ctx, startx, starty)
ctx.fillStyle = 'rgba(0,0,0, ' + alpha + ')'
ctx.fill()
}
function strokeClip(canvas, startx, starty) {
var ctx = canvas.getContext('2d')
clipPath(ctx, startx, starty)
ctx.strokeStyle = '#fff'
ctx.stroke()
}
function randomNum(min, max) {
var rangeNum = max - min
var num = min + Math.round(Math.random() * rangeNum)
return num
}
function getStartPoint(w, h) {
var padding = 10
var startw = opts.cw + padding
var starth = opts.ch + padding
if (w < startw * 2 || h < starth) return
var startPoint = {
startx: randomNum(startw, w - startw),
starty: randomNum(padding, h - starth)
}
return startPoint
}
function eventInit(startx, refreshMethod) {
var dragBox = document.getElementById('drag-box')
var slider = document.getElementById('drag-slider')
var clipcanvas = document.getElementById('captcha-clipcanvas')
var result = document.getElementById('captcha-result')
var refreshBtn = document.getElementById('drag-btn-refresh')
var resultClass = result.className
opts.eventinfo.left = parseFloat(getComputedStyle(slider, null).getPropertyValue('left'))
opts.eventinfo.clipleft = parseFloat(getComputedStyle(clipcanvas, null).getPropertyValue('left'))
// var close = function close() {}
var reset = function reset() {
var boxClassName = window.captchaBox.className
// window.captchaBox.className += ' shake';
setTimeout(function () {
slider.style.left = '10px'
clipcanvas.style.left = '20px'
opts.eventinfo.left = 10
opts.eventinfo.clipleft = 20
}, 500)
setTimeout(function () {
result.className = resultClass
window.captchaBox.className = boxClassName
}, 1000)
}
var moveStart = function moveStart(e) {
opts.eventinfo.flag = true
if (e.touches) {
opts.eventinfo.currentX = e.touches[0].clientX
} else {
opts.eventinfo.currentX = e.clientX
}
dragBox.className = dragBox.className + ' drag-box-over'
}
var move = function move(e) {
if (opts.eventinfo.flag) {
if (e.touches) {
var disX = e.touches[0].clientX - opts.eventinfo.currentX
} else {
disX = e.clientX - opts.eventinfo.currentX
}
if (disX >= -10 && disX <= (dragBox.clientWidth - opts.cw - 10)) {
slider.style.left = opts.eventinfo.left + disX + 'px'
clipcanvas.style.left = opts.eventinfo.clipleft + disX + 'px'
} else {
e.preventDefault()
}
if (e.preventDefault) {}
return false
}
}
var moveEnd = function moveEnd(e) {
dragBox.className = 'drag-box'
if (opts.eventinfo.flag) {
opts.eventinfo.flag = false
opts.eventinfo.left = parseFloat(getComputedStyle(slider, null).getPropertyValue('left'))
opts.eventinfo.clipleft = parseFloat(getComputedStyle(clipcanvas, null).getPropertyValue('left'))
if (Math.abs(startx - opts.eventinfo.left) <= opts.precision) {
result.innerHTML = opts.successText
result.className = resultClass + ' success'
opts.onSuccess && opts.onSuccess()
} else {
result.innerHTML = opts.failText
result.className = resultClass + ' fail'
reset()
opts.onError && opts.onError()
}
}
}
window.captchaMoveEnd = moveEnd
slider.addEventListener('touchstart', moveStart)
slider.addEventListener('mousedown', moveStart)
slider.addEventListener('touchmove', move)
slider.addEventListener('mousemove', move)
document.addEventListener('touchend', moveEnd)
document.addEventListener('mouseup', moveEnd)
dragBox.addEventListener('touchmove', move)
dragBox.addEventListener('mousemove', move)
refreshBtn.addEventListener('click', refreshMethod)
}
var imgCaptcha = function imgCaptcha(canvas, options) {
if (window.captchaMoveEnd) {
document.removeEventListener('touchend', window.captchaMoveEnd)
document.removeEventListener('mouseup', window.captchaMoveEnd)
window.captchaMoveEnd = undefined
}
for (var k in options) {
if (options.hasOwnProperty(k)) {
opts[k] = options[k]
}
}
if (!canvas || !opts.imgurl) {
console.error('verify params is error')
return
}
if (canvas.tagName !== 'CANVAS') {
console.error('param canvas must be canvas')
return
}
const resetCanvas = canvas.cloneNode()
window.captchaBox = createCaptchaBox(canvas)
var refresh = function refresh() {
if (options.container) {
options.container.innerHTML = ''
const innerCanvas = resetCanvas.cloneNode()
options.container.appendChild(innerCanvas)
imgCaptcha(innerCanvas, options)
}
}
readerCaptcha(refresh)
return {
refresh
}
}
var readerCaptcha = function readerCaptcha(refresh) {
let canvas = window.captchaBox.children[0].children[0]
canvas.className += canvas.className + ' captcha-bg'
var img = new Image()
img.onload = function () {
var w = canvas.width
var h = canvas.height
var startPoint = getStartPoint(w, h)
if (!startPoint) {
console.error('can not get the start point')
return
}
var startx = startPoint.startx
var starty = startPoint.starty
canvas.getContext('2d').drawImage(img, 0, 0, w, h)
fillClip(canvas, startx, starty, 0.7)
var sourceCanvas = createCanvas(w, h)
var sctx = sourceCanvas.getContext('2d')
sctx.drawImage(img, 0, 0, w, h)
sctx.globalCompositeOperation = 'destination-in'
var destCanvas = createCanvas(opts.cw, opts.ch)
fillClip(destCanvas, 0, 0, 1)
sctx.drawImage(destCanvas, startx, starty)
var clipCanvas = createCanvas(opts.cw, opts.ch)
clipCanvas.id = 'captcha-clipcanvas'
clipCanvas.className = 'captcha-clipcanvas'
clipCanvas.getContext('2d').putImageData(sctx.getImageData(startx, starty, opts.cw, opts.ch), 0, 0)
strokeClip(clipCanvas, 0, 0)
clipCanvas.style.top = starty + 'px'
// captchaBox.appendChild(clipCanvas)
eventInit(startx, refresh)
}
opts.imgurl = isArray(opts.imgurl) ? opts.imgurl : [opts.imgurl]
var urlIndex = Math.floor(Math.random() * opts.imgurl.length)
img.src = opts.imgurl[urlIndex]
}
// if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
// module.exports = imgCaptcha
// } else if (typeof define === 'function' && define.amd) {
// define([], function () {
// return imgCaptcha
// })
// } else if (window) {
// window.imgCaptcha = imgCaptcha
// }
})()
'use strict'
var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (obj) { return typeof obj } : function (obj) { return obj && typeof Symbol === 'function' && obj.constructor === Symbol ? 'symbol' : typeof obj };
(function () {
// var canvasRef = ''
var opts = {
imgurl: '',
cw: 60,
ch: 60,
precision: 5,
onSuccess: null,
onError: null,
successText: '',
failText: '',
eventinfo: {
flag: false,
left: 0,
clipleft: 0,
currentX: 0
}
}
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]'
}
function createCaptchaBox(canvas) {
var captchaBox = document.createElement('div')
captchaBox.className = 'captcha-box'
captchaBox.style.width = canvas.width + 'px'
var dragBox = document.createElement('div')
dragBox.className = 'drag-box'
dragBox.id = 'drag-box'
var canvasBox = document.createElement('div')
canvasBox.className = 'canvas-box'
canvasBox.appendChild(canvas.cloneNode(true))
canvasBox.appendChild(createResult())
captchaBox.appendChild(canvasBox)
captchaBox.appendChild(createDragBar())
canvas.parentNode.replaceChild(captchaBox, canvas)
captchaBox.appendChild(dragBox)
return captchaBox
}
function createDragBar() {
var dragbar = document.createElement('div')
dragbar.className = 'captcha-dragbar'
dragbar.innerHTML = '\n <div class="drag-option-bg">\n <div class="drag-option">\n <div class="drag-track"></div>\n <div id="drag-slider" class="drag-slider"></div>\n <div class="drag-btn">\n <i id="drag-btn-refresh" class="refresh"></i>\n </div>\n </div>\n </div>\n '
return dragbar
}
function createResult() {
var result = document.createElement('div')
result.id = 'captcha-result'
result.className = 'captcha-result'
return result
}
function createCanvas(w, h) {
var canvas = document.createElement('canvas')
canvas.width = w
canvas.height = h
return canvas
}
function clipPath(ctx, startx, starty) {
startx = startx + 0.2
starty = starty + 0.2
var subw = parseInt((opts.cw - 1) / 6)
var subh = parseInt((opts.ch - 1) / 6)
var radius = Math.min(subw, subh)
var clipw = subw * 5 + 0.5
var cliph = subh * 5 + 0.5
ctx.beginPath()
ctx.moveTo(startx, starty)
ctx.lineTo(startx + clipw, starty)
ctx.lineTo(startx + clipw, starty + parseInt(cliph / 2) - radius)
ctx.arc(startx + clipw, starty + parseInt(cliph / 2), radius, -Math.PI / 2, Math.PI / 2, false)
ctx.lineTo(startx + clipw, starty + cliph)
ctx.lineTo(startx + clipw - (parseInt(clipw / 2) - radius), starty + cliph)
ctx.arc(startx + parseInt(clipw / 2), starty + cliph, radius, 0, Math.PI, false)
ctx.lineTo(startx, starty + cliph)
ctx.lineTo(startx, starty)
ctx.closePath()
}
function fillClip(canvas, startx, starty, alpha) {
var ctx = canvas.getContext('2d')
clipPath(ctx, startx, starty)
ctx.fillStyle = 'rgba(0,0,0, ' + alpha + ')'
ctx.fill()
}
function strokeClip(canvas, startx, starty) {
var ctx = canvas.getContext('2d')
clipPath(ctx, startx, starty)
ctx.strokeStyle = '#fff'
ctx.stroke()
}
function randomNum(min, max) {
var rangeNum = max - min
var num = min + Math.round(Math.random() * rangeNum)
return num
}
function getStartPoint(w, h) {
var padding = 10
var startw = opts.cw + padding
var starth = opts.ch + padding
if (w < startw * 2 || h < starth) return
var startPoint = {
startx: randomNum(startw, w - startw),
starty: randomNum(padding, h - starth)
}
return startPoint
}
function eventInit(startx, refreshMethod) {
var dragBox = document.getElementById('drag-box')
var slider = document.getElementById('drag-slider')
var clipcanvas = document.getElementById('captcha-clipcanvas')
var result = document.getElementById('captcha-result')
var refreshBtn = document.getElementById('drag-btn-refresh')
var resultClass = result.className
opts.eventinfo.left = parseFloat(getComputedStyle(slider, null).getPropertyValue('left'))
opts.eventinfo.clipleft = parseFloat(getComputedStyle(clipcanvas, null).getPropertyValue('left'))
// var close = function close() {}
var reset = function reset() {
var boxClassName = window.captchaBox.className
// window.captchaBox.className += ' shake';
setTimeout(function () {
slider.style.left = '10px'
clipcanvas.style.left = '20px'
opts.eventinfo.left = 10
opts.eventinfo.clipleft = 20
}, 500)
setTimeout(function () {
result.className = resultClass
window.captchaBox.className = boxClassName
}, 1000)
}
var moveStart = function moveStart(e) {
opts.eventinfo.flag = true
if (e.touches) {
opts.eventinfo.currentX = e.touches[0].clientX
} else {
opts.eventinfo.currentX = e.clientX
}
dragBox.className = dragBox.className + ' drag-box-over'
}
var move = function move(e) {
if (opts.eventinfo.flag) {
if (e.touches) {
var disX = e.touches[0].clientX - opts.eventinfo.currentX
} else {
disX = e.clientX - opts.eventinfo.currentX
}
if (disX >= -10 && disX <= (dragBox.clientWidth - opts.cw - 10)) {
slider.style.left = opts.eventinfo.left + disX + 'px'
clipcanvas.style.left = opts.eventinfo.clipleft + disX + 'px'
} else {
e.preventDefault()
}
if (e.preventDefault) {}
return false
}
}
var moveEnd = function moveEnd(e) {
dragBox.className = 'drag-box'
if (opts.eventinfo.flag) {
opts.eventinfo.flag = false
opts.eventinfo.left = parseFloat(getComputedStyle(slider, null).getPropertyValue('left'))
opts.eventinfo.clipleft = parseFloat(getComputedStyle(clipcanvas, null).getPropertyValue('left'))
if (Math.abs(startx - opts.eventinfo.left) <= opts.precision) {
result.innerHTML = opts.successText
result.className = resultClass + ' success'
opts.onSuccess && opts.onSuccess()
} else {
result.innerHTML = opts.failText
result.className = resultClass + ' fail'
reset()
opts.onError && opts.onError()
}
}
}
window.captchaMoveEnd = moveEnd
slider.addEventListener('touchstart', moveStart)
slider.addEventListener('mousedown', moveStart)
slider.addEventListener('touchmove', move)
slider.addEventListener('mousemove', move)
document.addEventListener('touchend', moveEnd)
document.addEventListener('mouseup', moveEnd)
dragBox.addEventListener('touchmove', move)
dragBox.addEventListener('mousemove', move)
refreshBtn.addEventListener('click', refreshMethod)
}
var imgCaptcha = function imgCaptcha(canvas, options) {
if (window.captchaMoveEnd) {
document.removeEventListener('touchend', window.captchaMoveEnd)
document.removeEventListener('mouseup', window.captchaMoveEnd)
window.captchaMoveEnd = undefined
}
for (var k in options) {
if (options.hasOwnProperty(k)) {
opts[k] = options[k]
}
}
if (!canvas || !opts.imgurl) {
console.error('verify params is error')
return
}
if (canvas.tagName !== 'CANVAS') {
console.error('param canvas must be canvas')
return
}
const resetCanvas = canvas.cloneNode()
window.captchaBox = createCaptchaBox(canvas)
var refresh = function refresh() {
if (options.container) {
options.container.innerHTML = ''
const innerCanvas = resetCanvas.cloneNode()
options.container.appendChild(innerCanvas)
imgCaptcha(innerCanvas, options)
}
}
readerCaptcha(refresh)
return {
refresh
}
}
var readerCaptcha = function readerCaptcha(refresh) {
let canvas = window.captchaBox.children[0].children[0]
canvas.className += canvas.className + ' captcha-bg'
var img = new Image()
img.onload = function () {
var w = canvas.width
var h = canvas.height
var startPoint = getStartPoint(w, h)
if (!startPoint) {
console.error('can not get the start point')
return
}
var startx = startPoint.startx
var starty = startPoint.starty
canvas.getContext('2d').drawImage(img, 0, 0, w, h)
fillClip(canvas, startx, starty, 0.7)
var sourceCanvas = createCanvas(w, h)
var sctx = sourceCanvas.getContext('2d')
sctx.drawImage(img, 0, 0, w, h)
sctx.globalCompositeOperation = 'destination-in'
var destCanvas = createCanvas(opts.cw, opts.ch)
fillClip(destCanvas, 0, 0, 1)
sctx.drawImage(destCanvas, startx, starty)
var clipCanvas = createCanvas(opts.cw, opts.ch)
clipCanvas.id = 'captcha-clipcanvas'
clipCanvas.className = 'captcha-clipcanvas'
clipCanvas.getContext('2d').putImageData(sctx.getImageData(startx, starty, opts.cw, opts.ch), 0, 0)
strokeClip(clipCanvas, 0, 0)
clipCanvas.style.top = starty + 'px'
// captchaBox.appendChild(clipCanvas)
eventInit(startx, refresh)
}
opts.imgurl = isArray(opts.imgurl) ? opts.imgurl : [opts.imgurl]
var urlIndex = Math.floor(Math.random() * opts.imgurl.length)
img.src = opts.imgurl[urlIndex]
}
// if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
// module.exports = imgCaptcha
// } else if (typeof define === 'function' && define.amd) {
// define([], function () {
// return imgCaptcha
// })
// } else if (window) {
// window.imgCaptcha = imgCaptcha
// }
})()

View File

@ -1,33 +1,33 @@
[
{
"id":"123",
"userName":"张嘉豪",
"department":"结构开发部"
},
{
"id":"2131",
"userName":"李四",
"department":"结构开发部"
},
{
"id":"3214",
"userName":"杜学凯",
"department":"平台部"
},
{
"id":"1231",
"userName":"李亚松",
"department":"平台部"
},
{
"id":"1232",
"userName":"王五",
"department":"结构开发部"
},
{
"id":"1233",
"userName":"张三",
"department":"平台部"
},
[
{
"id":"123",
"userName":"张嘉豪",
"department":"结构开发部"
},
{
"id":"2131",
"userName":"李四",
"department":"结构开发部"
},
{
"id":"3214",
"userName":"杜学凯",
"department":"平台部"
},
{
"id":"1231",
"userName":"李亚松",
"department":"平台部"
},
{
"id":"1232",
"userName":"王五",
"department":"结构开发部"
},
{
"id":"1233",
"userName":"张三",
"department":"平台部"
},
]

View File

@ -1,32 +1,32 @@
// 主题色
$--app-primary-color: #027AFF;
$--app-sky-color: #1296db;
$--app-danger-color: #F56C6C;
$--app-info-color: #F5F7FA;
$--app-notice-color: #B2B2B2;
$--app-selected-color: #E6F2FF;
$--app-active-color: #7ED321;
$--app-success-color: #5ebf70;
$--app-fail-color: #de715b;
$--app-light-color: #ffffff;
$--app-opacity-color: #eeeeee;
$--app-warning-color: #F5A623;
$--app-description-color: #929292;
// 标准盒子边框色
$--app-border-color: #DCDFE6;
// 分割线颜色
$--app-split-color: #EBEEF5;
// 标准字体颜色
$--app-font-color: #303133;
// 标准背景色
$--app-bg-Color: #F7F7F7;
// 标准盒子阴影
$--app-box-shadow: 0 0 8px 0 $--app-split-color;
// 标准圆角
$--app-border-radius: 2px;
// 标准加粗字体
$--app-font-weight: bold;
// 标准字体大小
$--app-font-size: 12px;
// 标题字体大小
$--app-title-fontSize: 14px;
// 主题色
$--app-primary-color: #027AFF;
$--app-sky-color: #1296db;
$--app-danger-color: #F56C6C;
$--app-info-color: #F5F7FA;
$--app-notice-color: #B2B2B2;
$--app-selected-color: #E6F2FF;
$--app-active-color: #7ED321;
$--app-success-color: #5ebf70;
$--app-fail-color: #de715b;
$--app-light-color: #ffffff;
$--app-opacity-color: #eeeeee;
$--app-warning-color: #F5A623;
$--app-description-color: #929292;
// 标准盒子边框色
$--app-border-color: #DCDFE6;
// 分割线颜色
$--app-split-color: #EBEEF5;
// 标准字体颜色
$--app-font-color: #303133;
// 标准背景色
$--app-bg-Color: #F7F7F7;
// 标准盒子阴影
$--app-box-shadow: 0 0 8px 0 $--app-split-color;
// 标准圆角
$--app-border-radius: 2px;
// 标准加粗字体
$--app-font-weight: bold;
// 标准字体大小
$--app-font-size: 12px;
// 标题字体大小
$--app-title-fontSize: 14px;

View File

@ -1,18 +1,18 @@
@import './app-variable.scss';
/* Color-------------------------- */
$--color-primary: $--app-primary-color;
$--border-radius-base: $--app-border-radius;
$--size-base: $--app-font-size ;
$--input-height: 32px;
$--button-border-radius: $--app-border-radius;
$--button-medium-border-radius: $--app-border-radius;
$--button-small-border-radius: $--app-border-radius;
$--button-mini-border-radius: $--app-border-radius;
@import './app-variable.scss';
/* Color-------------------------- */
$--color-primary: $--app-primary-color;
$--border-radius-base: $--app-border-radius;
$--size-base: $--app-font-size ;
$--input-height: 32px;
$--button-border-radius: $--app-border-radius;
$--button-medium-border-radius: $--app-border-radius;
$--button-small-border-radius: $--app-border-radius;
$--button-mini-border-radius: $--app-border-radius;

View File

@ -1,179 +1,179 @@
@import "~normalize.css";
@import "./app-variable.scss";
@import "./mixin.scss";
body * {
font-family: Avenir, Helvetica, Arial, sans-serif;
}
*:focus {
outline: none;
}
.x-svg-icon .svg-icon {
width: 24px !important;
height: 24px !important;
}
.x-product-skeleton {
background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);
background-size: 400% 100%;
animation: x-product-skeleton-loading 1.4s ease infinite;
&.x-product-skeleton-block {
width: 100%;
height: 24px;
margin: 0 8px;
}
&.x-product-skeleton-tag {
display: inline-block;
box-sizing: content-box;
padding: 0 8px;
width: 60px;
height: 24px;
}
}
@keyframes x-product-skeleton-loading {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
.el-button {
height: 32px;
line-height: 32px;
padding: 0 20px !important;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100% !important;
}
.el-dropdown-menu {
margin-top: 0 !important;
.popper__arrow {
display: none !important;
}
}
.x-block-table .el-table thead {
font-size: $--app-font-size;
}
.x-loading .mask {
background-color: $--app-light-color;
}
.app-workbench__icon {
display: flex;
align-items: center;
margin-right: 36px;
&:hover {
cursor: pointer;
color: $--app-primary-color;
}
}
.app-menu__switch {
position: absolute;
top: calc(50% - 40px);
right: -16px;
display: flex;
justify-content: center;
align-items: center;
z-index: 200;
width: 16px;
height: 80px;
border-top-right-radius: 16px;
border-bottom-right-radius: 16px;
border: 1px solid $--app-light-color;
border-left: 0;
cursor: pointer;
opacity: 0.5;
border: 1px solid $--app-border-color;
border-left: none;
background-color: $--app-light-color;
}
.el-dialog__wrapper {
display: flex;
align-items: center;
padding: 12px 0;
.x-modal-wrapper {
margin: 0 auto !important;
padding: 12px 20px;
.el-dialog__header {
padding: 12px 8px 12px 12px !important;
}
.el-dialog__body {
padding: 12px;
}
.el-dialog__footer {
padding: 12px !important;
}
}
.x-modal-wrapper {
.modal-header-row {
display: flex;
align-items: center;
.header-title {
font-size: 14px;
font-weight: bold;
}
.search-block {
margin-left: 16px;
margin-right: 24px;
border-left: 1px solid $--app-border-color;
flex: 1;
height: 14px;
display: flex;
align-items: center;
.el-input {
height: 100%;
display: flex;
align-items: center;
.el-input__inner {
position: relative;
left: 28px;
height: 100%;
font-size: 12px;
border: 0;
}
.el-input__prefix {
display: flex;
align-items: center;
left: 12px;
.header-search-icon {
width: 14px;
height: 14px;
}
}
}
}
.block {
flex: 1;
}
.header-close-icon {
cursor: pointer;
&:hover {
color: $--app-primary-color;
}
}
}
}
@import "~normalize.css";
@import "./app-variable.scss";
@import "./mixin.scss";
body * {
font-family: Avenir, Helvetica, Arial, sans-serif;
}
*:focus {
outline: none;
}
.x-svg-icon .svg-icon {
width: 24px !important;
height: 24px !important;
}
.x-product-skeleton {
background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);
background-size: 400% 100%;
animation: x-product-skeleton-loading 1.4s ease infinite;
&.x-product-skeleton-block {
width: 100%;
height: 24px;
margin: 0 8px;
}
&.x-product-skeleton-tag {
display: inline-block;
box-sizing: content-box;
padding: 0 8px;
width: 60px;
height: 24px;
}
}
@keyframes x-product-skeleton-loading {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
.el-button {
height: 32px;
line-height: 32px;
padding: 0 20px !important;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100% !important;
}
.el-dropdown-menu {
margin-top: 0 !important;
.popper__arrow {
display: none !important;
}
}
.x-block-table .el-table thead {
font-size: $--app-font-size;
}
.x-loading .mask {
background-color: $--app-light-color;
}
.app-workbench__icon {
display: flex;
align-items: center;
margin-right: 36px;
&:hover {
cursor: pointer;
color: $--app-primary-color;
}
}
.app-menu__switch {
position: absolute;
top: calc(50% - 40px);
right: -16px;
display: flex;
justify-content: center;
align-items: center;
z-index: 200;
width: 16px;
height: 80px;
border-top-right-radius: 16px;
border-bottom-right-radius: 16px;
border: 1px solid $--app-light-color;
border-left: 0;
cursor: pointer;
opacity: 0.5;
border: 1px solid $--app-border-color;
border-left: none;
background-color: $--app-light-color;
}
.el-dialog__wrapper {
display: flex;
align-items: center;
padding: 12px 0;
.x-modal-wrapper {
margin: 0 auto !important;
padding: 12px 20px;
.el-dialog__header {
padding: 12px 8px 12px 12px !important;
}
.el-dialog__body {
padding: 12px;
}
.el-dialog__footer {
padding: 12px !important;
}
}
.x-modal-wrapper {
.modal-header-row {
display: flex;
align-items: center;
.header-title {
font-size: 14px;
font-weight: bold;
}
.search-block {
margin-left: 16px;
margin-right: 24px;
border-left: 1px solid $--app-border-color;
flex: 1;
height: 14px;
display: flex;
align-items: center;
.el-input {
height: 100%;
display: flex;
align-items: center;
.el-input__inner {
position: relative;
left: 28px;
height: 100%;
font-size: 12px;
border: 0;
}
.el-input__prefix {
display: flex;
align-items: center;
left: 12px;
.header-search-icon {
width: 14px;
height: 14px;
}
}
}
}
.block {
flex: 1;
}
.header-close-icon {
cursor: pointer;
&:hover {
color: $--app-primary-color;
}
}
}
}
}

View File

@ -1,26 +1,26 @@
/**
* @description: 如果font-size为10的话则使用缩放处理
* @param {type}
* @return:
*/
@mixin fontSize($fontSize) {
@if $fontSize == 10px {
font-size: 12px;
transform: scale(.83);
} @else {
font-size: $fontSize;
}
}
/**
* @description: 把图形变成圆形
* @param {type}
* @return:
*/
@mixin circleShape($width) {
width: $width;
min-width: $width;
height: $width;
min-height: $width;
border-radius: 50%;
}
/**
* @description: 如果font-size为10的话则使用缩放处理
* @param {type}
* @return:
*/
@mixin fontSize($fontSize) {
@if $fontSize == 10px {
font-size: 12px;
transform: scale(.83);
} @else {
font-size: $fontSize;
}
}
/**
* @description: 把图形变成圆形
* @param {type}
* @return:
*/
@mixin circleShape($width) {
width: $width;
min-width: $width;
height: $width;
min-height: $width;
border-radius: 50%;
}

View File

@ -1,4 +1,4 @@
@import "./app-variable.scss";
@import "./element-variable.scss";
// 引入mixin
@import "./mixin.scss";
@import "./app-variable.scss";
@import "./element-variable.scss";
// 引入mixin
@import "./mixin.scss";

View File

@ -1,108 +1,108 @@
<template>
<x-app-layout
:layoutEngine="layoutEngine"
:isCollapse="isCollapse"
>
<template v-slot:header>
<x-app-header v-if="appInfo" :layoutEngine="layoutEngine" :appInfo="appInfo"></x-app-header>
</template>
<template v-slot:menu>
<x-app-menu
:menuConfig="menuConfig"
:showMenu="showMenu && !!appInfo"
:isCollapse="isCollapse"
:layoutEngine="layoutEngine"
@menu-add-click="menuAddClick"
></x-app-menu>
</template>
<template slot="appPage">
<div class="menu-switch" @click="changeCollapse">
<x-svg-icon v-if="isCollapse" name="arrow-right-icon"></x-svg-icon>
<x-svg-icon v-else name="arrow-left-icon"></x-svg-icon>
</div>
<slot name="appPage"></slot>
</template>
</x-app-layout>
</template>
<script>
export default {
name: 'AppLayout',
props: {
layoutEngine: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
isCollapse: false,
showMenu: true
}
},
computed: {
appInfo() {
return (this.layoutEngine && this.layoutEngine.layoutDataControl && this.layoutEngine.layoutDataControl.appInfo) || {}
},
menuConfig() {
return (this.layoutEngine && this.layoutEngine.layoutDataControl && this.layoutEngine.layoutDataControl.menuConfig) || {
menu: [],
defaultActive: null,
menuTreeData: []
}
}
},
methods: {
changeCollapse() {
this.showMenu = false
this.$nextTick(() => {
this.isCollapse = !this.isCollapse
this.showMenu = true
})
},
menuAddClick(e) {
this.$emit('menu-add-click', e)
}
}
}
</script>
<style lang="scss">
$--app-box-bgColor: #ffffff;
$--app-box-border-color: #DCDFE6;
.x-app-layout {
.layout-middle {
.layout-center {
.menu-switch {
width: 14px;
height: 80px;
padding-right: 2px;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
border: 1px solid $--app-box-bgColor;
border-left: 0;
background-color: $--app-box-bgColor;
position: absolute;
top: calc(50vh - 87px);
left: -20px;
transform: translateX(120%);
cursor: pointer;
opacity: 0.5;
display: flex;
justify-content: center;
align-items: center;
z-index: 500;
border: 1px solid $--app-box-border-color;
border-left: none;
}
.menu-switch:hover {
background-color: $--app-box-bgColor;
opacity: 1;
box-shadow: 2px 0px 4px 0px $--app-box-border-color;
}
}
}
}
</style>
<template>
<x-app-layout
:layoutEngine="layoutEngine"
:isCollapse="isCollapse"
>
<template v-slot:header>
<x-app-header v-if="appInfo" :layoutEngine="layoutEngine" :appInfo="appInfo"></x-app-header>
</template>
<template v-slot:menu>
<x-app-menu
:menuConfig="menuConfig"
:showMenu="showMenu && !!appInfo"
:isCollapse="isCollapse"
:layoutEngine="layoutEngine"
@menu-add-click="menuAddClick"
></x-app-menu>
</template>
<template slot="appPage">
<div class="menu-switch" @click="changeCollapse">
<x-svg-icon v-if="isCollapse" name="arrow-right-icon"></x-svg-icon>
<x-svg-icon v-else name="arrow-left-icon"></x-svg-icon>
</div>
<slot name="appPage"></slot>
</template>
</x-app-layout>
</template>
<script>
export default {
name: 'AppLayout',
props: {
layoutEngine: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
isCollapse: false,
showMenu: true
}
},
computed: {
appInfo() {
return (this.layoutEngine && this.layoutEngine.layoutDataControl && this.layoutEngine.layoutDataControl.appInfo) || {}
},
menuConfig() {
return (this.layoutEngine && this.layoutEngine.layoutDataControl && this.layoutEngine.layoutDataControl.menuConfig) || {
menu: [],
defaultActive: null,
menuTreeData: []
}
}
},
methods: {
changeCollapse() {
this.showMenu = false
this.$nextTick(() => {
this.isCollapse = !this.isCollapse
this.showMenu = true
})
},
menuAddClick(e) {
this.$emit('menu-add-click', e)
}
}
}
</script>
<style lang="scss">
$--app-box-bgColor: #ffffff;
$--app-box-border-color: #DCDFE6;
.x-app-layout {
.layout-middle {
.layout-center {
.menu-switch {
width: 14px;
height: 80px;
padding-right: 2px;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
border: 1px solid $--app-box-bgColor;
border-left: 0;
background-color: $--app-box-bgColor;
position: absolute;
top: calc(50vh - 87px);
left: -20px;
transform: translateX(120%);
cursor: pointer;
opacity: 0.5;
display: flex;
justify-content: center;
align-items: center;
z-index: 500;
border: 1px solid $--app-box-border-color;
border-left: none;
}
.menu-switch:hover {
background-color: $--app-box-bgColor;
opacity: 1;
box-shadow: 2px 0px 4px 0px $--app-box-border-color;
}
}
}
}
</style>

View File

@ -1,135 +1,135 @@
<template>
<div class="base-header">
<div class="base-header__prefix">
<img class="base-header__logo" src="~@/assets/img/logo.png" />
</div>
<div class="base-header__container">
<slot></slot>
</div>
<div class="base-header__suffix">
<slot name="append"></slot>
<el-dropdown trigger="click" placement="bottom" @command="handleCommand">
<person-avatar
:personName="userInfo.userName"
></person-avatar>
<el-dropdown-menu slot="dropdown" class="base-header__menu">
<el-dropdown-item command="personal">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="personal-icon"></x-svg-icon>
<span class="base-header__text">个人中心</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="admin">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="admin-icon"></x-svg-icon>
<span class="base-header__text">后台管理</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="logout">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="logout-icon"></x-svg-icon>
<span class="base-header__text">退出登录</span>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import PersonAvatar from '@/components/person-avatar'
import { mapState } from 'vuex'
export default {
name: 'BaseHeader',
components: {
PersonAvatar
},
data() {
return {}
},
computed: {
...mapState({
userInfo: state => state.authModule.userInfo
})
},
methods: {
handleCommand(command) {
console.log(command)
if (command === 'personal') {
this.$router.push({ name: 'personal' })
} else if (command === 'admin') {
this.$router.push({ name: 'admin' })
} else if (command === 'logout') {
this.$router.push({ name: 'account' })
}
}
}
}
</script>
<style lang="scss">
.base-header {
display: flex;
align-items: center;
position: relative;
z-index: 101;
height: 64px;
box-shadow: $--app-box-shadow;
background-color: $--app-light-color;
.base-header__prefix, .base-header__suffix {
flex: 1;
}
.base-header__prefix {
display: flex;
padding-left: 88px;
}
.base-header__suffix {
display: flex;
justify-content: flex-end;
padding-right: 20px;
.person-avatar {
cursor: pointer;
@include circleShape(36px);
}
}
.base-header__container {
width: 1100px;
}
.base-header__logo {
width: 140px;
height: 36px;
}
}
.base-header__text {
font-size: $--app-font-size;
color: $--app-font-color;
}
.base-header__icon {
color: $--app-font-color;
}
.el-dropdown-menu.base-header__menu {
padding: 4px 0;
margin-right: 12px;
width: 112px;
box-shadow: $--app-box-shadow;
.el-dropdown-menu__item {
padding-left: 16px;
padding-right: 20px;
i {
margin-right: 4px;
}
}
.popper__arrow {
display: none !important;
}
.base-header__menu-item {
display: flex;
}
}
</style>
<template>
<div class="base-header">
<div class="base-header__prefix">
<img class="base-header__logo" src="~@/assets/img/logo.png" />
</div>
<div class="base-header__container">
<slot></slot>
</div>
<div class="base-header__suffix">
<slot name="append"></slot>
<el-dropdown trigger="click" placement="bottom" @command="handleCommand">
<person-avatar
:personName="userInfo.userName"
></person-avatar>
<el-dropdown-menu slot="dropdown" class="base-header__menu">
<el-dropdown-item command="personal">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="personal-icon"></x-svg-icon>
<span class="base-header__text">个人中心</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="admin">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="admin-icon"></x-svg-icon>
<span class="base-header__text">后台管理</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="logout">
<div class="base-header__menu-item">
<x-svg-icon class="base-header__icon" name="logout-icon"></x-svg-icon>
<span class="base-header__text">退出登录</span>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import PersonAvatar from '@/components/person-avatar'
import { mapState } from 'vuex'
export default {
name: 'BaseHeader',
components: {
PersonAvatar
},
data() {
return {}
},
computed: {
...mapState({
userInfo: state => state.authModule.userInfo
})
},
methods: {
handleCommand(command) {
console.log(command)
if (command === 'personal') {
this.$router.push({ name: 'personal' })
} else if (command === 'admin') {
this.$router.push({ name: 'admin' })
} else if (command === 'logout') {
this.$router.push({ name: 'account' })
}
}
}
}
</script>
<style lang="scss">
.base-header {
display: flex;
align-items: center;
position: relative;
z-index: 101;
height: 64px;
box-shadow: $--app-box-shadow;
background-color: $--app-light-color;
.base-header__prefix, .base-header__suffix {
flex: 1;
}
.base-header__prefix {
display: flex;
padding-left: 88px;
}
.base-header__suffix {
display: flex;
justify-content: flex-end;
padding-right: 20px;
.person-avatar {
cursor: pointer;
@include circleShape(36px);
}
}
.base-header__container {
width: 1100px;
}
.base-header__logo {
width: 140px;
height: 36px;
}
}
.base-header__text {
font-size: $--app-font-size;
color: $--app-font-color;
}
.base-header__icon {
color: $--app-font-color;
}
.el-dropdown-menu.base-header__menu {
padding: 4px 0;
margin-right: 12px;
width: 112px;
box-shadow: $--app-box-shadow;
.el-dropdown-menu__item {
padding-left: 16px;
padding-right: 20px;
i {
margin-right: 4px;
}
}
.popper__arrow {
display: none !important;
}
.base-header__menu-item {
display: flex;
}
}
</style>

View File

@ -1,43 +1,43 @@
<template>
<el-menu-item
v-bind="$attrs"
class="base-menu-item"
v-on="$listeners"
>
<x-svg-icon class="base-menu-item__icon" :name="icon"></x-svg-icon>
<span class="base-menu-item__name">{{ name }}</span>
</el-menu-item>
</template>
<script>
export default {
name: 'BaseMenuItem',
props: {
icon: String,
name: String
}
}
</script>
<style lang="scss">
.el-menu-item.base-menu-item {
display: flex;
height: 44px;
line-height: 44px;
&.is-active {
background-color: $--app-selected-color;
}
&:hover, &:focus {
color: $--app-primary-color;
font-weight: $--app-font-weight;
background-color: $--app-info-color;
}
.base-menu-item__icon {
margin-right: 12px;
color: inherit;
}
.base-menu-item__name {
font-size: $--app-title-fontSize;
}
}
</style>
<template>
<el-menu-item
v-bind="$attrs"
class="base-menu-item"
v-on="$listeners"
>
<x-svg-icon class="base-menu-item__icon" :name="icon"></x-svg-icon>
<span class="base-menu-item__name">{{ name }}</span>
</el-menu-item>
</template>
<script>
export default {
name: 'BaseMenuItem',
props: {
icon: String,
name: String
}
}
</script>
<style lang="scss">
.el-menu-item.base-menu-item {
display: flex;
height: 44px;
line-height: 44px;
&.is-active {
background-color: $--app-selected-color;
}
&:hover, &:focus {
color: $--app-primary-color;
font-weight: $--app-font-weight;
background-color: $--app-info-color;
}
.base-menu-item__icon {
margin-right: 12px;
color: inherit;
}
.base-menu-item__name {
font-size: $--app-title-fontSize;
}
}
</style>

View File

@ -1,76 +1,76 @@
<template>
<el-submenu
v-bind="$attrs"
class="base-submenu-tree"
v-on="$listeners"
>
<template v-slot:title>
<div class="base-submenu-tree__title">
<x-svg-icon class="base-submenu-tree__icon" :name="icon"></x-svg-icon>
<span class="base-submenu-tree__name">{{ name }}</span>
</div>
</template>
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<base-submenu-tree
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
:menuData="menu.children"
:popper-append-to-body="false"
></base-submenu-tree>
</template>
<template v-else>
<base-menu-item
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
></base-menu-item>
</template>
</template>
</el-submenu>
</template>
<script>
import BaseMenuItem from './base-menu-item'
export default {
name: 'BaseSubmenuTree',
components: {
BaseMenuItem
},
props: {
icon: String,
name: String,
menuData: {
type: Array,
default() {
return []
}
}
}
}
</script>
<style lang="scss">
.el-submenu.base-submenu-tree {
line-height: 44px;
.el-submenu__title {
height: 44px;
line-height: 44px;
}
.base-submenu-tree__title {
display: flex;
height: 100%;
.base-submenu-tree__icon {
margin-right: 12px;
color: inherit;
}
.base-submenu-tree__name {
font-size: $--app-title-fontSize;
}
}
}
</style>
<template>
<el-submenu
v-bind="$attrs"
class="base-submenu-tree"
v-on="$listeners"
>
<template v-slot:title>
<div class="base-submenu-tree__title">
<x-svg-icon class="base-submenu-tree__icon" :name="icon"></x-svg-icon>
<span class="base-submenu-tree__name">{{ name }}</span>
</div>
</template>
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<base-submenu-tree
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
:menuData="menu.children"
:popper-append-to-body="false"
></base-submenu-tree>
</template>
<template v-else>
<base-menu-item
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
></base-menu-item>
</template>
</template>
</el-submenu>
</template>
<script>
import BaseMenuItem from './base-menu-item'
export default {
name: 'BaseSubmenuTree',
components: {
BaseMenuItem
},
props: {
icon: String,
name: String,
menuData: {
type: Array,
default() {
return []
}
}
}
}
</script>
<style lang="scss">
.el-submenu.base-submenu-tree {
line-height: 44px;
.el-submenu__title {
height: 44px;
line-height: 44px;
}
.base-submenu-tree__title {
display: flex;
height: 100%;
.base-submenu-tree__icon {
margin-right: 12px;
color: inherit;
}
.base-submenu-tree__name {
font-size: $--app-title-fontSize;
}
}
}
</style>

View File

@ -1,63 +1,63 @@
<template>
<el-menu
class="base-menu-tree"
v-bind="$attrs"
v-on="$listeners"
>
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<base-submenu-tree
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
:menuData="menu.children"
:popper-append-to-body="false"
></base-submenu-tree>
</template>
<template v-else>
<base-menu-item
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
></base-menu-item>
</template>
</template>
</el-menu>
</template>
<script>
import BaseSubmenuTree from './base-submenu-tree'
import BaseMenuItem from './base-menu-item'
export default {
name: 'BaseMenuTree',
components: {
BaseMenuItem,
BaseSubmenuTree
},
props: {
menuData: {
type: Array,
default() {
return []
}
}
}
}
</script>
<style lang="scss">
.el-menu.base-menu-tree {
border-right: 0;
padding: 16px 0;
max-height: calc(100vh - 64px);
overflow-y: auto;
background-color: $--app-light-color;
box-shadow: $--app-box-shadow;
&:not(.el-menu--collapse) {
width: 220px;
}
}
</style>
<template>
<el-menu
class="base-menu-tree"
v-bind="$attrs"
v-on="$listeners"
>
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<base-submenu-tree
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
:menuData="menu.children"
:popper-append-to-body="false"
></base-submenu-tree>
</template>
<template v-else>
<base-menu-item
:key="menu.index"
:index="menu.index"
:icon="menu.icon"
:name="menu.name"
></base-menu-item>
</template>
</template>
</el-menu>
</template>
<script>
import BaseSubmenuTree from './base-submenu-tree'
import BaseMenuItem from './base-menu-item'
export default {
name: 'BaseMenuTree',
components: {
BaseMenuItem,
BaseSubmenuTree
},
props: {
menuData: {
type: Array,
default() {
return []
}
}
}
}
</script>
<style lang="scss">
.el-menu.base-menu-tree {
border-right: 0;
padding: 16px 0;
max-height: calc(100vh - 64px);
overflow-y: auto;
background-color: $--app-light-color;
box-shadow: $--app-box-shadow;
&:not(.el-menu--collapse) {
width: 220px;
}
}
</style>

View File

@ -1,48 +1,48 @@
<template>
<div :class="className">
<span class="base-status-tag__text">{{ status === 'ENABLED' ? enableText : disableText }}</span>
</div>
</template>
<script>
export default {
name: 'BaseStatusTag',
props: {
status: String,
enableText: {
type: String,
default: '启用'
},
disableText: {
type: String,
default: '未启用'
}
},
computed: {
className() {
return `base-status-tag ${this.status ? 'is-enable' : 'is-disable'}`
}
}
}
</script>
<style lang="scss">
.base-status-tag {
display: flex;
align-items: center;
justify-content: center;
width: 52px;
height: 24px;
border-radius: 12px;
.base-status-tag__text {
font-size: $--app-font-size;
color: $--app-light-color;
}
&.is-enable {
background-color: $--app-active-color;
}
&.is-disable {
background-color: $--app-notice-color;
}
}
</style>
<template>
<div :class="className">
<span class="base-status-tag__text">{{ status === 'ENABLED' ? enableText : disableText }}</span>
</div>
</template>
<script>
export default {
name: 'BaseStatusTag',
props: {
status: String,
enableText: {
type: String,
default: '启用'
},
disableText: {
type: String,
default: '未启用'
}
},
computed: {
className() {
return `base-status-tag ${this.status ? 'is-enable' : 'is-disable'}`
}
}
}
</script>
<style lang="scss">
.base-status-tag {
display: flex;
align-items: center;
justify-content: center;
width: 52px;
height: 24px;
border-radius: 12px;
.base-status-tag__text {
font-size: $--app-font-size;
color: $--app-light-color;
}
&.is-enable {
background-color: $--app-active-color;
}
&.is-disable {
background-color: $--app-notice-color;
}
}
</style>

View File

@ -1,14 +1,14 @@
export default {
'input-code': {
codePlaceholder: '验证码',
codeBtnText: '发送验证码',
codeDisabledSuffixText: '无',
slideBlock: {
failText: '拖动滑块将悬浮图像正确拼合',
successText: '验证通过'
}
},
'input-password': {
placeholder: '密码'
}
}
export default {
'input-code': {
codePlaceholder: '验证码',
codeBtnText: '发送验证码',
codeDisabledSuffixText: '无',
slideBlock: {
failText: '拖动滑块将悬浮图像正确拼合',
successText: '验证通过'
}
},
'input-password': {
placeholder: '密码'
}
}

View File

@ -1,117 +1,117 @@
<template>
<div class="identify-code">
<el-popover
v-model="visiable"
trigger="click"
placement="top"
:popperClass="popperClass"
:disabled="!btnDisabled && disabled"
@show="handleShow"
@hide="handleHide"
>
<slide-block v-if="visiable" @success="handleSuccess"></slide-block>
<template v-if="disabled">
<el-button slot="reference" type="info" class="identigy-btn">
{{ count + $t('component.input-code.codeDisabledSuffixText') }}
</el-button>
</template>
<template v-else>
<el-button slot="reference" type="primary" class="identigy-btn" :disabled="btnDisabled" :loading="loading">
{{ loading ? '' : btnText }}
</el-button>
</template>
</el-popover>
</div>
</template>
<script>
import SlideBlock from './slide-block'
export default {
components: {
'slide-block': SlideBlock
},
props: {
'btnText': {
type: String,
default() {
return this.$t('component.input-code.codeBtnText')
}
},
'btnDisabled': {
type: Boolean,
default: false
},
'popperClass': {
type: String,
default: ''
}
},
data() {
return {
visiable: false,
disabled: false,
count: 60,
timer: null,
loading: false,
showCanvas: true
}
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
handleShow() {
this.visiable = true
this.$emit('show-popover')
},
handleHide() {
this.visiable = false
},
handleSuccess() {
this.handleHide()
this.loading = true
this.$emit('verify-success', (isNeedTimer) => {
this.loading = false
if (typeof isNeedTimer === 'undefined' || isNeedTimer) {
this.disabled = true
this.initTimer()
}
})
},
initTimer() {
this.count = 60
if (this.timer) clearInterval(this.timer)
this.timer = setInterval(() => {
this.count--
if (this.count === 0) {
this.disabled = false
}
}, 1000)
}
}
}
</script>
<style lang="scss" scoped>
.identify-code {
height: 34px;
line-height: 34px;
.identigy-btn {
width: 100px;
text-align: center;
padding: 0 !important;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
</style>
<style lang="scss">
.identify-code {
.el-button--info {
background-color: $--app-notice-color;
border-color: $--app-notice-color;
}
}
</style>
<template>
<div class="identify-code">
<el-popover
v-model="visiable"
trigger="click"
placement="top"
:popperClass="popperClass"
:disabled="!btnDisabled && disabled"
@show="handleShow"
@hide="handleHide"
>
<slide-block v-if="visiable" @success="handleSuccess"></slide-block>
<template v-if="disabled">
<el-button slot="reference" type="info" class="identigy-btn">
{{ count + $t('component.input-code.codeDisabledSuffixText') }}
</el-button>
</template>
<template v-else>
<el-button slot="reference" type="primary" class="identigy-btn" :disabled="btnDisabled" :loading="loading">
{{ loading ? '' : btnText }}
</el-button>
</template>
</el-popover>
</div>
</template>
<script>
import SlideBlock from './slide-block'
export default {
components: {
'slide-block': SlideBlock
},
props: {
'btnText': {
type: String,
default() {
return this.$t('component.input-code.codeBtnText')
}
},
'btnDisabled': {
type: Boolean,
default: false
},
'popperClass': {
type: String,
default: ''
}
},
data() {
return {
visiable: false,
disabled: false,
count: 60,
timer: null,
loading: false,
showCanvas: true
}
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
handleShow() {
this.visiable = true
this.$emit('show-popover')
},
handleHide() {
this.visiable = false
},
handleSuccess() {
this.handleHide()
this.loading = true
this.$emit('verify-success', (isNeedTimer) => {
this.loading = false
if (typeof isNeedTimer === 'undefined' || isNeedTimer) {
this.disabled = true
this.initTimer()
}
})
},
initTimer() {
this.count = 60
if (this.timer) clearInterval(this.timer)
this.timer = setInterval(() => {
this.count--
if (this.count === 0) {
this.disabled = false
}
}, 1000)
}
}
}
</script>
<style lang="scss" scoped>
.identify-code {
height: 34px;
line-height: 34px;
.identigy-btn {
width: 100px;
text-align: center;
padding: 0 !important;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
</style>
<style lang="scss">
.identify-code {
.el-button--info {
background-color: $--app-notice-color;
border-color: $--app-notice-color;
}
}
</style>

View File

@ -1,196 +1,196 @@
<template>
<div class="slide-block">
<div ref="canvas-container">
<canvas ref="canvas" width="260" height="160"></canvas>
</div>
</div>
</template>
<script>
import imgCaptcha from '@/assets/js/captcha.js'
export default {
props: {
'failText': {
type: String,
default() {
return this.$t('component.input-code.slideBlock.failText')
}
},
'successText': {
type: String,
default() {
return this.$t('component.input-code.slideBlock.successText')
}
}
},
mounted() {
this.$nextTick(() => {
const self = this
imgCaptcha(this.$refs.canvas, {
container: this.$refs['canvas-container'],
imgurl: [
`${this.$envUrl('/img/slide-block/1@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/2@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/3@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/4@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/5@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/6@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/7@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/8@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/9@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/10@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/11@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/12@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/13@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/14@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/15@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/16@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/17@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/18@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/19@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/20@2x.jpg')}`
],
cw: 50,
ch: 50,
successText: this.successText,
failText: this.failText,
onSuccess: function() {
setTimeout(() => {
self.$emit('success')
}, 1000)
},
onError: function() {
self.$emit('error')
}
})
})
}
}
</script>
<style lang="scss">
@keyframes shake {
0%,
to {
transform: translateZ(0);
}
5%,
10% {
transform: translate3d(-3px, 0, 0);
}
10%,
15% {
transform: translate3d(3px, 0, 0);
}
}
.captcha-box {
position: relative;
background: $--app-light-color;
border: 1px solid $--app-border-color;
padding: 0 10px;
box-sizing: content-box;
}
.captcha-box.shake {
animation: shake 0.5s;
}
.captcha-box .canvas-box {
overflow: hidden;
position: relative;
}
.canvas-box .captcha-result {
position: absolute;
left: 0;
width: 100%;
color: $--app-light-color;
bottom: -25px;
height: 24px;
text-indent: 16px;
font-size: 14px;
line-height: 24px;
-moz-transition: bottom 0.3s ease;
-o-transition: bottom 0.3s ease;
-webkit-transition: bottom 0.3s ease;
transition: bottom 0.3s ease;
}
.canvas-box .captcha-result.fail {
background-color: $--app-fail-color;
bottom: 0;
}
.canvas-box .captcha-result.success {
background-color: $--app-success-color;
bottom: 0;
}
.captcha-box .captcha-bg {
display: block;
}
.captcha-box .captcha-clipcanvas {
position: absolute;
left: 20px;
}
.captcha-box .captcha-dragbar {
margin-top: 5px;
margin-bottom: 10px;
padding-top: 8px;
position: relative;
box-sizing: border-box;
}
.captcha-dragbar .drag-track {
width: 100%;
height: 10px;
border-radius: 5px;
background: $--app-selected-color;
position: relative;
}
.captcha-dragbar .drag-slider {
width: 40px;
height: 30px;
position: absolute;
top: 0;
left: 10px;
background-color: $--app-sky-color;
background-image: url('~@/assets/img/slider.png');
background-position: center;
background-repeat: no-repeat;
background-size: 50%;
border-radius: 23px;
cursor: pointer;
}
.captcha-dragbar .drag-btn {
height: 22px;
margin-top: 10px;
}
.captcha-dragbar .drag-btn i {
float: right;
margin-right: 10px;
}
.captcha-dragbar .drag-btn .refresh {
cursor: pointer;
height: 22px;
width: 22px;
background: url('~@/assets/img/refresh.png') center no-repeat;
background-size: 100%;
}
.captcha-dragbar .drag-btn .close {
height: 22px;
width: 22px;
background: url('~@/assets/img/close.png') center no-repeat;
background-size: 100%;
}
.drag-box {
width: calc(100% - 16px);
height: 100%;
position: absolute;
top: 0;
z-index: -1;
cursor: pointer;
}
.drag-box-over {
z-index: 100;
cursor: pointer;
}
</style>
<template>
<div class="slide-block">
<div ref="canvas-container">
<canvas ref="canvas" width="260" height="160"></canvas>
</div>
</div>
</template>
<script>
import imgCaptcha from '@/assets/js/captcha.js'
export default {
props: {
'failText': {
type: String,
default() {
return this.$t('component.input-code.slideBlock.failText')
}
},
'successText': {
type: String,
default() {
return this.$t('component.input-code.slideBlock.successText')
}
}
},
mounted() {
this.$nextTick(() => {
const self = this
imgCaptcha(this.$refs.canvas, {
container: this.$refs['canvas-container'],
imgurl: [
`${this.$envUrl('/img/slide-block/1@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/2@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/3@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/4@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/5@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/6@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/7@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/8@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/9@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/10@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/11@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/12@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/13@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/14@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/15@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/16@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/17@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/18@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/19@2x.jpg')}`,
`${this.$envUrl('/img/slide-block/20@2x.jpg')}`
],
cw: 50,
ch: 50,
successText: this.successText,
failText: this.failText,
onSuccess: function() {
setTimeout(() => {
self.$emit('success')
}, 1000)
},
onError: function() {
self.$emit('error')
}
})
})
}
}
</script>
<style lang="scss">
@keyframes shake {
0%,
to {
transform: translateZ(0);
}
5%,
10% {
transform: translate3d(-3px, 0, 0);
}
10%,
15% {
transform: translate3d(3px, 0, 0);
}
}
.captcha-box {
position: relative;
background: $--app-light-color;
border: 1px solid $--app-border-color;
padding: 0 10px;
box-sizing: content-box;
}
.captcha-box.shake {
animation: shake 0.5s;
}
.captcha-box .canvas-box {
overflow: hidden;
position: relative;
}
.canvas-box .captcha-result {
position: absolute;
left: 0;
width: 100%;
color: $--app-light-color;
bottom: -25px;
height: 24px;
text-indent: 16px;
font-size: 14px;
line-height: 24px;
-moz-transition: bottom 0.3s ease;
-o-transition: bottom 0.3s ease;
-webkit-transition: bottom 0.3s ease;
transition: bottom 0.3s ease;
}
.canvas-box .captcha-result.fail {
background-color: $--app-fail-color;
bottom: 0;
}
.canvas-box .captcha-result.success {
background-color: $--app-success-color;
bottom: 0;
}
.captcha-box .captcha-bg {
display: block;
}
.captcha-box .captcha-clipcanvas {
position: absolute;
left: 20px;
}
.captcha-box .captcha-dragbar {
margin-top: 5px;
margin-bottom: 10px;
padding-top: 8px;
position: relative;
box-sizing: border-box;
}
.captcha-dragbar .drag-track {
width: 100%;
height: 10px;
border-radius: 5px;
background: $--app-selected-color;
position: relative;
}
.captcha-dragbar .drag-slider {
width: 40px;
height: 30px;
position: absolute;
top: 0;
left: 10px;
background-color: $--app-sky-color;
background-image: url('~@/assets/img/slider.png');
background-position: center;
background-repeat: no-repeat;
background-size: 50%;
border-radius: 23px;
cursor: pointer;
}
.captcha-dragbar .drag-btn {
height: 22px;
margin-top: 10px;
}
.captcha-dragbar .drag-btn i {
float: right;
margin-right: 10px;
}
.captcha-dragbar .drag-btn .refresh {
cursor: pointer;
height: 22px;
width: 22px;
background: url('~@/assets/img/refresh.png') center no-repeat;
background-size: 100%;
}
.captcha-dragbar .drag-btn .close {
height: 22px;
width: 22px;
background: url('~@/assets/img/close.png') center no-repeat;
background-size: 100%;
}
.drag-box {
width: calc(100% - 16px);
height: 100%;
position: absolute;
top: 0;
z-index: -1;
cursor: pointer;
}
.drag-box-over {
z-index: 100;
cursor: pointer;
}
</style>

View File

@ -1,58 +1,58 @@
<template>
<div class="input-code">
<el-input :value="value" :autocomplete="autocomplete" :placeholder="placeholder" type="text" :disabled="disabled" :maxlength="6" @input="handleInput">
<template v-slot:suffix>
<identify-code
:popperClass="popperClass"
:btnDisabled="disabled"
@show-popover="showPopover"
@verify-success="handleVerifySuccess"
></identify-code>
</template>
</el-input>
</div>
</template>
<script>
import IdentifyCode from './identify-code'
export default {
components: {
'identify-code': IdentifyCode
},
props: {
value: {
type: String,
default: ''
},
autocomplete: {
type: String,
default: 'off'
},
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default() {
return this.$t('component.input-code.codePlaceholder')
}
},
popperClass: {
type: String,
default: ''
}
},
methods: {
handleVerifySuccess(callback) {
this.$emit('verify-success', callback)
},
handleInput(value) {
this.$emit('input', value)
},
showPopover() {
this.$emit('show-popover')
}
}
}
</script>
<template>
<div class="input-code">
<el-input :value="value" :autocomplete="autocomplete" :placeholder="placeholder" type="text" :disabled="disabled" :maxlength="6" @input="handleInput">
<template v-slot:suffix>
<identify-code
:popperClass="popperClass"
:btnDisabled="disabled"
@show-popover="showPopover"
@verify-success="handleVerifySuccess"
></identify-code>
</template>
</el-input>
</div>
</template>
<script>
import IdentifyCode from './identify-code'
export default {
components: {
'identify-code': IdentifyCode
},
props: {
value: {
type: String,
default: ''
},
autocomplete: {
type: String,
default: 'off'
},
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default() {
return this.$t('component.input-code.codePlaceholder')
}
},
popperClass: {
type: String,
default: ''
}
},
methods: {
handleVerifySuccess(callback) {
this.$emit('verify-success', callback)
},
handleInput(value) {
this.$emit('input', value)
},
showPopover() {
this.$emit('show-popover')
}
}
}
</script>

View File

@ -1,79 +1,79 @@
<template>
<div class="input-password">
<el-input :value="value" :type="type" :autocomplete="autocomplete" :placeholder="placeholder" @input="handleInput">
<template v-slot:suffix>
<div v-if="showPassword" class="password-visiable" @click="toggleVisiable">
<x-svg-icon v-if="!visiable" class="visiable-icon" name="password-hide"></x-svg-icon>
<x-svg-icon v-else class="visiable-icon" name="password-show"></x-svg-icon>
</div>
</template>
</el-input>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
},
autocomplete: {
type: String,
default: 'off'
},
placeholder: {
type: String,
default() {
return this.$t('common.input-password.placeholder')
}
},
showPassword: {
type: Boolean,
default: true
}
},
data() {
return {
type: 'password',
visiable: false
}
},
methods: {
toggleVisiable() {
this.visiable = !this.visiable
if (this.visiable) {
this.type = 'text'
} else {
this.type = 'password'
}
},
handleInput(value) {
this.$emit('input', value)
}
}
}
</script>
<style lang="scss" scoped>
.input-password {
.password-visiable {
.visiable-icon {
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>
<style lang="scss">
.input-password {
.el-input__suffix {
display: flex;
justify-content: center;
align-items: center;
right: 8px !important;
}
}
</style>
<template>
<div class="input-password">
<el-input :value="value" :type="type" :autocomplete="autocomplete" :placeholder="placeholder" @input="handleInput">
<template v-slot:suffix>
<div v-if="showPassword" class="password-visiable" @click="toggleVisiable">
<x-svg-icon v-if="!visiable" class="visiable-icon" name="password-hide"></x-svg-icon>
<x-svg-icon v-else class="visiable-icon" name="password-show"></x-svg-icon>
</div>
</template>
</el-input>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
},
autocomplete: {
type: String,
default: 'off'
},
placeholder: {
type: String,
default() {
return this.$t('common.input-password.placeholder')
}
},
showPassword: {
type: Boolean,
default: true
}
},
data() {
return {
type: 'password',
visiable: false
}
},
methods: {
toggleVisiable() {
this.visiable = !this.visiable
if (this.visiable) {
this.type = 'text'
} else {
this.type = 'password'
}
},
handleInput(value) {
this.$emit('input', value)
}
}
}
</script>
<style lang="scss" scoped>
.input-password {
.password-visiable {
.visiable-icon {
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>
<style lang="scss">
.input-password {
.el-input__suffix {
display: flex;
justify-content: center;
align-items: center;
right: 8px !important;
}
}
</style>

View File

@ -1,220 +1,220 @@
<template>
<div class="menutree">
<label v-for="menu in menuData" :key="menu.id">
<el-submenu v-if="menu.menuType === 'GROUP'" class="menu-item" :index="menu.id">
<template slot="title">
<div class="menu-item-div">
<div
slot="title"
class="route-link router-link-parent"
:class="collapse ? 'route-link-min route-link-min-parent' : 'route-link-max'"
>
<template v-if="collapse">
<el-tooltip effect="dark" :content="menu.menuName" placement="top-start">
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</el-tooltip>
</template>
<template v-else>
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</template>
<div class="menu-title" :style="{ 'display' : collapse ? 'none' : 'flex' }">
<x-ellipsis :label="menu.menuName" mode="origin" :max-lines="1"></x-ellipsis>
</div>
</div>
</div>
</template>
<label>
<menu-tree
class="child-menu"
:menuData="menu.submenus"
:isChild="true"
@click-add-button="showAddModal"
></menu-tree>
</label>
</el-submenu>
<el-menu-item v-else class="menu-item" :index="menu.id">
<div class="menu-item-div" :class="isChild ? 'is-child' : ''">
<div
slot="title"
class="route-link"
:class="collapse ? 'route-link-min' : 'route-link-max'"
@click="toRouter(menu)"
>
<template v-if="collapse">
<el-tooltip effect="dark" :content="menu.menuName" placement="top-start">
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</el-tooltip>
</template>
<template v-else>
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</template>
<div class="menu-title" :style="{ 'display' : collapse ? 'none' : 'flex' }">
<x-ellipsis :label="menu.menuName" mode="origin" :max-lines="1"></x-ellipsis>
</div>
<template v-if="menu.menuType === 'MENU' && menu.canAddStatus">
<div class="add-icon" @click.prevent="clickAddButton($event, menu)">
<x-svg-icon name="menu-add-form" class="pointer"></x-svg-icon>
</div>
</template>
</div>
</div>
</el-menu-item>
</label>
</div>
</template>
<script>
import MenuTree from '@/components/menus-tree/index'
export default {
name: 'MenuTree',
components: {
MenuTree
},
props: {
menuData: {
type: Array,
default: function() {
return []
}
},
collapse: {
type: Boolean,
default: false
},
isChild: {
type: Boolean,
default: false
}
},
data() {
return {
menu_data: {}
}
},
methods: {
clickAddButton(event, data) {
event.stopPropagation()
this.$emit('click-add-button', data)
},
showAddModal(data) {
this.$emit('click-add-button', data)
},
timestamp() {
return new Date().getTime()
},
toRouter(menu) {
// t
if (menu.menuType === 'MENU') {
this.$router.push({ name: 'app-page', query: { appId: menu.appId, formId: menu.formId, title: menu.menuName, currentMenu: menu.id, t: this.timestamp() } })
} else {
this.$router.push({ name: 'report-page', query: { appId: menu.appId, formId: menu.formId, title: menu.menuName, currentMenu: menu.id, t: this.timestamp() } })
}
}
}
}
</script>
<style lang="scss">
.menutree {
.el-menu-item {
padding: 0 !important;
height: 44px!important;
line-height: 44px!important;
}
.is-child {
.route-link {
padding-left: 46px !important;
}
}
.menu-item {
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
.menu-item-div {
width: 100%;
.el-tooltip {
justify-content: center;
align-items: center;
}
.router-link-parent {
padding-left: 0 !important;
}
.route-link {
display: flex;
align-items: center;
width: 100%;
padding-left: 20px;
padding-right: 40px !important;
box-sizing: border-box;
color: unset;
.add-icon {
color: $--app-notice-color;
position: absolute;
right: 20px;
display: none;
}
.arrow-down-icon {
.svg-arrow-down-icon {
position: absolute;
right: 20px;
transform: scale(0.81);
color: $--app-description-color;
}
}
}
.route-link-min-parent {
padding-left: 28px !important;
}
.route-link-min {
height: 44px;
justify-content: center;
padding-left: 40px;
}
.route-link-max {
height: 44px;
padding-left: 20px;
}
.route-link:hover {
.add-icon {
display: block !important;
}
}
}
.el-menu {
&.el-menu--inline {
width: 100% !important;
}
}
}
.menu-title {
max-width: 80%;
margin-left: 12px;
white-space: normal;
font-size: $--app-title-fontSize;
.x-ellipsis {
max-width: 100%;
line-height: normal;
}
}
.menu-icon {
width: 14px;
height: 14px;
}
.x-svg-icon {
display: flex;
align-items: center;
}
.el-submenu__title {
width: 100%;
height: 44px;
line-height: 44px;
.el-submenu__icon-arrow {
right: 26px;
}
}
.child-menu {
.menu-item {
padding-left: 24px;
}
}
}
</style>
<template>
<div class="menutree">
<label v-for="menu in menuData" :key="menu.id">
<el-submenu v-if="menu.menuType === 'GROUP'" class="menu-item" :index="menu.id">
<template slot="title">
<div class="menu-item-div">
<div
slot="title"
class="route-link router-link-parent"
:class="collapse ? 'route-link-min route-link-min-parent' : 'route-link-max'"
>
<template v-if="collapse">
<el-tooltip effect="dark" :content="menu.menuName" placement="top-start">
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</el-tooltip>
</template>
<template v-else>
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</template>
<div class="menu-title" :style="{ 'display' : collapse ? 'none' : 'flex' }">
<x-ellipsis :label="menu.menuName" mode="origin" :max-lines="1"></x-ellipsis>
</div>
</div>
</div>
</template>
<label>
<menu-tree
class="child-menu"
:menuData="menu.submenus"
:isChild="true"
@click-add-button="showAddModal"
></menu-tree>
</label>
</el-submenu>
<el-menu-item v-else class="menu-item" :index="menu.id">
<div class="menu-item-div" :class="isChild ? 'is-child' : ''">
<div
slot="title"
class="route-link"
:class="collapse ? 'route-link-min' : 'route-link-max'"
@click="toRouter(menu)"
>
<template v-if="collapse">
<el-tooltip effect="dark" :content="menu.menuName" placement="top-start">
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</el-tooltip>
</template>
<template v-else>
<x-svg-icon class="menu-icon" :name="menu.menuIcon"></x-svg-icon>
</template>
<div class="menu-title" :style="{ 'display' : collapse ? 'none' : 'flex' }">
<x-ellipsis :label="menu.menuName" mode="origin" :max-lines="1"></x-ellipsis>
</div>
<template v-if="menu.menuType === 'MENU' && menu.canAddStatus">
<div class="add-icon" @click.prevent="clickAddButton($event, menu)">
<x-svg-icon name="menu-add-form" class="pointer"></x-svg-icon>
</div>
</template>
</div>
</div>
</el-menu-item>
</label>
</div>
</template>
<script>
import MenuTree from '@/components/menus-tree/index'
export default {
name: 'MenuTree',
components: {
MenuTree
},
props: {
menuData: {
type: Array,
default: function() {
return []
}
},
collapse: {
type: Boolean,
default: false
},
isChild: {
type: Boolean,
default: false
}
},
data() {
return {
menu_data: {}
}
},
methods: {
clickAddButton(event, data) {
event.stopPropagation()
this.$emit('click-add-button', data)
},
showAddModal(data) {
this.$emit('click-add-button', data)
},
timestamp() {
return new Date().getTime()
},
toRouter(menu) {
// t
if (menu.menuType === 'MENU') {
this.$router.push({ name: 'app-page', query: { appId: menu.appId, formId: menu.formId, title: menu.menuName, currentMenu: menu.id, t: this.timestamp() } })
} else {
this.$router.push({ name: 'report-page', query: { appId: menu.appId, formId: menu.formId, title: menu.menuName, currentMenu: menu.id, t: this.timestamp() } })
}
}
}
}
</script>
<style lang="scss">
.menutree {
.el-menu-item {
padding: 0 !important;
height: 44px!important;
line-height: 44px!important;
}
.is-child {
.route-link {
padding-left: 46px !important;
}
}
.menu-item {
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
.menu-item-div {
width: 100%;
.el-tooltip {
justify-content: center;
align-items: center;
}
.router-link-parent {
padding-left: 0 !important;
}
.route-link {
display: flex;
align-items: center;
width: 100%;
padding-left: 20px;
padding-right: 40px !important;
box-sizing: border-box;
color: unset;
.add-icon {
color: $--app-notice-color;
position: absolute;
right: 20px;
display: none;
}
.arrow-down-icon {
.svg-arrow-down-icon {
position: absolute;
right: 20px;
transform: scale(0.81);
color: $--app-description-color;
}
}
}
.route-link-min-parent {
padding-left: 28px !important;
}
.route-link-min {
height: 44px;
justify-content: center;
padding-left: 40px;
}
.route-link-max {
height: 44px;
padding-left: 20px;
}
.route-link:hover {
.add-icon {
display: block !important;
}
}
}
.el-menu {
&.el-menu--inline {
width: 100% !important;
}
}
}
.menu-title {
max-width: 80%;
margin-left: 12px;
white-space: normal;
font-size: $--app-title-fontSize;
.x-ellipsis {
max-width: 100%;
line-height: normal;
}
}
.menu-icon {
width: 14px;
height: 14px;
}
.x-svg-icon {
display: flex;
align-items: center;
}
.el-submenu__title {
width: 100%;
height: 44px;
line-height: 44px;
.el-submenu__icon-arrow {
right: 26px;
}
}
.child-menu {
.menu-item {
padding-left: 24px;
}
}
}
</style>

View File

@ -1,68 +1,68 @@
<!--
* @Author: your name
* @Date: 2020-05-30 12:25:09
* @LastEditTime: 2020-05-30 16:00:23
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/org-avatar/index.vue
-->
<template>
<div class="org-avatar">
<img v-if="iconUrl" class="org-icon" :src="iconUrl" alt="">
<div v-else class="org-icon no-icon">
{{ computOrgName[0] }}<br />{{ computOrgName[1] }}
</div>
</div>
</template>
<script>
export default {
name: 'OrgAvatar',
props: {
orgName: {
type: String,
required: true
},
iconUrl: {
type: String,
default: ''
}
},
data() {
return {}
},
computed: {
computOrgName: function () {
if (this.orgName) {
const orgName = this.orgName.slice(0, 4)
return [orgName.slice(0, 2), orgName.slice(2, 4)]
}
return ['', '']
}
}
}
</script>
<style lang="scss">
.org-avatar {
display: flex;
align-items: center;
width: 100%;
height: 100%;
.org-icon {
width: 100%;
height: 100%;
border-radius: 2px;
&.no-icon {
background-color: $--app-primary-color;
color: $--app-light-color;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: $--app-font-weight;
line-height: 18px;
}
}
}
</style>
<!--
* @Author: your name
* @Date: 2020-05-30 12:25:09
* @LastEditTime: 2020-05-30 16:00:23
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/org-avatar/index.vue
-->
<template>
<div class="org-avatar">
<img v-if="iconUrl" class="org-icon" :src="iconUrl" alt="">
<div v-else class="org-icon no-icon">
{{ computOrgName[0] }}<br />{{ computOrgName[1] }}
</div>
</div>
</template>
<script>
export default {
name: 'OrgAvatar',
props: {
orgName: {
type: String,
required: true
},
iconUrl: {
type: String,
default: ''
}
},
data() {
return {}
},
computed: {
computOrgName: function () {
if (this.orgName) {
const orgName = this.orgName.slice(0, 4)
return [orgName.slice(0, 2), orgName.slice(2, 4)]
}
return ['', '']
}
}
}
</script>
<style lang="scss">
.org-avatar {
display: flex;
align-items: center;
width: 100%;
height: 100%;
.org-icon {
width: 100%;
height: 100%;
border-radius: 2px;
&.no-icon {
background-color: $--app-primary-color;
color: $--app-light-color;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: $--app-font-weight;
line-height: 18px;
}
}
}
</style>

View File

@ -1,84 +1,84 @@
<!--
* @Author: your name
* @Date: 2020-07-02 10:56:20
* @LastEditTime: 2020-07-02 19:20:24
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/person-avatar/index.vue
-->
<template>
<div class="person-avatar">
<template v-if="avatarUrl">
<img class="img-avatar" :src="avatarRealUrl" alt="avatar">
</template>
<template v-else>
<div class="default-avatar" :style="{'background-color': defaultAvatarColor === 'primaryColor' ? '' : defaultAvatarColor}">
<span>{{ displayName }}</span>
</div>
</template>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
avatarUrl: {
type: String,
default: ''
},
personName: {
type: String,
default: ''
},
defaultAvatarColor: {
type: String,
default: 'primaryColor'
}
},
computed: {
...mapState({
token: state => state.authModule.token
}),
displayName: function () {
if (this.personName) {
return this.personName.slice(this.personName.length - 2, this.personName.length)
} else {
return ''
}
},
avatarRealUrl: function () {
return `${this.avatarUrl}&token=${this.token}`
}
}
}
</script>
<style lang="scss" scoped>
.person-avatar {
@include circleShape(24px);
display: flex;
align-items: center;
justify-content: center;
color: $--app-light-color;
overflow: hidden;
cursor: pointer;
.img-avatar {
width: 100%;
height: 100%;
border-radius: 50%;
}
.default-avatar {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: $--app-primary-color;
span {
@include fontSize(10px);
}
}
}
</style>
<!--
* @Author: your name
* @Date: 2020-07-02 10:56:20
* @LastEditTime: 2020-07-02 19:20:24
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/person-avatar/index.vue
-->
<template>
<div class="person-avatar">
<template v-if="avatarUrl">
<img class="img-avatar" :src="avatarRealUrl" alt="avatar">
</template>
<template v-else>
<div class="default-avatar" :style="{'background-color': defaultAvatarColor === 'primaryColor' ? '' : defaultAvatarColor}">
<span>{{ displayName }}</span>
</div>
</template>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
avatarUrl: {
type: String,
default: ''
},
personName: {
type: String,
default: ''
},
defaultAvatarColor: {
type: String,
default: 'primaryColor'
}
},
computed: {
...mapState({
token: state => state.authModule.token
}),
displayName: function () {
if (this.personName) {
return this.personName.slice(this.personName.length - 2, this.personName.length)
} else {
return ''
}
},
avatarRealUrl: function () {
return `${this.avatarUrl}&token=${this.token}`
}
}
}
</script>
<style lang="scss" scoped>
.person-avatar {
@include circleShape(24px);
display: flex;
align-items: center;
justify-content: center;
color: $--app-light-color;
overflow: hidden;
cursor: pointer;
.img-avatar {
width: 100%;
height: 100%;
border-radius: 50%;
}
.default-avatar {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: $--app-primary-color;
span {
@include fontSize(10px);
}
}
}
</style>

View File

@ -1,75 +1,75 @@
<!--
* @Author: your name
* @Date: 2020-05-26 17:59:30
* @LastEditTime: 2020-05-27 18:48:29
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/person-name/index.vue
-->
<template>
<div class="person-name">
<div class="icon">
{{ displayName }}
</div>
<div v-if="showTag" class="real-name">
{{ name }}
</div>
</div>
</template>
<script>
export default {
name: 'PersonName',
props: {
name: {
type: String,
required: true
},
showTag: {
type: Boolean,
default: function () {
return true
}
}
},
computed: {
displayName: function () {
if (this.name) {
return this.name.slice(this.name.length - 2, this.name.length)
}
return ''
}
}
}
</script>
<style lang="scss">
.person-name {
display: flex;
align-items: center;
position: relative;
.icon {
position: absolute;
left: -4px;
padding: 2px;
@include circleShape(24px);
@include fontSize(10px);
background-color: $--app-primary-color;
display: flex;
align-items: center;
justify-content: center;
color: $--app-light-color;
}
.real-name {
padding: 0 8px;
height: 24px;
padding-left: 32px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background-color: $--app-info-color;
}
}
</style>
<!--
* @Author: your name
* @Date: 2020-05-26 17:59:30
* @LastEditTime: 2020-05-27 18:48:29
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /x-product-workspace/packages/x-project-app/src/components/person-name/index.vue
-->
<template>
<div class="person-name">
<div class="icon">
{{ displayName }}
</div>
<div v-if="showTag" class="real-name">
{{ name }}
</div>
</div>
</template>
<script>
export default {
name: 'PersonName',
props: {
name: {
type: String,
required: true
},
showTag: {
type: Boolean,
default: function () {
return true
}
}
},
computed: {
displayName: function () {
if (this.name) {
return this.name.slice(this.name.length - 2, this.name.length)
}
return ''
}
}
}
</script>
<style lang="scss">
.person-name {
display: flex;
align-items: center;
position: relative;
.icon {
position: absolute;
left: -4px;
padding: 2px;
@include circleShape(24px);
@include fontSize(10px);
background-color: $--app-primary-color;
display: flex;
align-items: center;
justify-content: center;
color: $--app-light-color;
}
.real-name {
padding: 0 8px;
height: 24px;
padding-left: 32px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background-color: $--app-info-color;
}
}
</style>

View File

@ -1,12 +1,12 @@
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-list-demo"],
"list": {
"apaas-custom-list-view-demo": {
"renderLogic": "FORM_LIST_VIEW",
"desc": "描述",
"status": "ENABLE"
}
},
"outputName": "apaas-custom-list-demo"
}
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-list-demo"],
"list": {
"apaas-custom-list-view-demo": {
"renderLogic": "FORM_LIST_VIEW",
"desc": "描述",
"status": "ENABLE"
}
},
"outputName": "apaas-custom-list-demo"
}

View File

@ -1,184 +1,184 @@
<template>
<div class="custom-list-view">
<x-list-view
:listEngine="listEngine"
>
<template v-slot:listSearch>
<div></div>
</template>
<template v-slot:listTable>
<x-list-table ref="listTable">
<template v-slot:customHeadSlot="scopeSlot">
<div class="custom-list-view-header" @keyup.enter="handlerSearch">
<x-ellipsis class="custom-list-view-label" :label="scopeSlot.column.label" mode="origin" />
<div class="custom-list-view-search">
<el-form :inline="formInline" @submit.native.prevent>
<component
:is="getSearchComponent(scopeSlot.column.property)"
v-if="getSearchComponent(scopeSlot.column.property)"
:value="searchValue(scopeSlot.column.property)"
:compInfo="getComponentConfig(scopeSlot.column.property)"
:tileFormComponent="getComponentConfig(scopeSlot.column.property)"
:showOpt="false"
@change="searchValueChange($event, scopeSlot.column.property)"
></component>
</el-form>
</div>
</div>
</template>
</x-list-table>
</template>
</x-list-view>
</div>
</template>
<script>
import CustomInputSearchItem from './search-compont/custom-input-search-item'
export default {
name: 'CustomListViewDemo',
components: {
CustomInputSearchItem
},
props: {
listEngine: {
type: Object
}
},
data() {
return {
formInline: false
}
},
computed: {
searchComponentConfig() {
return (this.listEngine && this.listEngine.listDataControl.searchComponentConfig) || []
},
getSearchComponent() {
return function(uuid) {
const componetConfig = this.allTiledComps.find(item => item.uuid === uuid) || {}
const searchComponentConfig = this.searchComponentConfig.find(item => item.componentType === componetConfig.componentType)
if (searchComponentConfig && searchComponentConfig.searchComponent) {
// 使apaas
if (componetConfig.componentType === 'FORM_TEXT_INPUT') {
return 'custom-input-search-item'
}
return searchComponentConfig.searchComponent + '-search-item'
} else {
return undefined
}
}
},
allTiledComps() {
return (this.listEngine && this.listEngine.listDataControl.allTiledComps) || []
},
getComponentConfig() {
return function(uuid) {
return this.allTiledComps.find((comp) => comp.uuid === uuid)
}
},
searchList() {
return (this.listEngine && this.listEngine.listDataControl.searchList) || []
},
searchValue() {
return function(uuid) {
const searchConfig = this.searchList.find(item => item.componentUuid === uuid)
return (searchConfig && searchConfig.params) || []
}
}
},
methods: {
searchValueChange(value, uuid) {
const searchConfig = this.searchList.find(item => item.componentUuid === uuid)
if (searchConfig && searchConfig.params) {
searchConfig.params = value
}
},
//
handlerSearch(e) {
e.stopPropagation()
e.preventDefault()
this.listEngine.listDataControl.tableConfig.pagination.currentPage = 1
this.listEngine.listDataControl.destroyVirtualAdvanceSearch()
this.listEngine.actionControl.executeActionWithSync('DO_LIST_SEARCH')
}
}
}
</script>
<style lang="scss">
.custom-list-view {
height: 100%;
.custom-list-view-label {
height: 40px;
}
.custom-list-view-search {
border-top: 1px solid #e8eaec;
margin: 0 -10px;
height: 40px;
//
.el-input, .el-date-editor {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
* {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
}
}
.el-form {
.el-form-item {
margin: 0 2px;
//
.el-form-item__label {
display: none;
}
.el-form-item__content {
line-height: 40px !important;
padding: 0;
margin: 0;
}
}
//
.x-lov-switch-search-item {
//
.title-label {
display: none;
}
.x-select {
height: 40px;
position: relative;
background-color: #fafafa;
.form-select-input {
top: 50%;
transform: translateY(-50%);
}
.select-input-tag {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
height: 32px;
z-index: 0;
}
.x-select-suffix {
z-index: 1;
}
}
}
//
.x-number-search-item, .x-money-search-item {
.range-item-divide {
margin: 0;
}
}
.el-select .el-input .el-select__caret {
font-size: 14px !important;
top: 0px;
}
}
}
}
</style>
<template>
<div class="custom-list-view">
<x-list-view
:listEngine="listEngine"
>
<template v-slot:listSearch>
<div></div>
</template>
<template v-slot:listTable>
<x-list-table ref="listTable">
<template v-slot:customHeadSlot="scopeSlot">
<div class="custom-list-view-header" @keyup.enter="handlerSearch">
<x-ellipsis class="custom-list-view-label" :label="scopeSlot.column.label" mode="origin" />
<div class="custom-list-view-search">
<el-form :inline="formInline" @submit.native.prevent>
<component
:is="getSearchComponent(scopeSlot.column.property)"
v-if="getSearchComponent(scopeSlot.column.property)"
:value="searchValue(scopeSlot.column.property)"
:compInfo="getComponentConfig(scopeSlot.column.property)"
:tileFormComponent="getComponentConfig(scopeSlot.column.property)"
:showOpt="false"
@change="searchValueChange($event, scopeSlot.column.property)"
></component>
</el-form>
</div>
</div>
</template>
</x-list-table>
</template>
</x-list-view>
</div>
</template>
<script>
import CustomInputSearchItem from './search-compont/custom-input-search-item'
export default {
name: 'CustomListViewDemo',
components: {
CustomInputSearchItem
},
props: {
listEngine: {
type: Object
}
},
data() {
return {
formInline: false
}
},
computed: {
searchComponentConfig() {
return (this.listEngine && this.listEngine.listDataControl.searchComponentConfig) || []
},
getSearchComponent() {
return function(uuid) {
const componetConfig = this.allTiledComps.find(item => item.uuid === uuid) || {}
const searchComponentConfig = this.searchComponentConfig.find(item => item.componentType === componetConfig.componentType)
if (searchComponentConfig && searchComponentConfig.searchComponent) {
// 使apaas
if (componetConfig.componentType === 'FORM_TEXT_INPUT') {
return 'custom-input-search-item'
}
return searchComponentConfig.searchComponent + '-search-item'
} else {
return undefined
}
}
},
allTiledComps() {
return (this.listEngine && this.listEngine.listDataControl.allTiledComps) || []
},
getComponentConfig() {
return function(uuid) {
return this.allTiledComps.find((comp) => comp.uuid === uuid)
}
},
searchList() {
return (this.listEngine && this.listEngine.listDataControl.searchList) || []
},
searchValue() {
return function(uuid) {
const searchConfig = this.searchList.find(item => item.componentUuid === uuid)
return (searchConfig && searchConfig.params) || []
}
}
},
methods: {
searchValueChange(value, uuid) {
const searchConfig = this.searchList.find(item => item.componentUuid === uuid)
if (searchConfig && searchConfig.params) {
searchConfig.params = value
}
},
//
handlerSearch(e) {
e.stopPropagation()
e.preventDefault()
this.listEngine.listDataControl.tableConfig.pagination.currentPage = 1
this.listEngine.listDataControl.destroyVirtualAdvanceSearch()
this.listEngine.actionControl.executeActionWithSync('DO_LIST_SEARCH')
}
}
}
</script>
<style lang="scss">
.custom-list-view {
height: 100%;
.custom-list-view-label {
height: 40px;
}
.custom-list-view-search {
border-top: 1px solid #e8eaec;
margin: 0 -10px;
height: 40px;
//
.el-input, .el-date-editor {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
* {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
}
}
.el-form {
.el-form-item {
margin: 0 2px;
//
.el-form-item__label {
display: none;
}
.el-form-item__content {
line-height: 40px !important;
padding: 0;
margin: 0;
}
}
//
.x-lov-switch-search-item {
//
.title-label {
display: none;
}
.x-select {
height: 40px;
position: relative;
background-color: #fafafa;
.form-select-input {
top: 50%;
transform: translateY(-50%);
}
.select-input-tag {
border: none;
border-radius: 0;
outline: none;
background-color: #fafafa;
height: 32px;
z-index: 0;
}
.x-select-suffix {
z-index: 1;
}
}
}
//
.x-number-search-item, .x-money-search-item {
.range-item-divide {
margin: 0;
}
}
.el-select .el-input .el-select__caret {
font-size: 14px !important;
top: 0px;
}
}
}
}
</style>

View File

@ -1,68 +1,68 @@
<template>
<div class="custom-input-search-item">
<el-form-item>
<!-- <template slot="label">
<x-ellipsis
class="fix-cursor"
mode="origin"
:openDelay="300"
:label="compInfo.label"
></x-ellipsis>
</template> -->
<el-input
v-model="computeValue[0]"
:placeholder="'请输入'"
@input="change"
></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'CustomInputSearchItem',
model: {
prop: 'value',
event: 'change'
},
props: {
compInfo: {
type: Object,
default: function() {
return {}
}
},
value: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {}
},
computed: {
computeValue: {
get: function() {
return this.value
},
set: function(value) {
this.$emit('change', value)
}
}
},
watch: {},
methods: {
change(e) {
if (e === '') {
this.computeValue = []
}
}
}
}
</script>
<style lang="scss">
// .custom-input-search-item {
// }
</style>
<template>
<div class="custom-input-search-item">
<el-form-item>
<!-- <template slot="label">
<x-ellipsis
class="fix-cursor"
mode="origin"
:openDelay="300"
:label="compInfo.label"
></x-ellipsis>
</template> -->
<el-input
v-model="computeValue[0]"
:placeholder="'请输入'"
@input="change"
></el-input>
</el-form-item>
</div>
</template>
<script>
export default {
name: 'CustomInputSearchItem',
model: {
prop: 'value',
event: 'change'
},
props: {
compInfo: {
type: Object,
default: function() {
return {}
}
},
value: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {}
},
computed: {
computeValue: {
get: function() {
return this.value
},
set: function(value) {
this.$emit('change', value)
}
}
},
watch: {},
methods: {
change(e) {
if (e === '') {
this.computeValue = []
}
}
}
}
</script>
<style lang="scss">
// .custom-input-search-item {
// }
</style>

View File

@ -1,11 +1,11 @@
import CustomListViewDemo from './custom-list/custom-list-view.vue'
const install = function(Vue, opts) {
Vue.component('apaas-custom-list-view-demo', CustomListViewDemo)
}
const ListDemoCustomPlugin = {
install: install
}
export default ListDemoCustomPlugin
import CustomListViewDemo from './custom-list/custom-list-view.vue'
const install = function(Vue, opts) {
Vue.component('apaas-custom-list-view-demo', CustomListViewDemo)
}
const ListDemoCustomPlugin = {
install: install
}
export default ListDemoCustomPlugin

View File

@ -1,160 +1,167 @@
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-mydemo"],
"router": {
"apaas-custom-modalContorl":{
"name": "apaas-custom-modalContorl",
"path": "apaas-custom-modalContorl",
"meta": {
"title": "模板管理"
}
},
"apaas-custom-selfEnginedata":{
"name": "apaas-custom-selfEnginedata",
"path": "apaas-custom-selfEnginedata",
"meta": {
"title": "玉柴发动机数据"
}
},
"apaas-custom-otherEnginedata":{
"name": "apaas-custom-otherEnginedata",
"path": "apaas-custom-otherEnginedata",
"meta": {
"title": "竞品发动机数据"
}
},
"apaas-custom-checkData":{
"name": "apaas-custom-checkData",
"path": "apaas-custom-checkData",
"meta": {
"title": "数据检查"
}
},
"apaas-custom-report":{
"name": "apaas-custom-report",
"path": "apaas-custom-report",
"meta": {
"title": "对标报告"
}
},
"apaas-custom-reportList":{
"name": "apaas-custom-reportList",
"path": "apaas-custom-reportList",
"meta": {
"title": "报告列表"
}
},
"apaas-custom-reportDetail":{
"name": "apaas-custom-reportDetail",
"path": "apaas-custom-reportDetail",
"meta": {
"title": "报告详情"
}
},
"apaas-custom-reportCheck":{
"name": "apaas-custom-reportCheck",
"path": "apaas-custom-reportCheck",
"meta": {
"title": "报告检查"
}
},
"apaas-custom-modelDetail":{
"name": "apaas-custom-modelDetail",
"path": "apaas-custom-modelDetail",
"meta": {
"title": "系统参数管理"
}
},
"apaas-custom-engineDetail":{
"name": "apaas-custom-engineDetail",
"path": "apaas-custom-engineDetail",
"meta": {
"title": "发动机参数详情"
}
},
"apaas-custom-approvalManagement":{
"name": "apaas-custom-approvalManagement",
"path": "apaas-custom-approvalManagement",
"meta": {
"title": "模板审批管理"
}
},
"apaas-custom-toDoList":{
"name": "apaas-custom-toDoList",
"path": "apaas-custom-toDoList",
"meta": {
"title": "数据待办"
}
},
"apaas-custom-myDone":{
"name": "apaas-custom-myDone",
"path": "apaas-custom-myDone",
"meta": {
"title": "我的已办"
}
},
"apaas-custom-mySend":{
"name": "apaas-custom-mySend",
"path": "apaas-custom-mySend",
"meta": {
"title": "我发起的"
}
},
"apaas-custom-myDemo":{
"name": "apaas-custom-myDemo",
"path": "apaas-custom-myDemo",
"meta": {
"title": "我的测试"
}
},
"apaas-custom-selfEngineCheck":{
"name": "apaas-custom-selfEngineCheck",
"path": "apaas-custom-selfEngineCheck",
"meta": {
"title": "玉柴发动机审核"
}
},
"apaas-custom-otherEngineCheck":{
"name": "apaas-custom-otherEngineCheck",
"path": "apaas-custom-otherEngineCheck",
"meta": {
"title": "竞品发动机审核"
}
},
"apaas-custom-managerData":{
"name": "apaas-custom-managerData",
"path": "apaas-custom-managerData",
"meta": {
"title": "责任人管理"
}
},
"apaas-custom-fillerData":{
"name": "apaas-custom-fillerData",
"path": "apaas-custom-fillerData",
"meta": {
"title": "填写人管理"
}
},
"apaas-custom-permissionManagement":{
"name": "apaas-custom-permissionManagement",
"path": "apaas-custom-permissionManagement",
"meta": {
"title": "权限管理"
}
},
"apaas-custom-checkPersonPermission":{
"name": "apaas-custom-checkPersonPermission",
"path": "apaas-custom-checkPersonPermission",
"meta": {
"title": "权限检查"
}
}
},
"customWidgetList": [
{
"code": "mydemo",
"text": "mydemo"
}
],
"outputName": "apaas-custom-mydemo"
}
{
"entry": "index.js",
"copyAssets": ["public/custom/apaas-custom-mydemo"],
"router": {
"apaas-custom-modalContorl":{
"name": "apaas-custom-modalContorl",
"path": "apaas-custom-modalContorl",
"meta": {
"title": "模板管理"
}
},
"apaas-custom-selfEnginedata":{
"name": "apaas-custom-selfEnginedata",
"path": "apaas-custom-selfEnginedata",
"meta": {
"title": "玉柴发动机数据"
}
},
"apaas-custom-otherEnginedata":{
"name": "apaas-custom-otherEnginedata",
"path": "apaas-custom-otherEnginedata",
"meta": {
"title": "竞品发动机数据"
}
},
"apaas-custom-checkData":{
"name": "apaas-custom-checkData",
"path": "apaas-custom-checkData",
"meta": {
"title": "数据检查"
}
},
"apaas-custom-report":{
"name": "apaas-custom-report",
"path": "apaas-custom-report",
"meta": {
"title": "对标报告"
}
},
"apaas-custom-reportList":{
"name": "apaas-custom-reportList",
"path": "apaas-custom-reportList",
"meta": {
"title": "报告列表"
}
},
"apaas-custom-reportDetail":{
"name": "apaas-custom-reportDetail",
"path": "apaas-custom-reportDetail",
"meta": {
"title": "报告详情"
}
},
"apaas-custom-reportCheck":{
"name": "apaas-custom-reportCheck",
"path": "apaas-custom-reportCheck",
"meta": {
"title": "报告检查"
}
},
"apaas-custom-modelDetail":{
"name": "apaas-custom-modelDetail",
"path": "apaas-custom-modelDetail",
"meta": {
"title": "系统参数管理"
}
},
"apaas-custom-engineDetail":{
"name": "apaas-custom-engineDetail",
"path": "apaas-custom-engineDetail",
"meta": {
"title": "发动机参数详情"
}
},
"apaas-custom-approvalManagement":{
"name": "apaas-custom-approvalManagement",
"path": "apaas-custom-approvalManagement",
"meta": {
"title": "模板审批管理"
}
},
"apaas-custom-toDoList":{
"name": "apaas-custom-toDoList",
"path": "apaas-custom-toDoList",
"meta": {
"title": "数据待办"
}
},
"apaas-custom-myDone":{
"name": "apaas-custom-myDone",
"path": "apaas-custom-myDone",
"meta": {
"title": "我的已办"
}
},
"apaas-custom-mySend":{
"name": "apaas-custom-mySend",
"path": "apaas-custom-mySend",
"meta": {
"title": "我发起的"
}
},
"apaas-custom-myDemo":{
"name": "apaas-custom-myDemo",
"path": "apaas-custom-myDemo",
"meta": {
"title": "我的测试"
}
},
"apaas-custom-selfEngineCheck":{
"name": "apaas-custom-selfEngineCheck",
"path": "apaas-custom-selfEngineCheck",
"meta": {
"title": "玉柴发动机审核"
}
},
"apaas-custom-otherEngineCheck":{
"name": "apaas-custom-otherEngineCheck",
"path": "apaas-custom-otherEngineCheck",
"meta": {
"title": "竞品发动机审核"
}
},
"apaas-custom-managerData":{
"name": "apaas-custom-managerData",
"path": "apaas-custom-managerData",
"meta": {
"title": "责任人管理"
}
},
"apaas-custom-fillerData":{
"name": "apaas-custom-fillerData",
"path": "apaas-custom-fillerData",
"meta": {
"title": "填写人管理"
}
},
"apaas-custom-permissionManagement":{
"name": "apaas-custom-permissionManagement",
"path": "apaas-custom-permissionManagement",
"meta": {
"title": "权限管理"
}
},
"apaas-custom-roleMemberManagement":{
"name": "apaas-custom-roleMemberManagement",
"path": "apaas-custom-roleMemberManagement",
"meta": {
"title": "人员管理"
}
},
"apaas-custom-checkPersonPermission":{
"name": "apaas-custom-checkPersonPermission",
"path": "apaas-custom-checkPersonPermission",
"meta": {
"title": "权限检查"
}
}
},
"customWidgetList": [
{
"code": "mydemo",
"text": "mydemo"
}
],
"outputName": "apaas-custom-mydemo"
}

View File

@ -1,11 +1,11 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:00:51
* @LastEditTime: 2021-07-08 16:07:03
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/edit/index.js
*/
const editFormComponentList = [] /* vue组件的集合 */
export default editFormComponentList
/*
* @Author: your name
* @Date: 2021-07-08 16:00:51
* @LastEditTime: 2021-07-08 16:07:03
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/edit/index.js
*/
const editFormComponentList = [] /* vue组件的集合 */
export default editFormComponentList

View File

@ -1,11 +1,11 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:01:44
* @LastEditTime: 2021-07-08 16:16:29
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/ide/index.js
*/
const ideFormComponentList = [] /* vue组件的集合 */
export default ideFormComponentList
/*
* @Author: your name
* @Date: 2021-07-08 16:01:44
* @LastEditTime: 2021-07-08 16:16:29
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/ide/index.js
*/
const ideFormComponentList = [] /* vue组件的集合 */
export default ideFormComponentList

View File

@ -1,19 +1,19 @@
/*
* @Author: your name
* @Date: 2021-07-06 12:00:52
* @LastEditTime: 2021-07-08 16:06:47
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/index.js
*/
import ideFormComponentList from './ide'
import editFormComponentList from './edit'
import readFormComponentList from './read'
const customFormComponentList = [
...ideFormComponentList,
...editFormComponentList,
...readFormComponentList
]
export default customFormComponentList
/*
* @Author: your name
* @Date: 2021-07-06 12:00:52
* @LastEditTime: 2021-07-08 16:06:47
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/index.js
*/
import ideFormComponentList from './ide'
import editFormComponentList from './edit'
import readFormComponentList from './read'
const customFormComponentList = [
...ideFormComponentList,
...editFormComponentList,
...readFormComponentList
]
export default customFormComponentList

View File

@ -1,11 +1,11 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:02:09
* @LastEditTime: 2021-07-08 16:16:36
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/read/index.js
*/
const readFormComponentList = [] /* vue组件的集合 */
export default readFormComponentList
/*
* @Author: your name
* @Date: 2021-07-08 16:02:09
* @LastEditTime: 2021-07-08 16:16:36
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-components/form-widget/read/index.js
*/
const readFormComponentList = [] /* vue组件的集合 */
export default readFormComponentList

View File

@ -1,9 +1,9 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:18:27
* @LastEditTime: 2021-07-08 16:20:06
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-component/index.js
*/
export { default as customFormComponentList } from './form-widget'
/*
* @Author: your name
* @Date: 2021-07-08 16:18:27
* @LastEditTime: 2021-07-08 16:20:06
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-component/index.js
*/
export { default as customFormComponentList } from './form-widget'

View File

@ -1,11 +1,11 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:05:38
* @LastEditTime: 2021-07-08 16:07:43
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-config/form-widget/index.js
*/
const widgetConfigList = []
export default widgetConfigList
/*
* @Author: your name
* @Date: 2021-07-08 16:05:38
* @LastEditTime: 2021-07-08 16:07:43
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-config/form-widget/index.js
*/
const widgetConfigList = []
export default widgetConfigList

View File

@ -1,13 +1,13 @@
/*
* @Author: your name
* @Date: 2021-07-08 16:07:54
* @LastEditTime: 2021-07-08 16:11:02
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-config/index.js
*/
import widgetConfigList from './form-widget'
export {
widgetConfigList
}
/*
* @Author: your name
* @Date: 2021-07-08 16:07:54
* @LastEditTime: 2021-07-08 16:11:02
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: /apaas-custom-vue-starter/src/custom/apaas-custom-hello/form-config/index.js
*/
import widgetConfigList from './form-widget'
export {
widgetConfigList
}

View File

@ -1,171 +1,171 @@
<template>
<x-app-layout :layoutEngine="layoutEngine" :isCollapse="isCollapse">
<template v-slot:header>
<x-app-header v-if="appInfo" :layoutEngine="layoutEngine" :appInfo="appInfo"></x-app-header>
</template>
<template v-slot:menu>
<x-app-menu
:menuConfig="menuConfig"
:showMenu="showMenu && !!appInfo"
:isCollapse="isCollapse"
:layoutEngine="layoutEngine"
@menu-add-click="menuAddClick"
></x-app-menu>
</template>
<template slot="appPage">
<div class="menu-switch" @click="changeCollapse">
<x-svg-icon v-if="isCollapse" name="arrow-right-icon"></x-svg-icon>
<x-svg-icon v-else name="arrow-left-icon"></x-svg-icon>
</div>
<!-- <div v-for="menu of layoutEngine.layoutConfig.keepAliveComps" :key="menu.id">
<div :style="{color: menu.id === layoutEngine.layoutConfig.currentMenu.id ? 'red' : '#000'}" @click="handlerclick(menu)">
{{ menu.menuName }}
<el-button @click.stop="closed(menu)">关闭</el-button>
</div>
</div> -->
<slot name="appPage"></slot>
</template>
</x-app-layout>
</template>
<script>
import api from '@/api'
import { getUserId } from '@/utils'
export default {
name: 'CustomLayout',
props: {
layoutEngine: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
isCollapse: false,
showMenu: true,
badgeNum: 0
}
},
computed: {
appInfo() {
return (
(this.layoutEngine &&
this.layoutEngine.layoutDataControl &&
this.layoutEngine.layoutDataControl.appInfo) ||
{}
)
},
menuConfig() {
// 访 $route.fullPath 使
void this.$route.fullPath
const data = (this.layoutEngine &&
this.layoutEngine.layoutDataControl &&
this.layoutEngine.layoutDataControl.menuConfig) || {
menu: [],
defaultActive: null,
menuTreeData: []
}
console.log(data, 2222323232, 'data')
data.menuTreeData[0].badgeNum = this.badgeNum
return data
}
},
watch: {
$route: {
handler() {
console.log(2222323232, '2222323232')
this.setBadgeNum()
},
immediate: false
}
},
mounted() {
console.log(this.layoutEngine.layoutConfig.keepAliveComps, 545454545454545454545454)
},
methods: {
setBadgeNum() {
const request = {
...api.GET_TODO_LIST,
params: {
page: 1,
size: 10,
personId: getUserId()
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen((resp) => {
this.badgeNum = resp.data.totalCount
})
.asyncErrorCatch((err) => {
console.error('获取待办列表失败:', err)
})
},
changeCollapse() {
this.showMenu = false
this.$nextTick(() => {
this.isCollapse = !this.isCollapse
this.showMenu = true
})
},
menuAddClick(e) {
this.$emit('menu-add-click', e)
},
closed(menu) {
const currentMenuId = this.layoutEngine.layoutConfig.currentMenu.id
this.layoutEngine.removeKeepAliveComps(menu)
if (menu.id === currentMenuId) {
this.layoutEngine.actionControl.executeActionWithSync('TO_ROUTER', {
menu: this.layoutEngine.layoutConfig.currentMenu
})
}
},
handlerclick(menu) {
this.layoutEngine.addKeepAliveComps(menu)
this.layoutEngine.actionControl.executeActionWithSync('TO_ROUTER', {
menu: this.layoutEngine.layoutConfig.currentMenu
})
}
}
}
</script>
<style lang="scss">
$--app-box-bgColor: #ffffff;
$--app-box-border-color: #dcdfe6;
.x-app-layout {
.layout-middle {
.layout-center {
.menu-switch {
width: 14px;
height: 80px;
padding-right: 2px;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
border: 1px solid $--app-box-bgColor;
border-left: 0;
background-color: $--app-box-bgColor;
position: absolute;
top: calc(50vh - 87px);
left: -20px;
transform: translateX(120%);
cursor: pointer;
opacity: 0.5;
display: flex;
justify-content: center;
align-items: center;
z-index: 500;
border: 1px solid $--app-box-border-color;
border-left: none;
}
.menu-switch:hover {
background-color: $--app-box-bgColor;
opacity: 1;
box-shadow: 2px 0px 4px 0px $--app-box-border-color;
}
}
}
}
</style>
<template>
<x-app-layout :layoutEngine="layoutEngine" :isCollapse="isCollapse">
<template v-slot:header>
<x-app-header v-if="appInfo" :layoutEngine="layoutEngine" :appInfo="appInfo"></x-app-header>
</template>
<template v-slot:menu>
<x-app-menu
:menuConfig="menuConfig"
:showMenu="showMenu && !!appInfo"
:isCollapse="isCollapse"
:layoutEngine="layoutEngine"
@menu-add-click="menuAddClick"
></x-app-menu>
</template>
<template slot="appPage">
<div class="menu-switch" @click="changeCollapse">
<x-svg-icon v-if="isCollapse" name="arrow-right-icon"></x-svg-icon>
<x-svg-icon v-else name="arrow-left-icon"></x-svg-icon>
</div>
<!-- <div v-for="menu of layoutEngine.layoutConfig.keepAliveComps" :key="menu.id">
<div :style="{color: menu.id === layoutEngine.layoutConfig.currentMenu.id ? 'red' : '#000'}" @click="handlerclick(menu)">
{{ menu.menuName }}
<el-button @click.stop="closed(menu)">关闭</el-button>
</div>
</div> -->
<slot name="appPage"></slot>
</template>
</x-app-layout>
</template>
<script>
import api from '@/api'
import { getUserId } from '@/utils'
export default {
name: 'CustomLayout',
props: {
layoutEngine: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
isCollapse: false,
showMenu: true,
badgeNum: 0
}
},
computed: {
appInfo() {
return (
(this.layoutEngine &&
this.layoutEngine.layoutDataControl &&
this.layoutEngine.layoutDataControl.appInfo) ||
{}
)
},
menuConfig() {
// 访 $route.fullPath 使
void this.$route.fullPath
const data = (this.layoutEngine &&
this.layoutEngine.layoutDataControl &&
this.layoutEngine.layoutDataControl.menuConfig) || {
menu: [],
defaultActive: null,
menuTreeData: []
}
console.log(data, 2222323232, 'data')
data.menuTreeData[0].badgeNum = this.badgeNum
return data
}
},
watch: {
$route: {
handler() {
console.log(2222323232, '2222323232')
this.setBadgeNum()
},
immediate: false
}
},
mounted() {
console.log(this.layoutEngine.layoutConfig.keepAliveComps, 545454545454545454545454)
},
methods: {
setBadgeNum() {
const request = {
...api.GET_TODO_LIST,
params: {
page: 1,
size: 10,
personId: getUserId()
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen((resp) => {
this.badgeNum = resp.data.totalCount
})
.asyncErrorCatch((err) => {
console.error('获取待办列表失败:', err)
})
},
changeCollapse() {
this.showMenu = false
this.$nextTick(() => {
this.isCollapse = !this.isCollapse
this.showMenu = true
})
},
menuAddClick(e) {
this.$emit('menu-add-click', e)
},
closed(menu) {
const currentMenuId = this.layoutEngine.layoutConfig.currentMenu.id
this.layoutEngine.removeKeepAliveComps(menu)
if (menu.id === currentMenuId) {
this.layoutEngine.actionControl.executeActionWithSync('TO_ROUTER', {
menu: this.layoutEngine.layoutConfig.currentMenu
})
}
},
handlerclick(menu) {
this.layoutEngine.addKeepAliveComps(menu)
this.layoutEngine.actionControl.executeActionWithSync('TO_ROUTER', {
menu: this.layoutEngine.layoutConfig.currentMenu
})
}
}
}
</script>
<style lang="scss">
$--app-box-bgColor: #ffffff;
$--app-box-border-color: #dcdfe6;
.x-app-layout {
.layout-middle {
.layout-center {
.menu-switch {
width: 14px;
height: 80px;
padding-right: 2px;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
border: 1px solid $--app-box-bgColor;
border-left: 0;
background-color: $--app-box-bgColor;
position: absolute;
top: calc(50vh - 87px);
left: -20px;
transform: translateX(120%);
cursor: pointer;
opacity: 0.5;
display: flex;
justify-content: center;
align-items: center;
z-index: 500;
border: 1px solid $--app-box-border-color;
border-left: none;
}
.menu-switch:hover {
background-color: $--app-box-bgColor;
opacity: 1;
box-shadow: 2px 0px 4px 0px $--app-box-border-color;
}
}
}
}
</style>

View File

@ -32,10 +32,11 @@
</div>
<div class="detail-content">
<section class="block-section">
<div class="section-title">
<div class="section-title" @click="toggleBasicInfo">
基础信息
<i :class="basicInfoCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
</div>
<div class="info-grid">
<div v-show="!basicInfoCollapsed" class="info-grid">
<!-- 流程主题单独一行 -->
<div class="info-item-full">
<span class="label">流程主题</span>
@ -87,10 +88,11 @@
</div>
</section>
<section class="block-section">
<div class="section-title">
<div class="section-title" @click="toggleDetailInfo">
详细信息
<i :class="detailInfoCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
</div>
<div class="info-grid">
<div v-show="!detailInfoCollapsed" class="info-grid">
<div class="info-row">
<div class="info-item">
<span class="label">产品型号</span>
@ -157,10 +159,12 @@
</div>
</section>
<section class="block-section">
<div class="section-title">
<div class="section-title" @click="toggleApprovalContent">
审批内容
<i :class="approvalContentCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
</div>
<el-table :data="changeTable || []" border class="change-table" :max-height="500">
<div v-show="!approvalContentCollapsed">
<el-table :data="changeTable || []" border class="change-table" :max-height="500">
<el-table-column label="序号" type="index" width="60" />
<el-table-column
prop="subsystemName"
@ -192,26 +196,31 @@
<el-table-column prop="changeComment" label="修改描述" min-width="160">
</el-table-column>
</el-table>
<el-pagination
v-if="changeTableTotal > 0"
class="pagination-wrapper"
:current-page="changeTablePageNumber"
:page-size="changeTablePageSize"
:total="changeTableTotal"
layout="total, prev, pager, next, jumper"
@current-change="handlePageChange"
/>
<div class="pagination-wrapper">
<el-pagination
:current-page="changeTablePageNumber"
:page-size="changeTablePageSize"
:total="changeTableTotal"
layout="total, prev, pager, next, jumper, sizes"
:page-sizes="[10, 20, 50, 100, 9999]"
popper-class="pagination-select-dropdown"
@current-change="handlePageChange"
@size-change="handlePageSizeChange"
/>
</div>
<div v-if="progressDetail.description" class="description-block">
<span class="label">说明</span>
<span class="value">{{ detailOption }}</span>
</div>
</div>
</section>
<section class="block-section">
<div class="section-title">
<div class="section-title" @click="toggleApprovalFlow">
审批流程
<i :class="approvalFlowCollapsed ? 'el-icon-caret-left' : 'el-icon-caret-bottom'" class="collapse-icon"></i>
</div>
<div v-if="timelineNodes && timelineNodes.length > 0" class="approval-timeline">
<div v-show="!approvalFlowCollapsed" v-if="timelineNodes && timelineNodes.length > 0" class="approval-timeline">
<el-timeline>
<el-timeline-item
v-for="(node, index) in timelineNodes"
@ -247,7 +256,7 @@
</el-timeline-item>
</el-timeline>
</div>
<div v-else class="empty-progress">
<div v-show="!approvalFlowCollapsed" v-else class="empty-progress">
<span class="empty-text">暂无审批流程数据</span>
</div>
</section>
@ -369,6 +378,10 @@ export default {
},
data() {
return {
basicInfoCollapsed: true, //
detailInfoCollapsed: false, //
approvalContentCollapsed: false, //
approvalFlowCollapsed: true, //
changeTable: [],
showTopDetail: {
processTitle: '',
@ -422,6 +435,9 @@ export default {
}
},
computed: {
changeTablePage() {
return this.changeTablePageNumber
},
titleText() {
console.log(this.engineType, 'this.engineType', this.detail, 111111)
return this.engineType === '玉柴' ? '玉柴发动机审批详情' : '竞品发动机审批详情'
@ -617,6 +633,18 @@ export default {
// this.getApprovalChange()
},
methods: {
toggleBasicInfo() {
this.basicInfoCollapsed = !this.basicInfoCollapsed
},
toggleDetailInfo() {
this.detailInfoCollapsed = !this.detailInfoCollapsed
},
toggleApprovalContent() {
this.approvalContentCollapsed = !this.approvalContentCollapsed
},
toggleApprovalFlow() {
this.approvalFlowCollapsed = !this.approvalFlowCollapsed
},
canResendApproval() {
const request = {
...api.CHECK_DATA_CAN_RETURN,
@ -1253,6 +1281,11 @@ export default {
//
this.updatePagedData()
},
handlePageSizeChange(size) {
this.changeTablePageSize = size
this.changeTablePageNumber = 1
this.updatePagedData()
},
changeTypeClass(type) {
if (type === 'create') return 'change-create'
if (type === 'delete') return 'change-delete'
@ -1486,6 +1519,21 @@ export default {
font-weight: 600;
color: #303133;
margin-bottom: 16px;
cursor: pointer;
user-select: none;
display: flex;
align-items: center;
gap: 8px;
.collapse-icon {
font-size: 14px;
color: #909399;
transition: transform 0.3s;
&:hover {
color: #409eff;
}
}
}
}
@ -1623,8 +1671,22 @@ export default {
.pagination-wrapper {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 16px;
margin-bottom: 16px;
padding-right: 0;
::v-deep .el-pagination {
display: flex;
justify-content: flex-end;
align-items: center;
.el-select {
.el-input {
width: 100px !important;
}
}
}
}
.modify-details-text {
@ -1882,3 +1944,21 @@ export default {
line-height: 0.85 !important;
}
</style>
<style lang="scss">
.pagination-select-dropdown {
width: 110px !important;
min-width: 110px !important;
max-width: 110px !important;
.el-select-dropdown__wrap {
max-height: 200px;
}
.el-select-dropdown__item {
width: 100%;
text-align: left;
padding: 0 10px;
}
}
</style>

View File

@ -25,6 +25,13 @@
</div>
<div v-if="!isApprovalMode && !hideOperations" class="operation">
<template v-if="isDispatchMode">
<el-button
v-if="dispatchType !== 'update_param'"
size="small"
@click="handleBatchModifyDept"
>
批量修改部门
</el-button>
<el-button
v-if="shouldShowRejectButton"
size="small"
@ -62,12 +69,12 @@
<el-button size="small" v-if="!isEditDeptMode && hasAnyEditPermission() && detail &&( detail.distributeStatus === '已完成' || detail.distributeStatus === '未分发')" @click="handleEditDept">
编辑部门
</el-button>
<el-button
v-if="!isEditMode && !isEditDeptMode && hasAnyEditPermission() && detail && detail.distributeStatus === '已完成'"
<!-- <el-button
v-if="!isEditMode && !isEditDeptMode && hasAnyEditPermission() && (detail && detail.distributeStatus === '已完成' || fromTodo)"
size="small"
@click="handleEdit">
编辑
</el-button>
</el-button> -->
<el-button
v-if="!isEditMode && !isEditDeptMode && !isJustCheckMode"
size="small"
@ -194,8 +201,11 @@
<!-- 发动机基本信息表格 -->
<template v-for="(sectionData, sectionKey) in wholeEngineParamsData">
<div v-if="isWholeEngineParamsSelected" class="section" :key="sectionKey">
<div class="section-title">{{ sectionKey }}</div>
<div class="grid whole-engine-grid">
<div class="section-title" @click="detailInfoCollapsed = !detailInfoCollapsed" style="cursor: pointer;">
<span>{{ sectionKey }}</span>
<i :class="detailInfoCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
</div>
<div class="grid whole-engine-grid" v-show="!detailInfoCollapsed">
<div
class="grid-header whole-engine-header"
:class="{ 'without-parameter-source': isCompetitiveEngineEntry }"
@ -226,6 +236,9 @@
</div>
</template>
<!-- 子系统参数表格 -->
<div class="params-control" style="margin-bottom: 10px; text-align: right;" v-if="!isWholeEngineParamsSelected">
<el-checkbox v-model="showAllParams">全部显示不分页</el-checkbox>
</div>
<template v-for="(sectionData, sectionKey) in display">
<div class="section" v-if="shouldShowSection(sectionKey)" :key="sectionKey">
<div class="section-title">{{ formatSectionTitle(sectionKey, sectionData) }}</div>
@ -376,10 +389,11 @@
<div v-if="isApprovalMode" class="page-approval-content">
<!-- 基础信息 -->
<section v-if="detail" class="block-section">
<div class="section-title">
基础信息
<div class="section-title" @click="basicInfoCollapsed = !basicInfoCollapsed" style="cursor: pointer;">
<span>基础信息</span>
<i :class="basicInfoCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
</div>
<div class="info-grid">
<div class="info-grid" v-show="!basicInfoCollapsed">
<!-- 流程主题单独一行 -->
<div class="info-item-full">
<span class="label">流程主题 <span class="required-mark">*</span></span>
@ -476,10 +490,11 @@
<!-- 审批环节 -->
<div class="approval-workflow">
<div class="workflow-title">
审批环节
<div class="workflow-title" @click="approvalWorkflowCollapsed = !approvalWorkflowCollapsed" style="cursor: pointer;">
<span>审批环节</span>
<i :class="approvalWorkflowCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" style="margin-left: 8px;"></i>
</div>
<div class="workflow-table">
<div class="workflow-table" v-show="!approvalWorkflowCollapsed">
<table class="workflow-table-content">
<thead>
<tr>
@ -558,10 +573,147 @@
:resolve-department-id="resolveDepartmentId"
:project-parts-name="treeFirstLevelPartsName"
:tree-subsystem-names="treeSubsystemNames"
:dispatch-param-draft-cache="dispatchParamDraftCache"
@confirm="handleBatchModifyConfirm"
@refresh-responsible-persons="loadResponsiblePersons"
@refresh-department="handleRefreshDepartment"
@update-draft-cache="handleUpdateDraftCache"
/>
<!-- 修改部门弹窗 -->
<el-dialog
title="修改部门"
:visible.sync="batchModifyDeptDialogVisible"
width="600px"
:close-on-click-modal="false"
append-to-body
@close="handleBatchModifyDeptDialogClose"
>
<el-form ref="batchModifyDeptForm" :model="batchModifyDeptFormData" label-width="110px">
<el-form-item label="原部门:">
<el-input
v-model="batchModifyDeptFormData.originalDept"
placeholder="请选择原部门"
readonly
style="width: 100%"
@click.native="handleSelectOriginalDept"
>
<el-button slot="append" icon="el-icon-search" @click="handleSelectOriginalDept"></el-button>
</el-input>
</el-form-item>
<el-form-item label="部门:">
<el-input
v-model="batchModifyDeptFormData.targetDept"
placeholder="请选择部门"
readonly
style="width: 100%"
@click.native="handleSelectTargetDept"
>
<el-button slot="append" icon="el-icon-search" @click="handleSelectTargetDept"></el-button>
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleBatchModifyDeptDialogClose">
取消
</el-button>
<el-button
type="primary"
:loading="batchModifyDeptSubmitting"
:disabled="!batchModifyDeptFormData.originalDept || !batchModifyDeptFormData.targetDept"
@click="handleBatchModifyDeptConfirm"
>
确定
</el-button>
</div>
</el-dialog>
<!-- 原填写部门选择弹窗 -->
<el-dialog
title="选择原填写部门"
:visible.sync="originalDeptDialogVisible"
width="500px"
:close-on-click-modal="false"
append-to-body
@close="handleOriginalDeptDialogClose"
>
<el-input
v-model="originalDeptTreeFilterText"
size="small"
placeholder="请输入部门名称进行搜索"
clearable
class="department-tree-search"
>
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
<el-tree
ref="originalDeptTree"
:data="departmentList"
:props="{ children: 'children', label: 'name' }"
node-key="id"
:filter-node-method="filterDepartmentNode"
highlight-current
:expand-on-click-node="false"
class="department-tree"
@node-click="handleOriginalDeptNodeClick"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleOriginalDeptDialogClose">
取消
</el-button>
<el-button
type="primary"
:disabled="!selectedOriginalDeptId"
@click="handleOriginalDeptDialogConfirm"
>
确定
</el-button>
</div>
</el-dialog>
<!-- 填写部门选择弹窗 -->
<el-dialog
title="选择填写部门"
:visible.sync="targetDeptDialogVisible"
width="500px"
:close-on-click-modal="false"
append-to-body
@close="handleTargetDeptDialogClose"
>
<el-input
v-model="targetDeptTreeFilterText"
size="small"
placeholder="请输入部门名称进行搜索"
clearable
class="department-tree-search"
>
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
<el-tree
ref="targetDeptTree"
:data="departmentList"
:props="{ children: 'children', label: 'name' }"
node-key="id"
:filter-node-method="filterDepartmentNode"
highlight-current
:expand-on-click-node="false"
class="department-tree"
@node-click="handleTargetDeptNodeClick"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="handleTargetDeptDialogClose">
取消
</el-button>
<el-button
type="primary"
:disabled="!selectedTargetDeptId"
@click="handleTargetDeptDialogConfirm"
>
确定
</el-button>
</div>
</el-dialog>
<!-- 竞品发动机修改全部填写人/责任人仅选人不触发修改责任人接口 -->
<el-dialog
:title="dispatchType === 'update_param' ? '修改全部填写人' : '修改全部责任人'"
@ -611,76 +763,7 @@
</span>
</el-dialog>
<!-- 批量修改部门弹窗 -->
<el-dialog
title="批量修改部门"
:visible.sync="batchModifyDeptDialogVisible"
width="600px"
append-to-body
@close="handleBatchModifyDeptDialogClose"
>
<el-form
ref="batchModifyDeptForm"
:model="batchModifyDeptFormData"
:rules="batchModifyDeptFormRules"
label-width="120px"
>
<el-form-item label="子系统:" prop="subsystem">
<el-select
v-model="batchModifyDeptFormData.subsystem"
placeholder="请选择子系统"
clearable
style="width: 100%"
@change="handleBatchModifyDeptSubsystemChange"
>
<el-option
v-for="item in batchModifyDeptSubsystemList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item label="零部件名称:" prop="partsName">
<el-select
v-model="batchModifyDeptFormData.partsName"
placeholder="请选择零部件名称"
clearable
multiple
style="width: 100%"
:disabled="!batchModifyDeptFormData.subsystem"
>
<el-option
v-for="item in batchModifyDeptPartsNameList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item label="部门:" prop="department">
<el-select
v-model="batchModifyDeptFormData.department"
placeholder="请选择部门"
clearable
filterable
style="width: 100%"
:filter-method="handleBatchModifyDeptRemoteSearch"
>
<el-option
v-for="dept in filteredBatchModifyDeptOptions"
:key="dept.id"
:value="dept.name"
:label="dept.name"
/>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleBatchModifyDeptDialogClose">取消</el-button>
<el-button type="primary" :loading="batchModifyDeptSubmitting" @click="handleBatchModifyDeptConfirm">确定</el-button>
</span>
</el-dialog>
</div>
</template>
@ -810,6 +893,24 @@ export default {
},
replaceAllPersonUserOptions: [],
replaceAllPersonUserLoading: false,
//
batchModifyDeptDialogVisible: false,
batchModifyDeptSubmitting: false,
batchModifyDeptFormData: {
originalDept: '',
originalDeptId: '',
targetDept: '',
targetDeptId: ''
},
originalDeptDialogVisible: false,
originalDeptTreeFilterText: '',
selectedOriginalDeptId: '',
selectedOriginalDeptName: '',
targetDeptDialogVisible: false,
targetDeptTreeFilterText: '',
selectedTargetDeptId: '',
selectedTargetDeptName: '',
// ID
versions: [],
treeData: [],
@ -817,6 +918,10 @@ export default {
currentEngineModelID: '', // ID
versionData: {},
changeData: [], //
basicInfoCollapsed: false, //
detailInfoCollapsed: false, //
approvalWorkflowCollapsed: true, //
showAllParams: false, //
importing: false, //
isApprovalMode: false, //
engineDetailInfo: null, // modelName projectNumber
@ -880,6 +985,16 @@ export default {
console.log('data', data)
return data
},
//
displayParams() {
const data = this.display
if (this.showAllParams) {
return data
}
//
//
return data
},
currentVersionLabel() {
const version = this.versions.find((v) => v.id === this.currentVersionId)
return version ? version.label : 'V1'
@ -1016,6 +1131,22 @@ export default {
})
return names
},
//
subsystemList() {
const currentData = this.versionData[this.currentVersionId] || {}
const subsystemSet = new Set()
Object.keys(currentData).forEach((partsName) => {
const params = currentData[partsName] || []
params.forEach((param) => {
if (param.subsystemName) {
subsystemSet.add(param.subsystemName)
}
})
})
return Array.from(subsystemSet).sort()
},
// justCheck
isJustCheckMode() {
return this.dispatchType === 'justCheck'
@ -1179,10 +1310,25 @@ export default {
},
// 退
canShowTodoHeaderOperations() {
console.log('canShowTodoHeaderOperations - isFillerTodoEntry:', this.isFillerTodoEntry)
console.log('canShowTodoHeaderOperations - fromTodo:', this.fromTodo)
console.log('canShowTodoHeaderOperations - detail:', this.detail)
console.log('canShowTodoHeaderOperations - distributeStatus:', this.detail && this.detail.distributeStatus)
if (this.isFillerTodoEntry) {
console.log('canShowTodoHeaderOperations - 返回 true (isFillerTodoEntry)')
return true
}
return !this.detail || this.detail.distributeStatus !== '已完成'
// 退
if (this.fromTodo) {
console.log('canShowTodoHeaderOperations - 返回 true (fromTodo)')
return true
}
// 使访
const distributeStatus = this.detail && this.detail.distributeStatus
const result = !this.detail || distributeStatus !== '已完成'
console.log('canShowTodoHeaderOperations - 返回:', result)
return result
},
// "退"
shouldShowRejectButton() {
@ -1315,6 +1461,20 @@ export default {
this.loadResponsiblePersons()
this.loadFillerPersons()
}
},
originalDeptTreeFilterText(val) {
this.$nextTick(() => {
if (this.$refs.originalDeptTree) {
this.$refs.originalDeptTree.filter(val)
}
})
},
targetDeptTreeFilterText(val) {
this.$nextTick(() => {
if (this.$refs.targetDeptTree) {
this.$refs.targetDeptTree.filter(val)
}
})
}
},
created() {
@ -1735,11 +1895,13 @@ export default {
},
// 使
hasAnyEditPermission() {
//
//
const dataTypeStr = String(this.detail.dataType || '')
console.log(dataTypeStr)
if (
this.fromTodo &&
this.detail &&
String(this.detail.dataType || '') === '数据维护'
(dataTypeStr === '数据维护' || dataTypeStr === '数据拒绝')
) {
return true
}
@ -1765,7 +1927,7 @@ export default {
const hasGlobalEdit = permissionData.some((perm) => {
const permissionPath = perm.permissionPath || ''
const parameterPer = perm.parameterPer || ''
// permissionPath engineTypePath parameterPer ""
// permissionPath engineTypePath parameterPer ""
return permissionPath === engineTypePath && parameterPer === '编辑'
})
@ -1782,6 +1944,7 @@ export default {
return parameterPer === '编辑' && permissionPath.startsWith(engineTypePath + '/')
})
return hasAnyEdit
} catch (err) {
console.error('检查编辑权限失败:', err)
@ -1797,30 +1960,34 @@ export default {
return (person.partsName || '') === treePartsName
},
//
//
isResponsiblePersonSubsystemDeptMatch(person, subsystemName, department) {
if (!person) {
return false
}
let subsystemMatch = false
if (subsystemName && person.subsystem) {
const personSubsystems = person.subsystem.split(',').map((s) => s.trim())
subsystemMatch = personSubsystems.includes(subsystemName)
} else if (!subsystemName && !person.subsystem) {
subsystemMatch = true
}
//
let departmentMatch = false
if (department && person.department) {
const normalizedParamDept = department.replace(/·/g, '-')
const normalizedPersonDept = person.department.replace(/·/g, '-')
departmentMatch =
//
const exactMatch =
normalizedPersonDept === normalizedParamDept ||
normalizedPersonDept.startsWith(normalizedParamDept + '-')
//
const aliasMatch =
this.isZQOrZZPowerPlatformDept(department) &&
this.isZQOrZZPowerPlatformDept(person.department)
departmentMatch = exactMatch || aliasMatch
} else if (!department && !person.department) {
departmentMatch = true
}
return subsystemMatch && departmentMatch
return departmentMatch
},
// GET_MANAGER_DATA
loadResponsiblePersons() {
@ -2162,6 +2329,12 @@ export default {
}
this.saveDispatchParamDraft(row)
},
// draft
handleUpdateDraftCache(draftKey, draft) {
if (draftKey && draft) {
this.$set(this.dispatchParamDraftCache, draftKey, draft)
}
},
//
getFilteredPersonsByDepartment(department) {
if (!department) {
@ -2990,6 +3163,227 @@ export default {
//
this.$refs.batchModifyResponsibleModal.showModal()
},
//
handleBatchModifyDeptDialogClose() {
this.batchModifyDeptDialogVisible = false
this.batchModifyDeptFormData = {
originalDept: '',
originalDeptId: '',
targetDept: '',
targetDeptId: ''
}
},
//
handleBatchModifyDeptConfirm() {
if (!this.batchModifyDeptFormData.originalDept || !this.batchModifyDeptFormData.targetDept) {
this.$message.warning('请选择原部门和部门')
return
}
if (this.batchModifyDeptFormData.originalDept === this.batchModifyDeptFormData.targetDept) {
this.$message.warning('原部门和部门不能相同')
return
}
// versionData
const currentVersionData = this.versionData[this.currentVersionId] || {}
//
const existingDepts = new Set()
Object.keys(currentVersionData).forEach((partsName) => {
const params = currentVersionData[partsName] || []
params.forEach((param) => {
if (param.department) {
existingDepts.add(param.department)
}
})
})
const existingDeptsArray = Array.from(existingDepts)
//
const originalDeptExists = existingDeptsArray.includes(this.batchModifyDeptFormData.originalDept)
if (!originalDeptExists) {
//
const message = `原部门【${this.batchModifyDeptFormData.originalDept}】不存在于当前数据中。\n当前存在的部门${existingDeptsArray.join('、')}`
this.$message.warning(message)
return
}
//
const itemsToUpdate = []
Object.keys(currentVersionData).forEach((partsName) => {
const params = currentVersionData[partsName] || []
params.forEach((param) => {
// 使
if (this.isDepartmentMatched(param.department, this.batchModifyDeptFormData.originalDept)) {
if (param.id) {
itemsToUpdate.push({
id: param.id,
department: this.batchModifyDeptFormData.targetDept
})
}
}
})
})
//
if (itemsToUpdate.length === 0) {
this.$message.warning('未找到匹配的参数数据')
return
}
//
const request = {
...api.BATCH_UPDATE_DEPARTMENT,
params: {
items: itemsToUpdate
}
}
this.batchModifyDeptSubmitting = true
this.$request(request)
.asyncThen((resp) => {
//
Object.keys(currentVersionData).forEach((partsName) => {
const params = currentVersionData[partsName] || []
params.forEach((param, index) => {
if (this.isDepartmentMatched(param.department, this.batchModifyDeptFormData.originalDept)) {
//
param.department = this.batchModifyDeptFormData.targetDept
//
const matchedPerson = this.responsiblePersons.find((person) => {
return this.isResponsiblePersonSubsystemDeptMatch(person, param.subsystemName, param.department)
})
if (matchedPerson) {
//
param.resPersonId = matchedPerson.userId || matchedPerson.id || ''
param.owner = matchedPerson.userName || matchedPerson.username || ''
}
}
})
})
this.batchModifyDeptSubmitting = false
this.batchModifyDeptDialogVisible = false
this.$message.success(`成功更新 ${itemsToUpdate.length} 个参数的部门`)
})
.asyncErrorCatch((err) => {
console.error('批量更新部门失败:', err)
this.$message.error('批量更新部门失败,请重试')
this.batchModifyDeptSubmitting = false
})
},
//
isDepartmentMatched(deptA, deptB) {
if (!deptA || !deptB) {
return false
}
//
const normalizeDept = (dept) => {
if (!dept) return ''
return dept.replace(/·/g, '-').trim()
}
const normalizedA = normalizeDept(deptA)
const normalizedB = normalizeDept(deptB)
//
if (normalizedA === normalizedB) {
return true
}
//
const aliasGroups = [
['中轻', '中重动力平台', '平台部', '中轻动力平台部', '中重动力平台部']
]
for (const group of aliasGroups) {
if (group.some(alias => normalizedA.includes(alias)) && group.some(alias => normalizedB.includes(alias))) {
return true
}
}
return false
},
//
handleSelectOriginalDept() {
this.originalDeptDialogVisible = true
this.selectedOriginalDeptId = this.batchModifyDeptFormData.originalDeptId || ''
this.selectedOriginalDeptName = this.batchModifyDeptFormData.originalDept || ''
this.originalDeptTreeFilterText = ''
this.$nextTick(() => {
if (this.$refs.originalDeptTree && this.selectedOriginalDeptId) {
this.$refs.originalDeptTree.setCurrentKey(this.selectedOriginalDeptId)
}
})
},
//
handleOriginalDeptDialogClose() {
this.originalDeptDialogVisible = false
this.selectedOriginalDeptId = ''
this.selectedOriginalDeptName = ''
},
//
handleOriginalDeptNodeClick(data) {
this.selectedOriginalDeptId = data.id
this.selectedOriginalDeptName = data.name
},
//
handleOriginalDeptDialogConfirm() {
if (!this.selectedOriginalDeptId) {
this.$message.warning('请选择部门')
return
}
this.batchModifyDeptFormData.originalDept = this.selectedOriginalDeptName
this.batchModifyDeptFormData.originalDeptId = this.selectedOriginalDeptId
this.originalDeptDialogVisible = false
},
//
handleSelectTargetDept() {
this.targetDeptDialogVisible = true
this.selectedTargetDeptId = this.batchModifyDeptFormData.targetDeptId || ''
this.selectedTargetDeptName = this.batchModifyDeptFormData.targetDept || ''
this.targetDeptTreeFilterText = ''
this.$nextTick(() => {
if (this.$refs.targetDeptTree && this.selectedTargetDeptId) {
this.$refs.targetDeptTree.setCurrentKey(this.selectedTargetDeptId)
}
})
},
//
handleTargetDeptDialogClose() {
this.targetDeptDialogVisible = false
this.selectedTargetDeptId = ''
this.selectedTargetDeptName = ''
},
//
handleTargetDeptNodeClick(data) {
this.selectedTargetDeptId = data.id
this.selectedTargetDeptName = data.name
},
//
handleTargetDeptDialogConfirm() {
if (!this.selectedTargetDeptId) {
this.$message.warning('请选择部门')
return
}
this.batchModifyDeptFormData.targetDept = this.selectedTargetDeptName
this.batchModifyDeptFormData.targetDeptId = this.selectedTargetDeptId
this.targetDeptDialogVisible = false
},
//
handleRefreshDepartment() {
//
if (this.checkedKeys && this.checkedKeys.length > 0) {
this.loadTreeData()
}
},
// /
handleReplaceAllPerson() {
this.replaceAllPersonDialogVisible = true
@ -3223,10 +3617,22 @@ export default {
const subsystemMatched = selectedSubsystems.some((name) =>
this.isSubsystemNameMatch(param.subsystemName, name)
)
// "/"
let partsNameMatched = false
if (paramPartsName === '/') {
// "/" partsName
const displayName = `${param.subsystemName} - /`
partsNameMatched = partsName.includes(displayName)
} else {
// "/"
partsNameMatched = partsName.includes(paramPartsName)
}
// isDistributedFilled === 1
if (
subsystemMatched &&
partsName.includes(paramPartsName) &&
partsNameMatched &&
param.isDistributedFilled !== 1
) {
//
@ -3390,6 +3796,23 @@ export default {
fieldValue = currentParam.resPersonId || ''
if (fieldValue) {
shouldDispatch = true
//
const responsiblePerson = this.responsiblePersons.find(p => p.userId === fieldValue)
if (responsiblePerson && currentParam.department) {
const paramDept = this.formatDepartmentDisplay(currentParam.department)
const personDept = this.formatDepartmentDisplay(responsiblePerson.department || '')
//
if (paramDept !== personDept) {
// /
const isAliasMatch =
(this.isZQOrZZPowerPlatformDept(paramDept) && this.isZQOrZZPowerPlatformDept(personDept)) ||
(this.isZQOrZZPowerPlatformDept(currentParam.department) && this.isZQOrZZPowerPlatformDept(responsiblePerson.department || ''))
if (!isAliasMatch) {
//
shouldDispatch = false
}
}
}
}
}
@ -3427,6 +3850,7 @@ export default {
if (dispatchData.length === 0) {
const fieldName = isUpdateParamMode ? '填写人' : '责任人'
this.dispatchLoading = false
this.$message({
type: 'warning',
message: `没有${fieldName}的数据需要分发`
@ -4537,7 +4961,13 @@ export default {
const paramData = {
parameterName: parameterName,
partsName: partsName,
parameterValue: item.parameterValue || item.value || '', //
parameterValue: item.parameterValue !== undefined && item.parameterValue !== null && item.parameterValue !== ''
? item.parameterValue
: (item.value !== undefined && item.value !== null && item.value !== ''
? item.value
: (item.minorVersion !== undefined && item.minorVersion !== null && item.minorVersion !== ''
? item.minorVersion
: '')),
parameterSource: item.parameterSource || '', // 使 GET_ENGINE_DETAIL
unit: item.unit || '-',
department: department,
@ -4558,6 +4988,8 @@ export default {
isDistributedFilled: item.isDistributedFilled || 0 // 10
}
const mergedParamData = this.applyDispatchParamDraft(paramData)
// filler filledByUserId fillerUserOptions
@ -5476,14 +5908,21 @@ export default {
// selectedIds id : ['id1', 'id2', ...]
// v-model step.handlers id
},
// /
// / /
isZQOrZZPowerPlatformDept(department) {
if (!department) {
return false
}
const normalized = String(department).replace(/·/g, '-')
const displayName = this.formatDepartmentDisplay(normalized)
const aliasNames = ['中轻', '中重动力平台']
//
const aliasNames = [
'中轻',
'中重动力平台',
'平台部',
'中轻动力平台部', //
'中重动力平台部' //
]
return aliasNames.some(
(alias) =>
displayName === alias ||

View File

@ -5,6 +5,36 @@
<div class="title">
责任人管理
</div>
<div class="search-section">
<el-input
v-model="searchForm.department"
placeholder="搜索责任部门"
clearable
style="width: 180px; margin-right: 10px;"
@input="handleSearch"
/>
<el-input
v-model="searchForm.subsystem"
placeholder="搜索子系统"
clearable
style="width: 180px; margin-right: 10px;"
@input="handleSearch"
/>
<el-input
v-model="searchForm.username"
placeholder="搜索责任人"
clearable
style="width: 180px; margin-right: 10px;"
@input="handleSearch"
/>
<el-input
v-model="searchForm.partsName"
placeholder="搜索状态代号"
clearable
style="width: 180px; margin-right: 10px;"
@input="handleSearch"
/>
</div>
<div v-if="hasEditPermission()">
<el-button type="primary" @click="handleAdd">
新增
@ -36,8 +66,7 @@
{{ formatDepartmentDisplay(scope.row.department) }}
</template>
</el-table-column>
<el-table-column prop="subsystem" label="子系统" align="center" />
<el-table-column prop="partsName" label="状态代号" align="center" />
<el-table-column prop="partsName" label="项目编号" align="center" />
<el-table-column prop="username" label="责任人" width="250" align="center" />
<el-table-column v-if="hasEditPermission()" label="操作" width="200" align="center">
<template slot-scope="scope">
@ -308,7 +337,15 @@ export default {
importFileList: [], //
selectedImportFile: null, //
importing: false, //
canViewData: false //
canViewData: false, //
//
searchForm: {
department: '',
subsystem: '',
username: '',
partsName: ''
},
allTableData: [] //
}
},
computed: {
@ -521,8 +558,8 @@ export default {
const request = {
...api.GET_MANAGER_DATA,
params: {
pageNumber: this.pagination.currentPage,
pageSize: this.pagination.pageSize
pageNumber: 1,
pageSize: 9999 //
},
disableSuccessMsg: true
}
@ -530,20 +567,72 @@ export default {
.asyncThen((resp) => {
//
if (resp && resp.data) {
this.tableData = resp.data.result
// total
this.pagination.total = resp.data.count
this.allTableData = resp.data.result || []
this.pagination.total = resp.data.count || this.allTableData.length
//
this.handleSearch()
} else {
this.allTableData = []
this.tableData = []
this.pagination.total = 0
}
})
.asyncErrorCatch((err) => {
console.error('加载管理数据失败:', err)
this.allTableData = []
this.tableData = []
this.pagination.total = 0
})
},
//
handleSearch() {
let filteredData = [...this.allTableData]
//
if (this.searchForm.department && this.searchForm.department.trim()) {
const deptKeyword = this.searchForm.department.trim().toLowerCase()
filteredData = filteredData.filter(item => {
const dept = this.formatDepartmentDisplay(item.department || '')
return dept.toLowerCase().includes(deptKeyword) ||
(item.department || '').toLowerCase().includes(deptKeyword)
})
}
//
if (this.searchForm.subsystem && this.searchForm.subsystem.trim()) {
const subsystemKeyword = this.searchForm.subsystem.trim().toLowerCase()
filteredData = filteredData.filter(item => {
const subsystem = item.subsystem || ''
return subsystem.toLowerCase().includes(subsystemKeyword)
})
}
//
if (this.searchForm.username && this.searchForm.username.trim()) {
const usernameKeyword = this.searchForm.username.trim().toLowerCase()
filteredData = filteredData.filter(item => {
const username = item.username || item.userName || ''
return username.toLowerCase().includes(usernameKeyword)
})
}
//
if (this.searchForm.partsName && this.searchForm.partsName.trim()) {
const partsNameKeyword = this.searchForm.partsName.trim().toLowerCase()
filteredData = filteredData.filter(item => {
const partsName = item.partsName || ''
return partsName.toLowerCase().includes(partsNameKeyword)
})
}
//
this.pagination.total = filteredData.length
//
const startIndex = (this.pagination.currentPage - 1) * this.pagination.pageSize
const endIndex = startIndex + this.pagination.pageSize
this.tableData = filteredData.slice(startIndex, endIndex)
},
loadDepartmentList() {
const request = {
...api.GET_DEPT_OF_USER,
@ -983,12 +1072,12 @@ export default {
handleSizeChange(val) {
this.pagination.pageSize = val
this.pagination.currentPage = 1 //
this.loadManagerData()
this.handleSearch() //
},
//
handleCurrentChange(val) {
this.pagination.currentPage = val
this.loadManagerData()
this.handleSearch() //
},
//
handleRefresh() {
@ -1335,6 +1424,7 @@ export default {
justify-content: space-between;
align-items: center;
gap: 12px;
flex-wrap: wrap;
.comment-text {
color: #909399;
@ -1344,11 +1434,15 @@ export default {
color: #303133;
font-weight: 700;
margin-left: 20px;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
font-size: 18px;
}
.search-section {
display: flex;
align-items: center;
gap: 10px;
flex: 1;
justify-content: center;
}
}
.table-section {

View File

@ -104,6 +104,9 @@
<th class="param-column">
参数名称
</th>
<th class="unit-column">
单位
</th>
<th v-for="(model, index) in comparisonModels" :key="index" class="model-column">
<div class="model-header">
<div v-if="model.name" class="model-name"
@ -145,6 +148,9 @@
@click.stop="handleHideParam(param)"
></i>
</td>
<td class="unit-column">
{{ param.unit || '-' }}
</td>
<td
v-for="(model, modelIndex) in comparisonModels"
:key="modelIndex"
@ -490,7 +496,8 @@ export default {
subsystemName: subsystemName,
parameterId: parameterId,
partsName: partsName, // partsName
displayPartsName: displayPartsName //
displayPartsName: displayPartsName, //
unit: item.unit || '' //
})
}
}
@ -2481,7 +2488,8 @@ export default {
parameterId: param.parameterId || '',
parameterName: param.parameterName || '',
partsName: param.partsName || '',
subsystem: item.subsystem //
subsystem: item.subsystem, //
unit: param.unit || '' //
}))
}
})
@ -2858,6 +2866,13 @@ export default {
z-index: 15;
}
&.unit-column {
width: 80px;
min-width: 80px;
left: 460px;
z-index: 15;
}
&.model-column {
min-width: 180px;
text-align: center;
@ -2957,7 +2972,8 @@ export default {
td {
&.subsystem-column,
&.parts-column,
&.param-column {
&.param-column,
&.unit-column {
background: #f5f7fa;
}
}
@ -3007,6 +3023,14 @@ export default {
}
}
&.unit-column {
position: sticky;
left: 460px;
background: white;
z-index: 5;
text-align: center;
}
&.model-column {
text-align: center;
}

View File

@ -20,6 +20,9 @@
<el-button v-if="hasTemplateManagementEditPermission()" class="import-btn" @click="handleImportTemplate()">
导入参数模板
</el-button>
<el-button v-if="hasTemplateManagementEditPermission()" type="primary" @click="handleShowOrderDialog">
调整排序
</el-button>
<!-- <el-button v-if="hasTemplateManagementEditPermission()" type="primary" @click="handleAddTemplate()">
添加参数模板
</el-button> -->
@ -232,6 +235,37 @@
>
<div class="error-list"> {{ errorList }} </div>
</el-dialog>
<el-dialog
title="调整排序"
:visible.sync="orderDialogVisible"
width="600px"
append-to-body
@close="handleOrderDialogClose"
>
<div class="order-dialog-content">
<div class="order-tip" style="margin-bottom: 10px; color: #909399; font-size: 12px">
提示拖动行可调整排序拖动后排序号会自动更新
</div>
<el-table
:data="orderList"
row-key="id"
class="order-table"
max-height="600"
>
<el-table-column label="排序号" width="80" align="center">
<template slot-scope="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column label="模板名称" prop="templateName" />
</el-table>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleOrderDialogClose">取消</el-button>
<el-button type="primary" :loading="updatingOrder" @click="handleUpdateOrder">确定</el-button>
</span>
</el-dialog>
</div>
</template>
@ -280,7 +314,11 @@ export default {
userId: getUserId(),
errorDialogVisible: false,
templateManagementPermissions: [], // menuPath "/"
fromTodo: false //
fromTodo: false, //
orderDialogVisible: false,
orderList: [],
updatingOrder: false,
dragSortHandler: null
}
},
computed: {
@ -1090,13 +1128,130 @@ export default {
this.templateSelectLoading = false
})
},
// UUID
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
},
handleShowOrderDialog() {
const request = {
...api.GET_MODEL_LIST,
params: {
pageNumber: 1,
pageSize: 999
},
disableSuccessMsg: true
}
this.$request(request, false)
.asyncThen((resp) => {
const list = resp.data.result || []
this.orderList = list.map((item, index) => ({
id: item.id || item.row_id || `temp_${index}_${Date.now()}`,
templateName: item.templateName || item.po_name,
orderNum: item.orderNum || item.order_num || (index + 1)
}))
this.orderDialogVisible = true
this.$nextTick(() => {
this.initDragSort()
})
})
.asyncErrorCatch((err) => {
console.error('加载模板列表失败:', err)
this.$message.error('加载模板列表失败')
})
},
handleOrderDialogClose() {
this.orderDialogVisible = false
this.orderList = []
},
initDragSort() {
const table = document.querySelector('.order-table .el-table__body-wrapper tbody')
if (!table) return
const rows = table.querySelectorAll('tr')
rows.forEach((row) => {
row.draggable = true
row.style.cursor = 'move'
})
if (this.dragSortHandler) {
table.removeEventListener('dragstart', this.dragSortHandler.dragstart)
table.removeEventListener('dragend', this.dragSortHandler.dragend)
table.removeEventListener('dragover', this.dragSortHandler.dragover)
table.removeEventListener('drop', this.dragSortHandler.drop)
}
let draggedIndex = null
const dragstartHandler = (e) => {
const row = e.target.closest('tr')
if (!row) return
const rows = Array.from(table.querySelectorAll('tr'))
draggedIndex = rows.indexOf(row)
row.style.opacity = '0.5'
e.dataTransfer.effectAllowed = 'move'
}
const dragendHandler = (e) => {
const row = e.target.closest('tr')
if (row) row.style.opacity = '1'
draggedIndex = null
}
const dragoverHandler = (e) => {
e.preventDefault()
e.dataTransfer.dropEffect = 'move'
}
const dropHandler = (e) => {
e.preventDefault()
e.stopPropagation()
const targetRow = e.target.closest('tr')
if (!targetRow || draggedIndex === null) return
const rows = Array.from(table.querySelectorAll('tr'))
const targetIndex = rows.indexOf(targetRow)
if (draggedIndex !== targetIndex) {
const newOrderList = [...this.orderList]
const draggedItem = newOrderList[draggedIndex]
newOrderList.splice(draggedIndex, 1)
newOrderList.splice(targetIndex, 0, draggedItem)
this.orderList = newOrderList
this.$nextTick(() => {
this.initDragSort()
})
}
}
table.addEventListener('dragstart', dragstartHandler)
table.addEventListener('dragend', dragendHandler)
table.addEventListener('dragover', dragoverHandler)
table.addEventListener('drop', dropHandler)
this.dragSortHandler = {
dragstart: dragstartHandler,
dragend: dragendHandler,
dragover: dragoverHandler,
drop: dropHandler
}
},
handleUpdateOrder() {
this.updatingOrder = true
const updateList = this.orderList.map((item, index) => ({
id: item.id,
orderNum: index + 1
}))
const request = {
...api.UPDATE_TEMPLATE_ORDER,
params: {
items: updateList
}
}
this.$request(request)
.asyncThen((resp) => {
this.$message.success('排序更新成功')
this.handleOrderDialogClose()
this.loadData()
})
.asyncErrorCatch((err) => {
console.error('更新排序失败:', err)
this.$message.error('更新排序失败')
})
.finally(() => {
this.updatingOrder = false
})
}
}
}
@ -1299,4 +1454,24 @@ export default {
::v-deep .el-button {
line-height: 0.85 !important;
}
.order-dialog-content {
.order-table {
width: 100%;
}
.order-tip {
padding: 8px 12px;
background: #f4f4f5;
border-radius: 4px;
}
::v-deep .el-table__body tr {
cursor: move;
transition: all 0.3s;
}
::v-deep .el-table__body tr:hover {
background-color: #f5f7fa;
}
::v-deep .el-table__body tr[draggable="true"] {
cursor: move;
}
}
</style>

View File

@ -944,6 +944,13 @@ export default {
width: '100',
align: 'center'
},
{
prop: 'parameterValue',
label: '参数值',
showOverflowTooltip: true,
minWidth: '120',
align: 'center'
},
{
prop: 'isNumber',
label: '数值类型',
@ -1049,6 +1056,13 @@ export default {
width: '100',
align: 'center'
},
{
prop: 'parameterValue',
label: '参数值',
showOverflowTooltip: true,
minWidth: '120',
align: 'center'
},
{
prop: 'isNumber',
label: '数值类型',
@ -1391,6 +1405,12 @@ export default {
if (this.detail && this.detail.flowId) {
this.getApprovalSpet()
}
//
if (this.fromTodo && this.flowId) {
this.$nextTick(() => {
this.loadData()
})
}
},
methods: {
//

View File

@ -1,239 +1,239 @@
<template>
<div class="apaas-custom-page-todo custom-page">
<div class="list-container">
<div v-for="(item, index) in list" :key="index" class="list-item">
<div class="list-item-time">
{{ item.time }}
</div>
<div class="list-item-content-wrap">
<div
ref="contentEls"
class="list-item-content"
:class="{ 'is-expanded': expanded[index] }"
>
<span class="list-item-content-text">
{{
overflow[index] && !expanded[index]
? collapsedText[index]
: item.content
}}
</span>
<button
v-if="overflow[index]"
type="button"
class="list-item-toggle"
@click="toggle(index)"
>
{{ expanded[index] ? '收起' : '展开' }}
</button>
</div>
</div>
</div>
</div>
<div ref="measureEl" class="list-item-measure" aria-hidden="true"></div>
</div>
</template>
<script>
export default {
name: 'TodoPage',
data() {
return {
list: [
{
time: '123123',
content:
'74weugfiufbewbfewhfwiufhwefhwekfhwkjfasdkg撒扩大刚放假规范几个房间看过尽快发给外交国大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外防科技股份较为规范会计1疯狂攻击反馈'
},
{ time: '123123', content: '74weugfiufbewbfewhfwiufhwefhwekfhwkjf' },
{ time: '123123', content: '74weugfiufbewbfewhfwiufhwefhwekfhwkjf' }
],
expanded: [],
overflow: [],
collapsedText: []
}
},
watch: {
list: {
deep: true,
immediate: true,
handler() {
this.ensureStateSize()
this.measureOverflow()
}
}
},
mounted() {
window.addEventListener('resize', this.onResize, { passive: true })
this.ensureStateSize()
this.measureOverflow()
},
beforeDestroy() {
window.removeEventListener('resize', this.onResize)
},
methods: {
ensureStateSize() {
const n = this.list.length
if (this.expanded.length !== n) {
this.expanded = Array.from({ length: n }, (_, i) => !!this.expanded[i])
}
if (this.overflow.length !== n) {
this.overflow = Array.from({ length: n }, (_, i) => !!this.overflow[i])
}
if (this.collapsedText.length !== n) {
this.collapsedText = Array.from({ length: n }, (_, i) => this.collapsedText[i] || '')
}
},
measureOverflow() {
this.$nextTick(() => {
const els = Array.isArray(this.$refs.contentEls)
? this.$refs.contentEls
: this.$refs.contentEls
? [this.$refs.contentEls]
: []
const measureEl = this.$refs.measureEl
if (!measureEl) return
const nextOverflow = []
const nextCollapsed = []
this.list.forEach((item, idx) => {
const hostEl = els[idx]
if (!hostEl) {
nextOverflow[idx] = false
nextCollapsed[idx] = ''
return
}
const hostStyle = window.getComputedStyle(hostEl)
const contentWidth = hostEl.clientWidth
if (!contentWidth) {
nextOverflow[idx] = false
nextCollapsed[idx] = ''
return
}
measureEl.style.width = `${contentWidth}px`
measureEl.style.font = hostStyle.font
measureEl.style.fontSize = hostStyle.fontSize
measureEl.style.fontFamily = hostStyle.fontFamily
measureEl.style.fontWeight = hostStyle.fontWeight
measureEl.style.letterSpacing = hostStyle.letterSpacing
measureEl.style.lineHeight = hostStyle.lineHeight
measureEl.style.wordBreak = hostStyle.wordBreak
measureEl.style.whiteSpace = 'normal'
const lineHeightStr = hostStyle.lineHeight
let lineHeight = parseFloat(lineHeightStr)
if (!Number.isFinite(lineHeight)) {
const fontSize = parseFloat(hostStyle.fontSize) || 14
lineHeight = fontSize * 1.2
}
const maxHeight = lineHeight * 3 + 0.5
//
measureEl.textContent = item.content
const isOverflow = measureEl.scrollHeight > maxHeight
nextOverflow[idx] = isOverflow
if (!isOverflow) {
nextCollapsed[idx] = item.content
return
}
// ...
const suffixForMeasure = `…展开`
let low = 0
let high = item.content.length
let best = 0
while (low <= high) {
const mid = Math.floor((low + high) / 2)
const candidate = item.content.slice(0, mid) + suffixForMeasure
measureEl.textContent = candidate
if (measureEl.scrollHeight <= maxHeight) {
best = mid
low = mid + 1
} else {
high = mid - 1
}
}
nextCollapsed[idx] = item.content.slice(0, best) + '…'
})
this.overflow = nextOverflow
this.collapsedText = nextCollapsed
})
},
toggle(index) {
this.$set(this.expanded, index, !this.expanded[index])
this.measureOverflow()
},
onResize() {
this.ensureStateSize()
this.measureOverflow()
}
}
}
</script>
<style lang="scss">
.list-container {
width: 220px;
height: 100%;
border: 1px solid #e0e0e0;
background-color: #f0f0f0;
display: flex;
flex-direction: column;
gap: 10px;
.list-item {
width: 100%;
min-height: 100px;
height: auto;
background-color: #f0f0f0;
padding: 8px;
box-sizing: border-box;
}
.list-item:hover {
background-color: #e0e0e0;
}
.list-item-content-wrap {
display: flex;
flex-direction: column;
gap: 6px;
}
.list-item-content {
position: relative;
word-break: break-word;
}
.list-item-toggle {
padding: 0 0 0 6px;
border: 0;
background: transparent;
color: #1677ff;
cursor: pointer;
font-size: 12px;
line-height: 1.2;
}
.list-item-toggle:hover {
text-decoration: underline;
}
.list-item-measure {
position: absolute;
left: -99999px;
top: -99999px;
visibility: hidden;
pointer-events: none;
word-break: break-word;
white-space: normal;
}
}
</style>
<template>
<div class="apaas-custom-page-todo custom-page">
<div class="list-container">
<div v-for="(item, index) in list" :key="index" class="list-item">
<div class="list-item-time">
{{ item.time }}
</div>
<div class="list-item-content-wrap">
<div
ref="contentEls"
class="list-item-content"
:class="{ 'is-expanded': expanded[index] }"
>
<span class="list-item-content-text">
{{
overflow[index] && !expanded[index]
? collapsedText[index]
: item.content
}}
</span>
<button
v-if="overflow[index]"
type="button"
class="list-item-toggle"
@click="toggle(index)"
>
{{ expanded[index] ? '收起' : '展开' }}
</button>
</div>
</div>
</div>
</div>
<div ref="measureEl" class="list-item-measure" aria-hidden="true"></div>
</div>
</template>
<script>
export default {
name: 'TodoPage',
data() {
return {
list: [
{
time: '123123',
content:
'74weugfiufbewbfewhfwiufhwefhwekfhwkjfasdkg撒扩大刚放假规范几个房间看过尽快发给外交国大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外大刚放假规范几个房间看过尽快发给外防科技股份较为规范会计1疯狂攻击反馈'
},
{ time: '123123', content: '74weugfiufbewbfewhfwiufhwefhwekfhwkjf' },
{ time: '123123', content: '74weugfiufbewbfewhfwiufhwefhwekfhwkjf' }
],
expanded: [],
overflow: [],
collapsedText: []
}
},
watch: {
list: {
deep: true,
immediate: true,
handler() {
this.ensureStateSize()
this.measureOverflow()
}
}
},
mounted() {
window.addEventListener('resize', this.onResize, { passive: true })
this.ensureStateSize()
this.measureOverflow()
},
beforeDestroy() {
window.removeEventListener('resize', this.onResize)
},
methods: {
ensureStateSize() {
const n = this.list.length
if (this.expanded.length !== n) {
this.expanded = Array.from({ length: n }, (_, i) => !!this.expanded[i])
}
if (this.overflow.length !== n) {
this.overflow = Array.from({ length: n }, (_, i) => !!this.overflow[i])
}
if (this.collapsedText.length !== n) {
this.collapsedText = Array.from({ length: n }, (_, i) => this.collapsedText[i] || '')
}
},
measureOverflow() {
this.$nextTick(() => {
const els = Array.isArray(this.$refs.contentEls)
? this.$refs.contentEls
: this.$refs.contentEls
? [this.$refs.contentEls]
: []
const measureEl = this.$refs.measureEl
if (!measureEl) return
const nextOverflow = []
const nextCollapsed = []
this.list.forEach((item, idx) => {
const hostEl = els[idx]
if (!hostEl) {
nextOverflow[idx] = false
nextCollapsed[idx] = ''
return
}
const hostStyle = window.getComputedStyle(hostEl)
const contentWidth = hostEl.clientWidth
if (!contentWidth) {
nextOverflow[idx] = false
nextCollapsed[idx] = ''
return
}
measureEl.style.width = `${contentWidth}px`
measureEl.style.font = hostStyle.font
measureEl.style.fontSize = hostStyle.fontSize
measureEl.style.fontFamily = hostStyle.fontFamily
measureEl.style.fontWeight = hostStyle.fontWeight
measureEl.style.letterSpacing = hostStyle.letterSpacing
measureEl.style.lineHeight = hostStyle.lineHeight
measureEl.style.wordBreak = hostStyle.wordBreak
measureEl.style.whiteSpace = 'normal'
const lineHeightStr = hostStyle.lineHeight
let lineHeight = parseFloat(lineHeightStr)
if (!Number.isFinite(lineHeight)) {
const fontSize = parseFloat(hostStyle.fontSize) || 14
lineHeight = fontSize * 1.2
}
const maxHeight = lineHeight * 3 + 0.5
//
measureEl.textContent = item.content
const isOverflow = measureEl.scrollHeight > maxHeight
nextOverflow[idx] = isOverflow
if (!isOverflow) {
nextCollapsed[idx] = item.content
return
}
// ...
const suffixForMeasure = `…展开`
let low = 0
let high = item.content.length
let best = 0
while (low <= high) {
const mid = Math.floor((low + high) / 2)
const candidate = item.content.slice(0, mid) + suffixForMeasure
measureEl.textContent = candidate
if (measureEl.scrollHeight <= maxHeight) {
best = mid
low = mid + 1
} else {
high = mid - 1
}
}
nextCollapsed[idx] = item.content.slice(0, best) + '…'
})
this.overflow = nextOverflow
this.collapsedText = nextCollapsed
})
},
toggle(index) {
this.$set(this.expanded, index, !this.expanded[index])
this.measureOverflow()
},
onResize() {
this.ensureStateSize()
this.measureOverflow()
}
}
}
</script>
<style lang="scss">
.list-container {
width: 220px;
height: 100%;
border: 1px solid #e0e0e0;
background-color: #f0f0f0;
display: flex;
flex-direction: column;
gap: 10px;
.list-item {
width: 100%;
min-height: 100px;
height: auto;
background-color: #f0f0f0;
padding: 8px;
box-sizing: border-box;
}
.list-item:hover {
background-color: #e0e0e0;
}
.list-item-content-wrap {
display: flex;
flex-direction: column;
gap: 6px;
}
.list-item-content {
position: relative;
word-break: break-word;
}
.list-item-toggle {
padding: 0 0 0 6px;
border: 0;
background: transparent;
color: #1677ff;
cursor: pointer;
font-size: 12px;
line-height: 1.2;
}
.list-item-toggle:hover {
text-decoration: underline;
}
.list-item-measure {
position: absolute;
left: -99999px;
top: -99999px;
visibility: hidden;
pointer-events: none;
word-break: break-word;
white-space: normal;
}
}
</style>

View File

@ -1,11 +1,21 @@
<template>
<div class="permission-management-page custom-page">
<div class="page-header">
<div class="title">
权限管理
<!-- 人员管理组件 -->
<apaas-custom-roleMemberManagement
v-if="showRoleMemberManagement"
:role-id="currentRoleId"
:role-name="currentRoleName"
@back="handleBackFromRoleMember"
/>
<!-- 权限管理主页面 -->
<div v-if="!showRoleMemberManagement">
<div class="page-header">
<div class="title">
权限管理
</div>
</div>
</div>
<div class="page-content">
<div class="page-content">
<div class="header-section">
<el-button type="primary" @click="handleAddRole">
新增角色
@ -78,6 +88,7 @@
</div>
</div>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
@ -146,7 +157,7 @@
<el-dialog
title="人员配置"
:visible.sync="personConfigDialogVisible"
width="500px"
width="800px"
:close-on-click-modal="false"
:modal="false"
class="person-config-dialog"
@ -194,34 +205,28 @@
</template>
<!-- 配置人员模式 -->
<template v-else>
<!-- <el-form-item label="责任部门:" prop="department">
<el-cascader
ref="departmentCascader"
v-model="personConfigFormData.department"
:options="departmentList"
:props="departmentCascaderProps"
filterable
placeholder="请选择责任部门"
<el-form-item label="搜索人员:">
<el-input
v-model="personSearchKeyword"
placeholder="在已选人员中搜索人名"
clearable
style="width: 100%"
@change="handlePersonDepartmentChange"
@input="handlePersonSearchInList"
/>
</el-form-item> -->
<el-form-item label="人员:" prop="person">
</el-form-item>
<el-form-item label="添加人员:">
<el-select
v-model="personConfigFormData.person"
multiple
v-model="personToAdd"
filterable
remote
reserve-keyword
collapse-tags
:max-collapse-tags="3"
placeholder="请输入人员姓名进行搜索"
placeholder="请输入人员姓名进行搜索并添加"
style="width: 100%"
clearable
:remote-method="queryPersonByDepartment"
:loading="personSearchLoading"
class="person-select"
@change="handleAddPersonToList"
>
<el-option
v-for="person in personOptions"
@ -234,6 +239,32 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item label="已选人员:">
<el-table
:data="filteredPersonList"
border
max-height="300"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="username" label="姓名" align="center" />
<el-table-column prop="userNumber" label="ID" align="center" />
<el-table-column label="操作" width="80" align="center">
<template slot-scope="{ row }">
<el-button
type="text"
style="color: #f56c6c"
@click="handleRemovePersonFromList(row)"
>
移除
</el-button>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 8px; color: #909399; font-size: 12px">
{{ personConfigFormData.person.length }}
</div>
</el-form-item>
</template>
</el-form>
<div slot="footer" class="dialog-footer">
@ -348,7 +379,11 @@ export default {
roleDescription: '',
roleId: '' // 使
},
addRoleFormRules: {
//
showRoleMemberManagement: false,
currentRoleId: '',
currentRoleName: '',
addRoleFormRules: {
roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
roleCode: [{ required: true, message: '请输入角色代码', trigger: 'blur' }],
roleDescription: [{ required: true, message: '请输入角色描述', trigger: 'blur' }]
@ -383,6 +418,9 @@ export default {
},
personOptions: [], //
personSearchLoading: false, // loading
personSearchKeyword: '', //
personToAdd: '', // ID
selectedPersonList: [], // [{ userId, username, userNumber }]
selectedDepartmentOptions: [], // { value, label }
personConfigFormRules: {
department: [
@ -433,6 +471,21 @@ export default {
}
},
computed: {
filteredPersonList() {
let list = []
if (!this.personSearchKeyword || this.personSearchKeyword.trim() === '') {
list = this.selectedPersonList
} else {
//
const keyword = this.personSearchKeyword.trim().toLowerCase()
list = this.selectedPersonList.filter((person) => {
const name = (person.username || '').toLowerCase()
const number = (person.userNumber || '').toLowerCase()
return name.includes(keyword) || number.includes(keyword)
})
}
return list.slice().reverse()
},
dialogTitle() {
return this.dialogMode === 'add' ? '新增' : '修改'
},
@ -1507,96 +1560,21 @@ export default {
//
})
},
//
// -
handlePersonConfig(row) {
this.personConfigFormData = {
configType: 'person',
department: '',
person: [], // userId
selectDeptId: '',
selectDeptName: '',
selectDeptIds: [],
roleId: row.rowId || row.id || '',
roleName: row.roleName || ''
}
this.selectedDepartmentOptions = []
const request = {
...api.CHECK_ROLE_USER_DEPT,
params: {
roleId: row.rowId || row.id || ''
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen((resp) => {
if (resp && resp.data) {
// { "": ["-ID"], "": ["-yc90117847"] }
const respData = resp.data
const personArray = respData['人员'] || respData.person || []
const departmentArray = respData['部门'] || respData.department || []
// ["-ID"] [{ deptId, deptName }]ID
if (departmentArray.length > 0) {
const deptIds = []
const optionsFromApi = []
departmentArray.forEach((item) => {
if (typeof item === 'string' && item.includes('-')) {
const parts = item.split('-')
if (parts.length >= 2) {
const deptName = parts[0]
const deptId = parts.slice(1).join('-')
const idStr = deptId == null ? '' : String(deptId)
deptIds.push(idStr)
optionsFromApi.push({ value: idStr, label: deptName || idStr })
}
} else if (item && typeof item === 'object' && (item.deptId != null || item.id != null)) {
const id = item.deptId != null ? item.deptId : item.id
const name = item.deptName || item.name || item.label || ''
const idStr = id == null ? '' : String(id)
deptIds.push(idStr)
optionsFromApi.push({ value: idStr, label: name || idStr })
}
})
this.personConfigFormData.selectDeptIds = deptIds
this.personConfigFormData.department = deptIds
this.selectedDepartmentOptions = optionsFromApi
}
// ["userName-userId"]
const userIds = []
const personOptionsMap = new Map()
personArray.forEach((personStr) => {
if (typeof personStr === 'string' && personStr.includes('-')) {
const parts = personStr.split('-')
if (parts.length >= 2) {
const userName = parts[0]
const userId = parts.slice(1).join('-') // userId -
userIds.push(userId)
//
personOptionsMap.set(userId, {
userId: userId,
username: userName,
userNumber: userId // userNumber 使 userId
})
}
}
})
// ID
this.personConfigFormData.person = userIds
//
this.personOptions = Array.from(personOptionsMap.values())
}
})
.asyncErrorCatch((err) => {
console.error('加载人员列表失败:', err)
})
this.personConfigDialogVisible = true
this.$nextTick(() => {
if (this.$refs.personConfigForm) {
this.$refs.personConfigForm.clearValidate()
}
})
console.log('打开人员管理页面:', row)
this.currentRoleId = row.rowId || row.id || ''
this.currentRoleName = row.roleName || ''
this.showRoleMemberManagement = true
},
//
handleBackFromRoleMember() {
console.log('从人员管理页面返回')
this.showRoleMemberManagement = false
this.currentRoleId = ''
this.currentRoleName = ''
},
//
handleConfigTypeChange(value) {
// department id selectDeptIds el-select
@ -1960,6 +1938,9 @@ export default {
roleName: ''
}
this.personOptions = []
this.personSearchKeyword = ''
this.personToAdd = ''
this.selectedPersonList = []
//
if (this.personSearchTimer) {
clearTimeout(this.personSearchTimer)
@ -1970,6 +1951,40 @@ export default {
this.$refs.personConfigForm.clearValidate()
}
},
handlePersonSearchInList() {
},
handleAddPersonToList(userId) {
if (!userId) {
return
}
const person = this.personOptions.find((p) => p.userId === userId)
if (!person) {
return
}
const exists = this.selectedPersonList.some((p) => p.userId === userId)
if (exists) {
this.$message.warning('该人员已在列表中')
this.personToAdd = ''
return
}
this.selectedPersonList.push({
userId: person.userId,
username: person.username,
userNumber: person.userNumber
})
this.personConfigFormData.person.push(userId)
this.personToAdd = ''
},
handleRemovePersonFromList(row) {
const index = this.selectedPersonList.findIndex((p) => p.userId === row.userId)
if (index > -1) {
this.selectedPersonList.splice(index, 1)
const idIndex = this.personConfigFormData.person.indexOf(row.userId)
if (idIndex > -1) {
this.personConfigFormData.person.splice(idIndex, 1)
}
}
},
//
handleEdit(row) {
this.addRoleMode = 'edit'

View File

@ -0,0 +1,520 @@
<template>
<div class="role-member-management-page custom-page">
<div class="page-header">
<div class="header-left">
<el-button
type="text"
icon="el-icon-arrow-left"
class="back-button"
@click="handleBack"
>
返回
</el-button>
<div class="title-info">
<span class="title">人员管理</span>
<span class="role-tip">当前选择角色<span class="role-name">{{ roleName }}</span></span>
</div>
</div>
</div>
<div class="page-content">
<!-- 搜索区域 -->
<div class="search-section">
<div class="search-form">
<div class="search-item">
<span class="label">成员名称</span>
<el-input
v-model="searchForm.memberName"
placeholder="请输入成员名称"
clearable
style="width: 200px"
/>
</div>
<div class="search-item">
<span class="label">成员编码</span>
<el-input
v-model="searchForm.memberCode"
placeholder="请输入成员编码"
clearable
style="width: 200px"
/>
</div>
<div class="search-item">
<span class="label">部门</span>
<el-input
v-model="searchForm.department"
placeholder="请输入部门"
clearable
style="width: 200px"
/>
</div>
<div class="search-actions">
<el-button type="primary" @click="handleSearch">
查询
</el-button>
<el-button @click="handleReset">
重置
</el-button>
</div>
</div>
</div>
<!-- 操作区域 -->
<div class="action-section">
<el-button type="primary" @click="handleAddMember">
添加成员
</el-button>
<el-button :disabled="selectedMembers.length === 0" @click="handleDeleteMember">
删除成员
</el-button>
</div>
<!-- 表格区域 -->
<div class="table-section">
<el-table
ref="memberTable"
:data="tableData"
border
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="username" label="成员名称" min-width="120" align="center" />
<el-table-column prop="userNumber" label="成员编码" min-width="120" align="center" />
<el-table-column label="部门" min-width="200" align="center" show-overflow-tooltip>
<template slot-scope="{ row }">
{{ formatDepartment(row) }}
</template>
</el-table-column>
</el-table>
<div class="pagination-section">
<el-pagination
:current-page="pagination.currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pagination.pageSize"
:total="pagination.total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<!-- 添加成员弹窗 -->
<el-dialog
title="添加成员"
:visible.sync="addMemberDialogVisible"
width="600px"
:close-on-click-modal="false"
append-to-body
@close="handleAddMemberDialogClose"
>
<el-form ref="addMemberForm" :model="addMemberFormData" label-width="100px">
<el-form-item label="搜索人员:">
<el-select
v-model="addMemberFormData.selectedUsers"
filterable
remote
multiple
reserve-keyword
placeholder="请输入人员姓名进行搜索"
style="width: 100%"
:remote-method="queryPerson"
:loading="personSearchLoading"
>
<el-option
v-for="person in personOptions"
:key="person.userNumber"
:value="person.userId"
:label="person.username"
>
<span>{{ person.username }}</span>
<span style="float: right; color: #8492a6; font-size: 12px">{{ person.userNumber }}</span>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleAddMemberDialogClose">
取消
</el-button>
<el-button type="primary" :loading="addMemberSubmitting" @click="handleAddMemberSubmit">
确定
</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import api from '@/api'
export default {
name: 'RoleMemberManagement',
props: {
roleId: {
type: String,
default: ''
},
roleName: {
type: String,
default: ''
}
},
data() {
return {
searchForm: {
memberName: '',
memberCode: '',
department: ''
},
tableData: [],
selectedMembers: [],
pagination: {
currentPage: 1,
pageSize: 10,
total: 0
},
addMemberDialogVisible: false,
addMemberFormData: {
selectedUsers: []
},
personOptions: [],
personSearchLoading: false,
addMemberSubmitting: false
}
},
mounted() {
console.log('人员管理组件 mounted, roleId:', this.roleId, 'roleName:', this.roleName)
this.loadMemberList()
},
methods: {
// //
formatDepartment(row) {
const parts = []
if (row.username) parts.push(row.username)
if (row.userNumber) parts.push(row.userNumber)
if (row.department) parts.push(row.department)
return parts.join('/')
},
handleBack() {
this.$emit('back')
},
handleSearch() {
this.pagination.currentPage = 1
this.loadMemberList()
},
handleReset() {
this.searchForm = {
memberName: '',
memberCode: '',
department: ''
}
this.pagination.currentPage = 1
this.loadMemberList()
},
handleAddMember() {
this.addMemberDialogVisible = true
this.addMemberFormData.selectedUsers = []
this.personOptions = []
},
handleDeleteMember() {
if (this.selectedMembers.length === 0) {
this.$message.warning('请先选择要删除的成员')
return
}
this.$confirm(`确定要删除选中的 ${this.selectedMembers.length} 个成员吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.deleteMembers()
}).catch(() => {})
},
handleSelectionChange(selection) {
this.selectedMembers = selection
},
handleSizeChange(size) {
this.pagination.pageSize = size
this.pagination.currentPage = 1
this.loadMemberList()
},
handleCurrentChange(page) {
this.pagination.currentPage = page
this.loadMemberList()
},
loadMemberList() {
const request = {
...api.CHECK_ROLE_USER_DEPT,
params: {
roleId: this.roleId
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen((resp) => {
if (resp && resp.data) {
const respData = resp.data
const personArray = respData['人员'] || respData.person || []
//
// ["-ID:100771324098969075712-userNumber:yc90117846-department:"]
const members = []
personArray.forEach((personStr) => {
if (typeof personStr === 'string') {
// -
const nameMatch = personStr.match(/^([^-]+)/)
const username = nameMatch ? nameMatch[1] : ''
// ID
const idMatch = personStr.match(/ID:([^-]+)/)
const userId = idMatch ? idMatch[1] : ''
// userNumber
const userNumberMatch = personStr.match(/userNumber:([^-]+)/)
const userNumber = userNumberMatch ? userNumberMatch[1] : ''
// department
const deptMatch = personStr.match(/department:(.+)$/)
const department = deptMatch ? deptMatch[1] : ''
if (username && userId) {
members.push({
userId: userId,
username: username,
userNumber: userNumber, //
department: department //
})
}
}
})
//
let filteredMembers = members
if (this.searchForm.memberName) {
filteredMembers = filteredMembers.filter(m =>
m.username && m.username.includes(this.searchForm.memberName)
)
}
if (this.searchForm.memberCode) {
filteredMembers = filteredMembers.filter(m =>
m.userNumber && m.userNumber.includes(this.searchForm.memberCode)
)
}
if (this.searchForm.department) {
filteredMembers = filteredMembers.filter(m =>
m.department && m.department.includes(this.searchForm.department)
)
}
//
this.pagination.total = filteredMembers.length
const startIndex = (this.pagination.currentPage - 1) * this.pagination.pageSize
const endIndex = startIndex + this.pagination.pageSize
this.tableData = filteredMembers.slice(startIndex, endIndex)
} else {
this.tableData = []
this.pagination.total = 0
}
})
.asyncErrorCatch((err) => {
console.error('加载成员列表失败:', err)
this.$message.error('加载成员列表失败,请稍后重试')
this.tableData = []
this.pagination.total = 0
})
},
queryPerson(query) {
if (!query || query.trim() === '') {
this.personOptions = []
return
}
this.personSearchLoading = true
const request = {
...api.GET_ALLUSERS,
params: {
name: query.trim()
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen((resp) => {
const respData = resp && resp.data
let result = []
if (Array.isArray(respData)) {
result = respData
} else if (respData && Array.isArray(respData.result)) {
result = respData.result
} else if (respData && respData.data && Array.isArray(respData.data)) {
result = respData.data
}
this.personOptions = result.map((user) => ({
userId: user.userId || user.id,
username: user.username || user.name,
userNumber: user.userNumber || user.userId || user.id
})).filter((user) => user.userId && user.userNumber)
this.personSearchLoading = false
})
.asyncErrorCatch((err) => {
console.error('搜索人员失败:', err)
this.personOptions = []
this.personSearchLoading = false
})
},
handleAddMemberDialogClose() {
this.addMemberDialogVisible = false
this.addMemberFormData.selectedUsers = []
this.personOptions = []
},
handleAddMemberSubmit() {
if (!this.addMemberFormData.selectedUsers || this.addMemberFormData.selectedUsers.length === 0) {
this.$message.warning('请选择要添加的成员')
return
}
this.addMemberSubmitting = true
// 使
const request = {
...api.GET_ROLE_PERMISSION_BING,
data: {
roleID: this.roleId,
userIDs: this.addMemberFormData.selectedUsers
}
}
this.$request(request)
.asyncThen((resp) => {
this.$message.success('添加成员成功')
this.addMemberSubmitting = false
this.handleAddMemberDialogClose()
this.loadMemberList()
})
.asyncErrorCatch((err) => {
console.error('添加成员失败:', err)
this.$message.error('添加成员失败')
this.addMemberSubmitting = false
})
},
deleteMembers() {
const userIds = this.selectedMembers.map((member) => member.userId)
// 使
const request = {
...api.DELETE_ROLE_PERMISSION,
params: {
roleID: this.roleId,
userIDs: userIds.join(',')
}
}
this.$request(request)
.asyncThen((resp) => {
this.$message.success('删除成员成功')
this.loadMemberList()
})
.asyncErrorCatch((err) => {
console.error('删除成员失败:', err)
this.$message.error('删除成员失败')
})
}
}
}
</script>
<style lang="scss" scoped>
.role-member-management-page {
.page-header {
padding: 20px;
background: #fff;
border-bottom: 1px solid #ebeef5;
.header-left {
display: flex;
align-items: center;
gap: 20px;
.back-button {
font-size: 16px;
color: #409eff;
}
.title-info {
display: flex;
align-items: center;
gap: 20px;
.title {
font-size: 18px;
font-weight: 600;
color: #303133;
}
.role-tip {
font-size: 14px;
color: #606266;
.role-name {
color: #f56c6c;
font-weight: 600;
}
}
}
}
}
.page-content {
padding: 20px;
.search-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.search-form {
display: flex;
align-items: center;
gap: 20px;
flex-wrap: wrap;
.search-item {
display: flex;
align-items: center;
gap: 10px;
.label {
font-size: 14px;
color: #606266;
white-space: nowrap;
}
}
.search-actions {
display: flex;
gap: 10px;
}
}
}
.action-section {
margin-bottom: 20px;
}
.table-section {
background: #fff;
padding: 20px;
border-radius: 4px;
.pagination-section {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
}
}
}
</style>

View File

@ -215,7 +215,7 @@ export default {
formatter: this.formatDateTime
}
],
seqType: '',
seqType: 'normal',
seqConfig: {},
layout: 'total, prev, pager, next, jumper, sizes'
}

View File

@ -182,7 +182,8 @@ export default {
this.$message.info('下载导入模板功能')
},
handleRevert() {
this.$message.info('退回功能')
this.isEditable = true
this.$message.success('已进入编辑模式,可修改数据')
},
handleSave() {
this.$message.info('保存功能')

View File

@ -1,82 +1,84 @@
import ApaasCustomMydemo from './custom-page/demo.vue'
import ApaasCustomMydemo2 from './custom-page/page.vue'
import ApaasCustomModalContorl from './custom-page/modelContorl.vue'
import ApaasCustomModelDetail from './custom-page/modelDetail.vue'
import ApaasCustomSelfEnginedata from './custom-page/selfEnginedata.vue'
import ApaasCustomEngineDetail from './custom-page/engineDetail.vue'
import ApaasCustomOtherEnginedata from './custom-page/otherEnginedata.vue'
import ApaasCustomCheckData from './custom-page/checkData.vue'
import ApaasCustomReportCheck from './custom-page/reportCheck.vue'
import ApaasCustomReport from './custom-page/report.vue'
import ApaasCustomReportList from './custom-page/reportList.vue'
import ApaasSelfEngineCheck from './custom-page/selfEngineCheck.vue'
import ApaasOtherEngineCheck from './custom-page/otherEngineCheck.vue'
import ApaasCustomManagerData from './custom-page/managerData.vue'
import ApaasCustomFillerData from './custom-page/fillerData.vue'
import ApaasCustomReportDetail from './custom-page/reportDetail.vue'
import ApaasCustomApprovalManagement from './custom-page/approvalManagement.vue'
import ApaasCustomTodoList from './custom-page/todo.vue'
import ApaasCustomMyDone from './custom-page/myDone.vue'
import ApaasCustomMySend from './custom-page/mySend.vue'
import ApaasCustomCheckPersonPermission from './custom-page/checkPersonPermission.vue'
import ApaasCustomPermissionManagement from './custom-page/permissionManagement.vue'
import ApaasCustomLayout from './custom-layout/custom-layout.vue'
import { customFormComponentList } from './custom-component/form-component'
import { widgetConfigList } from './custom-component/form-config'
const install = function(Vue, opts) {
// 安装Mydemo模块, 此处的和apaas.json定义的路由必须一致
Vue.component('apaas-custom-mydemo', ApaasCustomMydemo2)
Vue.component('apaas-custom-mydemo-demo', ApaasCustomMydemo)
Vue.component('apaas-custom-modalContorl', ApaasCustomModalContorl)
Vue.component('apaas-custom-modelDetail', ApaasCustomModelDetail)
Vue.component('apaas-custom-selfEnginedata', ApaasCustomSelfEnginedata)
Vue.component('apaas-custom-otherEnginedata', ApaasCustomOtherEnginedata)
Vue.component('apaas-custom-checkData', ApaasCustomCheckData)
Vue.component('apaas-custom-reportCheck', ApaasCustomReportCheck)
Vue.component('apaas-custom-engineDetail', ApaasCustomEngineDetail)
Vue.component('apaas-custom-report', ApaasCustomReport)
Vue.component('apaas-custom-reportList', ApaasCustomReportList)
Vue.component('apaas-custom-reportDetail', ApaasCustomReportDetail)
Vue.component('apaas-custom-approvalManagement', ApaasCustomApprovalManagement)
Vue.component('apaas-custom-toDoList', ApaasCustomTodoList)
Vue.component('apaas-custom-managerData', ApaasCustomManagerData)
Vue.component('apaas-custom-fillerData', ApaasCustomFillerData)
Vue.component('apaas-custom-selfEngineCheck', ApaasSelfEngineCheck)
Vue.component('apaas-custom-otherEngineCheck', ApaasOtherEngineCheck)
Vue.component('apaas-custom-myDone', ApaasCustomMyDone)
Vue.component('apaas-custom-mySend', ApaasCustomMySend)
Vue.component('apaas-custom-checkPersonPermission', ApaasCustomCheckPersonPermission)
Vue.component('apaas-custom-permissionManagement', ApaasCustomPermissionManagement)
Vue.component('apaas-custom-layout', ApaasCustomLayout)
// 安装表单部件
// 注册自开发表单组件
if (
customFormComponentList && Array.isArray(customFormComponentList)
) {
customFormComponentList.forEach((comp) => {
Vue.component(comp.name, comp)
})
}
if (Vue.LayoutEngine) {
const layoutEngine = Vue.LayoutEngine.getInstance(Vue.LayoutEngine.currentLayoutId)
layoutEngine.registerLayoutComponent(ApaasCustomLayout)
}
// 表单引擎注册自开发组件配置
if (
widgetConfigList && Array.isArray(widgetConfigList)
) {
widgetConfigList.forEach((widgetConfig) => {
const compConfig = {
widgetConfig
}
Vue.FormEngine && Vue.FormEngine.registerCustomComponentConfig(compConfig)
})
}
}
const MydemoCustomPlugin = {
install: install
}
export default MydemoCustomPlugin
import ApaasCustomMydemo from './custom-page/demo.vue'
import ApaasCustomMydemo2 from './custom-page/page.vue'
import ApaasCustomModalContorl from './custom-page/modelContorl.vue'
import ApaasCustomModelDetail from './custom-page/modelDetail.vue'
import ApaasCustomSelfEnginedata from './custom-page/selfEnginedata.vue'
import ApaasCustomEngineDetail from './custom-page/engineDetail.vue'
import ApaasCustomOtherEnginedata from './custom-page/otherEnginedata.vue'
import ApaasCustomCheckData from './custom-page/checkData.vue'
import ApaasCustomReportCheck from './custom-page/reportCheck.vue'
import ApaasCustomReport from './custom-page/report.vue'
import ApaasCustomReportList from './custom-page/reportList.vue'
import ApaasSelfEngineCheck from './custom-page/selfEngineCheck.vue'
import ApaasOtherEngineCheck from './custom-page/otherEngineCheck.vue'
import ApaasCustomManagerData from './custom-page/managerData.vue'
import ApaasCustomFillerData from './custom-page/fillerData.vue'
import ApaasCustomReportDetail from './custom-page/reportDetail.vue'
import ApaasCustomApprovalManagement from './custom-page/approvalManagement.vue'
import ApaasCustomTodoList from './custom-page/todo.vue'
import ApaasCustomMyDone from './custom-page/myDone.vue'
import ApaasCustomMySend from './custom-page/mySend.vue'
import ApaasCustomCheckPersonPermission from './custom-page/checkPersonPermission.vue'
import ApaasCustomPermissionManagement from './custom-page/permissionManagement.vue'
import ApaasCustomRoleMemberManagement from './custom-page/roleMemberManagement.vue'
import ApaasCustomLayout from './custom-layout/custom-layout.vue'
import { customFormComponentList } from './custom-component/form-component'
import { widgetConfigList } from './custom-component/form-config'
const install = function(Vue, opts) {
// 安装Mydemo模块, 此处的和apaas.json定义的路由必须一致
Vue.component('apaas-custom-mydemo', ApaasCustomMydemo2)
Vue.component('apaas-custom-mydemo-demo', ApaasCustomMydemo)
Vue.component('apaas-custom-modalContorl', ApaasCustomModalContorl)
Vue.component('apaas-custom-modelDetail', ApaasCustomModelDetail)
Vue.component('apaas-custom-selfEnginedata', ApaasCustomSelfEnginedata)
Vue.component('apaas-custom-otherEnginedata', ApaasCustomOtherEnginedata)
Vue.component('apaas-custom-checkData', ApaasCustomCheckData)
Vue.component('apaas-custom-reportCheck', ApaasCustomReportCheck)
Vue.component('apaas-custom-engineDetail', ApaasCustomEngineDetail)
Vue.component('apaas-custom-report', ApaasCustomReport)
Vue.component('apaas-custom-reportList', ApaasCustomReportList)
Vue.component('apaas-custom-reportDetail', ApaasCustomReportDetail)
Vue.component('apaas-custom-approvalManagement', ApaasCustomApprovalManagement)
Vue.component('apaas-custom-toDoList', ApaasCustomTodoList)
Vue.component('apaas-custom-managerData', ApaasCustomManagerData)
Vue.component('apaas-custom-fillerData', ApaasCustomFillerData)
Vue.component('apaas-custom-selfEngineCheck', ApaasSelfEngineCheck)
Vue.component('apaas-custom-otherEngineCheck', ApaasOtherEngineCheck)
Vue.component('apaas-custom-myDone', ApaasCustomMyDone)
Vue.component('apaas-custom-mySend', ApaasCustomMySend)
Vue.component('apaas-custom-checkPersonPermission', ApaasCustomCheckPersonPermission)
Vue.component('apaas-custom-permissionManagement', ApaasCustomPermissionManagement)
Vue.component('apaas-custom-roleMemberManagement', ApaasCustomRoleMemberManagement)
Vue.component('apaas-custom-layout', ApaasCustomLayout)
// 安装表单部件
// 注册自开发表单组件
if (
customFormComponentList && Array.isArray(customFormComponentList)
) {
customFormComponentList.forEach((comp) => {
Vue.component(comp.name, comp)
})
}
if (Vue.LayoutEngine) {
const layoutEngine = Vue.LayoutEngine.getInstance(Vue.LayoutEngine.currentLayoutId)
layoutEngine.registerLayoutComponent(ApaasCustomLayout)
}
// 表单引擎注册自开发组件配置
if (
widgetConfigList && Array.isArray(widgetConfigList)
) {
widgetConfigList.forEach((widgetConfig) => {
const compConfig = {
widgetConfig
}
Vue.FormEngine && Vue.FormEngine.registerCustomComponentConfig(compConfig)
})
}
}
const MydemoCustomPlugin = {
install: install
}
export default MydemoCustomPlugin

View File

@ -1,24 +1,24 @@
import customFuncs from './custom-functions/index'
const install = function({ RuleEngine }, hookManager, definition) {
if (!RuleEngine) {
console.error('x-extension上下文中没有注册RuleEngine, 请检查')
return
}
Object.keys(customFuncs).forEach((funcKey) => {
const func = customFuncs[funcKey]
if (func && func.name && func.executeFunction && func.executeFunction instanceof Function) {
if (func.name.indexOf('custom') !== 0) {
console.error(`自定义函数-${func.name} 名称有误请以custom开头`)
return
}
RuleEngine.getInstance().registerContextMethod(
func.name,
func
)
} else {
console.error(`请检查${func && func.name}的规则函数定义`)
}
})
}
export default { install }
import customFuncs from './custom-functions/index'
const install = function({ RuleEngine }, hookManager, definition) {
if (!RuleEngine) {
console.error('x-extension上下文中没有注册RuleEngine, 请检查')
return
}
Object.keys(customFuncs).forEach((funcKey) => {
const func = customFuncs[funcKey]
if (func && func.name && func.executeFunction && func.executeFunction instanceof Function) {
if (func.name.indexOf('custom') !== 0) {
console.error(`自定义函数-${func.name} 名称有误请以custom开头`)
return
}
RuleEngine.getInstance().registerContextMethod(
func.name,
func
)
} else {
console.error(`请检查${func && func.name}的规则函数定义`)
}
})
}
export default { install }

View File

@ -1,10 +1,10 @@
{
"copyAssets": ["public/custom/apaas-custom-plugin-custom-rule"],
"code": "PLUGIN_CUSTOM_RULE",
"name": "自开发规则",
"description": "自开发规则集成",
"outputName": "apaas-custom-plugin-custom-rule",
"admin": "admin.js",
"app": "app.js",
"mobile": "mobile.js"
{
"copyAssets": ["public/custom/apaas-custom-plugin-custom-rule"],
"code": "PLUGIN_CUSTOM_RULE",
"name": "自开发规则",
"description": "自开发规则集成",
"outputName": "apaas-custom-plugin-custom-rule",
"admin": "admin.js",
"app": "app.js",
"mobile": "mobile.js"
}

Some files were not shown because too many files have changed in this diff Show More