提交 2a9c91fb 编写于 作者: ibizdev's avatar ibizdev

ibizdev提交

上级 eb80165e

要显示的变更太多。

为了保持性能,仅显示文件中的 1000/1000+

此差异已折叠。
## 前言
### 1. 简介
该web应用是基于iBiz平台提供的一套PC端前端解决方案Vue_R7【**一套基于Vue全家桶(Vue + Vue-router + Vuex)的前端框架**】生产而成,Vue_R7不仅适用于管理后台或管理系统开发,且广泛适用于B/S架构的项目开发。本文档主要介绍项目如何快速上手,成果物代码结构做一阐述,旨在能够为开发人员提供一定开发指导支持。而今框架开源,希望能有更多志同道合的伙伴参与Vue_R7的迭代 ^_^
### 2. 开发环境要求
- Node.js
- Yarn
- Vue Cli
### 3. 开发技术要求
掌握`Vue``TypeScript``less``html`等技术。
### 4. 技术栈
- 前端MVVM框架:vue.js 2.6.10
- 路由:vue-router 3.1.3
- 状态管理:vue-router 3.1.3
- 国际化:vue-i18n 8.15.3
- 数据交互:axios 0.19.1
- UI框架:element-ui 2.13.0, view-design 4.1.0
- 工具库:qs, path-to-regexp, rxjs
- 图标库:font-awesome 4.7.0
- 引入组件: tinymce 4.8.5
- 代码风格检测:eslint
## 快速上手
### 1. 开发环境
> 在安装使用 `Yarn` 和 `Vue Cli (3.0)` 前,务必确认 [Node.js](https://nodejs.org) 已经升级到 v4.8.0 或以上,强烈建议升级至最新版本。
> 如果你想了解更多 `Yarn` 工具链的功能和命令,建议访问 [Yarn](https://yarnpkg.com) 了解更多。
> 如果你想了解更多 `Vue Cli (3.0)` 工具链的功能和命令,建议访问 [Vue Cli (3.0)](https://cli.vuejs.org/) 了解更多。
- 访问 [Node.js](https://nodejs.org) ,根据文档安装 `Node.js`
- 访问 [Yarn](https://yarnpkg.com) ,根据文档安装 `Yarn`
- 访问 [Vue Cli (3.0)](https://cli.vuejs.org/) ,根据文档安装 `Vue Cli (3.0)`
<blockquote style="border-color: red;"><p>在安装 Vue Cli (3.0) ,请使用 Yarn 模式全局安装。</p></blockquote>
```bash
$ yarn global add @vue/cli
```
以下为 Windows 环境开发正常配置
<br>
<br>
![开发环境信息](./imgs/getting-started/development.png)
### 2. 安装依赖
打开前端项目,进入工作空间下,执行安装依赖命令
```bash
$ yarn install
```
### 3. 启动
在工作空间下,执行启动命令
```bash
$ yarn dev-serve
```
启动后,通过 vue.config.js 开发服务 devServer 下配置的本地启动端口号访问开发项目。<br>
示例:
```bash
$ http://localhost:8111
```
这儿需要注意一点,此时启动的项目访问的数据是我们前端的mock数据,如需与后台直接交互,请看第4点。
### 4. 远程代理
在工作空间下,执行启动命令
```bash
$ yarn serve
```
修改远程代理文件 vue.config.js 代理地址
![远程代理地址](./imgs/getting-started/proxy.png)
### 5. 打包
在工作空间下,执行打包命令
```bash
$ yarn build
```
打包完成,生成最终交付产物。
## 成果物结构
```
|─ ─ app_Web
​ |─ ─ public public文件夹
​ |─ ─ assets 静态文件夹
|─ ─ favicon.ico 图标
​ |─ ─ src 工程文件夹
|─ ─ assets 静态资源
|─ ─ components 基础组件,主要包含编辑器组件和其他全局使用的组件
|─ ─ engine 引擎文件,主要封装了内置视图的内置逻辑
|─ ─ environments 环境文件
​ |─ ─ interface 接口文件
​ |─ ─ locale 多语言文件
|─ ─ mock 模拟数据
|─ ─ pages 视图文件夹
|─ ─ module 模块名称
​ |─ ─ XXX-view 视图文件夹
|─ ─ XXX-view-base.vue 视图基类
|─ ─ XXX-view.vue 自定义视图文件
|─ ─ XXX-view.less 自定义视图样式文件
​ |─ ─ main.ts 应用主函数入口
​ |─ ─ page-register.ts 全局视图注册
​ |─ ─ router.ts 路由配置文件
|─ ─ service 应用实体数据服务文件夹
|─ ─ XXX 应用实体名称
|─ ─ XXX-service-base.ts 应用实体数据服务文件
|─ ─ XXX-service.ts 自定义应用实体数据服务文件
|─ ─ YYY-logic-base.ts 应用实体数据处理逻辑文件
|─ ─ YYY-logic.ts 自定义应用实体数据处理逻辑文件
|─ ─ store 全局状态管理
|─ ─ styles 样式文件夹
|─ ─ default.less 默认样式
|─ ─ user.less 用户自定义样式
|─ ─ theme 主题文件夹
|─ ─ uiservice 界面服务文件
|─ ─ XXX 应用实体名称
|─ ─ XXX-ui-service-base.ts 应用实体界面服务文件
|─ ─ XXX-ui-service.ts 自定义应用实体界面服务文件
|─ ─ YYY-ui-logic-base.ts 应用实体界面处理逻辑文件
|─ ─ YYY-ui-logic.ts 自定义应用实体界面处理逻辑文件
|─ ─ utils 工具类文件
|─ ─ widgets 部件文件夹
|─ ─ appde 应用实体名称
​ |─ ─ XXX 部件名称
|─ ─ XXX-base.vue 视图基类
|─ ─ XXX.vue 自定义部件文件
|─ ─ XXX.less 部件样式文件
​ |─ ─ XXX.model.ts 部件model文件
​ |─ ─ XXX.service.ts 部件服务文件
|─ ─ app-register.ts 公共组件全局注册
​ |─ ─ App.vue 入口组件
​ |─ ─ user-register.ts 自定义组件全局注册
​|─ ─ package.json 依赖管理文件
​ |─ ─ vue.config.js vue cli 配置
```
## 如何贡献
如果你希望参与贡献,欢迎 [Pull Request](<http://demo.ibizlab.cn/ibiz_r7/vue_r7/issues/new>),或通过自助服务群给我们报告 Bug。
强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)(本指南不提供此项目的实际支持服务!)[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545)[《如何有效地报告 Bug》](https://www.chiark.greenend.org.uk/~sgtatham/bugs-cn.html)[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。
## 社区互助
1.[iBizLab论坛](https://bbs.ibizlab.cn/)
2.加入钉钉 Vue_R7自助服务群(中文)
<img src="./imgs/getting-started/vue-r7-group.png" height="400" width="400">
\ No newline at end of file
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
{
"pluginsFile": "tests/e2e/plugins/index.js"
}
module.exports = {
preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel'
}
{
"name": "app",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "node --max_old_space_size=8102 ./node_modules/@vue/cli-service/bin/vue-cli-service serve --mode production",
"dev-serve": "node --max_old_space_size=8102 ./node_modules/@vue/cli-service/bin/vue-cli-service serve --mode development",
"build": "node --max_old_space_size=8102 ./node_modules/@vue/cli-service/bin/vue-cli-service build",
"dev-build": "node --max_old_space_size=8102 ./node_modules/@vue/cli-service/bin/vue-cli-service build --mode development",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.1",
"core-js": "^3.4.4",
"element-ui": "^2.13.0",
"font-awesome": "^4.7.0",
"path-to-regexp": "^6.1.0",
"qs": "^6.9.1",
"rxjs": "^6.5.4",
"tinymce": "4.8.5",
"view-design": "^4.1.0",
"vue": "^2.6.10",
"vue-class-component": "^7.0.2",
"vue-i18n": "^8.15.3",
"vue-property-decorator": "^8.3.0",
"vue-router": "^3.1.3",
"vuex": "^3.1.2"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@types/mockjs": "^1.0.2",
"@types/qs": "^6.9.0",
"@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-e2e-cypress": "^4.1.0",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-plugin-typescript": "^4.1.0",
"@vue/cli-plugin-unit-jest": "^4.1.0",
"@vue/cli-plugin-vuex": "^4.1.0",
"@vue/cli-service": "^4.1.0",
"@vue/test-utils": "1.0.0-beta.29",
"axios-mock-adapter": "^1.17.0",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"mockjs": "^1.1.0",
"typescript": "~3.5.3",
"vue-template-compiler": "^2.6.10"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>poc</artifactId>
<groupId>com.sinosig</groupId>
<version>1.0.0.0</version>
</parent>
<artifactId>poc-web</artifactId>
<name>Poc Web</name>
<description>Poc Web</description>
<dependencies>
</dependencies>
</project>
tinymce.addI18n('en_GB',{
"Cut": "Cut",
"Heading 5": "Heading 5",
"Header 2": "Header 2",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.",
"Heading 4": "Heading 4",
"Div": "Div",
"Heading 2": "Heading 2",
"Paste": "Paste",
"Close": "Close",
"Font Family": "Font Family",
"Pre": "Pre",
"Align right": "Align right",
"New document": "New document",
"Blockquote": "Blockquote",
"Numbered list": "Numbered list",
"Heading 1": "Heading 1",
"Headings": "Headings",
"Increase indent": "Increase indent",
"Formats": "Formats",
"Headers": "Headers",
"Select all": "Select all",
"Header 3": "Header 3",
"Blocks": "Blocks",
"Undo": "Undo",
"Strikethrough": "Strike-through",
"Bullet list": "Bullet list",
"Header 1": "Header 1",
"Superscript": "Superscript",
"Clear formatting": "Clear formatting",
"Font Sizes": "Font Sizes",
"Subscript": "Subscript",
"Header 6": "Header 6",
"Redo": "Redo",
"Paragraph": "Paragraph",
"Ok": "Ok",
"Bold": "Bold",
"Code": "Code",
"Italic": "Italic",
"Align center": "Align centre",
"Header 5": "Header 5",
"Heading 6": "Heading 6",
"Heading 3": "Heading 3",
"Decrease indent": "Decrease indent",
"Header 4": "Header 4",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.",
"Underline": "Underline",
"Cancel": "Cancel",
"Justify": "Justify",
"Inline": "Inline",
"Copy": "Copy",
"Align left": "Align left",
"Visual aids": "Visual aids",
"Lower Greek": "Lower Greek",
"Square": "Square",
"Default": "Default",
"Lower Alpha": "Lower Alpha",
"Circle": "Circle",
"Disc": "Disc",
"Upper Alpha": "Upper Alpha",
"Upper Roman": "Upper Roman",
"Lower Roman": "Lower Roman",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.",
"Name": "Name",
"Anchor": "Anchor",
"Id": "ID",
"You have unsaved changes are you sure you want to navigate away?": "You have unsaved changes are you sure you want to navigate away?",
"Restore last draft": "Restore last draft",
"Special character": "Special character",
"Source code": "Source code",
"Language": "Language",
"Insert\/Edit code sample": "Insert\/Edit code sample",
"B": "B",
"R": "R",
"G": "G",
"Color": "Colour",
"Right to left": "Right to left",
"Left to right": "Left to right",
"Emoticons": "Emoticons",
"Robots": "Robots",
"Document properties": "Document properties",
"Title": "Title",
"Keywords": "Keywords",
"Encoding": "Encoding",
"Description": "Description",
"Author": "Author",
"Fullscreen": "Full-screen",
"Horizontal line": "Horizontal line",
"Horizontal space": "Horizontal space",
"Insert\/edit image": "Insert\/edit image",
"General": "General",
"Advanced": "Advanced",
"Source": "Source",
"Border": "Border",
"Constrain proportions": "Constrain proportions",
"Vertical space": "Vertical space",
"Image description": "Image description",
"Style": "Style",
"Dimensions": "Dimensions",
"Insert image": "Insert image",
"Image": "Image",
"Zoom in": "Zoom in",
"Contrast": "Contrast",
"Back": "Back",
"Gamma": "Gamma",
"Flip horizontally": "Flip horizontally",
"Resize": "Resize",
"Sharpen": "Sharpen",
"Zoom out": "Zoom out",
"Image options": "Image options",
"Apply": "Apply",
"Brightness": "Brightness",
"Rotate clockwise": "Rotate clockwise",
"Rotate counterclockwise": "Rotate counterclockwise",
"Edit image": "Edit image",
"Color levels": "Colour levels",
"Crop": "Crop",
"Orientation": "Orientation",
"Flip vertically": "Flip vertically",
"Invert": "Invert",
"Date\/time": "Date\/time",
"Insert date\/time": "Insert date\/time",
"Remove link": "Remove link",
"Url": "URL",
"Text to display": "Text to display",
"Anchors": "Anchors",
"Insert link": "Insert link",
"Link": "Link",
"New window": "New window",
"None": "None",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?",
"Paste or type a link": "Paste or type a link",
"Target": "Target",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",
"Insert\/edit link": "Insert\/edit link",
"Insert\/edit video": "Insert\/edit video",
"Media": "Media",
"Alternative source": "Alternative source",
"Paste your embed code below:": "Paste your embed code below:",
"Insert video": "Insert video",
"Poster": "Poster",
"Insert\/edit media": "Insert\/edit media",
"Embed": "Embed",
"Nonbreaking space": "Non-breaking space",
"Page break": "Page break",
"Paste as text": "Paste as text",
"Preview": "Preview",
"Print": "Print",
"Save": "Save",
"Could not find the specified string.": "Could not find the specified string.",
"Replace": "Replace",
"Next": "Next",
"Whole words": "Whole words",
"Find and replace": "Find and replace",
"Replace with": "Replace with",
"Find": "Find",
"Replace all": "Replace all",
"Match case": "Match case",
"Prev": "Prev",
"Spellcheck": "Spell-check",
"Finish": "Finish",
"Ignore all": "Ignore all",
"Ignore": "Ignore",
"Add to Dictionary": "Add to Dictionary",
"Insert row before": "Insert row before",
"Rows": "Rows",
"Height": "Height",
"Paste row after": "Paste row after",
"Alignment": "Alignment",
"Border color": "Border colour",
"Column group": "Column group",
"Row": "Row",
"Insert column before": "Insert column before",
"Split cell": "Split cell",
"Cell padding": "Cell padding",
"Cell spacing": "Cell spacing",
"Row type": "Row type",
"Insert table": "Insert table",
"Body": "Body",
"Caption": "Caption",
"Footer": "Footer",
"Delete row": "Delete row",
"Paste row before": "Paste row before",
"Scope": "Scope",
"Delete table": "Delete table",
"H Align": "H Align",
"Top": "Top",
"Header cell": "Header cell",
"Column": "Column",
"Row group": "Row group",
"Cell": "Cell",
"Middle": "Middle",
"Cell type": "Cell type",
"Copy row": "Copy row",
"Row properties": "Row properties",
"Table properties": "Table properties",
"Bottom": "Bottom",
"V Align": "V Align",
"Header": "Header",
"Right": "Right",
"Insert column after": "Insert column after",
"Cols": "Cols",
"Insert row after": "Insert row after",
"Width": "Width",
"Cell properties": "Cell properties",
"Left": "Left",
"Cut row": "Cut row",
"Delete column": "Delete column",
"Center": "Centre",
"Merge cells": "Merge cells",
"Insert template": "Insert template",
"Templates": "Templates",
"Background color": "Background colour",
"Custom...": "Custom...",
"Custom color": "Custom colour",
"No color": "No colour",
"Text color": "Text colour",
"Table of Contents": "Table of Contents",
"Show blocks": "Show blocks",
"Show invisible characters": "Show invisible characters",
"Words: {0}": "Words: {0}",
"Insert": "Insert",
"File": "File",
"Edit": "Edit",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help",
"Tools": "Tools",
"View": "View",
"Table": "Table",
"Format": "Format"
});
\ No newline at end of file
此差异已折叠。
/* PrismJS 1.14.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body.mce-content-readonly *[contentEditable=true]:focus,.mce-content-body.mce-content-readonly *[contentEditable=true]:hover{outline:none}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.mce-content-body table{-webkit-nbsp-mode:normal}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2}.mce-content-body{line-height:1.3}
\ No newline at end of file
body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:1.3;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body.mce-content-readonly *[contentEditable=true]:focus,.mce-content-body.mce-content-readonly *[contentEditable=true]:hover{outline:none}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.mce-content-body table{-webkit-nbsp-mode:normal}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2}
\ No newline at end of file
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position:absolute;display:inline-block;background-color:green;opacity:.5}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}
\ No newline at end of file
<template>
<div id='app'>
<router-view/>
</div>
</template>
import { ViewTool } from './utils/view-tool/view-tool';
import { UIActionTool } from './utils/uiaction-tool/uiaction-tool';
import { Verify } from './utils/verify/verify';
import { Util } from './utils/util/util';
import { Http } from './utils/http/http';
import { AppPopover } from './utils/app-popover/app-popover';
import { AppModal } from './utils/app-modal/app-modal';
import { AppDrawer } from './utils/app-drawer/app-drawer';
import InputBox from './components/input-box/input-box.vue'
import AppKeepAlive from './components/app-keep-alive/app-keep-alive.vue'
import TabPageExp from './components/tab-page-exp/tab-page-exp.vue'
import AppLang from './components/app-lang/app-lang.vue'
import AppTheme from './components/app-theme/app-theme.vue'
import AppUser from './components/app-user/app-user.vue'
import AppForm from './components/app-form/app-form.vue'
import APPAutocomplete from './components/app-autocomplete/app-autocomplete.vue'
import AppFormDruipart from './components/app-form-druipart/app-form-druipart.vue'
import DropdownList from './components/dropdown-list/dropdown-list.vue'
import UploadFile from './components/upload-file/upload-file.vue'
import ContextMenuContainer from './components/context-menu-container/context-menu-container.vue'
import AppCheckboxList from './components/app-checkbox-list/app-checkbox-list.vue'
import AppRadioGroup from './components/app-radio-group/app-radio-group.vue'
import AppEmbedPicker from './components/app-embed-picker/app-embed-picker.vue'
import AppTreePicker from './components/app-tree-picker/app-tree-picker.vue'
import AppRichTextEditor from './components/app-rich-text-editor/app-rich-text-editor.vue'
import AppFileUpload from './components/app-file-upload/app-file-upload.vue'
import AppImageUpload from './components/app-image-upload/app-image-upload.vue'
import PropertyLayout from './components/property-layout/property-layout.vue'
import AppRangeEditor from './components/app-range-editor/app-range-editor.vue'
import AppExportExcel from './components/app-export-excel/app-export-excel.vue'
import AppFormGroup from './components/app-form-group/app-form-group.vue'
import AppFormItem from './components/app-form-item/app-form-item.vue'
import AppPicker from './components/app-picker/app-picker.vue'
import AppMpicker from './components/app-mpicker/app-mpicker.vue'
import AppFormGroup2 from './components/app-form-group2/app-form-group2.vue'
import AppFormItem2 from './components/app-form-item2/app-form-item2.vue'
import CodeList from './components/codelist/codelist.vue'
import AppQuickMenus from './components/app-quick-menus/app-quick-menus.vue'
import AppCheckbox from './components/app-checkbox/app-checkbox.vue'
import AppColumnRender from './components/app-column-render/app-column-render.vue'
import AppPickerSelectView from './components/app-picker-select-view/app-picker-select-view.vue'
import AppSiderMenus from './components/app-sider-menus/app-sider-menus.vue'
import AppSpan from './components/app-span/app-span.vue'
import AppAddressSelection from './components/app-address-selection/app-address-selection.vue'
import DropdownListMpicker from './components/dropdown-list-mpicker/dropdown-list-mpicker.vue'
import AppRate from './components/app-rate/app-rate.vue'
import appInputNumber from './components/app-input-number/app-input-number.vue'
import AppSwitch from './components/app-switch/app-switch.vue'
import AppFileUploadDrag from './components/app-file-upload-drag/app-file-upload-drag.vue'
export const AppComponents = {
install(v: any, opt: any) {
v.prototype.$appdrawer = AppDrawer.getInstance();
v.prototype.$appmodal = AppModal.getInstance();
v.prototype.$apppopover = AppPopover.getInstance();
v.prototype.$http = Http.getInstance();
v.prototype.$util = Util;
v.prototype.$verify = Verify;
v.prototype.$viewTool = ViewTool;
v.prototype.$uiActionTool = UIActionTool;
v.component('input-box', InputBox);
v.component('app-keep-alive',AppKeepAlive);
v.component('tab-page-exp',TabPageExp);
v.component('app-lang',AppLang);
v.component('app-theme',AppTheme);
v.component('app-user',AppUser);
v.component('app-form', AppForm);
v.component('app-autocomplete', APPAutocomplete);
v.component('app-form-druipart', AppFormDruipart);
v.component('dropdown-list', DropdownList);
v.component('upload-file', UploadFile);
v.component('context-menu-container', ContextMenuContainer);
v.component('app-checkbox-list',AppCheckboxList);
v.component('app-radio-group',AppRadioGroup);
v.component('app-embed-picker', AppEmbedPicker);
v.component('app-tree-picker', AppTreePicker);
v.component('app-rich-text-editor',AppRichTextEditor);
v.component('app-file-upload',AppFileUpload);
v.component('app-image-upload',AppImageUpload);
v.component('property-layout',PropertyLayout);
v.component('app-range-editor',AppRangeEditor);
v.component('app-export-excel',AppExportExcel);
v.component('app-form-group',AppFormGroup);
v.component('app-form-item',AppFormItem);
v.component('app-picker', AppPicker);
v.component('app-mpicker', AppMpicker);
v.component('app-form-group2', AppFormGroup2);
v.component('app-form-item2', AppFormItem2);
v.component('codelist', CodeList);
v.component('app-quick-menus', AppQuickMenus);
v.component('app-checkbox',AppCheckbox);
v.component('app-column-render',AppColumnRender);
v.component('app-picker-select-view',AppPickerSelectView);
v.component('app-sider-menus',AppSiderMenus);
v.component('app-span', AppSpan);
v.component('app-address-selection', AppAddressSelection);
v.component('dropdown-list-mpicker', DropdownListMpicker);
v.component('app-rate', AppRate);
v.component('app-input-number', appInputNumber);
v.component('app-switch', AppSwitch);
v.component('app-file-upload-drag', AppFileUploadDrag);
},
};
\ No newline at end of file
此差异已折叠。
/**
* 代码表--云系统操作者
*
* @export
* @class SysOperator
*/
export default class SysOperator {
/**
* 获取数据项
*
* @param {*} data
* @param {boolean} [isloading]
* @returns {Promise<any>}
* @memberof SysOperator
*/
public getItems(data: any={}, isloading?: boolean): Promise<any> {
return Promise.reject([]);
}
}
html, body {
height: 100%;
}
.app-error-view {
height: 100%;
width: 100%;
position: relative;
.app-error-container {
height: 380px;
width: 670px;
position: absolute;
top: calc((100% - 400px) / 2);
left: calc((100% - 670px) / 2);
display: flex;
align-items: center;
.error-text {
padding-left: 20px;
.error-text1 {
font-size: 20px;
margin-bottom: 20px;
}
.error-text2 {
font-size: 14px;
}
}
}
}
\ No newline at end of file
<template>
<div class="app-error-view">
<div class="app-error-container">
<img src="/assets/img/404.png" />
<div class="error-text">
<div class="error-text1">抱歉,您访问的页面不存在!</div>
<div class="error-text2">您要找的页面存在,请返回 <a on-click={this.gotoIndexView}>首页</a> 继续浏览</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component({})
export default class Error404 extends Vue {
/**
* 跳转首页
*
* @memberof Error404
*/
public gotoIndexView() {
this.$router.push('/');
}
}
</script>
<style lang='less'>
@import './404.less';
</style>
\ No newline at end of file
html, body {
height: 100%;
}
.app-error-view {
height: 100%;
width: 100%;
position: relative;
.app-error-container {
height: 380px;
width: 670px;
position: absolute;
top: calc((100% - 400px) / 2);
left: calc((100% - 670px) / 2);
display: flex;
align-items: center;
.error-text {
padding-left: 20px;
.error-text1 {
font-size: 20px;
margin-bottom: 20px;
}
.error-text2 {
font-size: 14px;
}
}
}
}
\ No newline at end of file
<template>
<div class="app-error-view">
<div class="app-error-container">
<img src="/assets/img/500.png" />
<div class="error-text">
<div class="error-text1">抱歉,服务器出错了!</div>
<div class="error-text2">服务器出错了,请返回 <a on-click={this.gotoIndexView}>首页</a> 继续浏览</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component({})
export default class Error404 extends Vue {
/**
* 跳转首页
*
* @memberof Error404
*/
public gotoIndexView() {
this.$router.push('/');
}
}
</script>
<style lang='less'>
@import './500.less';
</style>
\ No newline at end of file
<template>
<div class="appAddressSelection">
<el-cascader
:disabled="disabled"
size ="medium"
v-model="CurrentVal"
:options="city">
</el-cascader>
</div>
</template>
<script lang='ts'>
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import axios from 'axios';
@Component({})
export default class AppAddressSelection extends Vue {
/**
* 传入值
* @type {any}
* @memberof AppAddressSelection
*/
@Prop() public value?:any;
/**
* 是否禁用
* @type {boolean}
* @memberof AppAddressSelection
*/
@Prop() public disabled?: boolean;
/**
* 当前值
*
* @memberof AppAddressSelection
*/
get CurrentVal() {
return this.value;
}
/**
* 值变化
*
* @memberof AppAddressSelection
*/
set CurrentVal(val: any) {
this.$emit("change", val);
}
/**
* 城市数据
*
* @memberof AppAddressSelection
*/
public city :any = [];
/**
* 获取城市数据
*
* @memberof AppAddressSelection
*/
public getcity() {
axios.get("../../assets/json/city_code.json").then((response: any) => {
this.format(response.data);
}).catch((response: any) => {
console.log("城市数据加载失败");
});
}
/**
* 生命周期
*
* @memberof AppAddressSelection
*/
public created() {
this.getcity();
}
/**
* 数据格式化
*
* @memberof AppAddressSelection
*/
public format(data :any) {
let data1 = JSON.parse(JSON.stringify(data).replace(/city/g, 'children'))
let data2 = JSON.parse(JSON.stringify(data1).replace(/name/g, 'label'))
let data3 = JSON.parse(JSON.stringify(data2).replace(/area/g, 'children'))
let data4 = JSON.parse(JSON.stringify(data3).replace(/code/g, 'value'))
this.city = data4;
}
}
</script>
<style lang='less'>
@import './app-address-selection.less';
</style>
\ No newline at end of file
.ivu-auto-complete {
.ivu-select-dropdown-list {
height: 300px;
}
}
<template>
<el-autocomplete
class='text-value'
:value-key="deMajorField"
:disabled="disabled"
v-model="curvalue"
size='small'
:trigger-on-focus="true"
:fetch-suggestions="onSearch"
@select="onACSelect"
@input="onInput"
@blur="onBlur"
style='width:100%;'>
<template v-slot:suffix>
<i v-if="curvalue && !disabled" class='el-icon-circle-close' @click="onClear"></i>
<i class="el-icon-arrow-down"></i>
</template>
</el-autocomplete>
</template>
<script lang='ts'>
import { Component, Vue, Prop, Model, Watch } from 'vue-property-decorator';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
@Component({})
export default class AppAutocomplete extends Vue {
/**
* 表单数据
*
* @type {*}
* @memberof AppAutocomplete
*/
@Prop() public data: any;
/**
* 视图上下文
*
* @type {*}
* @memberof AppAutocomplete
*/
@Prop() public context!: any;
/**
* 视图参数
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public viewparams!: any;
/**
* AC参数
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop({default: {}}) public acParams?: any;
/**
* 表单服务
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public service?: any;
/**
* 应用实体主信息属性名称
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop({default: 'srfmajortext'}) public deMajorField!: string;
/**
* 应用实体主键属性名称
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop({default: 'srfkey'}) public deKeyField!: string;
/**
* 是否启用
*
* @type {boolean}
* @memberof AppAutocomplete
*/
@Prop() public disabled?: boolean;
/**
* 属性项名称
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop() public name!: string;
/**
* 编辑器参数
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop() public itemParam?: any;
/**
* 值项名称
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop() public valueitem?: string;
/**
* 值
*
* @type {*}
* @memberof AppPicker
*/
@Model('change') public value?: any;
/**
* 当前值
*
* @type {string}
* @memberof AppPicker
*/
public curvalue: string = '';
/**
* 远程请求url 地址
*
* @type {string}
* @memberof AppAutocomplete
*/
@Prop() public url?: string;
/**
* 数组
*
* @type {any[]}
* @memberof AppAutocomplete
*/
public items: any[] = [];
/**
* 输入状态
*
* @type {boolean}
* @memberof AppAutocomplete
*/
public inputState: boolean = false;
/**
* 值变化
*
* @param {*} newVal
* @param {*} oldVal
* @memberof AppPicker
*/
@Watch('value')
public onValueChange(newVal: any, oldVal: any) {
this.curvalue = newVal;
}
/**
* 执行搜索数据
* @param query
* @param callback
*/
public onSearch(query: any, callback: any): void {
// 处理搜索参数
query = !query ? '' : query;
if (!this.inputState && Object.is(query, this.value)) {
query = '';
}
this.inputState = false;
// 合并视图上下文参数和视图参数
let param: any = JSON.parse(JSON.stringify(this.viewparams));
let context: any = JSON.parse(JSON.stringify(this.context));
Object.assign(param, { query: query });
// 附加参数处理
if (this.itemParam.context) {
let _context = this.$util.formatData(this.data,this.itemParam.context);
Object.assign(context,_context);
}
if (this.itemParam.param) {
let _param = this.$util.formatData(this.data,this.itemParam.param);
Object.assign(param,_param);
}
if (this.itemParam.parentdata) {
let _parentdata = this.$util.formatData(this.data,this.itemParam.parentdata);
Object.assign(param,_parentdata);
}
if(!this.service){
this.$Notice.error({ title: '错误', desc: '缺少参数service' });
} else if(!this.acParams.serviceName) {
this.$Notice.error({ title: '错误', desc: '缺少参数serviceName' });
} else if(!this.acParams.interfaceName) {
this.$Notice.error({ title: '错误', desc: '缺少参数interfaceName' });
} else {
this.service.getItems(this.acParams.serviceName,this.acParams.interfaceName, context, param).then((response: any) => {
if (!response) {
this.$Notice.error({ title: '错误', desc: '请求异常' });
} else {
this.items = [...response];
}
if (callback) {
callback(this.items);
}
}).catch((error: any) => {
if (callback) {
callback([]);
}
});
}
}
/**
* 选中数据回调
* @param item
*/
public onACSelect(item: any): void {
if (this.name) {
this.$emit('formitemvaluechange', { name: this.name, value: item[this.deMajorField] });
}
if (this.valueitem) {
this.$emit('formitemvaluechange', { name: this.valueitem, value: item[this.deKeyField] });
}
}
/**
* 输入过程中
*
* @memberof AppAutocomplete
*/
public onInput($event: any) {
if (Object.is($event, this.value)) {
this.inputState = true;
}
}
/**
* 失去焦点事件
* @param e
*/
public onBlur(e: any): void {
let val: string = e.target.value;
if (!Object.is(val, this.value)) {
this.onACSelect({ [this.deMajorField]: val, [this.deKeyField]: '' });
}
this.$forceUpdate();
}
/**
* 清除
*/
public onClear($event: any): void {
if (this.name) {
this.$emit('formitemvaluechange', { name: this.name, value: '' });
}
if (this.valueitem) {
this.$emit('formitemvaluechange', { name: this.valueitem, value: '' });
}
this.$forceUpdate();
}
}
</script>
<style lang='less'>
@import './app-autocomplete.less';
</style>
\ No newline at end of file
.app-checkbox-list {
overflow: auto;
}
\ No newline at end of file
<template>
<checkbox-group class="app-checkbox-list" v-model="selectArray">
<checkbox v-for="(item,index) in items" :key="index" :label="item.value" :disabled="isDisabled || item.disabled">
<span>{{item.text}}</span>
</checkbox>
</checkbox-group >
</template>
<script lang="ts">
import { Component, Vue, Prop, Model } from 'vue-property-decorator';
import CodeListService from "@service/app/codelist-service";
@Component({})
export default class AppCheckBox extends Vue {
/**
* 代码表服务对象
*
* @type {CodeListService}
* @memberof AppCheckBox
*/
public codeListService:CodeListService = new CodeListService({ $store: this.$store });
/**
* 代码表标识
*
* @type {string}
* @memberof AppCheckBox
*/
@Prop() public tag?: string;
/**
* 代码表类型
*
* @type {string}
* @memberof AppCheckBox
*/
@Prop() public codelistType?: string;
/**
* 是否禁用
*
* @type {boolean}
* @memberof AppCheckBox
*/
@Prop() disabled?: boolean;
/**
* 获取启用禁用状态
*
* @readonly
* @memberof AppCheckBox
*/
get isDisabled() {
if (this.disabled) {
return true;
} else {
return false;
}
}
/**
* 属性名称
*
* @type {*}
* @memberof AppCheckBox
*/
@Prop() name?: any;
/**
* 模式(数字或者字符串)
*
* @type {*}
* @memberof AppCheckBox
*/
@Prop() mode: any;
/**
* 当前模式
*
* @readonly
* @memberof AppCheckBox
*/
get currentmode() {
if (this.mode) {
return this.mode;
} else {
return 'str';
}
}
/**
* 分隔符
*
* @type {*}
* @memberof AppCheckBox
*/
@Prop() separator: any;
/**
* 获取分隔符
*
* @readonly
* @memberof AppCheckBox
*/
get currentseparator() {
if (this.separator) {
return this.separator;
} else {
return ';';
}
}
/**
* 选中值
*
* @type {*}
* @memberof AppCheckBox
*/
@Model('change') selects?: any;
/**
* 选中数组
*
* @memberof AppCheckBox
*/
get selectArray() {
if (this.selects) {
if (Object.is(this.currentmode, 'num') && this.items) {
let selectsArray: Array<any> = [];
let num: number = parseInt(this.selects, 10);
this.items.forEach((item: any) => {
if ((num & item.value) == item.value) {
selectsArray.push(item.value);
}
});
return selectsArray;
} else if (Object.is(this.currentmode, 'str')) {
if (this.selects !== '') {
return this.selects.split(this.currentseparator);
}
}
} else {
return [];
}
}
/**
* 设置选中
*
* @memberof AppCheckBox
*/
set selectArray(val: any) {
let value: null | string | number = null;
if (Object.is(this.currentmode, 'num')) {
let temp: number = 0;
val.forEach((item: any) => {
temp = temp | parseInt(item, 10);
});
value = temp;
} else if (Object.is(this.currentmode, 'str')) {
let _datas: string[] = [];
this.items.forEach((item: any) => {
const index = val.findIndex((_key: any) => Object.is(item.value, _key));
if (index === -1) {
return;
}
_datas.push(item.value);
});
value = _datas.join(this.currentseparator);
}
this.$emit('change', value);
}
/**
* 代码表数组
*
* @type {any[]}
* @memberof AppCheckBox
*/
public items: any[] = [];
/**
* vue 生命周期
*
* @memberof AppCheckBox
*/
public created() {
if(this.tag){
if (Object.is(this.codelistType,"STATIC")) {
const codelist = this.$store.getters.getCodeList(this.tag);
if (codelist) {
this.items = [...JSON.parse(JSON.stringify(codelist.items))];
} else {
console.log(`----${this.tag}----代码表不存在`);
}
} else if (Object.is(this.codelistType,"DYNAMIC")) {
this.codeListService.getItems(this.tag).then((res:any) => {
this.items = res;
}).catch((error:any) => {
console.log(`----${this.tag}----代码表不存在`);
});
}
}
}
}
</script>
<style lang='less'>
@import './app-checkbox-list.less';
</style>
\ No newline at end of file
.app-checkbox-list {
overflow: auto;
}
\ No newline at end of file
<template>
<div class="checkbox">
<checkbox v-model="CurrentVal" :disabled="disabled"></checkbox>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop, Model, Emit } from "vue-property-decorator";
import { Subject } from "rxjs";
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
@Component({})
export default class AppCheckbox extends Vue {
/**
* 传入值
* @type {any}
* @memberof checkbox
*/
@Prop() public value?:any;
/**
* 是否禁用
* @type {boolean}
* @memberof checkbox
*/
@Prop() public disabled?: boolean;
/**
* 当前值
*
* @memberof checkbox
*/
get CurrentVal() {
if(this.value == 0){
return false;
}else if(this.value ==1){
return true;
}
}
/**
* 值变化
*
* @memberof checkbox
*/
set CurrentVal(val: any) {
this.$emit("change", val?1:0);
}
}
</script>
<style lang='less'>
@import "./app-checkbox.less";
</style>
\ No newline at end of file
.column-render{
.input-unit{
display: inline-block;
}
}
\ No newline at end of file
<template>
<div class="column-render">
{{textValue}}
<template v-if="Object.is(type,'input')">
<input-box :disabled="disabled" v-model="editorvalue" @change="($event)=>{onEditorValueChange($event)}"></input-box>
</template>
<template v-else-if="Object.is(type,'dropdown')">
<i-select v-model="editorvalue" :disabled="disabled" :clearable="true" placeholder='请选择...' >
<i-option v-for="(item, index) in codelist" :key="index" :value="item.value">{{item.text}}</i-option>
</i-select>
</template>
<template v-else>
<span>{{type}}不支持</span>
</template>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop, Model, Emit, Watch } from "vue-property-decorator";
import { Subject } from "rxjs";
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
@Component({})
export default class AppColumnRender extends Vue {
/**
* 值
* @type {any}
* @memberof AppColumnRender
*/
@Prop() public value?: any;
/**
* 是否禁用
* @type {boolean}
* @memberof AppColumnRender
*/
@Prop() public disabled?: boolean;
/**
* 列字段名称
*
* @type {string}
* @memberof AppColumnRender
*/
@Prop() public name?: string;
/**
* 表格行数据
*
* @type {string}
* @memberof AppColumnRender
*/
@Prop() public row?: any;
/**
* 自定义样式
*
* @type {string}
* @memberof AppColumnRender
*/
@Prop() public customStyle?: string;
/**
* 文本信息
* @type {String}
* @memberof AppColumnRender
*/
public textValue: string = "";
/**
* 编辑器类型
* @type {String}
* @memberof AppColumnRender
*/
public type: string = "";
/**
* 值项名称
*
* @type {string}
* @memberof AppColumnRender
*/
public valueitem: string = "";
/**
* 编辑器值
* @type {any}
* @memberof AppColumnRender
*/
public editorvalue: any = "";
/**
* 代码表选项数组
* @memberof AppColumnRender
*/
public codelist: any = [];
public created(){
this.onValueChange(this.value,"");
}
/**
* 自定义列值监控
*
* @param {*} newVal
* @param {*} oldVal
* @memberof AppColumnRender
*/
@Watch('value')
onValueChange(newVal: any, oldVal: any) {
if (newVal) {
let arrs = newVal.split("%");
this.textValue = arrs[0];
let params = [];
if(arrs[1]){
(arrs[1].split(";")).forEach((item:any)=>{
let temp = item.split("=");
if(Object.is(temp[0], "type")){
this.type = temp[1];
} else if(Object.is(temp[0], "value")) {
this.valueitem = temp[1];
if(this.valueitem && this.row[this.valueitem]){
this.editorvalue = this.row[this.valueitem];
}
} else if(Object.is(temp[0], "codelist")) {
this.codelist = temp[1];
}
});
}
}
}
/**
* 编辑器值变化回调
* @param item
*/
public onEditorValueChange(item: any): void {
if (this.name) {
// this.$emit('griditemvaluechange', { name: this.name, value: item });
}
if (this.valueitem) {
this.$emit('griditemvaluechange', { name: this.valueitem, value: item });
}
}
}
</script>
<style lang='less'>
@import "./app-column-render.less";
</style>
\ No newline at end of file
.app-embed-picker {
.app-embed-value, .app-embed-placeholder {
line-height: 32px;
height: 32px;
}
.app-embed-placeholder {
color: #c1c1c1;
}
> .ivu-card {
> .ivu-card-body {
> .content-container {
margin: 0;
}
}
}
}
\ No newline at end of file
<template>
<div v-if="refviewname" class="app-embed-picker">
<div :style="{ height: placeholder ? 'calc(100% - 32px)' : '100%' }">
<component
:is="refviewname"
:viewdata="viewdata"
:viewparam="viewparam"
:viewDefaultUsage="false"
@viewdataschange="setValue(args)"
style="height:100%;">
</component>
</div>
<template v-if="placeholder">
<div v-if="value" class="app-embed-value">{this.value}</div>
<div v-else class="app-embed-placeholder">{this.placeholder}</div>
</template>
</div>
<div v-else>{{emptyText}}</div>
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import { CreateElement } from 'vue';
import { Subject, Subscription } from 'rxjs';
@Component({})
export default class AppEmbedPicker extends Vue {
/**
* 视图上下文
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public context!: any;
/**
* 视图参数
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public viewparams!: any;
/**
* 视图参数
*
* @type {string}
* @memberof AppTreePicker
*/
public viewparam: any = JSON.stringify(this.viewparams);;
/**
* 视图参数
*
* @type {string}
* @memberof AppTreePicker
*/
public viewdata: any = JSON.stringify(this.context);
/**
* 表单数据
*
* @type {*}
* @memberof AppPicker
*/
@Prop() public data!: any;
/**
* 值
*
* @type {*}
* @memberof AppEmbedPicker
*/
@Prop() public value: any;
/**
* 表单状态
*
* @type {Subject<any>}
* @memberof AppEmbedPicker
*/
@Prop() public formState!: Subject<any>
/**
* 视图状态事件
*
* @protected
* @type {(Subscription | undefined)}
* @memberof SelectType
*/
protected formStateEvent: Subscription | undefined;
/**
* 值项名称
*
* @type {string}
* @memberof AppPicker
*/
@Prop() public valueItem?: string;
/**
* 关联视图名称
*
* @type {string}
* @memberof AppPicker
*/
@Prop() public refviewname?: string;
/**
* 提示信息
*
* @type {string}
* @memberof AppEmbedPicker
*/
@Prop() public placeholder!: string;
/**
* 空值文本
*
* @type {string}
* @memberof EmbedPicker
*/
@Prop() public emptyText?: string;
/**
* 属性项名称
*
* @type {string}
* @memberof AppPicker
*/
@Prop() public name!: string;
/**
* 关联视图参数
*
* @type {*}
* @memberof AppEmbedPicker
*/
@Prop() public itemParam: any;
/**
* 是否忽略之变化
*
* @type {boolean}
* @memberof AppEmbedPicker
*/
@Prop() public ignorefieldvaluechange!: boolean;
/**
* 重置项
*
* @type {string}
* @memberof AppEmbedPicker
*/
@Prop() public refreshitems?: string;
/**
* 设置视图参数
*
* @memberof AppEmbedPicker
*/
public setViewParam(activeData: any) {
if (!this.itemParam || !activeData) {
return;
}
let arg: any = {};
// 合并视图上下文参数和视图参数
let param: any = JSON.parse(JSON.stringify(this.viewparams));
let context: any = JSON.parse(JSON.stringify(this.context));
// 附加参数处理
if (this.itemParam.context) {
let _context = this.$util.formatData(activeData,this.itemParam.context);
Object.assign(context,_context);
}
if (this.itemParam.param) {
let _param = this.$util.formatData(activeData,this.itemParam.param);
Object.assign(param,_param);
}
if (this.itemParam.parentdata) {
let _parentdata = this.$util.formatData(activeData,this.itemParam.parentdata);
Object.assign(param,_parentdata);
}
this.viewdata = JSON.stringify(context);
this.viewparam = JSON.stringify(param);
}
/**
* 监控值
*
* @param {*} newVal
* @param {*} oldVal
* @memberof AppFormDRUIPart
*/
@Watch('data')
onActivedataChange(newVal: any, oldVal: any) {
const newFormData: any = JSON.parse(newVal);
const oldDormData: any = JSON.parse(oldVal);
this.setViewParam(newFormData);
if (!this.refreshitems || this.ignorefieldvaluechange) {
return;
}
if(Object.is(newFormData[this.refreshitems], oldDormData[this.refreshitems])) {
return;
}
this.setValue([{srfmajortext: null, srfkey: null}]);
}
/**
* 生命周期
*
* @memberof AppEmbedPicker
*/
public created() {
if(this.formState) {
this.formStateEvent = this.formState.subscribe(({ tag, action, data }) => {
if (Object.is('load', action)) {
this.setViewParam(JSON.parse(this.data));
}
});
}
}
/**
* vue 生命周期
*
* @memberof SelectType
*/
public destroyed() {
if (this.formStateEvent) {
this.formStateEvent.unsubscribe();
}
}
/**
* 设置值
*
* @param {*} item
* @memberof AppEmbedPicker
*/
public setValue(item: any) {
if (this.valueItem) {
this.$emit('formitemvaluechange', { name: this.valueItem, value: item[0].srfkey });
}
if (this.name) {
this.$emit('formitemvaluechange', { name: this.name, value: item[0].srfmajortext });
}
}
}
</script>
<style lang='less'>
@import './app-embed-picker.less';
</style>
\ No newline at end of file
<template>
<dropdown v-if="itemLevel === 0" :transfer="true" trigger='click'>
<i-button :disabled="item.disabled">
<i class='fa fa-file-excel-o'></i>
<span class='caption'>{{item.caption}}</span>
</i-button>
<dropdown-menu slot='list'>
<dropdown-item>
<p @click="exportExcel($event, 'maxRowCount')">
{{item.caption}}全部(最大{{item.caption}}{{item.MaxRowCount}}行)
</p>
</dropdown-item>
<dropdown-item>
<p @click="exportExcel($event, 'activatedPage')">
{{this.item.caption}}当前页
</p>
</dropdown-item>
</dropdown-menu>
</dropdown>
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
/**
* 数据导出组件
*
* @export
* @class AppExportExcel
* @extends {Vue}
*/
@Component({})
export default class AppExportExcel extends Vue {
/**
* 工具栏项
*
* @type {*}
* @memberof AppExportExcel
*/
@Prop() public item?: any;
/**
* 工具栏项层级
*
* @type {number}
* @memberof AppExportExcel
*/
@Prop({ default: 0 }) public itemLevel!: number;
/**
* 起始页
*
* @type {(string | null)}
* @memberof AppExportExcel
*/
public startPage: string | null = null;
/**
* 结束页
*
* @type {(string | null)}
* @memberof AppExportExcel
*/
public endPage: string | null = null;
/**
* 是否显示下拉菜单
*
* @type {boolean}
* @memberof AppExportExcel
*/
public visible: boolean = false;
/**
* 点击触发相似
*
* @memberof AppExportExcel
*/
public clickVisible(): void {
this.visible = !this.visible
}
/**
* 导出数据
*
* @param {*} $event
* @param {string} type
* @returns {void}
* @memberof AppExportExcel
*/
public exportExcel($event: any, type: string): void {
const exportparms: any = { type: type };
if (Object.is(type, 'maxRowCount')) {
Object.assign(exportparms, { maxRowCount: this.item.MaxRowCount })
this.visible = false;
} else if (Object.is(type, 'activatedPage')) {
this.visible = false;
} else if (Object.is(type, 'custom')) {
if (!this.startPage || !this.endPage) {
this.$Notice.warning({ title: '警告', desc: '请输入起始页' });
return;
}
const startPage: any = Number.parseInt(this.startPage, 10);
const endPage: any = Number.parseInt(this.endPage, 10);
if (Number.isNaN(startPage) || Number.isNaN(endPage)) {
this.$Notice.warning({ title: '警告', desc: '请输入有效的起始页' });
return;
}
if (startPage < 1 || endPage < 1 || startPage > endPage) {
this.$Notice.warning({ title: '警告', desc: '请输入有效的起始页' });
return;
}
this.startPage = null;
this.endPage = null;
Object.assign(exportparms, { startPage: startPage, endPage: endPage });
this.visible = false;
}
if (!this.visible) {
Object.assign($event, { exportparms: exportparms });
this.$emit('exportexcel', $event);
}
}
}
</script>
<style lang='less'>
@import './app-export-excel.less';
</style>
\ No newline at end of file
<template>
<el-upload
class="upload-demo"
:disabled="disabled"
:file-list="files"
:action="uploadUrl"
:headers="{}"
:before-upload="beforeUpload"
:before-remove="onRemove"
:on-success="onSuccess"
:on-error="onError"
:on-preview="onDownload"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import { Environment } from '@/environments/environment';
import { CreateElement } from 'vue';
import { Subject, Unsubscribable } from 'rxjs';
@Component({})
export default class AppFileUploadDrag extends Vue {
/**
* 表单状态
*
* @type {Subject<any>}
* @memberof AppFileUploadDrag
*/
@Prop() public formState?: Subject<any>
/**
* 是否忽略表单项书香值变化
*
* @type {boolean}
* @memberof AppFileUploadDrag
*/
@Prop() public ignorefieldvaluechange?: boolean;
/**
* 表单状态事件
*
* @private
* @type {(Unsubscribable | undefined)}
* @memberof AppFileUploadDrag
*/
private formStateEvent: Unsubscribable | undefined;
/**
* 表单数据
*
* @type {string}
* @memberof AppFileUploadDrag
*/
@Prop() public data!: string;
/**
* 初始化值
*
* @type {*}
* @memberof AppFileUploadDrag
*/
@Prop() public value?: any;
/**
* 数据值变化
*
* @param {*} newval
* @param {*} val
* @memberof AppFileUploadDrag
*/
@Watch('value')
onValueChange(newval: any, val: any) {
if (this.ignorefieldvaluechange) {
return;
}
if (newval) {
this.files = JSON.parse(newval);
this.dataProcess();
} else {
this.files = [];
}
}
/**
* 所属表单项名称
*
* @type {string}
* @memberof AppFileUploadDrag
*/
@Prop() public name!: string;
/**
* 是否禁用
*
* @type {boolean}
* @memberof AppFileUploadDrag
*/
@Prop() public disabled?: boolean;
/**
* 上传参数
*
* @type {string}
* @memberof AppFileUploadDrag
*/
@Prop() public uploadparams?: string;
/**
* 下载参数
*
* @type {string}
* @memberof AppFileUploadDrag
*/
@Prop() public exportparams?: string;
/**
* 自定义参数
*
* @type {*}
* @memberof AppFileUploadDrag
*/
@Prop() public customparams?: any;
/**
* 上传文件路径
*
* @memberof AppFileUploadDrag
*/
public uploadUrl = Environment.BaseUrl + Environment.UploadFile;
/**
* 下载文件路径
*
* @memberof AppFileUploadDrag
*/
public downloadUrl = Environment.BaseUrl + Environment.ExportFile;
/**
* 文件列表
*
* @memberof AppFileUploadDrag
*/
public files = [];
/**
* 上传keys
*
* @type {Array<any>}
* @memberof AppFileUploadDrag
*/
public upload_keys: Array<any> = [];
/**
* 导出keys
*
* @type {Array<any>}
* @memberof AppFileUploadDrag
*/
public export_keys: Array<any> = [];
/**
* 自定义数组
*
* @type {Array<any>}
* @memberof AppFileUploadDrag
*/
public custom_arr: Array<any> = [];
/**
* 应用参数
*
* @type {*}
* @memberof AppFileUploadDrag
*/
public appData: any;
/**
* 数据处理
*
* @private
* @memberof AppFileUploadDrag
*/
private dataProcess(): void {
let upload_arr: Array<string> = [];
let export_arr: Array<string> = [];
const _data: any = JSON.parse(this.data);
this.upload_keys.forEach((key: string) => {
upload_arr.push(`${key}=${_data[key]}`);
});
this.export_keys.forEach((key: string) => {
export_arr.push(`${key}=${_data[key]}`);
});
let _url = `${Environment.BaseUrl}${Environment.UploadFile}`;
if (upload_arr.length > 0 || this.custom_arr.length > 0) {
_url = `${_url}?${upload_arr.join('&')}${upload_arr.length > 0 ? '&' : ''}${this.custom_arr.join('&')}`;
}
this.uploadUrl = _url;
this.files.forEach((file: any) => {
let url = `${this.downloadUrl}/${file.id}`;
if (upload_arr.length > 0 || this.custom_arr.length > 0) {
url = `${url}?${upload_arr.join('&')}${upload_arr.length > 0 ? '&' : ''}${this.custom_arr.join('&')}`;
}
file.url = url;
});
}
/**
* vue 生命周期
*
* @memberof AppFileUploadDrag
*/
public created() {
if (this.formState) {
this.formStateEvent = this.formState.subscribe(($event: any) => {
// 表单加载完成
if (Object.is($event.type, 'load')) {
if (this.value) {
this.files = JSON.parse(this.value);
}
this.dataProcess();
}
});
}
}
/**
* vue 生命周期
*
* @returns
* @memberof AppFileUploadDrag
*/
public mounted() {
this.appData = this.$store.getters.getAppData();
let uploadparams: string = '';
let exportparams: string = '';
if (this.uploadparams && !Object.is(this.uploadparams, '')) {
uploadparams = this.uploadparams;
}
if (this.exportparams && !Object.is(this.exportparams, '')) {
exportparams = this.exportparams;
}
let upload_keys: Array<string> = uploadparams.split(';');
let export_keys: Array<string> = exportparams.split(';');
let custom_arr: Array<string> = [];
if (this.customparams && !Object.is(this.customparams, '')) {
Object.keys(this.customparams).forEach((name: string) => {
custom_arr.push(`${name}=${this.customparams[name]}`);
});
}
this.upload_keys = upload_keys;
this.export_keys = export_keys;
this.custom_arr = custom_arr;
if (this.value) {
this.files = JSON.parse(this.value);
}
this.dataProcess();
}
/**
* 组件销毁
*
* @memberof AppFileUploadDrag
*/
public destroyed(): void {
if (this.formStateEvent) {
this.formStateEvent.unsubscribe();
}
}
/**
* 上传之前
*
* @param {*} file
* @memberof AppFileUploadDrag
*/
public beforeUpload(file: any) {
// console.log('上传之前');
}
/**
* 上传成功回调
*
* @param {*} response
* @param {*} file
* @param {*} fileList
* @memberof AppFileUploadDrag
*/
public onSuccess(response: any, file: any, fileList: any) {
if (!response) {
return;
}
const data = { name: response.name, id: response.id };
let arr: Array<any> = [];
this.files.forEach((_file:any) => {
arr.push({name: _file.name, id: _file.id})
});
arr.push(data);
let value: any = arr.length > 0 ? JSON.stringify(arr) : null;
this.$emit('formitemvaluechange', { name: this.name, value: value });
}
/**
* 上传失败回调
*
* @param {*} error
* @param {*} file
* @param {*} fileList
* @memberof AppFileUploadDrag
*/
public onError(error: any, file: any, fileList: any) {
this.$Notice.error({ title: '上传失败' });
}
/**
* 删除文件
*
* @param {*} file
* @param {*} fileList
* @memberof AppFileUploadDrag
*/
public onRemove(file: any, fileList: any) {
let arr: Array<any> = [];
fileList.forEach((f: any) => {
if (f.id != file.id) {
arr.push({ name: f.name, id: f.id });
}
});
let value: any = arr.length > 0 ? JSON.stringify(arr) : null;
this.$emit('formitemvaluechange', { name: this.name, value: value });
}
/**
* 下载文件
*
* @param {*} file
* @memberof AppFileUploadDrag
*/
public onDownload(file: any) {
window.open(file.url);
}
}
</script>
<style lang='less'>
@import './app-file-upload-drag.less';
</style>
\ No newline at end of file
<template>
<el-upload
:disabled="disabled"
:file-list="files"
:action="uploadUrl"
:headers="{}"
:before-upload="beforeUpload"
:before-remove="onRemove"
:on-success="onSuccess"
:on-error="onError"
:on-preview="onDownload">
<el-button size='small' icon='el-icon-upload' :disabled="disabled">{{this.$t('app.fileUpload.caption')}}</el-button>
</el-upload>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import { Environment } from '@/environments/environment';
import { CreateElement } from 'vue';
import { Subject, Unsubscribable } from 'rxjs';
@Component({})
export default class AppFileUpload extends Vue {
/**
* 表单状态
*
* @type {Subject<any>}
* @memberof AppFileUpload
*/
@Prop() public formState?: Subject<any>
/**
* 是否忽略表单项书香值变化
*
* @type {boolean}
* @memberof AppFileUpload
*/
@Prop() public ignorefieldvaluechange?: boolean;
/**
* 表单状态事件
*
* @private
* @type {(Unsubscribable | undefined)}
* @memberof AppFileUpload
*/
private formStateEvent: Unsubscribable | undefined;
/**
* 表单数据
*
* @type {string}
* @memberof AppFileUpload
*/
@Prop() public data!: string;
/**
* 初始化值
*
* @type {*}
* @memberof AppFileUpload
*/
@Prop() public value?: any;
/**
* 数据值变化
*
* @param {*} newval
* @param {*} val
* @memberof AppFileUpload
*/
@Watch('value')
onValueChange(newval: any, val: any) {
if (this.ignorefieldvaluechange) {
return;
}
if (newval) {
this.files = JSON.parse(newval);
this.dataProcess();
} else {
this.files = [];
}
}
/**
* 所属表单项名称
*
* @type {string}
* @memberof AppFileUpload
*/
@Prop() public name!: string;
/**
* 是否禁用
*
* @type {boolean}
* @memberof AppFileUpload
*/
@Prop() public disabled?: boolean;
/**
* 上传参数
*
* @type {string}
* @memberof AppFileUpload
*/
@Prop() public uploadparams?: string;
/**
* 下载参数
*
* @type {string}
* @memberof AppFileUpload
*/
@Prop() public exportparams?: string;
/**
* 自定义参数
*
* @type {*}
* @memberof AppFileUpload
*/
@Prop() public customparams?: any;
/**
* 上传文件路径
*
* @memberof AppFileUpload
*/
public uploadUrl = Environment.BaseUrl + Environment.UploadFile;
/**
* 下载文件路径
*
* @memberof AppFileUpload
*/
public downloadUrl = Environment.BaseUrl + Environment.ExportFile;
/**
* 文件列表
*
* @memberof AppFileUpload
*/
public files = [];
/**
* 上传keys
*
* @type {Array<any>}
* @memberof AppFileUpload
*/
public upload_keys: Array<any> = [];
/**
* 导出keys
*
* @type {Array<any>}
* @memberof AppFileUpload
*/
public export_keys: Array<any> = [];
/**
* 自定义数组
*
* @type {Array<any>}
* @memberof AppFileUpload
*/
public custom_arr: Array<any> = [];
/**
* 应用参数
*
* @type {*}
* @memberof AppImageUpload
*/
public appData: any;
/**
* 数据处理
*
* @private
* @memberof AppFileUpload
*/
private dataProcess(): void {
let upload_arr: Array<string> = [];
let export_arr: Array<string> = [];
const _data: any = JSON.parse(this.data);
this.upload_keys.forEach((key: string) => {
upload_arr.push(`${key}=${_data[key]}`);
});
this.export_keys.forEach((key: string) => {
export_arr.push(`${key}=${_data[key]}`);
});
let _url = `${Environment.BaseUrl}${Environment.UploadFile}`;
if (upload_arr.length > 0 || this.custom_arr.length > 0) {
_url = `${_url}?${upload_arr.join('&')}${upload_arr.length > 0 ? '&' : ''}${this.custom_arr.join('&')}`;
}
this.uploadUrl = _url;
this.files.forEach((file: any) => {
let url = `${this.downloadUrl}/${file.id}`;
if (upload_arr.length > 0 || this.custom_arr.length > 0) {
url = `${url}?${upload_arr.join('&')}${upload_arr.length > 0 ? '&' : ''}${this.custom_arr.join('&')}`;
}
file.url = url;
});
}
/**
* vue 生命周期
*
* @memberof AppFileUpload
*/
public created() {
if (this.formState) {
this.formStateEvent = this.formState.subscribe(($event: any) => {
// 表单加载完成
if (Object.is($event.type, 'load')) {
if (this.value) {
this.files = JSON.parse(this.value);
}
this.dataProcess();
}
});
}
}
/**
* vue 生命周期
*
* @returns
* @memberof AppFileUpload
*/
public mounted() {
this.appData = this.$store.getters.getAppData();
let uploadparams: string = '';
let exportparams: string = '';
if (this.uploadparams && !Object.is(this.uploadparams, '')) {
uploadparams = this.uploadparams;
}
if (this.exportparams && !Object.is(this.exportparams, '')) {
exportparams = this.exportparams;
}
let upload_keys: Array<string> = uploadparams.split(';');
let export_keys: Array<string> = exportparams.split(';');
let custom_arr: Array<string> = [];
if (this.customparams && !Object.is(this.customparams, '')) {
Object.keys(this.customparams).forEach((name: string) => {
custom_arr.push(`${name}=${this.customparams[name]}`);
});
}
this.upload_keys = upload_keys;
this.export_keys = export_keys;
this.custom_arr = custom_arr;
if (this.value) {
this.files = JSON.parse(this.value);
}
this.dataProcess();
}
/**
* 组件销毁
*
* @memberof AppFileUpload
*/
public destroyed(): void {
if (this.formStateEvent) {
this.formStateEvent.unsubscribe();
}
}
/**
* 上传之前
*
* @param {*} file
* @memberof AppFileUpload
*/
public beforeUpload(file: any) {
// console.log('上传之前');
}
/**
* 上传成功回调
*
* @param {*} response
* @param {*} file
* @param {*} fileList
* @memberof AppFileUpload
*/
public onSuccess(response: any, file: any, fileList: any) {
if (!response) {
return;
}
const data = { name: response.name, id: response.id };
let arr: Array<any> = [];
this.files.forEach((_file:any) => {
arr.push({name: _file.name, id: _file.id})
});
arr.push(data);
let value: any = arr.length > 0 ? JSON.stringify(arr) : null;
this.$emit('formitemvaluechange', { name: this.name, value: value });
}
/**
* 上传失败回调
*
* @param {*} error
* @param {*} file
* @param {*} fileList
* @memberof AppFileUpload
*/
public onError(error: any, file: any, fileList: any) {
this.$Notice.error({ title: '上传失败' });
}
/**
* 删除文件
*
* @param {*} file
* @param {*} fileList
* @memberof AppFileUpload
*/
public onRemove(file: any, fileList: any) {
let arr: Array<any> = [];
fileList.forEach((f: any) => {
if (f.id != file.id) {
arr.push({ name: f.name, id: f.id });
}
});
let value: any = arr.length > 0 ? JSON.stringify(arr) : null;
this.$emit('formitemvaluechange', { name: this.name, value: value });
}
/**
* 下载文件
*
* @param {*} file
* @memberof AppFileUpload
*/
public onDownload(file: any) {
window.open(file.url);
}
}
</script>
<style lang='less'>
@import './app-file-upload.less';
</style>
\ No newline at end of file
.form-druipart {
position: relative;
}
\ No newline at end of file
<template>
<div class='form-druipart'>
<component
:is="viewname"
class="viewcontainer2"
:viewdata ="JSON.stringify(this.viewdata)"
:viewDefaultUsage="false"
:formDruipart="formDruipart"
@mditemsload="mditemsload"
@drdatasaved="drdatasaved"
@drdatachange="drdatachange"
@viewdataschange="viewdataschange"
@viewload="viewload">
</component>
<spin v-if="blockUI" class='app-druipart-spin' fix >{{ blockUITipInfo }}</spin>
</div>
</template>
<script lang = 'ts'>
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import { Subject, Unsubscribable } from 'rxjs';
@Component({})
export default class AppFormDRUIPart extends Vue {
/**
* 表单数据
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop() public data!: string;
/**
* 关联视图
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop() public viewname?: string;
/**
* 刷新关系项
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop({ default: '' }) public refreshitems!: string;
/**
* 关系视图类型
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop() public refviewtype?: string;
/**
* 父数据
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public parentdata!: any;
/**
* 传入参数项名称
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop() public paramItem!: string;
/**
* 是否忽略表单项值变化
*
* @type {boolean}
* @memberof AppFormDRUIPart
*/
@Prop() public ignorefieldvaluechange!: boolean;
/**
* 表单状态
*
* @type {Subject<any>}
* @memberof AppFormDRUIPart
*/
@Prop() public formState!: Subject<any>;
/**
* 视图参数
*
* @type {any[]}
* @memberof AppFormDRUIPart
*/
@Prop() public parameters!: any[];
/**
* 视图参数
*
* @type {*}
* @memberof AppFormDRUIPart
*/
@Prop() public viewParam!: any;
/**
* 应用实体参数名称
*
* @type {string}
* @memberof AppFormDRUIPart
*/
@Prop() public parameterName!: string;
/**
* 关系界面向视图下发指令对象
*
* @private
* @type {Subject<any>}
* @memberof AppFormDRUIPart
*/
private formDruipart: Subject<any> = new Subject<any>();
/**
* 表单状态事件
*
* @private
* @type {(Unsubscribable | undefined)}
* @memberof AppFormDRUIPart
*/
private formStateEvent: Unsubscribable | undefined;
/**
* 监控值
*
* @param {*} newVal
* @param {*} oldVal
* @memberof AppFormDRUIPart
*/
@Watch('data')
onActivedataChange(newVal: any, oldVal: any) {
if (this.ignorefieldvaluechange) {
return;
}
if (Object.is(newVal, oldVal)) {
return;
}
const newFormData: any = JSON.parse(newVal);
const oldDormData: any = JSON.parse(oldVal);
let refreshRefview = false;
this.hookItems.some((_hookItem: any) => {
if (!Object.is(newFormData[_hookItem], oldDormData[_hookItem])) {
refreshRefview = true;
return refreshRefview;
}
return refreshRefview;
});
if (refreshRefview) {
this.refreshDRUIPart();
}
}
/**
* 是否启用遮罩
*
* @type {boolean}
* @memberof AppFormDRUIPart
*/
public blockUI: boolean = false;
/**
* 遮罩提示信息
*
* @type {string}
* @memberof AppFormDRUIPart
*/
public blockUITipInfo: string = '请先保存主数据';
/**
* 是否刷新关系数据
*
* @private
* @type {boolean}
* @memberof AppFormDRUIPart
*/
private isRelationalData: boolean = true;
/**
* 刷新节点
*
* @private
* @type {string[]}
* @memberof AppFormDRUIPart
*/
private hookItems: string[] = [];
/**
* 父数据
*
* @type {*}
* @memberof AppFormDRUIPart
*/
public viewdata: any = {};
/**
* 刷新关系页面
*
* @private
* @returns {void}
* @memberof AppFormDRUIPart
*/
private refreshDRUIPart(data?:any): void {
if (Object.is(this.parentdata.SRFPARENTTYPE, 'CUSTOM')) {
this.isRelationalData = false;
}
const formData: any = data?data:JSON.parse(this.data);
const _paramitem = formData[this.paramItem];
this.viewdata = {};
Object.assign(this.viewdata, this.parentdata);
Object.assign(this.viewdata, this.$viewTool.getIndexViewParam());
const _parameters: any[] = [...this.$viewTool.getIndexParameters(), ...this.parameters];
_parameters.forEach((parameter: any) => {
const { pathName, parameterName }: { pathName: string, parameterName: string } = parameter;
if (this.viewParam[parameterName] && !Object.is(this.viewParam[parameterName], '')) {
Object.assign(this.viewdata, { [parameterName]: this.viewParam[parameterName] });
}
});
Object.assign(this.viewdata, { [this.paramItem]: _paramitem });
//设置顶层视图唯一标识
Object.assign(this.viewdata,{srfsessionid:this.viewParam.srfsessionid});
if (this.isRelationalData) {
if (!_paramitem || _paramitem == null || Object.is(_paramitem, '')) {
this.blockUIStart();
return;
} else {
this.blockUIStop();
}
}
this.formDruipart.next({action:'load',data:[]});
// this.$forceUpdate();
}
/**
* vue 生命周期
*
* @memberof AppFormDRUIPart
*/
public created(): void {
this.hookItems = [...this.refreshitems.split(';')];
if (!this.formState) {
return;
}
if (!Object.is(this.paramItem, this.parameterName)) {
this.hookItems.push(this.paramItem);
}
this.formStateEvent = this.formState.subscribe(($event: any) => {
// 表单加载完成
if (Object.is($event.type, 'load')) {
this.refreshDRUIPart($event.data);
}
// 表单保存之前
if (Object.is($event.type, 'beforesave')) {
if(Object.is(this.refviewtype,'DEMEDITVIEW9') || Object.is(this.refviewtype,'DEGRIDVIEW9')){
this.formDruipart.next({action:'save',data:$event.data});
} else {
// 不需要保存的界面也要抛出事件,供计数器计算
this.$emit('drdatasaved',$event);
}
}
// 表单保存完成
if (Object.is($event.type, 'save')) {
this.refreshDRUIPart($event.data);
}
// 表单项更新
if (Object.is($event.type, 'updateformitem')) {
if (!$event.data) {
return;
}
let refreshRefview = false;
Object.keys($event.data).some((name: string) => {
const index = this.hookItems.findIndex((_name: string) => Object.is(_name, name));
refreshRefview = index !== -1 ? true : false;
return refreshRefview;
});
if (refreshRefview) {
this.refreshDRUIPart();
}
}
});
this.refreshDRUIPart();
}
/**
* 部件销毁
*
* @memberof AppFormDRUIPart
*/
public destroyed(): void {
if (this.formStateEvent) {
this.formStateEvent.unsubscribe();
}
}
/**
* 开启遮罩
*
* @private
* @memberof AppFormDRUIPart
*/
private blockUIStart(): void {
this.blockUI = true;
}
/**
* 关闭遮罩
*
* @private
* @memberof AppFormDRUIPart
*/
private blockUIStop(): void {
this.blockUI = false;
}
/**
* 多数据视图加载完成
*
* @public
* @memberof AppFormDRUIPart
*/
public mditemsload(){
console.log('多数据视图加载完成,触发后续表单项更新');
}
/**
* DEMEDITVIEW9 关系数据保存完成
*
* @public
* @memberof AppFormDRUIPart
*/
public drdatasaved($event:any){
this.$emit('drdatasaved',$event);
console.log(this.viewname+'关系数据保存完成');
}
/**
* DEMEDITVIEW9 关系数据值变化
*
* @public
* @memberof AppFormDRUIPart
*/
public drdatachange(){
console.log('DEMEDITVIEW9 关系数据值变化');
}
/**
* 视图数据变化
*
* @public
* @memberof AppFormDRUIPart
*/
public viewdataschange(){
console.log('视图数据变化');
}
/**
* 视图加载完成
*
* @public
* @memberof AppFormDRUIPart
*/
public viewload(){
console.log('视图加载完成');
}
}
</script>
<style lang = "less">
@import './app-form-druipart.less';
</style>
\ No newline at end of file
.app-form-group {
>.ivu-card-head {
>p {
>i {
margin-right: 8px;
cursor: pointer;
}
}
}
>.ivu-card-extra {
.item-extract-mode {
.item {
margin-left: 12px;
}
}
}
}
.app-form-group.app-group-collapse-contant {
.ivu-card-body {
display: none;
}
}
.app-group-flex {
height: 100%;
overflow: auto;
> .ivu-card-body {
height: calc(100% - 51px);
overflow: auto;
}
}
\ No newline at end of file
<template>
<span>未实现</span>
</template>
<script lang="ts">
import { Vue, Component, Prop, } from 'vue-property-decorator';
@Component({})
export default class AppFormGroup2 extends Vue {
/**
* 标题
*
* @type {string}
* @memberof AppFormGroup2
*/
@Prop() public caption?: string;
/**
* 内置界面样式
*
* @type {string}
* @memberof AppFormGroup2
*/
@Prop() public uiStyle?: string;
/**
* 布局模式
*
* @type {string}
* @memberof AppFormGroup2
*/
@Prop() public layoutType?: string;
/**
* 是否显示标题
*
* @type {boolean}
* @memberof AppFormGroup2
*/
@Prop({ default: true }) public isShowCaption!: boolean;
/**
* 界面行为组
*
* @type {*}
* @memberof AppFormGroup2
*/
@Prop() public uiActionGroup?: any;
/**
* 标题栏关闭模式
* 0: 不支持关闭
* 1: 默认打开
* 2: 默认关闭
*
* @type {(number | 0 | 1 | 2)}
* @memberof AppFormGroup2
*/
@Prop({ default: 0 }) public titleBarCloseMode!: number | 0 | 1 | 2;
}
</script>
<style lang="less">
@import './app-form-group2.less';
</style>
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册