Commit 717a5684 authored by 范骋宇's avatar 范骋宇 🇺🇸

将文档中心合入主项目

parent 44da0193
// 开发环境
// const VUE_APP_BASE_API = 'http://192.168.1.124:9002' // eslint-disable-line
const VUE_APP_BASE_API = 'http://192.168.1.73/api/' // eslint-disable-line
const VUE_APP_BASE_API = 'http://8.130.87.222/api/' // eslint-disable-line
const TaskCenterSelectUserComponentName = 'DeeChooseScopeUserDialog' // eslint-disable-line
// 三元用户是否展示全局搜索
// eslint-disable-next-line
......
......@@ -113,6 +113,7 @@ router.beforeEach(async(to, from, next) => {
currentModuleRoute &&
!Vue.prototype.$loadModule.hasOwnProperty(currentModuleRoute) // eslint-disable-line
) {
console.log({ currentModuleRoute })
await loadMicroModule(currentModuleRoute)
next({ ...to, replace: true })
} else {
......
module.exports = {
title: 'DEX阳易数字化转型工业套件',
title: '多传感器联合标定与校准系统数据库管理软件',
/**
* @type {boolean} true | false
* @description Whether fix the header
......
......@@ -1306,6 +1306,7 @@ export async function loadMicroModule(module) {
Vue.prototype.$loadModule[module] = microModule.default // eslint-disable-line
return true
} catch (error) {
console.log({ error })
// setTimeout(() => {
// loadMicroModule(module)
// }, 20000)
......
......@@ -170,6 +170,7 @@ export default {
this.$router.push(toPage)
},
goContent(app) {
console.log({ app })
if (!app.dxApplicationMenus) {
return this.$utils.showMessageWarning('请在应用中心配置菜单页面')
}
......
build/*.js
src/assets/*.js
public
dist
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
# app-javascript
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn run serve
```
### Compiles and minifies for production
```
yarn run build
```
### Run your tests
```
yarn run test
```
### Lints and fixes files
```
yarn run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/app'
]
}
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
coverageDirectory: '<rootDir>/tests/unit/coverage',
// 'collectCoverage': true,
'coverageReporters': [
'lcov',
'text-summary'
],
testURL: 'http://localhost/'
}
{
"name": "dee-doc",
"devPort": 10252,
"version": "0.1.0",
"scripts": {
"serve": "vue-cli-service serve",
"lint": "vue-cli-service lint",
"build": "vue-cli-service build --report"
},
"dependencies": {
"axios": "^0.19.2",
"lodash.foreach": "^4.5.0",
"moment": "^2.26.0",
"vue": "^2.6.10",
"vue-router": "^3.1.3",
"vuex": "^3.1.2",
"vuedraggable": "2.23.0"
},
"devDependencies": {
"@babel/core": "7.0.0",
"@babel/register": "7.0.0",
"@vue/cli-plugin-babel": "3.6.0",
"@vue/cli-plugin-eslint": "^3.9.1",
"@vue/cli-plugin-unit-jest": "3.6.3",
"@vue/cli-service": "^4.1.0",
"@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "^9.5.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^8.0.1",
"babel-jest": "23.6.0",
"chalk": "2.4.2",
"connect": "3.6.6",
"css-loader": "^1.0.1",
"eslint": "5.15.3",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "5.2.2",
"html-webpack-plugin": "3.2.0",
"lint-staged": "^10.2.9",
"mockjs": "1.0.1-beta3",
"node-sass": "^4.14.1",
"runjs": "^4.3.2",
"sass-loader": "^7.3.1",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"style-loader": "^1.1.3",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.4.1"
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/prettier"
],
"rules": {
"no-console": "off",
"no-unused-vars": "off"
},
"parserOptions": {
"parser": "babel-eslint"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"lint-staged": {
"*.{js,vue}": [
"vue-cli-service lint",
"git add"
]
},
"license": "MIT"
}
<template>
<div class="app">
<router-view />
</div>
</template>
<script>
import './base'
export default {}
</script>
<style scoped>
.app {
height: 100%;
}
</style>
import {
post,
del
} from '../utils/http'
// 保存目录导航-容器
export function saveSearchLog(params) {
return post('/ObjectSearchLog/saveSearchLog', params)
}
// 查询目录导航-容器
export function getSearchLogPage(params) {
return post('/ObjectSearchLog/findSearchLogPage', params)
}
// 删除目录导航-容器
export function deleteSearchLog(params) {
return del('ObjectSearchLog/deleteSearchLog', { data: params })
}
import { get, post, put } from '../utils/http'
export function addComponents(params) {
return post(`/SystemComponent`, params)
}
export function updateComponents(params) {
return put(`/SystemComponent`, params)
}
export function getComponents(typeKey) {
return get(`/SystemComponent/query/typekey?typeKey=${typeKey}`)
}
export function updateLayouts(layoutModel) {
return put(`/model/systems/layouts`, layoutModel)
}
export function componentBindFun(layoutModel) {
return put(`/SystemComponent/all`, layoutModel)
}
import {
get,
post
// del
} from '../utils/http'
// 根据keyName 查询
export function getAppLayoutByKey(keyName) {
return get(`/AppLayout/find/${keyName}`)
}
// 查询模型配置信息
export function getLayouts(typeKey, layoutType) {
return new Promise(async(resolve, reject) => {
get('/DxModelComponent/findModelComponent', { modelDefName: typeKey, layoutType }).then(res => {
if (res.items && res.items.content) {
resolve({
items: res.items.content
})
}
})
})
}
// 查询所有基本属性
export function getappLayout(params) {
return get('/AppLayout/' + params)
}
// 查询模型配置信息
export function esSearch(typeKey, layoutType) {
return post('/DxDocument/search', { layoutType, typeKey })
}
// // 查询所有基本属性
// export function postappLayout(params) {
// return post('/AppLayout/', params)
// }
// // 查询所有基本属性
// export function putappLayout(params) {
// return put('/AppLayout/', params)
// }
// 查询勾选了文件夹插件的模型
export function findModelByPlugin(params) {
return get('/ModelDefinition/findModelByPlugin', params)
}
// 查询容器下用户
export function findUserByContext(params) {
return get('/DxContextTeam/findUserByContextAndReferenced', params)
}
// 查询文件夹下的成员权限
export function getOperateAuth(params) {
return get('/DxFolderOperationLink/search/operate/auth', params)
}
// 禁用文件夹成员的继承
export function disableInheritance(folderId, params) {
return post(`/DxFolderOperationLink/disableInheritance?folderId=${folderId}`, params)
}
// 获取容器下的团队
export function findTeamByContext(params) {
return get('/DxContextTeam/findTeamByContext', params)
}
import {
get,
post,
put
// del
} from '../utils/http'
// 查询模型配置信息
export function getLayouts(typeKey, layoutType) {
return new Promise(async(resolve, reject) => {
get('/DxModelComponent/findModelComponent', { modelDefName: typeKey, layoutType }).then(res => {
if (res.items && res.items.content) {
resolve({
items: res.items.content
})
}
})
})
}
export function getDxDocument(params) {
return post('/DxDocument/search', params)
}
// 查询所有基本属性
export function getappLayout(params) {
return get('/AppLayout/' + params)
}
// 查询模型配置信息
export function addDoc(params) {
return post('/DxDocument', params)
}
export function editDoc(params) {
return put('/DxDocument', params)
}
export function addDocWithRecursion(params, url) {
return post(url || '/DxDocument/recursion', params)
}
export function getDetail(params) {
return get('/DxDocument/detail?', params)
}
export function getDetailWithRecursion({ id, openProps }) {
const params = {
'openProps': [],
'pageFrom': 1,
'pageSize': 10,
'searchItems': {
'children': [
],
'items': [
{
'fieldName': 'id',
'operator': 'EQ',
'value': id
}
],
'operator': 'AND'
}
}
params.openProps = openProps
return post('/DxDocument/find/recursion', params)
}
export function approveAdd(params) {
return post('/DxDocument/approve', params)
}
export function getSubTypeName(packageId, clsName) {
return get('/ModelDefinition/select/children', { packageId, clsName })
}
export function getDocFolder(params) {
return post('/DxDocumentFolder/searchFolder', params)
}
export function DxDocumentMetrics(params) {
return post('/DxDocument/metrics', params)
}
export function DxFolder(params) {
return post('/DxFolder/search', params)
}
// 获取容器目录tree
export function folderTreeSearch(params) {
return post('/DxFolderLink/searchFolderWithAuthKey', params)
}
// 移动数据到文件夹
export function pasteData(sourceFolderId, targetFolderId, pasteType, params) {
return post(`/DxObjFolderLink/pasteData?sourceFolderId=${sourceFolderId}&targetFolderId=${targetFolderId}&pasteType=${pasteType}`, params)
}
import {
get
// post,
// put
// del
} from '../utils/http'
// 查询模型配置信息
export function getModelTree(params) {
return get('/ModelDefinition/all/base/tree', params)
}
import {
get
// del
} from '../utils/http'
export function getPermissions(appId, keyName, appName) {
return get('/perm/PageResource/childrenKeyNames', { appId, keyName, appName })
}
import {
get
} from '../utils/http'
// 根据pbo查询流程实例列表
export function getWFInsts(params) {
return get('/workflow/inst', params)
}
// 查询流程实例详情
export function instDetail(instId) {
return get(`/workflow/inst/${instId}/simple`)
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* @Description:
* @author cxg
* @date 2020/07/22
*/
<template>
<div class="add-page">
<div class="full-border-content">
<el-scrollbar class="scroll-container" style="height:100%">
<div class="task-name">新建文档</div>
<dee-form
:form="typeForm"
:form-data="typeFormData"
:border="configDetails&&configDetails.base&&configDetails.base.borderShow"
:label-width="configDetails&&configDetails.base&&configDetails.base.labelWidth"
/>
<dee-form
ref="addForm"
:form="addData"
:form-data="showFormData"
:rules="configDetails.rules"
:form-buttons="configDetails.formButtons"
:border="configDetails&&configDetails.base&&configDetails.base.borderShow"
:label-width="configDetails&&configDetails.base&&configDetails.base.labelWidth"
:form-btn-position="configDetails&&configDetails.base&&configDetails.base.formBtnPosition"
:label-position="configDetails&&configDetails.base&&configDetails.base.labelPosition"
@on-submit="submitFun"
@on-cancel="cancelFun"
/>
</el-scrollbar>
</div>
</div>
</template>
<script>
import { getLayouts } from '@/api/config'
import { addDocWithRecursion, getSubTypeName } from '@/api/doc'
export default {
name: 'DxDocumentAdd',
displayName: '新建文档',
modelRelationObjs: [],
components: {},
props: {
sandboxId: {
type: Number,
default: () => 0
}
},
data() {
return {
addData: {},
appUrl: '',
typeName: 'DxDocument',
typeForm: { subTypeName: '' },
configDetails: {
formData: []
},
docTypes: [],
layout: ''
}
},
computed: {
visitedViews() {
return this.$store.state.tagsView.visitedViews
},
previousRouter() {
return this.$store.state.tagsView.previousRouter.slice(-1)[0]
},
showFormData() {
if (!this.configDetails || !this.configDetails.formData) {
return []
}
return this.configDetails.formData
},
typeFormData() {
return [
{
title: '',
split: 3,
data: [
{ key: 'subTypeName',
title: '文档类型',
component: {
name: 'el-select',
options: this.docTypes
}
}
]
}
]
}
},
watch: {
'typeForm.subTypeName'(val) {
this.getLayouts()
},
// 重新打开页签则刷新页面
visitedViews(value) {
if (value.some(x => x.name === 'docAdd')) {
this.addData = {}
this.$refs.addForm.$refs.form.clearValidate()
this.getSubTypeName()
}
}
},
created() {
if (window.location.hash.includes('?layout=')) {
this.layout = window.location.hash.split('?layout=').slice(-1)[0]
this.layout = this.layout ? this.layout.split('&').slice(-1)[0] : ''
}
this.getSubTypeName()
},
mounted() {},
methods: {
getSubTypeName() {
if (this.typeName === null || this.typeName === '') {
return
}
getSubTypeName('', this.typeName).then(res => {
if (res.items) {
this.docTypes = res.items.map(item => {
return {
label: item.displayName,
value: item.name
}
})
this.typeForm.subTypeName = this.docTypes[0].value
}
})
},
getLayouts() {
if (!this.typeForm || !this.typeForm.subTypeName) {
return
}
getLayouts(this.typeForm.subTypeName, this.layout || this.$enums.layout['新建']).then((res) => {
const item = res.items.slice(-1)
if (item[0] && item[0].configDetails) {
this.configDetails = JSON.parse(item[0].configDetails)
this.appUrl = this.configDetails.tableConfig && this.configDetails.tableConfig.serverUrl
}
})
},
submitFun() {
// this.addData.state = '编制'
this.addData.subTypeName = this.typeForm.subTypeName
const params = this.$utils.saveDynamicAttr(this.addData, '.')
params.operator = 'ADD'
if (this.sandboxId !== 0) {
params.sandboxId = this.sandboxId
this.$emit('submitFun', params)
} else {
addDocWithRecursion(params, this.appUrl).then(res => {
this.$utils.showMessage('操作成功!', 'success')
this.$emit('submitFun', res.items)
})
}
},
cancelFun() {
this.$emit('cancel')
}
}
}
</script>
<style lang='scss'>
</style>
<template>
<div class="DocumentFolder">
<div class="DocumentFolder-top">
<dee-search-box
v-if="contextVisible"
type-name="DxDocument"
v-bind="filterConfig.configDetails"
@formChange="searchEvent"
/>
</div>
<div class="DocumentFolder-main">
<el-tree
ref="tree"
node-key="id"
empty-text="请选择容器"
class="tree-line"
icon-class="el-icon-circle-plus-outline"
:highlight-current="true"
:expand-on-click-node="false"
:data="data"
:props="defaultProps"
:lazy="lazy"
:load="loadNode"
:default-expanded-keys="defaultExpandedKeys"
@node-drag-end="handleDragEnd"
@current-change="currentChange"
>
<div slot-scope="{node}" class="DocumentFolder-node">
<template v-if="!node.edit">
<div class="DocumentFolder-label" :title="node.label">
<img v-if="node.expanded" class="folderIcon" src="../../icons/folder_open.svg" alt="">
<img v-else class="folderIcon" src="../../icons/folder_closed.svg" alt="">
<span v-if="node.label" class="change-text">
{{ node.label }}
</span>
<i v-else>&lt;未命名&gt;</i>
</div>
<div v-if="!readonly && !edit" class="DocumentFolder-btn">
<button v-if="node.level>1" title="重命名" class="DocumentFolder-btnItem btn-edit" @click.stop="editFolder(node)" />
<button title="添加" class="DocumentFolder-btnItem btn-add" @click.stop="addFolder(node)" />
<button v-if="node.level>1" slot="reference" title="删除" class="DocumentFolder-btnItem btn-delete" @click.stop="deleteFolder(node)" />
</div>
</template>
<template v-else>
<div class="DocumentFolder-label">
<el-input ref="input" v-model="node.rename" size="mini" @blur="endEdit(node)" @keyup.enter.native="editEnter(node)" @keyup.esc.native="cancelEdit(node)" />
</div>
</template>
</div>
</el-tree>
</div>
</div>
</template>
<script>
import { getLayouts } from '@/api/doc'
export default {
name: 'DxDocumentFolder',
displayName: '文档文件夹',
modelRelationObjs: ['DxDocumentFolder'],
props: {
fixContext: {
type: Object,
default() {
return null
}
},
contextVisible: {
type: Boolean,
default: true
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
edit: false,
canEdit: true,
lazy: true,
defaultExpandedKeys: [],
filterConfig: {},
dxDocumentFolderService: this.$getService('DxDocumentFolder'),
context: this.fixContext,
data: [],
defaultProps: {
children: 'children',
label: 'name',
isLeaf: 'isLeaf'
},
selectFolderObj: {
dxContext: {},
dxDocumentFolder: {}
}
}
},
watch: {
context() {
if (this.context && this.context.id) {
this.data = [this.context]
} else {
this.data = []
}
}
},
created() {
if (this.fixContext && this.fixContext.id) {
this.defaultExpandedKeys = [this.fixContext.id]
}
getLayouts('DxDocument', 'OnlyContext'/* 'OnlyContext'*/).then(res => {
this.filterConfig = res.items ? res.items.slice(-1)[0] : {}
this.filterConfig.configDetails = JSON.parse(this.filterConfig.configDetails)
})
},
methods: {
searchEvent(data) {
const contextId = data.contextId.value
this.$getService('DxContext').byId(contextId).then(r => {
this.selectFolderObj.dxContext = r
this.$emit('currentChange', {}, {}, this.selectFolderObj)
this.$set(this, 'defaultExpandedKeys', r ? [r.id] : [])
this.$set(this, 'context', r || null)
}).finally(() => {
})
},
// getTreeId(data) {
// alert(data.id)
// return Date.now()
// },
loadNode(node, resolve) {
if (node.level === 0) {
if (this.context && this.context.id) {
resolve([this.context])
}
} else if (node.level === 1) {
this.dxDocumentFolderService.getRootFolders(this.context.id).then(r => {
resolve(r.content)
}).catch(e => {
resolve([])
})
} else {
this.dxDocumentFolderService.getFolders(node.data.id).then(r => {
resolve(r.content)
}).catch(e => {
resolve([])
})
}
resolve([])
},
getItem() {
// this.docFolderModel.
},
currentChange(data, node) {
this.selectFolderObj.dxDocumentFolder = data
this.$emit('currentChange', data, node, this.selectFolderObj)
},
addFolder(node) {
this.$prompt('请输入名称', '新建目录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[^\\/:\*\?""<>|]{1,120}$/,
inputErrorMessage: '文件名不能包含:\\/:*?"<>|'
}).then(({ value }) => {
this.dxDocumentFolderService.addFolder(this.context.id, node.level > 1 ? node.data.id : 0, value).then((r) => {
if (node.loaded) {
this.$refs.tree.append(r.items, node)
}
node.expand()
this.$utils.showMessageSuccess('操作成功')
})
}).catch(() => {
this.$utils.showMessageInfo('取消输入')
})
// const newChild = { id: 'new', name: '', children: [] }
// node.expand()
// if (!node.data.children) {
// this.$set(node.data, 'children', [])
// }
// node.data.children.push(newChild)
// this.$nextTick(() => {
// var nodes = this.$refs.tree.store.nodesMap
// console.log('nodes', nodes)
// console.log('node', node)
// console.log('tree', this.$refs.tree)
// })
},
deleteFolder(node) {
const h = this.$createElement
const fullPath = this.getNodeFullPath(node)
this.$confirm(null, '提示', {
message: h('div', null, [
h('div', null, '请确认是否删除目录?'),
h('div', {
attrs: {
title: fullPath
},
style: {
marginTop: '8px',
color: '#909399',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
}
},
`"${fullPath}"`)
]),
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.dxDocumentFolderService.delete(node.data).then(() => {
this.$refs.tree.remove(node)
this.$utils.showMessageSuccess('删除成功!')
})
}).catch(() => {
this.$utils.showMessageInfo('已取消删除')
})
},
getNodeFullPath(node) {
let path = node.label
let parentNode = node.parent
while (parentNode && parentNode.level > 0) {
path = `${parentNode.label}/${path}`
parentNode = parentNode.parent
}
return '/' + path
},
// 修改名称
editFolder(node) {
this.edit = true
this.$set(node, 'edit', true)
this.$set(node, 'rename', node.data.name)
this.$nextTick(() => {
this.$refs.input.focus()
this.$refs.input.select()
})
},
// 失去焦点确定修改
endEdit(node) {
if (!node.rename && !node.cancelEdit) {
this.$refs.input.focus()
this.$utils.showMessageWarning(`名称不能为空`)
return
}
this.$set(node, 'edit', false)
this.$set(this, 'edit', false)
if (!node.cancelEdit) {
if (node.data.name !== node.rename) {
const oldName = node.data.name
node.data.name = node.rename
node.data.fullPath = null
this.dxDocumentFolderService.save(node.data).then(() => {
this.$utils.showMessageSuccess('修改成功')
}).catch(() => {
this.$set(node.data, 'name', oldName)
})
}
} else {
this.$utils.showMessageInfo('已取消修改')
}
node.cancelEdit && delete node.cancelEdit
},
// 回车确定
editEnter(node) {
node.cancelEdit = false
this.$refs.input.blur()
},
// ESC 退出
cancelEdit(node) {
node.cancelEdit = true
this.$refs.input.blur()
},
handleDragEnd(before, after, inner) {
alert(after.level)
before.data.parentId = after.level > 2 ? after.data.id : null
before.data.fullPath = null
this.dxDocumentFolderService.save(before.data).then(r => {
this.$utils.showMessageSuccess('操作成功')
})
}
}
}
</script>
<style lang="scss">
.DocumentFolder{
height: 100%;
box-sizing: border-box;
padding: 8px;
// display: flex;
// flex-direction: column;
overflow: hidden;
// .DocumentFolder-top{
// padding: 0px 8px;
// }
.DocumentFolder-main{
flex: 1;
height: calc(100% - 70px);
overflow: auto;
}
.search-form-box{
padding:0px;
}
.search-form-box .dee-search-form .el-form-item__label {
text-align: center;
}
.search-form-box .search-box-item {
width: 100%;
}
.dee-search-form{
&>div{
padding-bottom: 8px !important;
}
}
.dee-search-form{
border-bottom: 1px solid #dcdfe6;
}
.dee-search-form{
margin-bottom: 0px !important;
margin-top: 20px;
// padding-bottom: 20px;
.dee-form-item{
width: 100%;
}
}
.search-box-btn{
display: none;
}
.searchBtn{
display: none !important;
}
.el-tree{
background-color: transparent;
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
.el-tree>.el-tree-node {
min-width: 100%;
display:inline-block;
}
.el-tree-node__content {
align-self: baseline;
}
.el-tree-node__content{
padding:1px 8px;
&:hover{
.DocumentFolder-btn{
display: block;
visibility: visible;
}
}
}
.el-tree-node__expand-icon{
font-size: 16px;
// &::after{
// content: "";
// position:absolute;
// width: 1px;
// top:0px;
// display: block;
// height: 100%;
// border-left: 1px dotted #52627C;
// z-index: 2;
// }
}
.el-tree-node__expand-icon.expanded{
transform:none;
&::before{
content: "\e722" !important;
}
}
.DocumentFolder-btnItem{
width: 18px;
height: 18px;
border: none;
background-color: transparent;
background-size:100% 100%;
border-radius: 0;
outline:none;
cursor: pointer;
// &:hover{
// // border-top: 1px solid transparent;
// }
&.btn-add{
background-image: url("/icons/c-add.png");
}
&.btn-edit{
background-image: url("/icons/c-edit.png");
}
&.btn-delete{
background-image: url("/icons/c-creatbackups.png");
}
}
&-node{
width: 100%;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
&-label{
flex: 1;
overflow: hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
&-btn{
// display: none;
visibility: hidden;
// width: 180px;
text-align: right;
button {
margin-left: 8px;
}
}
}
.tree-line{
// .el-tree-node {
// position: relative;
// // padding-left: 16px; // 缩进量
// }
// .el-tree-node__children {
// // padding-left: 16px; // 缩进量
// }
// // 当前层最后一个节点的竖线高度固定
// .el-tree-node:last-child::before {
// height: 38px; // 可以自己调节到合适数值
// }
// // 横线
// .el-tree-node::after {
// content: "";
// width: 8px;
// height: 20px;
// position: absolute;
// left: 14px;
// top: 13px;
// border-width: 1px;
// border-top: 1px dotted #52627C;
// }
// // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
// & > .el-tree-node::after {
// border-top: none;
// }
// & > .el-tree-node::before {
// border-left: none;
// }
// // 展开关闭的icon
// .el-tree-node__expand-icon{
// font-size: 16px;
// // 叶子节点(无子节点)
// &.is-leaf{
// color: transparent;
// // display: none; // 也可以去掉
// }
// }
}
</style>
<template>
<dee-dialog :key="dialogKey" class="DxDocumentFolderDialog" :visible.sync="dialogVisible" title="选择文档目录">
<div v-if="fullPath && fullPath.split('/').length>2" class="pathInfo" :title="fullPath">已选择: {{ fullPath.split('/').join(' / ') }}</div>
<div v-else class="pathInfo">请选择目录</div>
<div class="folderBox">
<DxDocumentFolder ref="folder" :readonly="true" :fix-context="context" :context-visible="false" @currentChange="currentChange" />
</div>
<div slot="footer">
<el-button size="small" @click="dialogVisible = false">取 消</el-button>
<el-button size="small" type="primary" @click="ok()">确 定</el-button>
</div>
</dee-dialog>
</template>
<script>
export default {
name: 'DxDocumentFolderDialog',
displayName: '文档目录对话框',
modelRelationObjs: ['DxDocumentFolderDialog'],
data() {
return {
context: null,
fullPath: '',
dialogKey: 1,
dialogVisible: false,
selectData: null,
selectNode: null
}
},
methods: {
open(dxContext) {
this.fullPath = ''
this.selectNode = null
this.selectData = null
this.context = dxContext
this.dialogKey++
this.dialogVisible = true
},
currentChange(data, node) {
this.fullPath = this.$refs.folder.getNodeFullPath(node)
this.selectData = data
this.selectNode = node
},
ok() {
if (this.selectData) {
this.dialogVisible = false
this.$emit('ok', this.selectData, this.selectNode)
} else {
this.$utils.showMessageWarning('未选择任何目录')
}
}
}
}
</script>
<style lang="scss">
.DxDocumentFolderDialog{
.pathInfo{
overflow: hidden;
white-space:nowrap;
text-overflow:ellipsis;
margin-bottom: 10px;
color:#2e2e2e;
font-weight: bold;
cursor: default;
}
.folderBox{
max-height: 400px;
overflow: auto;
border: 1px solid #eaeefb;
background-color: #fafafa;
}
}
</style>
import Vue from 'vue'
let resultComps = []
const requireComponent = require.context(
'./', // 在当前目录下查找
true, // 遍历子文件夹
/\.vue$/ // 正则匹配 以 .vue结尾的文件
)
resultComps = handleData(requireComponent.keys())
function findKey(data) {
const allkey = []
const finalData = []
const obj = {}
data.forEach(el => {
const comp = requireComponent(el)
const item = comp.default
if (!(item.modelRelationObjs.length === 0 || (item.modelRelationObjs.length === 1 && item.modelRelationObjs[0] === ''))) {
item.modelRelationObjs.forEach(key => {
if (allkey.indexOf(key) <= -1) {
allkey.push(key)
finalData.push({
[key]: []
})
obj[key] = []
}
})
}
})
return { finalData, allkey, obj }
}
function handleData(data) {
if (!data) return
const { finalData, obj } = findKey(data)
data.forEach(el => {
const comp = requireComponent(el)
const item = comp.default
const mfileName = el.split('/')[el.split('/').length - 1]
Vue.component(mfileName.slice(0, -4), comp.default)
if (item.modelRelationObjs.length === 0 || (item.modelRelationObjs.length === 1 && item.modelRelationObjs[0] === '')) {
if (!obj['commonComponent']) {
obj['commonComponent'] = []
}
obj['commonComponent'].push({
name: mfileName.slice(0, -4),
displayName: item.displayName,
modelRelationObjs: item.modelRelationObjs,
codePath: el.slice(1)
})
} else {
item.modelRelationObjs.forEach(key => {
const index = finalData.findIndex(y => y[key])
if (index > -1) {
finalData[index][key].push({
name: mfileName.slice(0, -4),
displayName: item.displayName,
modelRelationObjs: item.modelRelationObjs,
codePath: el.slice(1)
})
obj[key] = finalData[index][key]
}
})
}
})
return obj
}
export default resultComps
import Vue from 'vue'
import store from './store'
// 子项目异步注册 store module
// Vue.__share_pool__.store.registerModule(process.env.VUE_APP_NAME, store)
Vue.__share_pool__.store.registerModule('config', store)
export default null
import Vue from 'vue'
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./', true, /\.vue$/)
// it will auto require all vuex module from modules file
modulesFiles.keys().reduce((modules, modulePath) => {
Vue.component(modulePath.replace(/^\.\/(.*)\.\w+$/, '$1'), modulePath)
}, {})
<?xml version="1.0" encoding="UTF-8"?>
<svg width="67px" height="57px" viewBox="0 0 67 57" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 64 (93537) - https://sketch.com -->
<title>文件</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="0 0.20027027 66.7083977 0.20027027 66.7083977 57 0 57"></polygon>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="通用2" transform="translate(-1177.000000, -524.000000)">
<g id="文件" transform="translate(1177.000000, 524.000000)">
<g id="编组">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<path d="M59.6748443,52.1858108 L7.03378182,52.1858108 C5.77715114,52.1858108 4.75844659,51.1551892 4.75844659,49.8838581 L4.75844659,26.3470946 L61.9425659,26.3470946 L61.9425659,49.8838581 C61.9425659,51.1478716 60.9238614,52.1858108 59.6748443,52.1858108 M7.03378182,5.01445946 L27.3911227,5.01445946 C28.3131341,5.01445946 29.1384523,5.57097973 29.4879182,6.42829054 L29.5400716,6.55615541 L31.9638727,10.9343716 C33.0865034,13.5143919 35.5997648,15.1693176 38.395492,15.1693176 L59.6672307,15.1693176 C60.9238614,15.1693176 61.9425659,16.1995541 61.9425659,17.4708851 L61.9425659,21.5329054 L4.75844659,21.5329054 L4.75844659,7.31602703 C4.75844659,6.04469595 5.77715114,5.01445946 7.03378182,5.01445946 M59.6748443,10.3551284 L38.395492,10.3551284 C37.4734807,10.3551284 36.6481625,9.79822297 36.2986966,8.94091216 L36.2465432,8.8130473 L33.822742,4.43521622 C32.7001114,1.85481081 30.18685,0.20027027 27.3911227,0.20027027 L7.03378182,0.20027027 C3.15996364,0.20027027 -7.61363636e-05,3.38957432 -7.61363636e-05,7.31602703 L-7.61363636e-05,49.8838581 C-7.61363636e-05,53.8029932 3.15235,57 7.03378182,57 L59.6748443,57 C63.5486625,57 66.7087023,53.8106959 66.7087023,49.8838581 L66.7087023,17.4708851 C66.7010886,13.5444324 63.5486625,10.3551284 59.6748443,10.3551284" id="Fill-1" fill="#000000" mask="url(#mask-2)"></path>
</g>
<line x1="4.75844659" y1="24" x2="62" y2="24" id="路径-3" stroke="#4A90E2" stroke-width="5" fill="#4A90E2"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="13px" viewBox="0 0 18 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>关闭</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#EDBD44" offset="0%"></stop>
<stop stop-color="#DDB043" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
<stop stop-color="#F4D781" offset="0%"></stop>
<stop stop-color="#E0AD33" offset="100%"></stop>
</linearGradient>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="综合查询" transform="translate(-150.000000, -648.000000)" fill-rule="nonzero">
<g id="Group-66" transform="translate(90.000000, 329.000000)">
<g id="Rectangle-Copy-38" transform="translate(20.000000, 153.000000)">
<g id="tree_1" transform="translate(6.886486, 156.000000)">
<g id="关闭" transform="translate(34.000000, 10.000000)">
<path d="M16.0839948,2.92151172 C16.0656914,2.4215957 15.9010392,2.29662305 15.4528084,2.29662305 L8.48864326,2.29662305 C7.58304948,2.29662305 7.47328133,1.30554785 6.78722386,0.591385742 C6.2200537,-0.00672851562 6.43960302,0.00130761719 5.25957585,0.00130761719 L1.12198623,0.00130761719 C0.399348048,0.00130761719 0.143205009,-0.0611914062 0.0700305755,0.679757813 C0.00600132015,1.3582207 0.0183033649,4.18211984 1.4033219e-13,4.44100265 L15.9864023,4.33357347 L16.0839948,2.92151172 Z" id="Path" fill="url(#linearGradient-1)"></path>
<path d="M0.74987129,3.90332617 C0.00891673412,3.90332617 -0.0276639782,4.27825684 0.0180619122,4.73353613 L0.554115046,12.1697773 C0.590695758,12.6250693 0.700463913,13 1.43226028,13 L14.5955018,13 C15.3455885,13 15.4279341,12.6250693 15.47366,12.1697773 L15.9767749,4.6442627 C16.0133686,4.1889834 15.9804304,3.90332617 15.2394888,3.90332617 L0.74987129,3.90332617 Z" id="Path" fill="url(#linearGradient-2)"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="17px" height="13px" viewBox="0 0 17 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>wenjianjia-3</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#F4D781" offset="0%"></stop>
<stop stop-color="#E0AD33" offset="100%"></stop>
</linearGradient>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
<stop stop-color="#EDBD44" offset="0%"></stop>
<stop stop-color="#CA9E36" offset="100%"></stop>
</linearGradient>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="综合查询" transform="translate(-150.000000, -616.000000)" fill-rule="nonzero">
<g id="Group-66" transform="translate(90.000000, 329.000000)">
<g id="Rectangle-Copy-38" transform="translate(20.000000, 153.000000)">
<g id="tree_1" transform="translate(6.886486, 124.000000)">
<g id="wenjianjia-3" transform="translate(34.000000, 10.000000)">
<path d="M15.2395018,3.90332617 L0.74987129,3.90332617 C0.00891673412,3.90332617 -0.0276639782,4.27825684 0.0180619122,4.73353613 L0.554115046,12.1697773 C0.590695758,12.6250693 0.700463913,13 1.43226028,13 L14.5955018,13 C15.3455885,13 15.4279341,12.6250693 15.47366,12.1697773 L15.9767749,4.6442627 C16.0133686,4.1889834 15.9804304,3.90332617 15.2394888,3.90332617 L15.2395018,3.90332617 Z" id="Path" fill="url(#linearGradient-1)"></path>
<path d="M15.0839948,1.92151172 C15.0656914,1.4215957 14.9010392,1.29662305 14.4528084,1.29662305 L8.48864326,1.29662305 C7.58304948,1.29662305 7.47328133,1.30554785 6.78722386,0.591385742 C6.2200537,-0.00672851562 6.43960302,0.00130761719 5.25957585,0.00130761719 L2.12198623,0.00130761719 C1.39934805,0.00130761719 1.14320501,-0.0611914062 1.07003058,0.679757813 C1.00600132,1.3582207 0.859639445,3.00079102 0.84133608,3.25967383 L15.148011,3.25967383 L15.0839948,1.92151172 Z" id="Path" fill="url(#linearGradient-2)"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
// import Vue from 'vue'
// import routes from './routes'
import '@/styles/index.scss' // global css
import asyncComponents from './asyncCompontents/index'
import privateComponents from './privateComponents/index'
import signConfig from './privateComponents/signConfig'
// const sharePool = (Vue.__share_pool__ = Vue.__share_pool__ || {})
// const store = (sharePool.store = sharePool.store || {})
function loadComponent(comName, type) {
let resolveComponent
if (!type) {
resolveComponent = resolve => { require([`@/asyncCompontents${comName}`], resolve) }
} else if (type === 'customComponent') {
resolveComponent = resolve => { require([`@/customComponent${comName}`], resolve) }
} else if (type === 'privateComponents') {
resolveComponent = resolve => { require([`@/privateComponents/${'components' + comName}`], resolve) }
} else if (type === 'view') {
resolveComponent = resolve => { require([`@/views/${comName}`], resolve) }
}
return resolveComponent
}
require('./business-components/tabCom/index.js')
export default {
name: 'dee-doc',
privateComponents,
signConfig,
asyncComponents,
loadComponent,
beforeEach(from, to, next) {
next()
},
init() {}
}
/**
* @Description: 目录导航
* @author wx
* @date 2023/03/14
*/
<template>
<div ref="CatalogNavigation" class="catalogNavigation-com">
<div :key="catalogIndex">
<div v-for="item in catalogList" :key="item.id" class="flex-s dee-row-item" :class="{'dee-active-row-background': curItemName(item.name)}" @click="typeSearch(item)">
<span class="name">{{ item.name }}</span>
<i class="el-icon-close del-icon" @click.stop="deleteSearchLog(item)" />
</div>
</div>
<dee-dialog
:dialog-visible="dialogVisible"
title="选择容器"
width="1080px"
@handleClose="handleClose"
>
<dee-as-com
:lay-config="{
typeName: 'DxContext',
layKey: 'defaultResult'
}"
@row-click="handleRowClick"
@on-selectDxContext="selectDxContext"
/>
</dee-dialog>
</div>
</template>
<script>
import { saveSearchLog, getSearchLogPage, deleteSearchLog } from '@/api/catalogNavigation'
export default {
name: 'CatalogNavigation',
componentName: '目录导航',
components: {},
props: {
modelName: {
type: String,
default: 'DxDocument'
}
},
data() {
return {
dialogVisible: false,
catalogList: [],
pageId: '',
catalogIndex: 0
}
},
computed: {
},
watch: {
},
mounted() {
this.pageId = this.$route.path
this.getSearchLogPage()
},
methods: {
openDialog() {
this.dialogVisible = true
},
handleClose() {
this.dialogVisible = false
},
getSearchLogPage() {
const params = {
modelName: this.modelName,
pageId: this.pageId
}
getSearchLogPage(params).then(res => {
this.catalogIndex++
this.catalogList = res.items
})
},
selectDxContext(val) {
this.handleRowClick({ row: val })
},
handleRowClick(row) {
const data = row.row
const params = {
id: data.id,
modelName: this.modelName,
pageId: this.pageId,
userId: localStorage.getItem('userId'),
name: data.name
}
saveSearchLog(params).then(res => {
this.handleClose()
this.getSearchLogPage()
})
},
deleteSearchLog(item) {
const params = {
id: item.id,
modelName: this.modelName,
pageId: this.pageId
}
deleteSearchLog(params).then(res => {
this.$utils.showMessageSuccess('删除成功')
this.getSearchLogPage()
})
},
typeSearch(item) {
this.$emit('typeSearch', 'catalogNavigationSearch', item, '目录导航')
},
curItemName(name) {
const visitePath = this.$store.state.breadcrumb.visitePath[this.pageId] || []
return !!(visitePath.length >= 2 && name === visitePath[1])
}
}
}
</script>
<style lang='scss'>
.catalogNavigation-com{
// .name{
// font-size: 14px;
// color: #686868;
// }
.del-icon{
font-size: 8px;
line-height: 34px;
display: none;
}
.dee-row-item:hover{
.del-icon {
display: block;
}
}
}
</style>
<template>
<div class="dee-flow-attachment">
<label class="label">
{{ $nextTick("附件") }}
</label>
<div class="table">
<DeeUploadTable
v-model="pbo.objFileLinks"
attr-key="objFileLinks"
:read-only="false"
:state="state"
:app-name="appName"
:config-item="{}"
:remove-check-fn="removeCheckFn"
:table-columns="tableColumns"
:table-config="tableConfig"
@input="onInput"
/>
</div>
</div>
</template>
<script>
export default {
name: 'DeeFlowAttachment',
componentName: '上传附件',
props: {
basicData: {
type: Object,
default: () => {}
}
},
data() {
return {
appName: '',
pboId: '',
pbo: {},
modelName: '',
state: 'view',
modifyed: false,
tableColumns: [{ 'title': '文件名', 'key': 'target.originalFileName', 'parentKey': 'target', 'headerAlign': 'center', 'align': 'left' }, { 'title': '文件大小', 'key': 'target.fileSize', 'parentKey': 'target', 'level': 1, 'show': true, 'headerAlign': 'center', 'align': 'left' }, { 'title': '扩展名', 'key': 'target.fileExtension', 'parentKey': 'target', 'level': 1, 'show': true, 'headerAlign': 'center', 'align': 'left' }, { 'title': '文件状态', 'key': 'target.fileStatus', 'fildProp': { 'id': 164, 'refId': null, 'type': 'DictDataVO', 'rule': { 'typeName': 'DictDataVO', 'comment': null, 'length': null, 'defaultValue': '', 'notNull': false, 'unique': false, 'scale': null, 'dictTypeCode': 'FileStatus' }, 'attrType': 'BASE' }, 'parentKey': 'target', 'level': 1, 'show': true, 'headerAlign': 'center', 'align': 'left' }, { title: '创建者', key: 'target.creator.userName' }],
tableConfig: { 'filterKey': 'contentType', 'serverUrl': '', 'pageShow': true, 'pageDefs': { 'currentPage': 1, 'pageSize': 20, 'pageSizes': [10, 20, 50, 100, 200], 'total': 0 }, 'taleType': 'single', 'url': '/dfs/fileManager/feign/uploadFile', 'showFileList': true, 'identFilter': ['FLOW_FILE'], 'uploadFilter': 'FLOW_FILE' }
}
},
computed: {},
watch: {
'basicData': {
immediate: true,
deep: true,
handler: function(val) {
if (!val || !val.id) {
return
}
if (this.pboId === val.id) {
return
}
// bugfix 7674 【141】【质检】提交归零报告上传不了附件且列表显示信息不一致 保留原来的传值this.basicData.basicInfo
this.state = this.getState(this.basicData.basicInfo || this.basicData.state)
this.pboId = val.id
this.modelName = this.$utils.getModelName4dxClassName(val)
this.getAttachmentList()
}
},
'modelName': {
immediate: true,
handler: function(val) {
if (!val || !val.id) {
if (val) {
this.$api.ModelAppByModelName({ name: val }).then(res => {
this.appName = res.items.serverName
})
}
}
}
}
},
// 生命周期 - 创建完成(访问当前this实例)
created() {},
// 生命周期 - 挂载完成(访问DOM元素)
mounted() {},
methods: {
onInput(data) {
// TODO 质量问题增加保存附件逻辑 后续如果其他模块也有此需求,可以增加判断条件
if (this.basicData.subTypeName === 'DxQiProblem') {
this.savePboFilesLinks(data)
}
this.modifyed = true
},
savePboFilesLinks(data) {
const params = {
id: this.basicData.id,
operator: 'MODIFY',
objFileLinks: data.map(r => { return { operator: 'ADD', target: r } })
}
const modelName = this.basicData.subTypeName
this.$api.searchApi(modelName, params)
},
getState(basicInfo) {
// if (!basicInfo) {
// return 'view'
// }
// if (basicInfo.name === '编制') {
// return 'view'
// }
return 'edit'
},
getAttachmentList() {
this.$getService(this.modelName)
.byId(this.pboId, ['objFileLinks.target']).then(res => {
if (res) {
this.pbo = res
}
})
},
removeCheckFn(rows) {
let flag = true
const userId = localStorage.getItem('userId')
const files = []
rows.forEach(row => {
if (row.creatorId && (row.creatorId.toString() !== userId)) {
flag = false
files.push(row.target.originalFileName)
return true
}
})
if (files.length) {
this.$utils.showMessageWarning(`没有移除文件(${files.join()})权限!`)
}
return flag
},
validate() {
return new Promise((resolve, reject) => {
if (!this.modifyed) {
resolve(true)
return
}
this.$getService(this.modelName).save(this.pbo).then(res => {
if (res) {
resolve(true)
} else {
resolve(false)
}
}).catch(() => {
resolve(false)
})
})
}
}
}
</script>
<style lang="scss">
/* @import url(); 引入css类 */
.dee-flow-attachment{
padding-left:40px ;
padding-right:10px ;
display: flex;
flex-direction: column;
&>.label{
font-size: 14px;
text-align: left;
padding-right: 12px;
font-weight: 700;
color: #333;
}
&>.table{
flex: 1;
}
}
</style>
/**
* @Description: 目录导航
* @author wx
* @date 2023/03/14
*/
<template>
<div ref="documentOverview" class="documentOverview-com">
<div v-if="basicData" class="content">
<div class="title">{{ basicData.name }}</div>
<dee-as-com
:lay-config="{
typeName: 'DxDocument',
layKey: '0b61ac22-e752-4eea-bb11-1f35c5b7a9ec'
}"
:basic-data="basicData"
/>
<div class="scanFile-title">浏览</div>
<DxDocumentScanFile :basic-data="basicData" style="height:50%" />
</div>
<div v-if="basicData" class="toPage-btn">
<el-button @click="goDetail">查看详情</el-button>
</div>
</div>
</template>
<script>
export default {
name: 'DocumentOverview',
componentName: '文档概览',
components: {},
data() {
return {
emitMethods: [
{
methods: 'getData',
methodsName: '获取数据'
}
],
basicData: null
}
},
computed: {
},
watch: {
},
mounted() {},
methods: {
eventFunc(params) {
console.log({ params })
},
getData(item) {
this.basicData = item
},
goDetail() {
this.$router.push({
path: `/configured-page/cd/${this.basicData.subTypeName}/defaultInfo/${this.basicData.id}`,
query: { title: (this.basicData.name || this.basicData.id) + '详情' }
})
}
}
}
</script>
<style lang='scss'>
.documentOverview-com{
.content{
height: calc(100% - 46px);
overflow-y: scroll;
.title{
color: #353535;
font-size: 15px;
line-height: 21px;
font-weight: bold;
margin-left: 6px;
}
}
.toPage-btn{
display: flex;
justify-content: center;
.el-button{
width: 249px;
height: 36px;
background: #3A94C2;
border-radius: 4px;
line-height: 12px;
font-size: 16px;
color: #FFFFFF;
}
}
.scanFile-title{
height: 30px;
border-top: 1px solid #E3E3E3;
border-bottom: 1px solid #E3E3E3;
font-size: 14px;
color: #353535;
font-weight: bold;
line-height: 30px;
padding-left: 8px;
}
}
</style>
export default {
props: {},
layoutConfigData: [
{
title: '高级组件配置',
data: [
{
key: 'fixContext',
title: '显示搜索',
component: {
name: 'el-checkbox',
defaultValue: true
}
}, {
key: 'readonly',
title: '只读',
component: {
name: 'el-checkbox',
defaultValue: false
}
}
]
}
],
data() {
return {
}
},
created() {
},
computed: {
},
methods: {
}
}
<template>
<div class="DocumentFolder">
<div class="DocumentFolder-main" dee-loading="loading">
<el-tree
ref="tree"
node-key="id"
empty-text="请选择容器"
class="tree-line"
icon-class="el-icon-circle-plus-outline"
:highlight-current="true"
:expand-on-click-node="false"
:data="data"
:props="defaultProps"
:lazy="lazy"
:load="loadNode"
:default-expanded-keys="defaultExpandedKeys"
@node-drag-end="handleDragEnd"
@current-change="currentChange"
>
<div slot-scope="{node}" class="DocumentFolder-node">
<template v-if="!node.edit">
<div class="DocumentFolder-label" :title="node.label">
<img v-if="node.level === 1" class="dxcontext-icon" src="/icons/rongqi.png" alt="">
<img v-else-if="node.expanded" class="folderIcon" src="/icons/folder_open.svg" alt="">
<img v-else class="folderIcon" src="/icons/folder_closed.svg" alt="">
<span v-if="node.label" class="change-text">
{{ node.label }}
</span>
<i v-else>&lt;未命名&gt;</i>
</div>
<div v-if="!readonly && !edit" class="DocumentFolder-btn">
<button v-if="node.level>1" title="重命名" class="DocumentFolder-btnItem btn-edit" @click.stop="editFolder(node)" />
<button title="添加" class="DocumentFolder-btnItem btn-add" @click.stop="addFolder(node)" />
<button v-if="node.level>1" slot="reference" title="删除" class="DocumentFolder-btnItem btn-delete" @click.stop="deleteFolder(node)" />
</div>
</template>
<template v-else>
<div class="DocumentFolder-label">
<el-input ref="input" v-model="node.rename" size="mini" @blur="endEdit(node)" @keyup.enter.native="editEnter(node)" @keyup.esc.native="cancelEdit(node)" />
</div>
</template>
</div>
</el-tree>
</div>
</div>
</template>
<script>
import { getDocFolder } from '@/api/doc'
import config from './config'
export default {
componentName: '文档目录',
name: 'DxDocumentFolder',
modelRelationObjs: ['DxDocumentFolder'],
mixins: [config],
props: {
fixContext: {
type: Object,
default() {
return null
}
},
contextVisible: {
type: Boolean,
default: true
},
levelOneDisable: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
},
layConfig: {
type: Object,
default: null
}
},
data() {
return {
evenList: [
{
even: 'searchEvent',
name: '点击查询事件'
}
],
emitMethods: [
{
methods: 'searchEvent',
methodsName: '查询目录'
}
],
loading: false,
edit: false,
canEdit: true,
lazy: true,
defaultExpandedKeys: [],
filterConfig: {},
dxDocumentFolderService: this.$getService('DxDocumentFolder'),
context: this.fixContext,
data: [],
defaultProps: {
children: 'children',
label: 'name',
isLeaf: 'isLeaf'
},
selectFolderObj: {
dxContext: {},
dxDocumentFolder: {}
}
}
},
computed: {
showSearchContent() {
if (this.layConfig) {
return false
} else {
return this.contextVisible
}
}
},
watch: {
context() {
if (this.context && this.context.id) {
this.data = [this.context]
} else {
this.data = []
}
}
},
created() {
if (this.fixContext && this.fixContext.id) {
this.defaultExpandedKeys = [this.fixContext.id]
}
},
methods: {
searchEvent(data) {
this.loading = true
const contextId = data.id
this.$getService('DxContext').byId(contextId).then(r => {
this.selectFolderObj.dxContext = r
// this.$emit('currentChange', {}, {}, this.selectFolderObj)
this.$set(this, 'defaultExpandedKeys', r ? [r.id] : [])
this.$set(this, 'context', r || null)
}).finally(() => {
this.loading = false
})
},
// getTreeId(data) {
// alert(data.id)
// return Date.now()
// },
loadNode(node, resolve) {
if (node.level === 0) {
if (this.context && this.context.id) {
resolve([this.context])
}
} else if (node.level === 1) {
const params = {
'indices': [
'DxDocumentFolder'
],
'pageFrom': 1,
'pageSize': 9999,
'openProps': [
],
'searchItems': {
'operator': 'AND',
'items': [
{
'fieldName': 'dxContextId',
'operator': 'EQ',
'value': this.context.id
},
{
'fieldName': 'parentId',
'operator': 'EQ',
'value': 0
}
]
}
}
getDocFolder(params).then(r => {
resolve(r.items.content)
}).catch(e => {
resolve([])
})
} else {
const params = {
'indices': [
'DxDocumentFolder'
],
'pageFrom': 1,
'pageSize': 9999,
'openProps': [
],
'searchItems': {
'operator': 'AND',
'items': [
{
'fieldName': 'parentId',
'operator': 'EQ',
'value': node.data.id
}
]
}
}
getDocFolder(params).then(r => {
resolve(r.items.content)
}).catch(e => {
resolve([])
})
}
resolve([])
},
getItem() {
// this.docFolderModel.
},
currentChange(data, node) {
if (node.level === 1 && this.levelOneDisable) {
this.$utils.showMessageInfo('第一层目录不可选择')
} else {
this.selectFolderObj.dxDocumentFolder = data.target
this.$emit('currentChange', data.target, node, this.selectFolderObj)
if (data.dxContextId) {
this.$emit('searchEvent', [
{ fieldName: 'dxContextId', operator: 'EQ', value: data.target.dxContextId },
{ fieldName: 'dxDocumentFolderId', operator: 'EQ', value: data.targetId }
])
} else {
this.$emit('searchEvent', [{ fieldName: 'dxContextId', operator: 'EQ', value: data.targetId }])
}
}
},
addFolder(node) {
this.$prompt('请输入名称', '新建目录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[^\\/:\*\?""<>|]{1,120}$/,
inputErrorMessage: '文件名不能包含:\\/:*?"<>|'
}).then(({ value }) => {
const params = {
dxContextId: this.context.id,
parentId: node.level > 1 ? node.data.id : 0,
name: value
}
this.$api.recursion('DxDocumentFolder', params).then((r) => {
if (node.loaded) {
this.$refs.tree.append(r.items, node)
}
node.expand()
this.$utils.showMessageSuccess('操作成功')
})
}).catch((e) => {
this.$utils.showMessageInfo('取消输入')
})
// const newChild = { id: 'new', name: '', children: [] }
// node.expand()
// if (!node.data.children) {
// this.$set(node.data, 'children', [])
// }
// node.data.children.push(newChild)
// this.$nextTick(() => {
// var nodes = this.$refs.tree.store.nodesMap
// console.log('nodes', nodes)
// console.log('node', node)
// console.log('tree', this.$refs.tree)
// })
},
deleteFolder(node) {
const h = this.$createElement
const fullPath = this.getNodeFullPath(node)
this.$confirm(null, '提示', {
message: h('div', null, [
h('div', null, '请确认是否删除目录?'),
h('div', {
attrs: {
title: fullPath
},
style: {
marginTop: '8px',
color: '#909399',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
}
},
`"${fullPath}"`)
]),
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.dxDocumentFolderService.delete(node.data).then(() => {
this.$refs.tree.remove(node)
this.$utils.showMessageSuccess('删除成功!')
})
}).catch(() => {
this.$utils.showMessageInfo('已取消删除')
})
},
getNodeFullPath(node) {
let path = node.label
let parentNode = node.parent
while (parentNode && parentNode.level > 0) {
path = `${parentNode.label}/${path}`
parentNode = parentNode.parent
}
return '/' + path
},
// 修改名称
editFolder(node) {
this.edit = true
this.$set(node, 'edit', true)
this.$set(node, 'rename', node.data.name)
this.$nextTick(() => {
this.$refs.input.focus()
this.$refs.input.select()
})
},
// 失去焦点确定修改
endEdit(node) {
if (!node.rename && !node.cancelEdit) {
this.$refs.input.focus()
this.$utils.showMessageWarning(`名称不能为空`)
return
}
this.$set(node, 'edit', false)
this.$set(this, 'edit', false)
if (!node.cancelEdit) {
if (node.data.name !== node.rename) {
const oldName = node.data.name
node.data.name = node.rename
node.data.fullPath = null
this.dxDocumentFolderService.save(node.data).then(() => {
this.$utils.showMessageSuccess('修改成功')
}).catch(() => {
this.$set(node.data, 'name', oldName)
})
}
} else {
this.$utils.showMessageInfo('已取消修改')
}
node.cancelEdit && delete node.cancelEdit
},
// 回车确定
editEnter(node) {
node.cancelEdit = false
this.$refs.input.blur()
},
// ESC 退出
cancelEdit(node) {
node.cancelEdit = true
this.$refs.input.blur()
},
handleDragEnd(before, after, inner) {
alert(after.level)
before.data.parentId = after.level > 2 ? after.data.id : null
before.data.fullPath = null
this.dxDocumentFolderService.save(before.data).then(r => {
this.$utils.showMessageSuccess('操作成功')
})
}
}
}
</script>
<style lang="scss">
.DocumentFolder{
height: 100%;
box-sizing: border-box;
padding: 8px;
// display: flex;
// flex-direction: column;
overflow: hidden;
// .DocumentFolder-top{
// padding: 0px 8px;
// }
.DocumentFolder-main{
flex: 1;
height: calc(100% - 70px);
overflow: auto;
}
.search-form-box{
padding:0px;
}
.search-form-box .dee-search-form .el-form-item__label {
text-align: center;
}
.search-form-box .search-box-item {
width: 100%;
}
.dee-search-form{
&>div{
padding-bottom: 8px !important;
}
}
.dee-search-form{
border-bottom: 1px solid #dcdfe6;
}
.dee-search-form{
margin-bottom: 0px !important;
margin-top: 20px;
// padding-bottom: 20px;
.dee-form-item{
width: 100%;
}
}
.search-box-btn{
display: none;
}
.dxcontext-icon {
display: block;
width: 16px;
margin-right: 2px;
}
.searchBtn{
display: none !important;
}
.el-tree{
background-color: transparent;
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
.el-tree>.el-tree-node {
min-width: 100%;
display:inline-block;
}
.el-tree-node__content {
align-self: baseline;
}
.el-tree-node__content{
padding:1px 8px;
&:hover{
.DocumentFolder-btn{
display: block;
visibility: visible;
}
}
}
.el-tree-node__expand-icon{
font-size: 16px;
// &::after{
// content: "";
// position:absolute;
// width: 1px;
// top:0px;
// display: block;
// height: 100%;
// border-left: 1px dotted #52627C;
// z-index: 2;
// }
}
.el-tree-node__expand-icon.expanded{
transform:none;
&::before{
content: "\e722" !important;
}
}
.DocumentFolder-btnItem{
width: 18px;
height: 18px;
border: none;
background-color: transparent;
background-size:100% 100%;
border-radius: 0;
outline:none;
cursor: pointer;
// &:hover{
// // border-top: 1px solid transparent;
// }
&.btn-add{
background-image: url("/icons/add-L.png");
}
&.btn-edit{
background-image: url("/icons/edit-L.png");
}
&.btn-delete{
background-image: url("/icons/delete-L.png");
}
}
&-node{
width: 100%;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
&-label{
flex: 1;
overflow: hidden;
white-space:nowrap;
text-overflow:ellipsis;
display: flex;
}
&-btn{
// display: none;
visibility: hidden;
// width: 180px;
text-align: right;
button {
margin-left: 8px;
}
}
}
.tree-line{
// .el-tree-node {
// position: relative;
// // padding-left: 16px; // 缩进量
// }
// .el-tree-node__children {
// // padding-left: 16px; // 缩进量
// }
// // 当前层最后一个节点的竖线高度固定
// .el-tree-node:last-child::before {
// height: 38px; // 可以自己调节到合适数值
// }
// // 横线
// .el-tree-node::after {
// content: "";
// width: 8px;
// height: 20px;
// position: absolute;
// left: 14px;
// top: 13px;
// border-width: 1px;
// border-top: 1px dotted #52627C;
// }
// // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
// & > .el-tree-node::after {
// border-top: none;
// }
// & > .el-tree-node::before {
// border-left: none;
// }
// // 展开关闭的icon
// .el-tree-node__expand-icon{
// font-size: 16px;
// // 叶子节点(无子节点)
// &.is-leaf{
// color: transparent;
// // display: none; // 也可以去掉
// }
// }
}
</style>
<template>
<div class="DocumentFolder">
<div class="DocumentFolder-top">
<dee-search-box
v-if="contextVisible"
type-name="DxDocument"
v-bind="filterConfig.configDetails"
@formChange="searchEvent"
/>
</div>
<div class="DocumentFolder-main" dee-loading="loading">
<el-tree
ref="tree"
node-key="id"
empty-text="请选择容器"
class="tree-line"
icon-class="el-icon-circle-plus-outline"
:highlight-current="true"
:expand-on-click-node="false"
:data="data"
:props="defaultProps"
:lazy="lazy"
:load="loadNode"
:default-expanded-keys="defaultExpandedKeys"
@node-drag-end="handleDragEnd"
@current-change="currentChange"
>
<div slot-scope="{node}" class="DocumentFolder-node">
<template v-if="!node.edit">
<div class="DocumentFolder-label" :title="node.label">
<img v-if="node.expanded" class="folderIcon" src="/icons/folder_open.svg" alt="">
<img v-else class="folderIcon" src="/icons/folder_closed.svg" alt="">
<span v-if="node.label" class="change-text">
{{ node.label }}
</span>
<i v-else>&lt;未命名&gt;</i>
</div>
<div v-if="!readonly && !edit" class="DocumentFolder-btn">
<button v-if="node.level>1" title="重命名" class="DocumentFolder-btnItem btn-edit" @click.stop="editFolder(node)" />
<button title="添加" class="DocumentFolder-btnItem btn-add" @click.stop="addFolder(node)" />
<button v-if="node.level>1" slot="reference" title="删除" class="DocumentFolder-btnItem btn-delete" @click.stop="deleteFolder(node)" />
</div>
</template>
<template v-else>
<div class="DocumentFolder-label">
<el-input ref="input" v-model="node.rename" size="mini" @blur="endEdit(node)" @keyup.enter.native="editEnter(node)" @keyup.esc.native="cancelEdit(node)" />
</div>
</template>
</div>
</el-tree>
</div>
</div>
</template>
<script>
import { getLayouts } from '@/api/config'
import { getDocFolder } from '@/api/doc'
export default {
// componentName: '文档目录2',
name: 'DxDocumentFolder2',
modelRelationObjs: ['DxDocumentFolder'],
props: {
fixContext: {
type: Object,
default() {
return null
}
},
contextVisible: {
type: Boolean,
default: true
},
levelOneDisable: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
evenList: [
{
even: 'searchEvent',
name: '条件点击查询事件'
}
],
loading: false,
edit: false,
canEdit: true,
lazy: true,
defaultExpandedKeys: [],
filterConfig: {},
dxDocumentFolderService: this.$getService('DxDocumentFolder'),
context: this.fixContext,
data: [],
defaultProps: {
children: 'children',
label: 'name',
isLeaf: 'isLeaf'
},
selectFolderObj: {
dxContext: {},
dxDocumentFolder: {}
}
}
},
watch: {
context() {
if (this.context && this.context.id) {
this.data = [this.context]
} else {
this.data = []
}
}
},
created() {
if (this.fixContext && this.fixContext.id) {
this.defaultExpandedKeys = [this.fixContext.id]
}
getLayouts('DxDocument', 'OnlyContext'/* 'OnlyContext'*/).then(res => {
this.filterConfig = res.items ? res.items.slice(-1)[0] : {}
this.filterConfig.configDetails = JSON.parse(this.filterConfig.configDetails)
})
},
methods: {
searchEvent(data) {
this.loading = true
const contextId = data.contextId.value
this.$getService('DxContext').byId(contextId).then(r => {
this.selectFolderObj.dxContext = r
// this.$emit('currentChange', {}, {}, this.selectFolderObj)
this.$set(this, 'defaultExpandedKeys', r ? [r.id] : [])
this.$set(this, 'context', r || null)
}).finally(() => {
this.loading = false
})
},
// getTreeId(data) {
// alert(data.id)
// return Date.now()
// },
loadNode(node, resolve) {
if (node.level === 0) {
if (this.context && this.context.id) {
resolve([this.context])
}
} else if (node.level === 1) {
const params = {
'indices': [
'DxDocumentFolder'
],
'pageFrom': 1,
'pageSize': 9999,
'openProps': [
],
'searchItems': {
'operator': 'AND',
'items': [
{
'fieldName': 'dxContextId',
'operator': 'EQ',
'value': this.context.id
},
{
'fieldName': 'parentId',
'operator': 'EQ',
'value': 0
}
]
}
}
getDocFolder(params).then(r => {
resolve(r.items.content)
}).catch(e => {
resolve([])
})
} else {
const params = {
'indices': [
'DxDocumentFolder'
],
'pageFrom': 1,
'pageSize': 9999,
'openProps': [
],
'searchItems': {
'operator': 'AND',
'items': [
{
'fieldName': 'parentId',
'operator': 'EQ',
'value': node.data.id
}
]
}
}
getDocFolder(params).then(r => {
resolve(r.items.content)
}).catch(e => {
resolve([])
})
}
resolve([])
},
getItem() {
// this.docFolderModel.
},
currentChange(data, node) {
if (node.level === 1 && this.levelOneDisable) {
this.$utils.showMessageInfo('第一层目录不可选择')
} else {
this.selectFolderObj.dxDocumentFolder = data
this.$emit('currentChange', data, node, this.selectFolderObj)
if (data.dxContextId) {
this.$emit('searchEvent', [
{ fieldName: 'dxContextId', operator: 'EQ', value: data.dxContextId },
{ fieldName: 'dxDocumentFolderId', operator: 'EQ', value: data.id }
])
} else {
this.$emit('searchEvent', [{ fieldName: 'dxContextId', operator: 'EQ', value: data.id }])
}
}
},
addFolder(node) {
this.$prompt('请输入名称', '新建目录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[^\\/:\*\?""<>|]{1,120}$/,
inputErrorMessage: '文件名不能包含:\\/:*?"<>|'
}).then(({ value }) => {
const params = {
dxContextId: this.context.id,
parentId: node.level > 1 ? node.data.id : 0,
name: value
}
this.$api.recursion('DxDocumentFolder', params).then((r) => {
if (node.loaded) {
this.$refs.tree.append(r.items, node)
}
node.expand()
this.$utils.showMessageSuccess('操作成功')
})
}).catch((e) => {
this.$utils.showMessageInfo('取消输入')
})
// const newChild = { id: 'new', name: '', children: [] }
// node.expand()
// if (!node.data.children) {
// this.$set(node.data, 'children', [])
// }
// node.data.children.push(newChild)
// this.$nextTick(() => {
// var nodes = this.$refs.tree.store.nodesMap
// console.log('nodes', nodes)
// console.log('node', node)
// console.log('tree', this.$refs.tree)
// })
},
deleteFolder(node) {
const h = this.$createElement
const fullPath = this.getNodeFullPath(node)
this.$confirm(null, '提示', {
message: h('div', null, [
h('div', null, '请确认是否删除目录?'),
h('div', {
attrs: {
title: fullPath
},
style: {
marginTop: '8px',
color: '#909399',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
}
},
`"${fullPath}"`)
]),
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.dxDocumentFolderService.delete(node.data).then(() => {
this.$refs.tree.remove(node)
this.$utils.showMessageSuccess('删除成功')
})
}).catch(() => {
this.$utils.showMessageInfo('已取消删除')
})
},
getNodeFullPath(node) {
let path = node.label
let parentNode = node.parent
while (parentNode && parentNode.level > 0) {
path = `${parentNode.label}/${path}`
parentNode = parentNode.parent
}
return '/' + path
},
// 修改名称
editFolder(node) {
this.edit = true
this.$set(node, 'edit', true)
this.$set(node, 'rename', node.data.name)
this.$nextTick(() => {
this.$refs.input.focus()
this.$refs.input.select()
})
},
// 失去焦点确定修改
endEdit(node) {
if (!node.rename && !node.cancelEdit) {
this.$refs.input.focus()
this.$utils.showMessageWarning(`名称不能为空`)
return
}
this.$set(node, 'edit', false)
this.$set(this, 'edit', false)
if (!node.cancelEdit) {
if (node.data.name !== node.rename) {
const oldName = node.data.name
node.data.name = node.rename
node.data.fullPath = null
this.dxDocumentFolderService.save(node.data).then(() => {
this.$utils.showMessageSuccess('修改成功')
}).catch(() => {
this.$set(node.data, 'name', oldName)
})
}
} else {
this.$utils.showMessageInfo('已取消修改')
}
node.cancelEdit && delete node.cancelEdit
},
// 回车确定
editEnter(node) {
node.cancelEdit = false
this.$refs.input.blur()
},
// ESC 退出
cancelEdit(node) {
node.cancelEdit = true
this.$refs.input.blur()
},
handleDragEnd(before, after, inner) {
alert(after.level)
before.data.parentId = after.level > 2 ? after.data.id : null
before.data.fullPath = null
this.dxDocumentFolderService.save(before.data).then(r => {
this.$utils.showMessageSuccess('操作成功')
})
}
}
}
</script>
<style lang="scss">
.DocumentFolder{
height: 100%;
box-sizing: border-box;
padding: 8px;
// display: flex;
// flex-direction: column;
overflow: hidden;
// .DocumentFolder-top{
// padding: 0px 8px;
// }
.DocumentFolder-main{
flex: 1;
height: calc(100% - 70px);
overflow: auto;
}
.search-form-box{
padding:0px;
}
.search-form-box .dee-search-form .el-form-item__label {
text-align: center;
}
.search-form-box .search-box-item {
width: 100%;
}
.dee-search-form{
&>div{
padding-bottom: 8px !important;
}
}
.dee-search-form{
border-bottom: 1px solid #dcdfe6;
}
.dee-search-form{
margin-bottom: 0px !important;
margin-top: 20px;
// padding-bottom: 20px;
.dee-form-item{
width: 100%;
}
}
.search-box-btn{
display: none;
}
.searchBtn{
display: none !important;
}
.el-tree{
background-color: transparent;
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
.el-tree>.el-tree-node {
min-width: 100%;
display:inline-block;
}
.el-tree-node__content {
align-self: baseline;
}
.el-tree-node__content{
padding:1px 8px;
&:hover{
.DocumentFolder-btn{
display: block;
visibility: visible;
}
}
}
.el-tree-node__expand-icon{
font-size: 16px;
// &::after{
// content: "";
// position:absolute;
// width: 1px;
// top:0px;
// display: block;
// height: 100%;
// border-left: 1px dotted #52627C;
// z-index: 2;
// }
}
.el-tree-node__expand-icon.expanded{
transform:none;
&::before{
content: "\e722" !important;
}
}
.DocumentFolder-btnItem{
width: 18px;
height: 18px;
border: none;
background-color: transparent;
background-size:100% 100%;
border-radius: 0;
outline:none;
cursor: pointer;
// &:hover{
// // border-top: 1px solid transparent;
// }
&.btn-add{
background-image: url("/icons/add-L.png");
}
&.btn-edit{
background-image: url("/icons/edit-L.png");
}
&.btn-delete{
background-image: url("/icons/delete-L.png");
}
}
&-node{
width: 100%;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
&-label{
flex: 1;
overflow: hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
&-btn{
// display: none;
visibility: hidden;
// width: 180px;
text-align: right;
button {
margin-left: 8px;
}
}
}
.tree-line{
// .el-tree-node {
// position: relative;
// // padding-left: 16px; // 缩进量
// }
// .el-tree-node__children {
// // padding-left: 16px; // 缩进量
// }
// // 当前层最后一个节点的竖线高度固定
// .el-tree-node:last-child::before {
// height: 38px; // 可以自己调节到合适数值
// }
// // 横线
// .el-tree-node::after {
// content: "";
// width: 8px;
// height: 20px;
// position: absolute;
// left: 14px;
// top: 13px;
// border-width: 1px;
// border-top: 1px dotted #52627C;
// }
// // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
// & > .el-tree-node::after {
// border-top: none;
// }
// & > .el-tree-node::before {
// border-left: none;
// }
// // 展开关闭的icon
// .el-tree-node__expand-icon{
// font-size: 16px;
// // 叶子节点(无子节点)
// &.is-leaf{
// color: transparent;
// // display: none; // 也可以去掉
// }
// }
}
</style>
export default {
props: {},
layoutConfigData: [
{
title: '高级组件配置',
data: [
{
key: 'fixContext',
title: '显示搜索',
component: {
name: 'el-checkbox',
defaultValue: true
}
}, {
key: 'readonly',
title: '只读',
component: {
name: 'el-checkbox',
defaultValue: false
}
}
]
}
],
data() {
return {
}
},
created() {
},
computed: {
},
methods: {
}
}
<template>
<div class="DocumentFolder">
<div class="DocumentFolder-main" dee-loading="loading">
<el-tree
ref="tree"
node-key="id"
:empty-text="$t('请选择容器')"
class="tree-line"
icon-class="el-icon-circle-plus-outline"
:highlight-current="true"
:expand-on-click-node="false"
:data="data"
:props="defaultProps"
:lazy="lazy"
:load="loadNode"
:default-expanded-keys="defaultExpandedKeys"
@node-drag-end="handleDragEnd"
@current-change="currentChange"
>
<div slot-scope="{node, data}" class="DocumentFolder-node">
<template v-if="!node.edit">
<div class="DocumentFolder-label" :class="data.disabled ? 'disabled-node' :''" :title="node.label">
<!-- <img v-if="node.level === 1" class="dxcontext-icon" src="/icons/rongqi.png" alt=""> -->
<img v-if="node.expanded" class="folderIcon" src="/icons/folder_open.svg" alt="">
<img v-else class="folderIcon" src="/icons/folder_closed.svg" alt="">
<span v-if="node.label" class="change-text">
{{ node.label }}
</span>
<i v-else>&lt;{{ $t('未命名') }}&gt;</i>
</div>
<div v-if="!readonly && !edit" class="DocumentFolder-btn">
<button v-if="node.level>1" :title="$t('重命名')" class="DocumentFolder-btnItem btn-edit" @click.stop="editFolder(node)" />
<button :title="$t('添加')" class="DocumentFolder-btnItem btn-add" @click.stop="addFolder(node)" />
<button v-if="node.level>1" slot="reference" :title="$t('删除')" class="DocumentFolder-btnItem btn-delete" @click.stop="deleteFolder(node)" />
</div>
</template>
<template v-else>
<div class="DocumentFolder-label">
<el-input ref="input" v-model="node.rename" size="mini" @blur="endEdit(node)" @keyup.enter.native="editEnter(node)" @keyup.esc.native="cancelEdit(node)" />
</div>
</template>
</div>
</el-tree>
</div>
</div>
</template>
<script>
import { folderTreeSearch } from '@/api/doc'
import config from './config'
export default {
componentName: '工艺容器目录',
name: 'DxFolder',
modelRelationObjs: ['DxFolder'],
mixins: [config],
props: {
fixContext: {
type: Object,
default() {
return null
}
},
contextVisible: {
type: Boolean,
default: true
},
levelOneDisable: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
},
layConfig: {
type: Object,
default: null
}
},
data() {
return {
evenList: [
{
even: 'searchEvent',
name: '点击查询事件'
}
],
emitMethods: [
{
methods: 'searchEvent',
methodsName: '查询目录'
}
],
loading: false,
edit: false,
canEdit: true,
lazy: true,
defaultExpandedKeys: [],
filterConfig: {},
dxDocumentFolderService: this.$getService('DxFolder'),
context: this.fixContext,
data: [],
defaultProps: {
children: 'children',
label: function(data, node) {
return data.target ? data.target.folderName : data.folderName
},
isLeaf: 'leaf'
},
selectFolderObj: {
dxContext: {},
dxFolder: {}
}
}
},
computed: {
showSearchContent() {
if (this.layConfig) {
return false
} else {
return this.contextVisible
}
}
},
watch: {
context() {
// if (this.context && this.context.id) {
// this.data = [{ ...this.context, folderName: this.context.name }]
// } else {
this.data = []
// }
}
},
created() {
if (this.fixContext && this.fixContext.id) {
this.defaultExpandedKeys = [this.fixContext.id]
}
},
methods: {
searchEvent(data) {
this.loading = true
const contextId = data.id
this.$getService('DxContext').byId(contextId).then(r => {
this.selectFolderObj.dxContext = r
// this.$emit('currentChange', {}, {}, this.selectFolderObj)
this.$set(this, 'defaultExpandedKeys', r ? [r.id] : [])
this.$set(this, 'context', r || null)
}).finally(() => {
this.loading = false
})
},
// getTreeId(data) {
// alert(data.id)
// return Date.now()
// },
loadNode(node, resolve) {
if (node.level === 0) {
const params = {
'searchItems': {
'children': [
],
'items': [
{
'fieldName': 'sourceId',
'operator': 'EQ',
'value': 0
},
{
'fieldName': 'target.dxContextId',
'operator': 'EQ',
'value': this.context.id
}
],
'operator': 'AND'
},
'openProps': [
{
'name': 'target'
}
],
'sortItem': [
{
'fieldName': 'createTime',
'sortOrder': 'desc'
}
],
'toValidateKeys': ''
}
folderTreeSearch(params).then(r => {
const data = r.items.content.map(r => {
r.disabled = !r.target.authKeys.find(x => x === '50')
return r
})
resolve(data)
}).catch(e => {
resolve([])
})
} else {
const params = {
'searchItems': {
'children': [
],
'items': [
{
'fieldName': 'sourceId',
'operator': 'EQ',
'value': node.data.targetId
},
{
'fieldName': 'target.dxContextId',
'operator': 'EQ',
'value': this.context.id
}
],
'operator': 'AND'
},
'openProps': [
{
'name': 'target'
}
],
'sortItem': [
{
'fieldName': 'modifyTime',
'sortOrder': 'desc'
}
],
'toValidateKeys': ''
}
folderTreeSearch(params).then(r => {
const data = r.items.content.map(r => {
r.disabled = !r.target.authKeys.find(x => x === '50')
return r
})
resolve(data)
}).catch(e => {
resolve([])
})
}
resolve([])
},
getItem() {
// this.docFolderModel.
},
currentChange(data, node) {
if (data.disabled) {
this.$utils.showMessageInfo('当前目录不可选择')
return
}
this.selectFolderObj.dxFolder = data
this.$emit('currentChange', data, node, this.selectFolderObj)
if (data.dxContextId) {
this.$emit('searchEvent', JSON.stringify({ items: [
{ fieldName: 'dxContextId', operator: 'EQ', value: data.dxContextId },
{ fieldName: 'dxDocumentFolderId', operator: 'EQ', value: data.id }
] }))
} else {
this.$emit('searchEvent', JSON.stringify({ items: [{ fieldName: 'dxContextId', operator: 'EQ', value: data.id }] }))
}
},
addFolder(node) {
this.$prompt('请输入名称', '新建目录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[^\\/:\*\?""<>|]{1,120}$/,
inputErrorMessage: '文件名不能包含:\\/:*?"<>|'
}).then(({ value }) => {
const params = {
dxContextId: this.context.id,
parentId: node.level > 1 ? node.data.id : 0,
name: value
}
this.$api.recursion('DxFolder', params).then((r) => {
if (node.loaded) {
this.$refs.tree.append(r.items, node)
}
node.expand()
this.$utils.showMessageSuccess('操作成功')
})
}).catch((e) => {
this.$utils.showMessageInfo('取消输入')
})
// const newChild = { id: 'new', name: '', children: [] }
// node.expand()
// if (!node.data.children) {
// this.$set(node.data, 'children', [])
// }
// node.data.children.push(newChild)
// this.$nextTick(() => {
// var nodes = this.$refs.tree.store.nodesMap
// console.log('nodes', nodes)
// console.log('node', node)
// console.log('tree', this.$refs.tree)
// })
},
deleteFolder(node) {
const h = this.$createElement
const fullPath = this.getNodeFullPath(node)
this.$confirm(null, '提示', {
message: h('div', null, [
h('div', null, '请确认是否删除目录?'),
h('div', {
attrs: {
title: fullPath
},
style: {
marginTop: '8px',
color: '#909399',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
}
},
`"${fullPath}"`)
]),
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.dxDocumentFolderService.delete(node.data).then(() => {
this.$refs.tree.remove(node)
this.$utils.showMessageSuccess('删除成功')
})
}).catch(() => {
this.$utils.showMessageInfo('已取消删除')
})
},
getNodeFullPath(node) {
let path = node.label
let parentNode = node.parent
while (parentNode && parentNode.level > 0) {
path = `${parentNode.label}/${path}`
parentNode = parentNode.parent
}
return '/' + path
},
// 修改名称
editFolder(node) {
this.edit = true
this.$set(node, 'edit', true)
this.$set(node, 'rename', node.data.name)
this.$nextTick(() => {
this.$refs.input.focus()
this.$refs.input.select()
})
},
// 失去焦点确定修改
endEdit(node) {
if (!node.rename && !node.cancelEdit) {
this.$refs.input.focus()
this.$utils.showMessageWarning(`名称不能为空`)
return
}
this.$set(node, 'edit', false)
this.$set(this, 'edit', false)
if (!node.cancelEdit) {
if (node.data.name !== node.rename) {
const oldName = node.data.name
node.data.name = node.rename
node.data.fullPath = null
this.dxDocumentFolderService.save(node.data).then(() => {
this.$utils.showMessageSuccess('修改成功')
}).catch(() => {
this.$set(node.data, 'name', oldName)
})
}
} else {
this.$utils.showMessageInfo('已取消修改')
}
node.cancelEdit && delete node.cancelEdit
},
// 回车确定
editEnter(node) {
node.cancelEdit = false
this.$refs.input.blur()
},
// ESC 退出
cancelEdit(node) {
node.cancelEdit = true
this.$refs.input.blur()
},
handleDragEnd(before, after, inner) {
alert(after.level)
before.data.parentId = after.level > 2 ? after.data.id : null
before.data.fullPath = null
this.dxDocumentFolderService.save(before.data).then(r => {
this.$utils.showMessageSuccess('操作成功')
})
}
}
}
</script>
<style lang="scss">
.DocumentFolder{
height: 100%;
box-sizing: border-box;
padding: 8px;
// display: flex;
// flex-direction: column;
overflow: hidden;
// .DocumentFolder-top{
// padding: 0px 8px;
// }
.DocumentFolder-main{
flex: 1;
height: calc(100% - 70px);
overflow: auto;
}
.disabled-node{
cursor: no-drop;
}
.search-form-box{
padding:0px;
}
.search-form-box .dee-search-form .el-form-item__label {
text-align: center;
}
.search-form-box .search-box-item {
width: 100%;
}
.dee-search-form{
&>div{
padding-bottom: 8px !important;
}
}
.dee-search-form{
border-bottom: 1px solid #dcdfe6;
}
.dee-search-form{
margin-bottom: 0px !important;
margin-top: 20px;
// padding-bottom: 20px;
.dee-form-item{
width: 100%;
}
}
.search-box-btn{
display: none;
}
.dxcontext-icon {
display: block;
width: 16px;
margin-right: 2px;
}
.searchBtn{
display: none !important;
}
.el-tree{
background-color: transparent;
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
.el-tree>.el-tree-node {
min-width: 100%;
display:inline-block;
}
.el-tree-node__content {
align-self: baseline;
}
.el-tree-node__content{
padding:1px 8px;
&:hover{
.DocumentFolder-btn{
display: block;
visibility: visible;
}
}
}
.el-tree-node__expand-icon{
font-size: 16px;
// &::after{
// content: "";
// position:absolute;
// width: 1px;
// top:0px;
// display: block;
// height: 100%;
// border-left: 1px dotted #52627C;
// z-index: 2;
// }
}
.el-tree-node__expand-icon.expanded{
transform:none;
&::before{
content: "\e722" !important;
}
}
.DocumentFolder-btnItem{
width: 18px;
height: 18px;
border: none;
background-color: transparent;
background-size:100% 100%;
border-radius: 0;
outline:none;
cursor: pointer;
// &:hover{
// // border-top: 1px solid transparent;
// }
&.btn-add{
background-image: url("/icons/add-L.png");
}
&.btn-edit{
background-image: url("/icons/edit-L.png");
}
&.btn-delete{
background-image: url("/icons/delete-L.png");
}
}
&-node{
width: 100%;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
&-label{
flex: 1;
overflow: hidden;
white-space:nowrap;
text-overflow:ellipsis;
display: flex;
}
&-btn{
// display: none;
visibility: hidden;
// width: 180px;
text-align: right;
button {
margin-left: 8px;
}
}
}
.tree-line{
// .el-tree-node {
// position: relative;
// // padding-left: 16px; // 缩进量
// }
// .el-tree-node__children {
// // padding-left: 16px; // 缩进量
// }
// // 当前层最后一个节点的竖线高度固定
// .el-tree-node:last-child::before {
// height: 38px; // 可以自己调节到合适数值
// }
// // 横线
// .el-tree-node::after {
// content: "";
// width: 8px;
// height: 20px;
// position: absolute;
// left: 14px;
// top: 13px;
// border-width: 1px;
// border-top: 1px dotted #52627C;
// }
// // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
// & > .el-tree-node::after {
// border-top: none;
// }
// & > .el-tree-node::before {
// border-left: none;
// }
// // 展开关闭的icon
// .el-tree-node__expand-icon{
// font-size: 16px;
// // 叶子节点(无子节点)
// &.is-leaf{
// color: transparent;
// // display: none; // 也可以去掉
// }
// }
}
</style>
<template>
<div style="height: 100%;" class="IntegratedQuery-com">
<dee-as-com
:lay-config="{
typeName: 'DxDocument',
layKey: 'defaultQuery'
}"
@searchEvent="searchEvent"
/>
<div>
<div
v-for="(item,index) in groupList"
:key="index"
class="d-s-g-item dee-list-item"
:class="{'active': activeObj && activeObj.showText === item.showText}"
@click="setActiveFun(item)"
>
<span>{{ $t(item.showText) }}</span>
<span>{{ item.masterIdCount }}</span>
</div>
</div>
</div>
</template>
<script>
import { DxDocumentMetrics, getSubTypeName } from '@/api/doc'
export default {
name: 'MyDocument',
// import引入的组件需要注入到对象中才能使用
components: {},
componentName: '综合查询',
props: {},
data() {
// 这里存放数据
return {
activeObj: null,
groupList: [],
subTypeObj: null,
filterData: {},
evenList: [
{
even: 'searchEvent',
name: '条件点击查询事件'
}
]
}
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
this.getDxDocumentMetrics()
},
activated() {
},
// 方法集合
methods: {
setActiveFun(item) {
this.activeObj = item
let groupFilter = []
if (item.showText !== '所有类型') {
groupFilter = [{
'fieldName': 'subTypeName',
'value': item.subTypeName,
'operator': 'EQ'
}]
}
let emitFilter
if (this.filterData && this.filterData.items) {
emitFilter = {
'items': this.filterData.items.concat(groupFilter),
'operator': 'AND'
}
} else {
emitFilter = {
'items': groupFilter,
'operator': 'AND'
}
}
this.$emit('searchEvent', emitFilter)
},
getDxDocumentMetrics() {
if (this.subTypeObj) {
this.getParams()
} else {
getSubTypeName('', 'DxDocument').then(res => {
if (res.items) {
this.subTypeObj = {
DxDocument: '文档'
}
res.items.forEach(el => {
this.$set(this.subTypeObj, el.name, el.displayName)
})
}
this.getParams()
})
}
},
getParams() {
const params = {
'maxPageSize': 10000,
'indices': [],
'globalSearch': false,
'aggregationSearchParam': {
'groupBys': [{
'fieldName': 'subTypeName',
'typeName': '.TermsAggregationGroupBy',
'ascOrder': true
}],
'metrics': [{
'name': 'masterIdCount',
'fieldName': 'masterId',
'metricsType': 'CARDINALITY'
}]
},
'openProps': [],
'searchItems': {
'items': [{
'fieldName': 'checkOuted',
'value': 'false',
'operator': 'EQ'
}],
'operator': 'AND'
},
'sortItem': []
}
if (this.filterData && this.filterData.items) {
params.searchItems.items = params.searchItems.items.concat(this.filterData.items)
}
DxDocumentMetrics(params).then(res => {
let masterIdCount = 0
this.groupList = []
if (res.items && res.items.data) {
console.log(res.items.data)
res.items.data.forEach(el => {
masterIdCount += parseInt(el.masterIdCount)
el.showText = this.subTypeObj[el.subTypeName] || el.subTypeName
this.groupList.push(el)
})
}
this.groupList = [
{
showText: '所有类型',
masterIdCount
},
...this.groupList
]
})
},
searchEvent(data) {
this.filterData = data
this.getDxDocumentMetrics()
this.$emit('searchEvent', data)
}
}
}
</script>
<style lang='scss'>
.IntegratedQuery-com{
overflow: auto;
.d-s-g-item{
padding: 0 12px;
display: flex;
font-size: 14px;
height: 40px;
line-height: 40px;
justify-content: space-between;
cursor: pointer;
}
}
</style>
<template>
<div style="height: 100%;">
<div class="my-document-box">
<div v-for="(item,i) in dateList" :key="i" :class="{'dee-active-row-background': index === i}" class="time dee-row-item" @click="timeSearch(item.value,i)">{{ item.label }}</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
componentName: '最近访问',
name: 'LastVisitorFilter',
// import引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
// 这里存放数据
return {
index: 0,
evenList: [
{
even: 'searchEvent',
name: '条件点击查询事件'
}
],
dateList: [
{
label: '全部',
value: 'all'
},
{
label: '最近一天',
value: -1
},
{
label: '最近三天',
value: -3
},
{
label: '最近七天',
value: -7
},
{
label: '最近一个月',
value: -30
}
]
}
},
// 监听属性 类似于data概念
computed: {
...mapGetters(['userInfo'])
},
// 监控data中的数据变化
watch: {},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
// this.timeSearch('all', 0)
},
activated() {
},
// 方法集合
methods: {
timeSearch(time, index) {
this.index = index
if (time !== 'all') {
this.$emit('searchEvent', {
searchType: 'recentLast',
searchData: [
{ fieldName: 'modifyTime', operator: 'GT', value: this.$utils.getComputeDay(time, ' 00:00:00') },
{ fieldName: 'visitedUserId', operator: 'EQ', value: this.userInfo.id }]
})
} else {
this.$emit('searchEvent', {
searchType: 'recentLast',
searchData: [{ fieldName: 'visitedUserId', operator: 'EQ', value: this.userInfo.id }]
})
}
}
}
}
</script>
<style lang='scss'>
</style>
<template>
<div style="height: 100%;">
<div class="my-document-box">
<div v-for="(item,i) in dateList" :key="i" :class="{'dee-active-row-background': index === i}" class="time dee-row-item" @click="timeSearch(item.value,i)">{{ item.label }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'MyDocument',
// import引入的组件需要注入到对象中才能使用
components: {},
componentName: '我的文档',
props: {},
data() {
// 这里存放数据
return {
evenList: [
{
even: 'searchEvent',
name: '条件点击查询事件'
}
],
index: 0,
dateList: [
{
label: '全部',
value: 'all'
},
{
label: '最近7天',
value: -7
},
{
label: '最近一个月',
value: -30
},
{
label: '最近二个月',
value: -60
},
{
label: '最近三个月',
value: -90
},
{
label: '最近一年',
value: -365
}
]
}
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
// this.timeSearch('all', 0)
},
activated() {
},
// 方法集合
methods: {
timeSearch(time, index) {
this.index = index
this.$emit('searchEvent', time === 'all' ? [{ fieldName: 'creatorId', operator: 'EQ', value: parseInt(localStorage.getItem('userId')) }]
: [
{ fieldName: 'createTime', operator: 'GT', value: this.$utils.getComputeDay(time, ' 00:00:00') },
{ fieldName: 'creatorId', operator: 'EQ', value: parseInt(localStorage.getItem('userId')) }
])
}
}
}
</script>
<style lang='scss'>
</style>
/**
* @Description:
* @author cxg
* @date 2022/10/09
*/
<template>
<div class="-page">
测试自定义组件
</div>
</template>
<script>
export default {
components: {},
props: {
baseComInfo: {
type: Object,
default: () => {}
}
},
data() {
return {
}
},
computed: {},
mounted() {},
methods: {
eventFunc(params) {
console.log(this.baseComInfo)
}
}
}
</script>
<style lang='scss'>
</style>
/**
* @Description: 高级搜索
* @author wx
* @date 2023/03/14
*/
<template>
<div ref="advanceSearch" class="advanceSearch-com">
<div v-for="(item, index) in viewSearchList[pageId]" :key="index" class="flex-s dee-row-item" :class="{'dee-active-row-background': curItemName(item.name)}" @click="clickItem(item)">
<span class="name">{{ item.name }}{{ item.isCommon ? "(公共)" : "" }}</span>
<div v-if="!item.isCommon || (item.isCommon && item.creatorId+'' === curUserId)" class="oparation-btn">
<img src="/icons/edit-L.png" alt="重命名" @click.stop="edit(item)">
<img src="/icons/delete-L.png" alt="删除" @click.stop="remove(item)">
</div>
</div>
<dee-dialog
:dialog-visible="dialogVisible"
title="重命名"
width="580px"
@handleClose="handleClose"
>
<dee-as-com
parent-show-mode="dialog"
:lay-config="{
typeName: 'DxSearchTemplate',
layKey: 'defaultEdit'
}"
:basic-data="editItem"
@close="handleClose"
@on-cancel="handleClose"
@completeEven="completeEven"
/>
</dee-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'AdvanceSearch',
componentName: '高级搜索',
components: {},
props: {
isConfiging: {
type: Boolean,
default: false
},
viewKey: {
type: String,
default: ''
},
modelName: {
type: String,
default: ''
}
},
data() {
return {
dialogVisible: false,
editItem: null,
clickCount: 0
}
},
computed: {
...mapGetters([
'viewSearchList'
]),
pageId() {
return this.modelName && this.viewKey ? `${this.modelName}-${this.viewKey}` : ''
},
curUserId() {
return localStorage.getItem('userId')
}
},
watch: {
},
created() {
this.$bus.$on('refreshSearchList', (data) => {
!this.isConfiging && this.getSearchList(data.pageId)
})
},
mounted() {
!this.isConfiging && this.getSearchList()
},
methods: {
handleClose() {
this.dialogVisible = false
},
completeEven() {
this.handleClose()
this.getSearchList()
},
getSearchList(pageId) {
const params = {
'pageFrom': 1,
'pageSize': 100,
'sortItem': [
{
'fieldName': 'modifyTime',
'sortOrder': 'asc'
}
],
'searchItems': {
'operator': 'OR',
'items': [],
'children': [
{
'operator': 'AND',
'items': [
{
'fieldName': 'isCommon',
'operator': 'EQ',
'value': false
},
{
'fieldName': 'pageId',
'operator': 'EQ',
'value': pageId || this.pageId
},
{
'fieldName': 'creatorId',
'operator': 'EQ',
'value': localStorage.getItem('userId')
}
]
},
{
'operator': 'AND',
'items': [
{
'fieldName': 'isCommon',
'operator': 'EQ',
'value': true
},
{
'fieldName': 'pageId',
'operator': 'EQ',
'value': pageId || this.pageId
}
]
}
]
},
'toValidateKeys': ''
}
this.$api.searchApi('DxSearchTemplate', params).then(res => {
this.updateList(res.items.content || [])
})
},
updateList(arr = []) {
const list = this.viewSearchList
this.$set(list, this.pageId, arr)
this.$store.dispatch('viewSearchList/updateList', list)
},
edit(item) {
this.editItem = item
this.dialogVisible = true
},
remove(item) {
this.$api.remove('DxSearchTemplate', item.id).then(res => {
this.$utils.showMessageSuccess('删除成功')
this.getSearchList()
})
},
clickItem(item) {
this.$emit('typeSearch', 'conditionSearch', item ? { ...item, clickCount: this.clickCount++ } : { queryCondition: '{}', isAdvancedSearch: false }, '我的搜索')
},
curItemName(name) {
const visitePath = this.$store.state.breadcrumb.visitePath[this.pageId] || []
return !!(visitePath.length >= 2 && name === visitePath[1])
}
}
}
</script>
<style lang='scss'>
.advanceSearch-com{
.flex-s{
display: flex;
justify-content: space-between;
}
.dee-row-item{
font-size: 13px;
color: #232323;
line-height: 34px;
padding: 0 14px 0 24px;
cursor: pointer;
}
.oparation-btn{
display: none;
img {
display: block;
width: 14px;
height: 14px;
margin: auto 0;
&:nth-child(1){
margin-right: 10px;
}
}
}
.dee-row-item:hover{
.oparation-btn {
display: flex;
}
}
}
</style>
/**
* @Description:
* @author wx
* @date 2023/03/23
*/
<template>
<div class="breadcrumb-com flex-start">
<img src="/icons/dee-doc/dingwei.png" alt="">
<span>
{{ visitePath }}
</span>
</div>
</template>
<script>
export default {
name: 'Breadcrumb',
componentName: '面包屑',
components: {},
data() {
return {
visitePath: ''
}
},
computed: {
pageId() {
// return this.$route.path.split('/')[2]
return this.$route.path
}
},
watch: {
'$store.state.breadcrumb.visitePath': {
immediate: true,
deep: true,
handler: function(data) {
if (data) {
this.visitePath = data[this.pageId].join('>')
}
}
}
},
mounted() {},
methods: {}
}
</script>
<style lang='scss'>
.breadcrumb-com{
// background:#E8EDEF;
font-size:11px;
color: #A3A3A3;
img{
display: block;
width: 9px;
height: 12px;
margin: 0 4px 0 10px;
};
}
</style>
/**
* @Description:文件夹权限选择器
* @author wx
* @date 2023/11/17
*/
<template>
<div>
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">{{ $t("全选") }}</el-checkbox>
<div style="margin: 15px 0;" />
<el-checkbox-group v-model="bindValue" @change="handleCheckedChange">
<el-checkbox v-for="item in options" :key="item.value" :label="item.value">{{ $t(item.label) }}</el-checkbox>
</el-checkbox-group>
</div>
</template>
<script>
export default {
name: 'FolderAuths',
componentName: '文件夹权限选择器',
components: {},
props: {
options: {
type: Array,
default: () => []
},
value: {
type: Array,
default: () => []
}
},
data() {
return {
bindValue: [],
checkAll: false,
isIndeterminate: false
}
},
computed: {},
watch: {
value: {
immediate: true,
handler: function(val) {
if (val !== this.bindValue) {
this.bindValue = val
}
if (val.length && val.length !== this.options.length) {
this.isIndeterminate = true
}
}
},
bindValue: {
immediate: true,
handler: function(val) {
if (val.length === this.options.length) {
this.checkAll = true
}
}
}
},
mounted() {},
methods: {
handleCheckAllChange(val) {
this.$emit('input', val ? this.options.map(r => r.value) : [])
this.isIndeterminate = false
},
handleCheckedChange(value) {
const checkedCount = value.length
this.checkAll = checkedCount === this.options.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.options.length
this.$emit('input', value)
}
}
}
</script>
<style lang='scss'>
</style>
/**
* @Description:文件夹的成员与存储设置
* @author wx
* @date 2023/11/13
*/
<template>
<div class="folder-member-setting-com">
<div class="sub-title">{{ $t("存储") }}</div>
<div class="flex-space">
<div class="folder-name">{{ $t("文件夹") }}{{ basicData ? basicData.folderName :'' }}</div>
<div class="flex-start save-wrap">
<span>{{ $t("允许存放对象") }}</span>
<el-select
v-model="bindValue"
class="modelName-select"
multiple
:options="options"
size="small"
@change="handleChange"
>
<el-option
v-for="(option,index) in options"
:key="index"
:label="$t(option.displayName)"
:value="option.id"
/>
</el-select>
</div>
</div>
<div class="sub-title">{{ $t("成员") }}</div>
<dee-up-table
:columns="tableColumns"
:data="tableData"
style="height:300px"
>
<dee-tools slot="header" :tools="tools" mode="normal" :collapse="false" />
</dee-up-table>
<dee-dialog
:dialog-visible="dialogVisible"
:title="title"
width="580px"
@handleClose="handleClose"
>
<dee-form
ref="memberForm"
:form="memberForm"
:form-data="memberFormData"
form-btn-position="center"
:rules="formRules"
label-width="120px"
:inline="true"
>
<span style="display:flex">
<el-button
type="primary"
class="searchBtn"
@click="handleSubmit"
>{{ $t("确定") }}</el-button>
<el-button
class="searchBtn"
@click="handleClose"
>{{ $t("取消") }}</el-button>
</span>
</dee-form>
</dee-dialog>
</div>
</template>
<script>
import { findModelByPlugin, findUserByContext, getOperateAuth, disableInheritance, findTeamByContext } from '@/api/config'
export default {
name: 'FolderMemberSetting',
componentName: '文件夹的存储和成员设置',
components: {},
props: {
basicData: {
type: Object,
default: null
}
},
data() {
const that = this
return {
bindValue: [],
originalArr: [],
options: [],
dialogVisible: false,
title: '',
tableColumns: [{ title: '操作', key: 'operate', align: 'center', width: 100, component: {
show: true,
name: 'EditTableRow',
fixed: true,
props: {
btns: [
{
operation: '编辑',
handleClick: (row, index) => {
this.handleEdit(true, row)
},
icon: '/icons/c-edit.png',
showFun: (row) => {
return !row.inherit
}
},
{
operation: '移除',
handleClick: (row, index) => {
this.deleteAuthLinks(row)
},
icon: '/icons/c-creatbackups.png',
showFun: (row) => {
return !row.inherit
}
},
{
operation: '禁用继承',
handleClick: (row, index) => {
this.disabledInherit(row)
},
icon: '/icons/disable.png',
showFun: (row) => {
return row.inherit
}
}
]
}
}},
{ title: '成员', key: 'memberName', align: 'center', width: 180 },
{
title: '继承',
key: 'inherit',
align: 'center',
i18nEnble: true,
width: 100,
formatter(row, column) {
return row.inherit ? '父' : '无'
} },
{ title: '应用于',
key: 'applyToChildren',
align: 'center', width: 180,
i18nEnble: true,
formatter(row, column) {
return row.applyToChildren ? '此文件夹及子文件夹' : '此文件夹'
} },
{ title: '访问权',
key: 'authLinks',
align: 'center',
formatter: (row, column) => {
return row.authLinks ? row.authLinks.map(r => {
return this.$t(that.FolderOperateOptions.find(x => x.value === r.target.operate).label)
}).join(',') : ''
} }],
tableData: [],
tools: [{
name: '新增',
icon: '/icons/c-add.png',
handler: {
click: () => {
this.handleEdit(false)
}
}
}],
FolderOperateOptions: [],
editData: null,
memberForm: {},
teams: [],
contextUsers: [],
formRules: {
memberType: [
{ required: true, message: '请选择', trigger: 'change' }
],
memberId: [
{ required: true, message: '请选择', trigger: 'change' }
],
applyToChildren: [
{ required: true, message: '请选择', trigger: 'change' }
]
}
}
},
computed: {
memberFormData() {
return [{
split: 1,
data: [{
key: 'memberType',
title: '成员类型',
component: {
name: 'el-select',
i18nEnble: true,
options: [{
label: '团队',
value: 'TEAM'
}, {
label: '用户',
value: 'USER'
}]
},
handler: {
change: (val) => {
this.$set(this.memberForm, 'memberId', '')
}
}
}, {
key: 'memberId',
title: '添加成员',
component: {
name: 'el-select',
options: this.memberForm.memberType === 'TEAM' ? this.teams : this.contextUsers
}
},
{
key: 'applyToChildren',
title: '应用于',
component: {
i18nEnble: true,
name: 'el-select',
options: [{
label: '此文件夹',
value: false
}, {
label: '此文件夹及子文件夹',
value: true
}]
}
},
{
key: 'permissions',
title: '访问权',
component: {
name: 'FolderAuths',
registrationType: 'custom',
codeApp: 'dee-doc',
codePath: '/folderAuths/index.vue',
options: this.FolderOperateOptions
}
}
]
}]
}
},
watch: {
'memberForm.memberType': {
handler: function(val) {
if (val === 'TEAM') {
this.getTeams()
}
if (val === 'USER') {
this.getUsers()
}
}
}
},
async created() {
this.FolderOperateOptions = this.$store.state.dictionaries && this.$store.state.dictionaries.FolderOperate ? this.$store.state.dictionaries.FolderOperate.default : await this.$utils.getDicListByCode('FolderOperate')
},
async mounted() {
await this.getModelList()
this.getSaveData()
this.getMemberPermissions()
},
methods: {
getUsers() {
findUserByContext({ contextId: this.basicData.dxContextId }).then(res => {
this.contextUsers = res.items.map(r => {
return {
label: r.name,
value: r.userId
}
})
})
},
async getTeams() {
const teamRole = this.$store.state.dictionaries && this.$store.state.dictionaries.TeamRole ? this.$store.state.dictionaries.TeamRole.default : await this.$utils.getDicListByCode('TeamRole')
findTeamByContext({ contextId: this.basicData.dxContextId }).then(res => {
this.teams = res.items && res.items.length ? res.items.map(r => {
return {
label: teamRole.find(role => role.value === r.teamRole) ? teamRole.find(role => role.value === r.teamRole).label : r.teamRole,
value: r.id
}
}) : []
})
},
getModelList() {
findModelByPlugin({ pluginName: 'DxObjFolderHolder' }).then(res => {
this.options = res.items || []
})
},
getSaveData() {
const params = {
// 'openProps': [{ name: 'target' }],
'sortItem': [
{
'fieldName': 'modifyTime',
'sortOrder': 'desc'
}
],
'searchItems': {
'operator': 'AND',
'items': [{
'fieldName': 'sourceId',
'operator': 'EQ',
'value': this.basicData.id
}]
}
}
this.$api.searchApi('DxFolderStorageLink', params).then(res => {
this.originalArr = []
this.bindValue = []
if (res.items.content.length) {
this.originalArr = JSON.parse(JSON.stringify(res.items.content))
}
this.bindValue = res.items.content.length ? res.items.content.map(r => r.targetId) : []
})
},
handleChange(val) {
const addArr = []
const delArr = []
this.originalArr.forEach(x => {
const findId = val.find(y => x.targetId === y)
if (!findId) {
delArr.push(x)
}
})
val.forEach(x => {
const findId = this.originalArr.find(y => y.targetId === x)
if (!findId) {
addArr.push(x)
}
})
const params = []
if (addArr.length) {
addArr.forEach(x => {
params.push({
sourceId: this.basicData.id,
sourceIdType: this.basicData.subTypeName,
operator: 'ADD',
modelName: this.options.find(r => r.id === x).name,
targetId: x,
targetIdType: 'VoModelDefinition'
})
})
}
if (delArr.length) {
delArr.forEach(x => {
params.push({
id: x.id,
operator: 'REMOVE'
})
})
}
this.$api.recursion('DxFolderStorageLink', params, true).then(res => {
this.getSaveData()
this.$utils.showMessageSuccess('保存成功')
})
},
handleEdit(isEdit, data) {
this.title = isEdit ? '编辑成员' : '新增成员'
this.editData = data || null
if (isEdit) {
this.memberForm = {
memberType: data.memberType,
inherit: data.inherit,
applyToChildren: data.applyToChildren,
memberId: data.memberId,
permissions: data.authLinks.map(r => r.target.operate),
groupKey: data.authLinks && data.authLinks[0].groupKey ? data.authLinks[0].groupKey : this.$utils.guid()
}
} else {
this.memberForm = {
groupKey: this.$utils.guid()
}
}
this.dialogVisible = true
},
handleSubmit() {
this.$refs['memberForm'].$refs.form.validate((valid) => {
// 验证是否通过
if (valid) {
if (!this.memberForm.permissions || !this.memberForm.permissions.length) {
this.$utils.showMessageError('请勾选权限')
return
}
const permissions = this.memberForm.permissions.filter(x => x !== 'all')
const addArr = []
const delArr = []
this.editData && this.editData.authLinks.forEach(x => {
const findId = permissions.find(y => x.target.operate === y)
if (!findId) {
delArr.push(x)
}
})
permissions.forEach(x => {
const findId = this.editData && this.editData.authLinks.find(y => y.target.operate === x)
if (!findId) {
addArr.push(x)
}
})
let params = []
if (addArr.length) {
addArr.forEach(x => {
params.push({
'sourceId': this.basicData.id,
'sourceIdType': this.basicData.subTypeName,
'applyToChildren': this.memberForm.applyToChildren,
'inherit': false,
operator: 'ADD',
groupKey: this.memberForm.groupKey,
'target': {
operator: 'ADD',
'operate': x,
'memberType': this.memberForm.memberType,
'memberId': this.memberForm.memberId
}
})
})
}
if (delArr.length) {
delArr.forEach(x => {
params.push({
id: x.id,
operator: 'REMOVE',
target: {
operator: 'REMOVE',
id: x.targetId
}
})
})
}
if (!addArr.length && !delArr.length) {
params = this.editData.authLinks.map(r => {
r.operator = 'MODIFY'
r.applyToChildren = this.memberForm.applyToChildren
r.target = {
...r.target,
...this.memberForm,
id: r.targetId,
operator: 'MODIFY'
}
return r
})
}
this.$api.recursion('DxFolderOperationLink', params, true).then(res => {
this.getMemberPermissions()
this.$utils.showMessageSuccess('保存成功')
this.handleClose()
})
}
})
},
getMemberPermissions() {
getOperateAuth({ folderId: this.basicData.id }).then(res => {
this.tableData = res.items || []
})
},
disabledInherit(row) {
disableInheritance(this.basicData.id, row.authLinks.map(r => r.id)).then(res => {
this.getMemberPermissions()
this.$utils.showMessageSuccess('禁用成功')
})
},
deleteAuthLinks(row) {
const params = row.authLinks.map(r => {
r.operator = 'REMOVE'
r.target.operator = 'REMOVE'
return r
})
this.$api.recursion('DxFolderOperationLink', params, true).then(res => {
this.getMemberPermissions()
this.$utils.showMessageSuccess('删除成功')
})
},
handleClose() {
this.dialogVisible = false
}
}
}
</script>
<style lang='scss'>
.folder-member-setting-com{
.flex-space{
display: flex;
justify-content: space-between;
}
.folder-name{
line-height: 32px;
}
.save-wrap{
width: 50%;
span{
margin-right:6px;
}
}
}
</style>
/**
* @Description:文件夹复制粘贴数据
* @author wx
* @date 2023/11/23
*/
<template>
<div class="folderPasteData-com">
<dee-as-com
:basic-data="searchOriParams ? searchOriParams.data : null"
:lay-config="{
typeName:'DxFolderLink',
layKey:'DxFolderLink-container-moveData-chooseFolder'
}"
@nodeClick="folderTreeNodeClick"
/>
</div>
</template>
<script>
import { pasteData } from '@/api/doc'
export default {
name: 'FolderPasteData',
componentName: '文件夹复制粘贴数据',
components: {},
props: {
searchOriParams: {
type: Object,
default: null
},
selectedData: {
type: Array,
default: () => []
}
},
data() {
return {
targetFolderId: ''
}
},
computed: {},
mounted() {},
methods: {
folderTreeNodeClick(data) {
this.targetFolderId = data.data.targetId
// sourceFolderId是数据所在的原文件夹的id
const sourceFolderId = this.searchOriParams && this.searchOriParams.data && this.searchOriParams.data.targetIdType === 'DxFolder' ? this.searchOriParams.data.targetId : 0
pasteData(sourceFolderId, this.targetFolderId, this.selectedData[0].pasteType, this.selectedData.map(r => {
return r.target
})).then(res => {
this.$utils.showMessageSuccess('操作成功')
this.$emit('completeEven')
})
}
}
}
</script>
<style lang='scss'>
</style>
const requireComponent = require.context(
'./components', // 在当前目录下查找
true, // 遍历子文件夹
/\.vue$/ // 正则匹配 以 .vue结尾的文件
)
const privateComponents = []
requireComponent.keys().forEach(fileName => {
const comp = requireComponent(fileName)
if (comp.default.componentName) {
let layoutConfigData = comp.default.layoutConfigData
if (!layoutConfigData && comp.default.mixins) {
const hasLayoutConfigData = comp.default.mixins.find(el => {
return el.layoutConfigData
})
if (hasLayoutConfigData) {
layoutConfigData = hasLayoutConfigData.layoutConfigData
}
}
privateComponents.push(
{
componentName: comp.default.componentName,
name: comp.default.name,
path: fileName.slice(1),
layoutConfigData: layoutConfigData || []
}
)
}
})
export default privateComponents
const containerComponents = [
'demo'
]
const formListComponents = [
'demo'
]
const tabComponents = [
'demo'
]
const tableListComponents = [
'demo'
]
export default {
containerComponents,
formListComponents,
tabComponents,
tableListComponents
}
/* routes-list */
// const APP_NAME = process.env.VUE_APP_NAME;
// import Vue from 'vue'
// const sharePool = (Vue.__share_pool__ = Vue.__share_pool__ || {})
// const store = (sharePool.store = sharePool.store || {})
const App = () => import('./App.vue')
export default [
{
path: '/docCenter',
name: 'docCenter',
component: () => import('@/views/doc/center'),
meta: { title: '文档中心', alive: true }
},
{
path: '/doc',
component: App,
name: 'doc',
meta: { title: '文档中心', icon: 'xitong' },
redirect: '/doc/add',
children: [
{
hidden: true,
path: 'add',
name: 'docAdd',
component: () => import('@/views/doc/add'),
meta: { title: '新建文档', alive: false }
},
{
hidden: true,
path: 'edit',
name: 'docEdit',
component: () => import('@/views/doc/edit'),
meta: { title: '编辑文档' }
}
]
}
]
const DEABaseService = window.top.mainVue.$store.getters.baseService
class DxDocumentService extends DEABaseService {
constructor() {
super('/DxDocument')
}
}
export default {
install() {
window.top.mainVue.$setService('DxDocument', DxDocumentService)
}
}
const DEABaseService = window.top.mainVue.$store.getters.baseService
// const ACTIONS = {
// // 获取子结构
// GET_CHILD: {
// path: '{{$modelPath}}/child/{{id}}',
// method: 'POST'
// }
// }
class DxDocumentFolderService extends DEABaseService {
// eslint-disable-next-line no-useless-constructor
constructor() {
super('/DxDocumentFolder')
}
// 获取子目录
getFolders(folderId, level = 1) {
const searchItems = this.newSearchItems().addItem('parentId', folderId)
return this.query(searchItems).search()
}
// 添加目录
addFolder(dxContextId, parentId, name) {
return this.save({
dxContextId,
parentId,
name
})
}
// 获取容器的根目录 (当前容器本身不建立目录,允许多个根目录)
getRootFolders(dxContextId) {
return this.query(
this.newSearchItems()
.and()
.addItem('dxContextId', dxContextId)
.addItem('parentId', 0)
).page(1, 9999).search()
}
moveTo(folderId, toFolderId) {
return this.query
}
}
export default {
install() {
window.top.mainVue.$setService('DxDocumentFolder', DxDocumentFolderService)
}
}
const DEABaseService = window.top.mainVue.$store.getters.baseService
const ACTIONS = {
// // 获取子结构
// GET_LAYOUT: {
// path: '{{$modelPath}}/form/config/layout?layoutType={{layoutType}}&typeKey={{typeKey}}',
// method: 'GET'
// }
GET: {
path: '{{$modelPath}}',
method: 'GET'
},
ADD: {
path: '{{$modelPath}}',
method: 'POST'
},
EDIT: {
path: '{{$modelPath}}',
method: 'PUT'
},
GET_BY_NAME: {
path: '{{$modelPath}}/name/{{modelName}}',
method: 'GET'
}
}
class ModelDefinitionService extends DEABaseService {
// eslint-disable-next-line no-useless-constructor
constructor() {
super('/ModelDefinition')
}
// // 获取Layout
// getLayout(layoutType, typeKey) {
// return this.apply(ACTIONS.GET_LAYOUT, { layoutType, typeKey })
// }
async get(appId, modelId) {
return await this.apply(ACTIONS.GET, null, {
appId,
modelId
}).items
}
async getByName(modelName) {
return await this.apply(ACTIONS.GET_BY_NAME, null, {
modelName
})
}
}
export default {
install() {
window.top.mainVue.$setService('ModelDefinition', ModelDefinitionService)
}
}
/* store module */
import { actionInit } from '@/utils/store.js'
export default {
namespaced: true, // namespaced must be true in module app.
state: {
name: process.env.VUE_APP_NAME
},
mutations: {},
actions: actionInit()
}
/**
* @Description: 样式统一位置
* @author arvin
* @date 2021/2/25
*/
/* */
.porcess-history-record-com{
margin-top: 10px;
}
/* */
.preview-com{
height: 100%;
overflow: auto;
.preview-box{
padding: 8px;
height: 100%;
overflow: auto;
background-color: #DEE1E7;
.preview-form{
padding:8px;
background: #FFF
}
}
}
.prop-tree-com{
height: 100%;
.model-icon{
border-width: 0;
color: #2A75CE;
}
}
.intermediate-region-com{
.left-s-box{
display: flex;
align-items: center
}
.more-info{
color: #2A75CE;
padding: 0 10px;
font-size: 16px;
cursor: pointer;
}
}
.add-page{
height: 100%;
box-sizing: border-box;
.scroll-container{
.el-scrollbar__wrap {
margin-bottom: 0 !important;
overflow-x: hidden;
.task-name{
font-weight: bold;
margin-bottom: 20px;
margin-top: 4px;
}
}
.is-horizontal{
display: none;
}
}
}
.doc-center{
height: 100%;
box-sizing: border-box;
display: flex;
justify-content: flex-start;
.detail-pane {
width: 100%;
height: 100%;
}
.left-box{
height: 100%;
box-sizing: border-box;
border: 1px solid #d9d9d9;
background-color: #fff;
.dee-panel{
height: calc(100% - 13px) !important;
width: 99%;
}
.el-tabs__content {
height: calc(100% - 68px) !important;
overflow: auto;
}
.el-tab-pane {
height: calc(100% - 13px) !important;
}
.el-tabs__nav-prev{
left: 4px;
}
.el-tabs__nav-next{
right: 4px;
}
.el-tabs__nav {
width: 100%;
}
.is-active:after {
position: absolute;
border-top: 4px solid transparent;
border-left: 4px solid transparent;
border-bottom: 4px solid #3281DE;
border-right: 4px solid transparent;
content: " ";
display: block;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
.el-tabs__nav-scroll{
border-left: none;
}
.el-tabs__item{
width: 25%;
background-color: #ffffff;
height: auto;
font-weight: bold;
border-left: 0;
border-right: 0;
border-top: 0;
span {
display: flex;
flex-direction: column;
align-items: center;
.imgStyle {
margin: 0;
}
}
}
.el-tabs__item.is-active {
border-bottom: 2px solid #3281DE;
background-color: #f3f3f3;
}
.slot{
height: 100%;
padding: 10px;
box-sizing: border-box;
}
.myDocument{
box-sizing: border-box;
}
}
.right-pane{
height: 100%;
background-color: #fff;
border: 1px solid #d9d9d9;
box-sizing: border-box;
.splitter-pane-resizer.horizontal {
opacity: 1;
background-color: #F1F4F5;
height: 8px;
border-bottom: 1px solid #e0e0e0;
border-top: 1px solid #e0e0e0;
}
.table-box{
height: calc(100% - 22px);
overflow: hidden;
background-color: #fff;
padding: 10px 16px;
.dee-table{
height: calc(100% - 32px);
.dee-table-body{
height: calc(100% - 96px);
overflow: auto;
}
}
}
.down-pic{
position: absolute;
left:0;
right: 0;
top: 5px;
z-index: 10;
margin:0 auto;
cursor: pointer;
}
.detail{
height: 100%;
}
.dee-table-pagination {
padding: 0;
}
}
}
.integratedQuery{
height: 100%;
}
.my-document-box{
margin-top: 13px;
.time{
cursor: pointer;
height: 36px;
font-size: 14px;
line-height: 36px;
padding-left: 22px;
}
// .time:hover{
// background: #EEF3F9;
// color: #4077CF;
// }
// .clickStyle{
// background: #EEF3F9;
// color: #4077CF;
// }
}
export const layoutExtendOptions = []
export const verificationMethods = {}
export const formateExtendOptions = [
// 参考格式 views\config\typePropManage\layoutConfig\config\formateOptions.js 格式
]
export const layout = {
'创建': '0',
'编辑': '1',
'详情信息': '2',
'流程任务': '3',
'主题': '4',
'查看': '5',
'列表查看': '6'
}
import moment from 'moment'
export function formatDate({ params: formatPattern, row, column, cellValue, index }) {
const date = 'YYYY-MM-DD'
return moment(cellValue).format(formatPattern || date)
}
export default {
formatDate
}
export const formateOptions = [
{
label: '年-月-日',
value: 'data1',
params: 'YYYY-MM-DD',
formate: 'formatDate'
}, {
label: '年-月-日 时:分:秒',
value: 'data2',
params: 'YYYY-MM-DD HH:mm:ss',
formate: 'formatDate'
}
]
import Vue from 'vue'
const sharePool = (Vue.__share_pool__ = Vue.__share_pool__ || {})
const http = (sharePool.http = sharePool.http || {})
function get(url, params) {
return http.get(url, params)
}
function post(url, params) {
return http.post(url, params)
}
function put(url, params) {
return http.put(url, params)
}
function patch(url, params) {
return http.patch(url, params)
}
function del(url, params) {
return http.del(url, params)
}
function downloadFile(url, type) {
return http.downloadFile(url, type)
}
function downloadZip(url, type) {
return http.downloadZip(url, type)
}
export { get, post, put, del, patch, downloadFile, downloadZip }
/**
* Created by CXG on 19/7/3.
*/
/**
* @param {Object} sapproval
* @param {Object} selfAction
* @returns {Object}
*/
export function actionInit(sapproval, selfAction) {
const resOBj = {}
if (sapproval) {
Object.keys(sapproval).forEach(function(key) {
resOBj[key] = ({ commit }, params) => {
return new Promise((resolve, reject) => {
sapproval[key](params).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
}
})
}
if (selfAction) {
return Object.assign(resOBj, selfAction)
} else {
return resOBj
}
}
export const forEach = (arr, fn) => {
if (!arr.length || !fn) return
let i = -1
const len = arr.length
while (++i < len) {
const item = arr[i]
fn(item, i, arr)
}
}
/**
* @param {Array} arr1
* @param {Array} arr2
* @description 得到两个数组的交集, 两个数组的元素为数值或字符串
*/
export const getIntersection = (arr1, arr2) => {
const len = Math.min(arr1.length, arr2.length)
let i = -1
const res = []
while (++i < len) {
const item = arr2[i]
if (arr1.indexOf(item) > -1) res.push(item)
}
return res
}
/**
* @param {Array} arr1
* @param {Array} arr2
* @description 得到两个数组的并集, 两个数组的元素为数值或字符串
*/
export const getUnion = (arr1, arr2) => {
return Array.from(new Set([...arr1, ...arr2]))
}
/**
* @param {Array} target 目标数组
* @param {Array} arr 需要查询的数组
* @description 判断要查询的数组是否至少有一个元素包含在目标数组中
*/
export const hasOneOf = (targetarr, arr) => {
return targetarr.some(_ => arr.indexOf(_) > -1)
}
/**
* @param {String|Number} value 要验证的字符串或数值
* @param {*} validList 用来验证的列表
*/
export function oneOf(value, validList) {
for (let i = 0; i < validList.length; i++) {
if (value === validList[i]) {
return true
}
}
return false
}
/**
* @param {Number} timeStamp 判断时间戳格式是否是毫秒
* @returns {Boolean}
*/
const isMillisecond = timeStamp => {
const timeStr = String(timeStamp)
return timeStr.length > 10
}
/**
* @param {Number} timeStamp 传入的时间戳
* @param {Number} currentTime 当前时间时间戳
* @returns {Boolean} 传入的时间戳是否早于当前时间戳
*/
const isEarly = (timeStamp, currentTime) => {
return timeStamp < currentTime
}
/**
* @param {Number} num 数值
* @returns {String} 处理后的字符串
* @description 如果传入的数值小于10,即位数只有1位,则在前面补充0
*/
const getHandledValue = num => {
return num < 10 ? '0' + num : num
}
/**
* @param {Number} timeStamp 传入的时间戳
* @param {Number} startType 要返回的时间字符串的格式类型,传入'year'则返回年开头的完整时间
*/
const getDate = (timeStamp, startType) => {
const d = new Date(timeStamp * 1000)
const year = d.getFullYear()
const month = getHandledValue(d.getMonth() + 1)
const date = getHandledValue(d.getDate())
const hours = getHandledValue(d.getHours())
const minutes = getHandledValue(d.getMinutes())
const second = getHandledValue(d.getSeconds())
let resStr = ''
if (startType === 'year') resStr = year + '-' + month + '-' + date + ' ' + hours + ':' + minutes + ':' + second
else resStr = month + '-' + date + ' ' + hours + ':' + minutes
return resStr
}
/**
* @param {String|Number} timeStamp 时间戳
* @returns {String} 相对时间字符串
*/
export const getRelativeTime = timeStamp => {
// 判断当前传入的时间戳是秒格式还是毫秒
const IS_MILLISECOND = isMillisecond(timeStamp)
// 如果是毫秒格式则转为秒格式
if (IS_MILLISECOND) Math.floor(timeStamp /= 1000)
// 传入的时间戳可以是数值或字符串类型,这里统一转为数值类型
timeStamp = Number(timeStamp)
// 获取当前时间时间戳
const currentTime = Math.floor(Date.parse(new Date()) / 1000)
// 判断传入时间戳是否早于当前时间戳
const IS_EARLY = isEarly(timeStamp, currentTime)
// 获取两个时间戳差值
let diff = currentTime - timeStamp
// 如果IS_EARLY为false则差值取反
if (!IS_EARLY) diff = -diff
let resStr = ''
const dirStr = IS_EARLY ? '前' : '后'
// 少于等于59秒
if (diff <= 59) resStr = diff + '秒' + dirStr
// 多于59秒,少于等于59分钟59秒
else if (diff > 59 && diff <= 3599) resStr = Math.floor(diff / 60) + '分钟' + dirStr
// 多于59分钟59秒,少于等于23小时59分钟59秒
else if (diff > 3599 && diff <= 86399) resStr = Math.floor(diff / 3600) + '小时' + dirStr
// 多于23小时59分钟59秒,少于等于29天59分钟59秒
else if (diff > 86399 && diff <= 2623859) resStr = Math.floor(diff / 86400) + '天' + dirStr
// 多于29天59分钟59秒,少于364天23小时59分钟59秒,且传入的时间戳早于当前
else if (diff > 2623859 && diff <= 31567859 && IS_EARLY) resStr = getDate(timeStamp)
else resStr = getDate(timeStamp, 'year')
return resStr
}
/**
* @returns {String} 当前浏览器名称
*/
export const getExplorer = () => {
const ua = window.navigator.userAgent
const isExplorer = (exp) => {
return ua.indexOf(exp) > -1
}
if (isExplorer('MSIE')) return 'IE'
else if (isExplorer('Firefox')) return 'Firefox'
else if (isExplorer('Chrome')) return 'Chrome'
else if (isExplorer('Opera')) return 'Opera'
else if (isExplorer('Safari')) return 'Safari'
}
/**
* @description 绑定事件 on(element, event, handler)
*/
export const on = (function() {
if (document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
})()
/**
* @description 解绑事件 off(element, event, handler)
*/
export const off = (function() {
if (document.removeEventListener) {
return function(element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
})()
/**
* 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
* 如果没有传入key这个参数,则判断obj对象是否有键值对
*/
export const hasKey = (obj, key) => {
if (key) return key in obj
else {
const keysArr = Object.keys(obj)
return keysArr.length
}
}
/**
* @param {*} obj1 对象
* @param {*} obj2 对象
* @description 判断两个对象是否相等,这两个对象的值只能是数字或字符串
*/
export const objEqual = (obj1, obj2) => {
const keysArr1 = Object.keys(obj1)
const keysArr2 = Object.keys(obj2)
if (keysArr1.length !== keysArr2.length) return false
else if (keysArr1.length === 0 && keysArr2.length === 0) return true
/* eslint-disable-next-line */
else return !keysArr1.some(key => obj1[key] != obj2[key])
}
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/**
* @Description:
* @author cxg
* @date 2020/07/22
*/
<template>
<div class="add-page">
<div class="full-border-content">
<div class="task-name">新建文档</div>
<dee-form
:form="typeForm"
:form-data="typeFormData"
:border="configDetails&&configDetails.base&&configDetails.base.borderShow"
:label-width="configDetails&&configDetails.base&&configDetails.base.labelWidth"
/>
<dee-form
ref="addForm"
:form="addData"
:form-data="showFormData"
:app-id="configDetails.appId"
:rules="configDetails.rules"
:form-buttons="configDetails.formButtons"
:border="configDetails&&configDetails.base&&configDetails.base.borderShow"
:label-width="configDetails&&configDetails.base&&configDetails.base.labelWidth"
:form-btn-position="configDetails&&configDetails.base&&configDetails.base.formBtnPosition"
:label-position="configDetails&&configDetails.base&&configDetails.base.labelPosition"
@on-submit="submitFun"
@on-cancel="cancelFun"
/>
</div>
</div>
</template>
<script>
import { getLayouts } from '@/api/config'
import { addDocWithRecursion, getSubTypeName } from '@/api/doc'
export default {
components: {},
data() {
return {
addData: {},
appUrl: '',
typeName: 'DxDocument',
typeForm: { subTypeName: '' },
configDetails: {
formData: []
},
docTypes: [],
layout: ''
}
},
computed: {
visitedViews() {
return this.$store.state.tagsView.visitedViews
},
previousRouter() {
return this.$store.state.tagsView.previousRouter.slice(-1)[0]
},
showFormData() {
if (!this.configDetails || !this.configDetails.formData) {
return []
}
return this.configDetails.formData
},
typeFormData() {
return [
{
title: '',
split: 3,
data: [
{ key: 'subTypeName',
title: '类型',
component: {
'name': 'customCmp',
'cptName': 'DeeSubTypeName',
'props': `{showSubType:${true},clsName:${this.typeName}}`
}
}
]
}
]
}
},
watch: {
'typeForm.subTypeName'(val) {
this.getLayouts()
},
'$route'(val) {
if (val.name === 'docAdd' && val.params.reset) {
this.addData = { dxContext: null }
this.$refs.addForm.$refs.form.clearValidate()
this.getSubTypeName()
}
}
},
created() {
if (window.location.hash.includes('?layout=')) {
this.layout = window.location.hash.split('?layout=').slice(-1)[0]
this.layout = this.layout ? this.layout.split('&').slice(-1)[0] : ''
}
this.getSubTypeName()
},
mounted() {},
methods: {
getSubTypeName() {
if (this.typeName === null || this.typeName === '') {
return
}
getSubTypeName('', this.typeName).then(res => {
if (res.items) {
this.docTypes = res.items.map(item => {
return {
label: item.displayName,
value: item.name
}
})
this.typeForm.subTypeName = this.docTypes[0].value
}
})
},
getLayouts() {
if (!this.typeForm || !this.typeForm.subTypeName) {
return
}
getLayouts(this.typeForm.subTypeName, this.layout || this.$enums.layout['新建']).then((res) => {
const item = res.items.slice(-1)
if (item[0] && item[0].configDetails) {
this.configDetails = JSON.parse(item[0].configDetails)
this.appUrl = this.configDetails.tableConfig && this.configDetails.tableConfig.serverUrl
}
})
},
submitFun() {
// this.addData.state = '编制'
this.addData.subTypeName = this.typeForm.subTypeName
const params = this.$utils.saveDynamicAttr(this.addData, '.')
params.operator = 'ADD'
addDocWithRecursion(params, this.appUrl).then(res => {
this.$utils.showMessage('添加成功!', 'success')
this.$store.dispatch('tagsView/delVisitedView', { path: '/doc/add' })
if (this.previousRouter && this.previousRouter.path === '/docCenter') {
this.$router.push({ name: 'docCenter', params: { refresh: true }})
} else {
this.$router.go(-1)
}
})
},
cancelFun() {
this.$store.dispatch('tagsView/delVisitedView', { path: '/doc/add' })
this.$router.go(-1)
}
}
}
</script>
<style lang='scss'>
</style>
/* eslint-disable vue/this-in-template */
<template>
<div class="doc-center">
<dee-fold-pane
:min-percent="minPercent"
:default-percent="defaultPercent"
split="vertical"
class="detail-pane"
>
<template slot="paneL">
<div class="left-box tabs">
<dee-tab ref="tabs" :tabs="tabs" @tabClick="tabClick">
<div slot="1" class="myDocument">
<my-document @getSearchTime="getSearchTime" />
</div>
<div slot="2" class="slot">
<integrated-query :config-details-map="configDetailsMap" @searchEvent="searchEvent" />
</div>
<div slot="3" style="overflow: hidden; height:100%;">
<!-- <DxDocumentFolderSelect /> -->
<DxDocumentFolder @currentChange="folderChange" />
</div>
<div slot="4" class="myDocument">
<lastVisitor @getVisitTime="getVisitTime" />
</div>
</dee-tab>
</div>
</template>
<template slot="paneR">
<div class="right-pane">
<split-pane
:min-percent="rightPageMinPercent"
:default-percent="rightPageDefaultPercent"
split="horizontal"
class="detail-pane"
>
<template slot="paneL">
<deeSearchServerTable
ref="mainTable"
:aggregation-search-param="aggregationSearchParam"
:create-time="createTime"
:search-mode="searchMode"
:is-search-my-doc="isSearchMyDoc"
type-name="DxDocument"
page-name="docCenter"
:page-data="pageData"
v-bind="configDetailsMap['table'].configDetails"
:config="{name: 'table'}"
v-on="layHandler"
/>
</template>
<template slot="paneR">
<div class="detail">
<img class="down-pic" src="/icons/d-down.png" @click="()=>{ close() }">
<general-detail :key="'detail' + key" :is-view="false" :is-self="false" :config="{ name: 'detail'}" :page-data="pageData" type-name="DxDocument" model-name="DxDocument" :lay-handler="{'refreshList':reloadTablelist}" page-name="docCenter" @close-detail="closeDetail" />
</div>
</template>
</split-pane>
</div>
</template>
</dee-fold-pane>
</div>
</template>
<script>
import integratedQuery from './integratedQuery'
import myDocument from './myDocument'
import lastVisitor from './lastVisitor'
export default {
name: 'DocCenter',
components: { integratedQuery, myDocument, lastVisitor },
props: {
detailShow: {
type: Boolean,
default: () => false
}
},
data() {
return {
dxDocumentService: this.$getService('DxDocument'),
searchMode: 'search',
isSearchMyDoc: false,
configDetails: {},
pageData: {},
selectFolderNode: null,
configDetailsMap: {
searchBox: {
},
searchGroup: {},
table: {}
},
layHandler: {
tableToolHander: (Obj) => {
this.tableToolFun(Obj)
},
rowClick: (row) => {
this.rowClick(row)
}
},
key: 0,
tabs: [
{ id: '1', name: '我的文档', icon: '/icons/m-doc.png' },
{ id: '2', name: '综合查询', icon: '/icons/c-search.png' },
{ id: '3', name: '文档目录', icon: '/icons/d-directory.png' },
{ id: '4', name: '最近访问', icon: '/icons/r-access.png' }
],
tabSearchCache: {},
layoutMap: {
'defaultQuery': 'searchBox',
'defaultGroup': 'searchGroup',
'defaultResult': 'table'
},
createTime: '',
rightPageMinPercent: 10,
rightPageDefaultPercent: 30,
folder: {},
minPercent: 10,
defaultPercent: 22,
aggregationSearchParam: null
}
},
computed: {},
mounted() {
this.$refs.tabs.activeName = '2'
this.getLayout(this.layoutMap)
},
methods: {
reloadTablelist() {
this.$refs['mainTable'].searchTableData()
},
close() {
this.rightPageDefaultPercent = 99
this.$nextTick(() => {
this.rightPageDefaultPercent = 100
})
},
closeDetail() {
if (this.isSelf) {
this.$store.dispatch('tagsView/delVisitedView', { path: this.$route.path })
return
}
this.rightPageDefaultPercent = 100
this.$refs['mainTable'].searchTableData()
},
folderChange(data, node, folder) {
this.folder = folder
this.setStoreFolder(folder)
if (Object.keys(node).length) {
this.selectFolderNode = node
this.filterByFolder()
}
},
setStoreFolder(folder) {
this.$store.dispatch('doc/setFolder', folder)
},
clearStoreFolder() {
this.$store.dispatch('doc/setFolder', {})
},
filterByFolder() {
const searchItems = this.dxDocumentService.newSearchItems()
if (this.selectFolderNode) {
searchItems.eq('dxContextId', this.selectFolderNode.level > 1 ? this.selectFolderNode.data.dxContextId : this.selectFolderNode.data.id)
if (this.selectFolderNode.level > 1) {
searchItems.eq('dxDocumentFolderId', this.selectFolderNode.data.id)
}
}
this.tabSearchCache['3'] = { customSearchItems: searchItems }
this.$refs.mainTable.reloadData(this.tabSearchCache['3'])
},
getLayout(layoutMap) {
const that = this
for (const key in layoutMap) {
this.$utils.getLayouts('DxDocument', key).then(res => {
that.configDetailsMap[layoutMap[key]] = res
if (that.configDetailsMap[layoutMap[key]]) {
that.configDetailsMap[layoutMap[key]].configDetails
}
})
}
},
tabClick(val) {
// this.pageData = {
// table: {
// load: {}
// }
// }
this.rightPageDefaultPercent = 100
this.rightPageMinPercent = 100
this.createTime = ''
this.isSearchMyDoc = val.name === '1'
if (val.name === '4') {
this.searchMode = 'findLastVisitor'
} else {
this.searchMode = 'search'
}
if (val.name === '3') {
if (Object.keys(this.folder).length) {
this.setStoreFolder(this.folder)
}
} else {
this.clearStoreFolder()
}
if (this.tabSearchCache[val.name]) {
this.$refs.mainTable.reloadData(this.tabSearchCache[val.name])
} else {
this.$refs.mainTable.clearData()
}
},
getSearchTime(data) {
this.rightPageDefaultPercent = 100
this.rightPageMinPercent = 100
// this.createTime = data
// this.pageData = {
// table: {
// load: {}
// }
// }
const searchItems = this.dxDocumentService.newSearchItems().eq('creatorId', parseInt(localStorage.getItem('userId')))
if (data) { searchItems.gt('createTime', data) }
this.tabSearchCache['1'] = { customSearchItems: searchItems }
this.$refs.mainTable.reloadData(this.tabSearchCache['1'])
},
getVisitTime(data) {
this.rightPageDefaultPercent = 100
this.rightPageMinPercent = 100
// this.createTime = data
// this.pageData = {
// table: {
// load: {}
// }
// }
const searchItems = this.dxDocumentService.newSearchItems().eq('visitedUserId', localStorage.getItem('userId'))
if (data) { searchItems.gt('modifyTime', data) }
searchItems.eq('targetIdType', 'DxDocument')
this.tabSearchCache['4'] = { customSearchItems: searchItems }
this.$refs.mainTable.reloadData(this.tabSearchCache['4'])
},
tableToolFun(Obj) {
if (Obj.btnValue === 'add') {
this.$router.push({
name: 'docAdd',
params: {
reset: true
}
})
}
},
searchEvent(data) {
console.info('搜索组件的事件值', data)
this.keyword = null
this.pageData = data.pageData
const searchItems = this.dxDocumentService.newSearchItems()
for (const key in data.pageData.table.load) {
if (!Object.hasOwnProperty.call(data.pageData.table.load, key)) {
continue
}
const v = data.pageData.table.load[key]
if (key === 'keyWord') {
this.keyword = v
continue
}
searchItems.$addItem(v.fieldName, v.value, v.operator, v.value1)
}
searchItems.$addItem('modifyTime', '2000-01-01 00:00:00', 'GT')
this.tabSearchCache['2'] = { customSearchItems: searchItems, keyword: this.keyword }
this.$refs.mainTable.reloadData(this.tabSearchCache['2'])
},
rowClick(data) {
this.rightPageDefaultPercent = 40
this.rightPageMinPercent = 28
this.pageData = {
detail: {
load: {
number: data.number,
id: data.id,
subTypeName: data.subType
}
}
}
this.key++
}
}
}
</script>
<style lang='scss'>
</style>
<template>
<div class="integratedQuery">
<div>
<dee-search-box
type-name="DxDocument"
v-bind="configDetailsMap['searchBox'].configDetails"
@searchEvent="searchEvent"
/>
</div>
<div>
<dee-search-group type-name="DxDocument" :page-data="pageData" :config="{name: 'searchGroup'}" v-bind="configDetailsMap['searchGroup'].configDetails" @groupSearchEvent="groupSearchEvent" />
</div>
</div>
</template>
<script>
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {
configDetailsMap: {
type: Object,
default: () => {
return {}
}
}
},
data() {
// 这里存放数据
return {
pageData: {},
loadPremed: false,
permissions: null
}
},
// 监听属性 类似于data概念
computed: {
typeKey() {
if (
!this.configDetailsMap ||
!this.configDetailsMap['searchBox']) {
return ''
}
return this.configDetailsMap['searchBox'].typeKey
},
layoutType() {
if (
!this.configDetailsMap ||
!this.configDetailsMap['searchBox']) {
return ''
}
return this.configDetailsMap['searchBox'].layoutType
}
},
// 监控data中的数据变化
watch: {
},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
this.searchEvent()
},
activated() {
},
// 方法集合
methods: {
searchEvent(data) {
this.pageData = {
searchGroup: {
load: data
},
table: {
load: data
}
}
this.$emit('searchEvent', { pageData: this.pageData, eventComName: 'deeSearchBox' })
},
groupSearchEvent(data) {
this.pageData = {
table: {
load: data
}
}
this.$emit('searchEvent', { pageData: this.pageData, eventComName: 'deeSearchGroup' })
}
}
}
</script>
<style lang='scss'>
</style>
<template>
<div style="height: 100%;">
<div class="my-document-box">
<div v-for="(item,i) in dateList" :key="i" :class="{'dee-active-row-background': index === i}" class="time dee-row-item" @click="timeSearch(item.value,i)">{{ item.label }}</div>
</div>
</div>
</template>
<script>
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
// 这里存放数据
return {
index: 0,
dateList: [
{
label: '全部',
value: 'all'
},
{
label: '最近一天',
value: -1
},
{
label: '最近三天',
value: -3
},
{
label: '最近七天',
value: -7
},
{
label: '最近一个月',
value: -30
}
]
}
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
this.timeSearch('all', 0)
},
activated() {
},
// 方法集合
methods: {
timeSearch(time, index) {
this.index = index
this.$emit('getVisitTime', time === 'all' ? '' : this.$utils.getComputeDay(time, ' 00:00:00'))
}
}
}
</script>
<style lang='scss'>
</style>
<template>
<div style="height: 100%;">
<div class="my-document-box">
<div v-for="(item,i) in dateList" :key="i" :class="{'dee-active-row-background': index === i}" class="time dee-row-item" @click="timeSearch(item.value,i)">{{ item.label }}</div>
</div>
</div>
</template>
<script>
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
// 这里存放数据
return {
index: 0,
dateList: [
{
label: '全部',
value: 'all'
},
{
label: '最近7天',
value: -7
},
{
label: '最近一个月',
value: -30
},
{
label: '最近二个月',
value: -60
},
{
label: '最近三个月',
value: -90
},
{
label: '最近一年',
value: -365
}
]
}
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
this.timeSearch('all', 0)
},
activated() {
},
// 方法集合
methods: {
timeSearch(time, index) {
this.index = index
this.$emit('getSearchTime', time === 'all' ? '' : this.$utils.getComputeDay(time, ' 00:00:00'))
}
}
}
</script>
<style lang='scss'>
</style>
/**
* @Description:
* @author cxg
* @date 2020/07/22
*/
<template>
<div class="add-page">
<div class="full-border-content">
<div class="task-name">编辑文档</div>
<dee-form
:app-id="configDetails.appId"
:form="addData"
:form-data="showFormData"
:rules="configDetails.rules"
:form-buttons="configDetails.formButtons"
:border="configDetails&&configDetails.base&&configDetails.base.borderShow"
:label-width="configDetails&&configDetails.base&&configDetails.base.labelWidth"
:form-btn-position="configDetails&&configDetails.base&&configDetails.base.formBtnPosition"
:label-position="configDetails&&configDetails.base&&configDetails.base.labelPosition"
@on-submit="submitFun"
@on-cancel="cancelFun"
/>
</div>
</div>
</template>
<script>
import { getLayouts } from '@/api/config'
import { addDocWithRecursion, getDetailWithRecursion } from '@/api/doc'
export default {
components: {},
data() {
return {
addData: {},
id: '',
appUrl: '',
typeName: 'DxDocument',
openProps: [],
configDetails: {
formData: []
}
}
},
computed: {
previousRouter() {
return this.$store.state.tagsView.previousRouter.slice(-1)[0]
},
showFormData() {
if (!this.configDetails || !this.configDetails.formData) {
return []
}
return this.configDetails.formData
}
},
created() {
this.id = this.$route.query && this.$route.query.id
this.subTypeName = this.$route.query && this.$route.query.subTypeName
if (!this.id || !this.subTypeName) {
return
}
this.layout = true
getLayouts(this.subTypeName, this.$enums.layout['编辑']).then((res) => {
const item = res.items.slice(-1)
if (item[0] && item[0].configDetails) {
this.configDetails = JSON.parse(item[0].configDetails)
this.appUrl = this.configDetails.tableConfig && this.configDetails.tableConfig.serverUrl
this.getBaiscData()
}
})
},
mounted() {},
methods: {
getBaiscData() {
if (this.configDetails && this.configDetails.formData) {
this.getOpenProps()
}
getDetailWithRecursion({ id: parseInt(this.id), openProps: this.openProps }).then(res => {
if (res.items && res.items.content) {
this.addData = res.items.content[0]
}
})
},
getOpenProps() {
const openProps = []
const openPropsAttr = ['VO_ONE', 'VO_MANY']
this.configDetails.formData.forEach(item => {
item.data.forEach(field => {
let str = null
if (field.fildProp && openPropsAttr.includes(field.fildProp.attrType)) {
str = field.key
} else if (field.parentKey) {
str = field.parentKey
}
if (field.component && field.component.openProps) {
str += '.' + field.component.openProps
}
if (str !== null && !openProps.includes(str)) {
openProps.push(str)
}
})
this.openProps = this.$utils.getOpenPropsByLists(openProps)
})
},
submitFun() {
const params = this.addData
params.operator = 'MODIFY'
if (params.master) {
params.master.operator = 'MODIFY'
}
addDocWithRecursion(params, this.appUrl).then(res => {
this.$utils.showMessage('编辑成功!', 'success')
this.$store.dispatch('tagsView/delVisitedView', { path: '/doc/edit' })
if (this.previousRouter && this.previousRouter.path === '/docCenter') {
this.$router.push({ name: 'docCenter', params: { infoReload: { type: 'edit' }}})
} else {
this.$router.go(-1)
}
})
},
cancelFun() {
this.$store.dispatch('tagsView/delVisitedView', { path: '/doc/edit' })
this.$router.go(-1)
// this.$router.push({ path: '/docCenter' })
}
}
}
</script>
<style lang='scss'>
</style>
const webpack = require('webpack')
const APP_NAME = require('./package.json').name
const PORT = require('./package.json').devPort
const NODE_ENV = process.env.NODE_ENV || 'development'
const path = require('path')
log('APP_NAME: ', APP_NAME)
log('NODE_ENV: ', NODE_ENV)
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: `${NODE_ENV === 'development' ? '' : '.'}/${APP_NAME}/`,
css: {
extract: false
},
productionSourceMap: false,
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
resolve: {
alias: {
'@': resolve('src')
}
}
},
chainWebpack: (config) => {
config.externals({
'vue': 'Vue'
})
config.output
.filename('main.js')
.chunkFilename('[name].[chunkhash:8].js')
.jsonpFunction(`webpackJsonp-${APP_NAME}`)
.library(`app-${APP_NAME}`)
.libraryExport('default')
.libraryTarget('umd')
config.optimization.splitChunks(false)
config.plugin('define').use(webpack.DefinePlugin, [{
'process.env.VUE_APP_NAME': JSON.stringify(APP_NAME)
}])
config.plugins
.delete('html')
.delete('preload')
.delete('prefetch')
},
devServer: {
port: PORT
}
}
function log(label, content, options) {
console.log('\x1b[1m%s\x1b[31m%s\x1b[0m', label, content)
}
......@@ -6,7 +6,7 @@ const startedWebServer = ['architecture-dee']
const fs = require('fs');
const { spawn } = require('child_process');
let runDevServers = ['architecture-dee', 'dee-dic', 'dee-file', 'dee-message', 'dee-perm', 'dee-task-center', 'dee-user']
let runDevServers = ['architecture-dee', 'dee-dic', 'dee-file', 'dee-message', 'dee-perm', 'dee-task-center', 'dee-user','dee-doc']
const startServerObj = {}
if (process.argv[2]) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment