基础框架

This commit is contained in:
liuxi 2024-11-29 16:04:56 +08:00
parent 1b3318fa96
commit 346d906fbd
142 changed files with 32530 additions and 86 deletions

33
.eslintrc.js Normal file
View File

@ -0,0 +1,33 @@
module.exports = {
root: true,
env: {
es6: true, // 启用 ES6 语法支持以及新的 ES6 全局变量或类型
node: true, // Node.js 全局变量和 Node.js 作用域
browser: true, // 浏览器全局变量
},
// extends: ["plugin:vue/essential", "@vue/prettier"],
rules: {
// 'no-console': process.env.NODE_ENV === 'production' ? 2 : 2,
// 'no-var': 0,//禁用var用let和const代替
// 'camelcase': 2,//强制驼峰法命名
// 'no-extra-semi': 2,//禁止多余的冒号
// 'no-invalid-regexp': 2,//禁止无效的正则表达式
// 'no-irregular-whitespace': 2,//不能有不规则的空格
// 'no-lonely-if': 2,//禁止else语句内只有if语句
// 'no-mixed-spaces-and-tabs': [2, false],//禁止混用tab和空格
// 'no-multiple-empty-lines': [1, {'max': 2}],//空行最多不能超过2行
// 'no-new': 1,//禁止在使用new构造一个实例后不赋值
// 'no-redeclare': 2,//禁止重复声明变量
// 'max-len': ["error", { "code": 360 }],//字符串最大长度
// 'default-case': 2,//switch语句最后必须有default
// 'indent': [2, 4], // 强制使用一致的缩进
// 'eqeqeq': [2, 'always'], // 要求使用 === 和 !==
},
parserOptions: {
parser: "babel-eslint", // 解析器默认使用Espree
sourceType: "module"
}
};

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# <20><><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD>豻 Git <20><><EFBFBD>Ե<EFBFBD><D4B5>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>У<EFBFBD>
.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?

94
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,94 @@
variables:
#docker仓库地址
REGISTRY_HOST: ccr.ccs.tencentyun.com
#准度科技信息化项目
PROJECT_NAME: trydo
#注册中心
SUB_PROJECT_NAME: mediate-manage-web
CEWCS_IMAGE: $REGISTRY_HOST/$PROJECT_NAME/$SUB_PROJECT_NAME:1.0.0-dev
CEWCS_IMAGE_STG: $REGISTRY_HOST/$PROJECT_NAME/$SUB_PROJECT_NAME:1.0.0-stg
CEWCS_IMAGE_PRD: $REGISTRY_HOST/$PROJECT_NAME/$SUB_PROJECT_NAME:1.0.0-prd
stages:
- build
- push
- clean
before_script:
- docker login --username=100010566009 --password=zd123456 $REGISTRY_HOST
构建:
stage: build
only:
- dev
script:
- export JAVA_HOME=/usr/local/java/jdk-11.0.2
- mvn -B clean package -DskipTests
- docker build -t $CEWCS_IMAGE -f dockerfile/Dockerfile .
推送:
stage: push
only:
- dev
script:
- docker push $CEWCS_IMAGE
部署:
stage: clean
only:
- dev
script:
# - echo '不用清理,用作缓存'
- docker rmi -f $CEWCS_IMAGE
构建测试环境:
stage: build
only:
- stg
script:
- export JAVA_HOME=/usr/local/java/jdk-11.0.2
- mvn -B clean package -DskipTests
- docker build -t $CEWCS_IMAGE_STG -f dockerfile/Dockerfile_stg .
推送测试环境:
stage: push
only:
- stg
script:
- docker push $CEWCS_IMAGE_STG
部署测试环境:
stage: clean
only:
- stg
script:
# - echo '不用清理,用作缓存'
- docker rmi -f $CEWCS_IMAGE_STG
构建发布环境:
stage: build
only:
- prd
script:
- export JAVA_HOME=/usr/local/java/jdk-11.0.2
- mvn -B clean package -DskipTests
- docker build -t $CEWCS_IMAGE_PRD -f dockerfile/Dockerfile_prd .
推送发布环境:
stage: push
only:
- prd
script:
- docker push $CEWCS_IMAGE_PRD
部署发布环境:
stage: clean
only:
- prd
script:
# - echo '不用清理,用作缓存'
- docker rmi -f $CEWCS_IMAGE_PRD

145
README.md
View File

@ -1,92 +1,65 @@
# mediate-manage-web #项目目录结构说明
######├── src/ # 源码目录(开发的项目文件都在此文件中写)
######│ ├── assets/ # 放置需要经由 Webpack 处理的静态文件通常为样式类文件如csssass以及一些外部的js
######│ ├── components/ # 公共组件
## Getting started ######│ ├── filters/ # 过滤器
######│ ├── store/ # 状态管理
To make it easy for you to get started with GitLab, here's a list of recommended next steps. ######│ ├── routes/ # 路由,此处配置项目路由
######│ ├── services/ # 服务(统一管理 XHR 请求)
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! ######│ ├── utils/ # 工具类
######│ ├── pages/ # 路由页面组件
## Add your files ######│ ├── App.vue # 根组件
######│ ├── main.js # 入口文件
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files ######├── static/ # 放置无需经由 Webpack 处理的静态文件,通常放置图片类资源
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: ######├── .gitignore # (配置)在上传中需被 Git 忽略的文件(夹)
######├── package.json # 本项目的配置信息,启动方式
######├── package-lock.json # 记录当前状态下实际安装的各个npm package的具体来源和版本号
``` ```
cd existing_repo 使用dart-sass替换node-sasssass-loader的版本为"^8.0.2"
git remote add origin http://139.155.124.81:8088/cloud-mediate/mediate-manage-web.git sass-loader版本过高会导致构建时报错this.getOptions is not a function.
git branch -M main ```
git push -uf origin main ```
element-ui的版本为"^2.15.6"
因为版本"2.15.6"以上版本的时候在date-picker组件里面
添加了一行直接修改placement的代码会导致控制台报错
Prop being mutated: "placement"
```
```icon
图标使用svg-icon,全局组件,直接使用:
<svg-icon icon-class="user"></svg-icon>
```
```
1.关于button、tag等标签主色已改不需要单独写样式.
2.项目图标除了菜单栏图标使用svg其余图标使用element ui icon.
```
```
util.js通用工具方法
1.获取当天、当月、近几周、近几月、近几年内日期/时间,格式化时间处理等
2.点击按钮后,去掉按钮焦点
3.处理base64数据
4.下载文件等
```
# project
### Project setup
```
npm install
``` ```
## Integrate with your tools ### Compiles and hot-reloads for development
```
npm run serve
```
- [ ] [Set up project integrations](http://139.155.124.81:8088/cloud-mediate/mediate-manage-web/-/settings/integrations) ### Compiles and minifies for production
```
npm run build
```
## Collaborate with your team ### Lints and fixes files
```
npm run lint
```
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) ### Customize configuration
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) See [Configuration Reference](https://cli.vuejs.org/config/).
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

18
babel.config.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
"import",
{ libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
],
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}

26
dockerfile/Dockerfile Normal file
View File

@ -0,0 +1,26 @@
# syntax=docker/dockerfile:experimental
FROM node:14.16.1 as build
WORKDIR /workspace
COPY package.json .
RUN npm config set registry https://registry.npm.taobao.org
RUN npm install
# 打包需要编译或配置的文件
COPY src src
COPY public public
COPY babel.config.js babel.config.js
COPY vue.config.js vue.config.js
# 打包命令
RUN npm run build
FROM nginx:1.21.0
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
# 打包后的产物部署
COPY --from=build workspace/dist /usr/share/nginx/html
EXPOSE 8065
CMD ["nginx", "-g", "daemon off;"]

26
dockerfile/Dockerfile_prd Normal file
View File

@ -0,0 +1,26 @@
# syntax=docker/dockerfile:experimental
FROM node:14.16.1 as build
WORKDIR /workspace
COPY package.json .
RUN npm config set registry https://registry.npm.taobao.org
RUN npm install
# 打包需要编译或配置的文件
COPY src src
COPY public public
COPY babel.config.js babel.config.js
COPY vue.config.js vue.config.js
# 打包命令
RUN npm run build
FROM nginx:1.21.0
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx_prd.conf /etc/nginx/conf.d
# 打包后的产物部署
COPY --from=build workspace/dist /usr/share/nginx/html
EXPOSE 8065
CMD ["nginx", "-g", "daemon off;"]

26
dockerfile/Dockerfile_stg Normal file
View File

@ -0,0 +1,26 @@
# syntax=docker/dockerfile:experimental
FROM node:14.16.1 as build
WORKDIR /workspace
COPY package.json .
RUN npm config set registry https://registry.npm.taobao.org
RUN npm install
# 打包需要编译或配置的文件
COPY src src
COPY public public
COPY babel.config.js babel.config.js
COPY vue.config.js vue.config.js
# 打包命令
RUN npm run build
FROM nginx:1.21.0
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx_stg.conf /etc/nginx/conf.d
# 打包后的产物部署
COPY --from=build workspace/dist /usr/share/nginx/html
EXPOSE 8065
CMD ["nginx", "-g", "daemon off;"]

24
nginx/nginx.conf Normal file
View File

@ -0,0 +1,24 @@
#gzip on;
server {
listen 8086;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 200m;
try_files $uri $uri/ @router; # 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
}
# 开发环境
location /manage-center {
proxy_pass http://221.236.31.182:8621/manage-center;
}
location /mediate {
proxy_pass http://221.236.31.182:8620/mediate;
}
}

28
nginx/nginx_prd.conf Normal file
View File

@ -0,0 +1,28 @@
#gzip on;
server {
listen 8086;
server_name localhost;
client_max_body_size 10M;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ @router; # 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
}
# 生产环境
location /manage-center {
proxy_pass http://221.236.31.182:8621/manage-center;
}
location /mediate {
proxy_pass http://221.236.31.182:8620/mediate;
}
location /mediate-center {
proxy_pass http://221.236.31.182:8620/mediate-center;
}
}

24
nginx/nginx_stg.conf Normal file
View File

@ -0,0 +1,24 @@
#gzip on;
server {
listen 8086;
server_name localhost;
client_max_body_size 10M;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ @router; # 需要指向下面的@router否则会出现vue的路由在nginx中刷新出现404
}
# 测试环境
location /manage-center {
proxy_pass http://221.236.31.183:8620/manage-center;
}
location /mediate {
proxy_pass http://221.236.31.183:8620/mediate;
}
}

17353
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

67
package.json Normal file
View File

@ -0,0 +1,67 @@
{
"name": "project",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.27.2",
"core-js": "^3.6.4",
"echarts": "^5.1.1",
"element-ui": "^2.15.6",
"install": "^0.13.0",
"lodash": "^4.17.21",
"moment": "^2.25.3",
"npm": "^6.14.5",
"quill": "^1.3.7",
"quill-image-drop-module": "^1.0.3",
"quill-image-resize-module": "^3.0.0",
"sm-crypto": "^0.3.7",
"style-loader": "^2.0.0",
"vue": "^2.6.11",
"vue-meta-info": "^0.1.7",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.1.6",
"vuex": "^3.4.0",
"vuex-persistedstate": "^4.0.0-beta.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.3.0",
"@vue/cli-plugin-eslint": "~4.3.0",
"@vue/cli-service": "~4.3.0",
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1",
"babel-plugin-import": "^1.13.1",
"crypto-js": "^4.1.1",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.53.0",
"sass-loader": "^8.0.2",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {
"vue/no-unused-components": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

30
profile/dev/nginx.conf Normal file
View File

@ -0,0 +1,30 @@
server {
listen 8086;
server_name localhost;
keepalive_timeout 60; #连接超时时间默认为75s可以在httpserverlocation块。
client_max_body_size 20M;
client_body_buffer_size 128k;
gzip on;
# 启用gzip压缩的最小文件小于设置值的文件将不会压缩
gzip_min_length 1k;
# 压缩级别1-10数字越大压缩的越好也越占用cpu时间
gzip_comp_level 5;
# 进行压缩的文件类型js有多种形式。其中的值可以在mime.types 文件中找到
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
# 是否在http header中添加vary: Accrpt-Encoeing 建议开启
gzip_vary on;
# 禁用ie6 gzip
gzip_disable "MSIE [1-6]\.";
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -0,0 +1,13 @@
const dev = {
NODE_ENV: 'production',
type: '开发版',
hostUrl: 'https://lz.dev.trydotec.com:8416',
fileUrl: 'https://lz.dev.trydotec.com:8416/8611',
}
const info = {
netHost: `${dev.hostUrl}/miniapp/`,
fileHost:`${dev.fileUrl}/notary/minio/preview/`,
weChatRedirectUri: 'https://dev.trydotec.com:8430/',
version: '2.0.0',
}
export default {...info}

30
profile/prd/nginx.conf Normal file
View File

@ -0,0 +1,30 @@
server {
listen 8086;
server_name localhost;
keepalive_timeout 60; #连接超时时间默认为75s可以在httpserverlocation块。
client_max_body_size 20M;
client_body_buffer_size 128k;
gzip on;
# 启用gzip压缩的最小文件小于设置值的文件将不会压缩
gzip_min_length 1k;
# 压缩级别1-10数字越大压缩的越好也越占用cpu时间
gzip_comp_level 5;
# 进行压缩的文件类型js有多种形式。其中的值可以在mime.types 文件中找到
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
# 是否在http header中添加vary: Accrpt-Encoeing 建议开启
gzip_vary on;
# 禁用ie6 gzip
gzip_disable "MSIE [1-6]\.";
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -0,0 +1,13 @@
const dev = {
NODE_ENV: 'production',
type: '生产版',
hostUrl: 'https://dev.trydotec.com:8416',
fileUrl: 'https://dev.trydotec.com:8416/8611',
}
const info = {
netHost: `${dev.hostUrl}/miniapp/`,
fileHost:`${dev.fileUrl}/notary/minio/preview/`,
weChatRedirectUri: 'https://dev.trydotec.com:8430/',
version: '2.0.0',
}
export default {...info}

30
profile/stg/nginx.conf Normal file
View File

@ -0,0 +1,30 @@
server {
listen 8086;
server_name localhost;
keepalive_timeout 60; #连接超时时间默认为75s可以在httpserverlocation块。
client_max_body_size 20M;
client_body_buffer_size 128k;
gzip on;
# 启用gzip压缩的最小文件小于设置值的文件将不会压缩
gzip_min_length 1k;
# 压缩级别1-10数字越大压缩的越好也越占用cpu时间
gzip_comp_level 5;
# 进行压缩的文件类型js有多种形式。其中的值可以在mime.types 文件中找到
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
# 是否在http header中添加vary: Accrpt-Encoeing 建议开启
gzip_vary on;
# 禁用ie6 gzip
gzip_disable "MSIE [1-6]\.";
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -0,0 +1,13 @@
const dev = {
NODE_ENV: 'production',
type: '测试版',
hostUrl: 'https://stg.lz.test.trydotec.com',
fileUrl: 'https://stg.lz.test.trydotec.com/8611',
}
const info = {
netHost: `${dev.hostUrl}/miniapp/`,
fileHost:`${dev.fileUrl}/notary/minio/preview/`,
weChatRedirectUri: 'https://portal.lz.test.trydotec.com/',
version: '2.0.0',
}
export default {...info}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

24
public/index.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
<!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
<title><%= htmlWebpackPlugin.options.title %></title>
<style>
body, html {
padding: 0;
margin: 0;
width: 100%;
}
</style>
</head>
<body style="background-color: #fff;">
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

36
src/App.vue Normal file
View File

@ -0,0 +1,36 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
methods: {},
mounted() {},
};
</script>
<style lang="scss">
@import "./assets/style/flex.scss";
@import "./assets/style/common.scss";
body,
html {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#app {
width: 100vw;
height: 100vh;
/* font-size: 3vw; */
}
#app button {
-webkit-tap-highlight-color: transparent;
}
.el-scrollbar__wrap{
overflow: hidden;
}
</style>

View File

@ -0,0 +1,9 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

View File

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.81836 6.75043C6.99469 6.24918 7.34272 5.82651 7.80083 5.55728C8.25893 5.28805 8.79753 5.18963 9.32124 5.27946C9.84495 5.36929 10.32 5.64157 10.6622 6.04807C11.0044 6.45458 11.1917 6.96907 11.1909 7.50043C11.1909 9.00043 8.94086 9.75043 8.94086 9.75043" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 12.75H9.0075" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 752 B

View File

@ -0,0 +1,11 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 7.5V10.5" stroke="currentColor" stroke-linecap="round"/>
<path d="M11 3V6" stroke="currentColor" stroke-linecap="round"/>
<path d="M11 12V15" stroke="currentColor" stroke-linecap="round"/>
<path d="M3 9H7" stroke="currentColor" stroke-linecap="round"/>
<path d="M15 4.5H13" stroke="currentColor" stroke-linecap="round"/>
<path d="M15 13.5H13" stroke="currentColor" stroke-linecap="round"/>
<path d="M9 9H15" stroke="currentColor" stroke-linecap="round"/>
<path d="M11 4.5H3" stroke="currentColor" stroke-linecap="round"/>
<path d="M11 13.5H3" stroke="currentColor" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 705 B

View File

@ -0,0 +1,7 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 1.5H4.5C4.10218 1.5 3.72064 1.65804 3.43934 1.93934C3.15804 2.22064 3 2.60218 3 3V15C3 15.3978 3.15804 15.7794 3.43934 16.0607C3.72064 16.342 4.10218 16.5 4.5 16.5H13.5C13.8978 16.5 14.2794 16.342 14.5607 16.0607C14.842 15.7794 15 15.3978 15 15V6L10.5 1.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.5 1.5V6H15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 9.75H6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 12.75H6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.5 6.75H6.75H6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 826 B

View File

@ -0,0 +1,7 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 6V9" stroke="currentColor" stroke-linecap="round"/>
<rect x="7" y="3" width="4" height="3" rx="0.5" stroke="currentColor"/>
<rect x="3" y="12" width="4" height="3" rx="0.5" stroke="currentColor"/>
<rect x="11" y="12" width="4" height="3" rx="0.5" stroke="currentColor"/>
<path d="M5 12V10C5 9.44772 5.44772 9 6 9H9H12C12.5523 9 13 9.44772 13 10V12" stroke="currentColor" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 511 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.25 6.75L9 1.5L15.75 6.75V15C15.75 15.3978 15.592 15.7794 15.3107 16.0607C15.0294 16.342 14.6478 16.5 14.25 16.5H3.75C3.35218 16.5 2.97064 16.342 2.68934 16.0607C2.40804 15.7794 2.25 15.3978 2.25 15V6.75Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.75 16.5V9H11.25V16.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@ -0,0 +1,8 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 4.5H15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 9H15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 13.5H15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.25 4.5H2.2575" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.25 9H2.2575" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.25 13.5H2.2575" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 677 B

View File

@ -0,0 +1,6 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.3075 6.25C11.5875 7.30627 10.3747 7.99979 9 7.99979C7.62525 7.99979 6.41249 7.30627 5.69248 6.25C4.65459 7.16618 4 8.50654 4 9.99979C6.20914 9.99979 8 11.7907 8 13.9998C8 14.3019 7.96651 14.5961 7.90305 14.8791C8.25605 14.9581 8.62316 14.9998 9 14.9998C9.37684 14.9998 9.74395 14.9581 10.097 14.8791C10.0335 14.5961 10 14.3019 10 13.9998C10 11.7907 11.7909 9.99979 14 9.99979C14 8.50654 13.3454 7.16618 12.3075 6.25Z" stroke="currentColor"/>
<circle cx="9" cy="4" r="1.5" stroke="currentColor"/>
<circle cx="4" cy="14" r="1.5" stroke="currentColor"/>
<circle cx="14" cy="14" r="1.5" stroke="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 723 B

View File

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 15.75V14.25C12 13.4544 11.6839 12.6913 11.1213 12.1287C10.5587 11.5661 9.79565 11.25 9 11.25H3.75C2.95435 11.25 2.19129 11.5661 1.62868 12.1287C1.06607 12.6913 0.75 13.4544 0.75 14.25V15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.375 8.25C8.03185 8.25 9.375 6.90685 9.375 5.25C9.375 3.59315 8.03185 2.25 6.375 2.25C4.71815 2.25 3.375 3.59315 3.375 5.25C3.375 6.90685 4.71815 8.25 6.375 8.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.75 8.25L14.25 9.75L17.25 6.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 739 B

View File

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 15.75V14.25C12 13.4544 11.6839 12.6913 11.1213 12.1287C10.5587 11.5661 9.79565 11.25 9 11.25H3.75C2.95435 11.25 2.19129 11.5661 1.62868 12.1287C1.06607 12.6913 0.75 13.4544 0.75 14.25V15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.375 8.25C8.03185 8.25 9.375 6.90685 9.375 5.25C9.375 3.59315 8.03185 2.25 6.375 2.25C4.71815 2.25 3.375 3.59315 3.375 5.25C3.375 6.90685 4.71815 8.25 6.375 8.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17.25 8.25H12.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 723 B

View File

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5 15V7.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 15V3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.5 15V10.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 380 B

View File

@ -0,0 +1,6 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.25 3H3.75C2.92157 3 2.25 3.67157 2.25 4.5V15C2.25 15.8284 2.92157 16.5 3.75 16.5H14.25C15.0784 16.5 15.75 15.8284 15.75 15V4.5C15.75 3.67157 15.0784 3 14.25 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 1.5V4.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 1.5V4.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.25 7.5H15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 630 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 11.25C10.2426 11.25 11.25 10.2426 11.25 9C11.25 7.75736 10.2426 6.75 9 6.75C7.75736 6.75 6.75 7.75736 6.75 9C6.75 10.2426 7.75736 11.25 9 11.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.55 11.25C14.4502 11.4762 14.4204 11.7271 14.4645 11.9704C14.5086 12.2137 14.6246 12.4382 14.7975 12.615L14.8425 12.66C14.982 12.7993 15.0926 12.9647 15.1681 13.1468C15.2436 13.3289 15.2824 13.5241 15.2824 13.7213C15.2824 13.9184 15.2436 14.1136 15.1681 14.2957C15.0926 14.4778 14.982 14.6432 14.8425 14.7825C14.7032 14.922 14.5378 15.0326 14.3557 15.1081C14.1736 15.1836 13.9784 15.2224 13.7812 15.2224C13.5841 15.2224 13.3889 15.1836 13.2068 15.1081C13.0247 15.0326 12.8593 14.922 12.72 14.7825L12.675 14.7375C12.4982 14.5646 12.2737 14.4486 12.0304 14.4045C11.7871 14.3604 11.5362 14.3902 11.31 14.49C11.0882 14.5851 10.899 14.7429 10.7657 14.9442C10.6325 15.1454 10.561 15.3812 10.56 15.6225V15.75C10.56 16.1478 10.402 16.5294 10.1207 16.8107C9.83936 17.092 9.45782 17.25 9.06 17.25C8.66218 17.25 8.28064 17.092 7.99934 16.8107C7.71804 16.5294 7.56 16.1478 7.56 15.75V15.6825C7.55419 15.4343 7.47384 15.1935 7.32938 14.9915C7.18493 14.7896 6.98305 14.6357 6.75 14.55C6.52379 14.4502 6.27286 14.4204 6.02956 14.4645C5.78626 14.5086 5.56176 14.6246 5.385 14.7975L5.34 14.8425C5.20069 14.982 5.03526 15.0926 4.85316 15.1681C4.67106 15.2436 4.47587 15.2824 4.27875 15.2824C4.08163 15.2824 3.88644 15.2436 3.70434 15.1681C3.52224 15.0926 3.35681 14.982 3.2175 14.8425C3.07804 14.7032 2.9674 14.5378 2.89191 14.3557C2.81642 14.1736 2.77757 13.9784 2.77757 13.7812C2.77757 13.5841 2.81642 13.3889 2.89191 13.2068C2.9674 13.0247 3.07804 12.8593 3.2175 12.72L3.2625 12.675C3.4354 12.4982 3.55139 12.2737 3.5955 12.0304C3.63962 11.7871 3.60984 11.5362 3.51 11.31C3.41493 11.0882 3.25707 10.899 3.05585 10.7657C2.85463 10.6325 2.61884 10.561 2.3775 10.56H2.25C1.85218 10.56 1.47064 10.402 1.18934 10.1207C0.908035 9.83936 0.75 9.45782 0.75 9.06C0.75 8.66218 0.908035 8.28064 1.18934 7.99934C1.47064 7.71804 1.85218 7.56 2.25 7.56H2.3175C2.56575 7.55419 2.8065 7.47384 3.00847 7.32938C3.21045 7.18493 3.36429 6.98305 3.45 6.75C3.54984 6.52379 3.57962 6.27286 3.5355 6.02956C3.49139 5.78626 3.3754 5.56176 3.2025 5.385L3.1575 5.34C3.01804 5.20069 2.9074 5.03526 2.83191 4.85316C2.75642 4.67106 2.71757 4.47587 2.71757 4.27875C2.71757 4.08163 2.75642 3.88644 2.83191 3.70434C2.9074 3.52224 3.01804 3.35681 3.1575 3.2175C3.29681 3.07804 3.46224 2.9674 3.64434 2.89191C3.82644 2.81642 4.02163 2.77757 4.21875 2.77757C4.41587 2.77757 4.61106 2.81642 4.79316 2.89191C4.97526 2.9674 5.14069 3.07804 5.28 3.2175L5.325 3.2625C5.50176 3.4354 5.72626 3.55139 5.96956 3.5955C6.21285 3.63962 6.46379 3.60984 6.69 3.51H6.75C6.97183 3.41493 7.16101 3.25707 7.29427 3.05585C7.42753 2.85463 7.49904 2.61884 7.5 2.3775V2.25C7.5 1.85218 7.65804 1.47064 7.93934 1.18934C8.22064 0.908035 8.60218 0.75 9 0.75C9.39782 0.75 9.77936 0.908035 10.0607 1.18934C10.342 1.47064 10.5 1.85218 10.5 2.25V2.3175C10.501 2.55884 10.5725 2.79463 10.7057 2.99585C10.839 3.19707 11.0282 3.35493 11.25 3.45C11.4762 3.54984 11.7271 3.57962 11.9704 3.5355C12.2137 3.49139 12.4382 3.3754 12.615 3.2025L12.66 3.1575C12.7993 3.01804 12.9647 2.9074 13.1468 2.83191C13.3289 2.75642 13.5241 2.71757 13.7213 2.71757C13.9184 2.71757 14.1136 2.75642 14.2957 2.83191C14.4778 2.9074 14.6432 3.01804 14.7825 3.1575C14.922 3.29681 15.0326 3.46224 15.1081 3.64434C15.1836 3.82644 15.2224 4.02163 15.2224 4.21875C15.2224 4.41587 15.1836 4.61106 15.1081 4.79316C15.0326 4.97526 14.922 5.14069 14.7825 5.28L14.7375 5.325C14.5646 5.50176 14.4486 5.72626 14.4045 5.96956C14.3604 6.21285 14.3902 6.46379 14.49 6.69V6.75C14.5851 6.97183 14.7429 7.16101 14.9442 7.29427C15.1454 7.42753 15.3812 7.49904 15.6225 7.5H15.75C16.1478 7.5 16.5294 7.65804 16.8107 7.93934C17.092 8.22064 17.25 8.60218 17.25 9C17.25 9.39782 17.092 9.77936 16.8107 10.0607C16.5294 10.342 16.1478 10.5 15.75 10.5H15.6825C15.4412 10.501 15.2054 10.5725 15.0042 10.7057C14.8029 10.839 14.6451 11.0282 14.55 11.25V11.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 15.75V14.25C15 13.4544 14.6839 12.6913 14.1213 12.1287C13.5587 11.5661 12.7956 11.25 12 11.25H6C5.20435 11.25 4.44129 11.5661 3.87868 12.1287C3.31607 12.6913 3 13.4544 3 14.25V15.75" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 8.25C10.6569 8.25 12 6.90685 12 5.25C12 3.59315 10.6569 2.25 9 2.25C7.34315 2.25 6 3.59315 6 5.25C6 6.90685 7.34315 8.25 9 8.25Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,735 @@
*,
*::before,
*::after {
box-sizing: border-box;
outline: 0 none;
}
ul, li{
list-style: none;
}
html{
font-family: 'PingFang SC';
color: $color-text-primary;
}
.cursor-pointer{
cursor: pointer;
}
//=================== start::全局自定义滚动条样式 =======================
/* 设置垂直滚动条的宽度和水平滚动条的高度 */
::-webkit-scrollbar{
width: 5px;
height: 5px;
}
/* 设置滚动条的滑轨 */
::-webkit-scrollbar-track {
background-color: rgba(0, 0, 0, 0.05);
}
/* 滑块 */
::-webkit-scrollbar-thumb {
background-color: $border-color-light;
border-radius: 4px;
}
/* 滑轨两头的监听按钮 */
::-webkit-scrollbar-button {
background-color: $border-color-light;
display: none;
}
/* 横向滚动条和纵向滚动条相交处尖角 */
::-webkit-scrollbar-corner {
/*background-color: black;*/
}
.el-scrollbar__wrap {
overflow-x: hidden !important;
overflow-y: auto !important;
}
.el-scrollbar__bar.is-horizontal{
display: none;
}
.overflow-y-scroll{
overflow-y: scroll !important;
}
.overflow-y-auto{
overflow-y: auto !important;
}
//=================== end::全局自定义滚动条样式 =========================
//=================== start::文字样式 =======================
.f12{
font-size: $f12;
}
.f14{
font-size: $f14;
}
.f16{
font-size: $f16;
}
.f18{
font-size: $f18;
}
.f20{
font-size: $f20;
}
.f22{
font-size: $f22;
}
.f24{
font-size: $f24;
}
.f32{
font-size: $f32;
}
.f-weight400{
font-weight: 400;
}
.f-weight500{
font-weight: 500;
}
.f-weight600{
font-weight: 600;
}
.color-fff{
color: $color-white;
}
.color-000{
color: $color-000000;
}
.color-text-primary{
color: $color-text-primary;
}
.color-text-regular{
color: $color-text-regular;
}
.color-text-secondary{
color: $color-text-secondary;
}
.color-text-placeholder{
color: $color-text-placeholder;
}
.bg-color-light{
background-color:$bg-color-light
}
.color-1960F4{
color: $color-1960F4;
}
.color-primary{
color: $color-primary;
}
.text-overflow{
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.text-center{
text-align: center;
}
.text-right{
text-align: right;
}
//=================== end::文字样式 =========================
//=================== start::定位样式 =======================
.position-r{
position: relative;
}
.position-a{
position: absolute;
}
.position-f{
position: fixed;
}
//=================== end::定位样式 =========================
//=================== start::边距样式 =======================
// 内边距
@mixin basePadding($top:$size8,$right:$top,$bottom:$top,$left:$right) {
padding: {
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
}
.pt-8{
padding-top: $size8;
}
.pb-8{
padding-bottom: $size8;
}
.pr-8{
padding-right: $size8;
}
.pl-8{
padding-left: $size8;
}
.p-8{
@include basePadding($size8)
}
.p-v-8{
@include basePadding($size8, 0);
}
.p-h-8{
@include basePadding(0, $size8);
}
.pt-16{
padding-top: $size16;
}
.pb-16{
padding-bottom: $size16;
}
.pr-16{
padding-right: $size16;
}
.pl-16{
padding-left: $size16;
}
.p-16{
@include basePadding($size16)
}
.p-v-16{
@include basePadding($size16, 0);
}
.p-h-16{
@include basePadding(0, $size16);
}
.p-h-22{
@include basePadding(0, $size22)
}
.pt-24{
padding-top: $size24;
}
.pb-24{
padding-bottom: $size24;
}
.pr-24{
padding-right: $size24;
}
.pl-24{
padding-left: $size24;
}
.p-24{
@include basePadding($size24);
}
.p-v-24{
@include basePadding($size24, 0);
}
.p-h-24{
@include basePadding(0, $size24);
}
.pt-32{
padding-top: $size32;
}
.pb-32{
padding-bottom: $size32;
}
.pr-32{
padding-right: $size32;
}
.pl-32{
padding-left: $size32;
}
.p-32{
@include basePadding($size32);
}
.p-v-32{
@include basePadding($size32, 0);
}
.p-h-32{
@include basePadding(0, $size32);
}
.pt-40{
padding-top: $size40;
}
.pb-40{
padding-bottom: $size40;
}
.pr-40{
padding-right: $size40;
}
.pl-40{
padding-left: $size40;
}
.p-40{
@include basePadding($size40);
}
.p-v-40{
@include basePadding($size40, 0);
}
.p-h-40{
@include basePadding(0, $size40);
}
// 外边距
@mixin baseMargin($top:$size8,$right:$top,$bottom:$top,$left:$right) {
margin: {
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
}
.mt-8{
margin-top: $size8;
}
.mb-8{
margin-bottom: $size8;
}
.mr-8{
margin-right: $size8;
}
.ml-8{
margin-left: $size8;
}
.m-8{
@include baseMargin($size8)
}
.m-v-8{
@include baseMargin($size8, 0)
}
.m-h-8{
@include baseMargin(0, $size8)
}
.mt-16{
margin-top: $size16;
}
.mb-16{
margin-bottom: $size16;
}
.mr-16{
margin-right: $size16;
}
.ml-16{
margin-left: $size16;
}
.m-16{
@include baseMargin($size16);
}
.m-v-16{
@include baseMargin($size16, 0);
}
.m-h-16{
@include baseMargin(0, $size16);
}
.mt-24{
margin-top: $size24;
}
.mb-24{
margin-bottom: $size24;
}
.mr-24{
margin-right: $size24;
}
.ml-24{
margin-left: $size24;
}
.m-24{
@include baseMargin($size24)
}
.m-v-24{
@include baseMargin($size24, 0)
}
.m-h-24{
@include baseMargin(0, $size24)
}
.mt-32{
margin-top: $size32;
}
.mb-32{
margin-bottom: $size32;
}
.mr-32{
margin-right: $size32;
}
.ml-32{
margin-left: $size32;
}
.m-32{
@include baseMargin($size32)
}
.m-v-32{
@include baseMargin($size32, 0)
}
.m-h-32{
@include baseMargin(0, $size32)
}
.mt-40{
margin-top: $size40;
}
.mb-40{
margin-bottom: $size40;
}
.mr-40{
margin-right: $size40;
}
.ml-40{
margin-left: $size40;
}
.m-40{
@include baseMargin($size40)
}
.m-v-40{
@include baseMargin($size40, 0)
}
.m-h-40{
@include baseMargin(0, $size40)
}
//=================== end::边距样式 =========================
//=================== start::宽高样式 =========================
.width100{
width: 100% !important;
}
.width75{
width: 75% !important;
}
.width-40{
width: $height40;
}
.width-120{
width: $height120;
}
.width70{
width: 70% !important;
}
.width30{
width: 30% !important;
}
.height100{
height: 100% !important;
}
.height-30 {
height: $height30;
}
.height-40{
height: $height40;
}
.height-48{
height: $height48;
}
.height-56{
height: $height56;
}
.height-90{
height: $height90;
}
.height-138{
height: $height138;
}
.line-height-30{
line-height: $height30;
}
.line-height-40{
line-height: $height40;
}
.line-height-48{
line-height: $height48;
}
//=================== end::宽高样式 ===========================
//=================== start::border边框 ===========================
.border-t-0{
border-top: 0 none !important;
}
.border-b-0{
border-bottom: 0 none !important;
}
.border-r-0{
border-right: 0 none !important;
}
.border-l-0{
border-left: 0 none !important;
}
.border-t-solid-lighter-1{
border-top: 1px solid $border-color-lighter;
}
.border-b-solid-lighter-1{
border-bottom: 1px solid $border-color-lighter;
}
.border-solid-lighter-1{
border:1px solid $border-color-lighter;
}
//=================== end::border边框 ===========================
//=================== start::圆角样式 ==============================
.border-radius50{
border-radius: 50%;
}
.border-radius-2{
border-radius: 2px;
}
.border-radius-4{
border-radius: 4px;
}
.border-radius-8{
border-radius: 8px;
}
//=================== end::圆角样式 ================================
//=================== start::旋转动画 ==============================
.transform-time-default{
transition: transform .3s
}
.rotate-0{
transform: rotate(0deg);
}
.rotate-45{
transform: rotate(45deg);
}
.rotate-90{
transform: rotate(90deg);
}
.rotate-180{
transform: rotate(180deg);
}
.rotate--180{
transform: rotate(-180deg);
}
//=================== end::旋转动画 ================================
//=================== start:: 自定义tabs样式 ==============================
.zd-el-tabs-custom{
.el-tabs__header{
margin: 0;
}
.el-tabs__item{
height: $height48;
line-height: $height48;
}
// tabs第一个菜单有左边的边距
.el-tabs__item.is-top:nth-child(2),
.el-tabs__item.is-bottom:nth-child(2), {
padding-left: $size24 !important;
}
// 被选中的tabs样式
.el-tabs__item.is-active{
color: $color-1960F4 !important;
}
// 被选中的tabs样式
.el-tabs__active-bar{
background-color: $color-1960F4 !important;
}
}
// tabs第一个菜单有padding-left
.zd-el-tabs-custom__left_padding{
.el-tabs__item.is-top:nth-child(2),
.el-tabs__item.is-bottom:nth-child(2), {
padding-left: $size24 !important;
}
}
// tabs最后一个菜单有padding-right
.zd-el-tabs-custom__right_padding{
.el-tabs__item.is-top:last-child,
.el-tabs__item.is-bottom:last-child{
padding-right: $size24 !important;
}
}
// 去调解页面 去掉tabs灰色的下横线
.layout-center-right-center .zd-el-tabs-custom{
.el-tabs__nav-wrap::after {
height: 0 !important;
background-color: transparent!important;
}
}
//=================== end::自定义tabs样式 ================================
//=================== start:: tabs内容区域通用样式 ==============================
.layout-tabs-content-box{
width: 100%;
height: calc(100% - $height48);
padding: $size16 $size24;
box-sizing: border-box;
.tabs__search-criteria-title{
@extend .f14;
@extend .color-text-regular;
@extend .text-right;
min-width: 88px;
white-space: nowrap;
box-sizing: content-box;
}
.tabs__search-criteria-titleminwidth120{
@extend .f14;
@extend .color-text-regular;
@extend .text-right;
min-width: 120px;
white-space: nowrap;
box-sizing: content-box;
}
}
//=================== end::tabs内容区域通用样式 =================================
//=================== start::border 样式 ===============================
//=================== end::border-bottom 样式 ==================================
//=================== start::图片宽高 样式 ===============================
.images24{
width:$height24 ;
height: $height24;
}
.images56{
width:$height56 ;
height: $height56;
}
.images120{
width: $height120;
height: $height120;
}
//=================== start::图片宽高 样式 ===============================
//=================== start::自定义drawer样式 ===============================
.el-drawer__wrapper {
.el-drawer__header{
height: $height64 !important;
line-height: $height64 !important;
margin: 0;
font-size:$f22;
color: $color-text-primary;
padding: 0 $height20;
}
}
//=================== start::自定义drawer样式 ===============================
//=================== start::自定义dialog样式 ===============================
.el-dialog__wrapper {
.el-dialog{
// 设置居中显示
position:absolute;
top:50%;
left:50%;
margin:0 !important;
transform:translate(-50%, -50%);
.el-dialog__header{
height: $height64 !important;
line-height: $height64 !important;
margin: 0;
font-size:$f16;
color: $color-text-primary;
padding: 0 $size24;
}
.el-dialog__body{
// padding: $size16 $size72 $size16 $size72;
padding: 0;
}
}
}
//=================== start::自定义dialog样式 ===============================
//=================== start::日期时间选择器 ===============================
.el-date-editor .el-range-separator{
box-sizing: content-box;
}
//=================== end::日期时间选择器 ===============================
// message提示框加优先级防止抽屉弹框等被遮挡
.messageZindex{
z-index: 4000!important;
}
//=================== start::提示框置顶 ===============================
.el-message.el-message--error.is-closable{z-index: 3000 !important;}
.el-message.el-message--warning.is-closable{z-index: 3000 !important;}
.el-message.el-message--success.is-closable{z-index: 3000 !important;}
.el-loading-mask.is-fullscreen{z-index: 9999 !important;}
//=================== end::提示框置顶 ===============================
//=================== start::解决Elementui输入框(text)与文本域(textarea)字体不一样问题 ===============================
.el-textarea__inner{
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
}
//去调解页 去掉textarea边框
.layout-center-right-bottom .el-textarea__inner {
border: none!important;
padding: 5px 0!important;
resize: none!important;
}
//=================== end::解决Elementui输入框(text)与文本域(textarea)字体不一样问题 ===============================
//=================== start::状态标签样式 ===============================
// 公用状态标签样式
.status-btn {
width: 60px;
border-radius: 4px;
font-size: 12px;
text-align: center;
border: 1px solid;
height: 24px;
line-height: 22px;
}
// 调解状态 0-待调解 1-调解中 2-已结束
.case-status0{
background-color: #fdf6ec;
border-color: #faecd8;
color: #e6a23c
}
.case-status1{
background-color: #ecf5ff;
border-color: #d9ecff;
color: #409EFF;
}
.case-status2{
background-color: #f0f9eb;
border-color: #e1f3d8;
color: #67c23a;
}
// 案件状态1-调解成功0-调解失败2-暂存
.result-status0{
background-color: #fef0f0;
border-color: #fde2e2;
color: #f56c6c;
}
.result-status1{
background-color: #f0f9eb;
border-color: #e1f3d8;
color: #67c23a;
}
.result-status2{
background-color: #fdf6ec;
border-color: #faecd8;
color: #e6a23c
}
//=================== end::状态标签样式 ===============================

View File

@ -0,0 +1,14 @@
// element-variables.scss 重置element-ui的变量
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
/* 修改按钮主题色 */
$--button-primary-background-color: #1960F4 !default;
$--button-primary-border-color: #1960F4 !default;
/// padding||Spacing|3
//$--button-padding-vertical: 9px !default;
/// padding||Spacing|3
//$--button-padding-horizontal: 20px !default;
@import "~element-ui/packages/theme-chalk/src/index";

139
src/assets/style/flex.scss Normal file
View File

@ -0,0 +1,139 @@
.flex {
display: flex;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-row-reverse {
display: flex;
flex-direction: row-reverse;
}
.flex-column-reverse {
display: flex;
flex-direction: column-reverse;
}
.flex-row-center {
// 横向居中
@extend .flex-row;
justify-content: center;
}
.flex-column-center {
// 纵向居中
@extend .flex-column;
align-items: center;
}
.flex-fill {
// 此样式可强制设置各个弹性子元素的宽度是一样的
-webkit-box-flex: 1 !important;
-ms-flex: 1 1 auto !important;
flex: 1 1 auto !important;
}
.flex-grow-0 {
flex-grow: 0 !important;
}
.flex-grow-1 {
flex-grow: 1 !important;
}
.flex-shrink-0 {
flex-shrink: 0 !important;
}
.flex-shrink-1 {
flex-shrink: 1 !important;
}
.justify-content-start {
justify-content: flex-start !important;
}
.justify-content-end {
justify-content: flex-end !important;
}
.justify-content-center {
justify-content: center !important;
}
.justify-content-between {
justify-content: space-between !important;
}
.justify-content-around {
justify-content: space-around !important;
}
.align-items-start {
align-items: flex-start !important;
}
.align-items-end {
align-items: flex-end !important;
}
.align-items-center {
align-items: center !important;
}
.align-items-baseline {
align-items: baseline !important;
}
.align-items-stretch {
align-items: stretch !important;
}
.align-content-start {
align-content: flex-start !important;
}
.align-content-end {
align-content: flex-end !important;
}
.align-content-center {
align-content: center !important;
}
.align-content-between {
align-content: space-between !important;
}
.align-content-around {
align-content: space-around !important;
}
.align-content-stretch {
align-content: stretch !important;
}
.align-self-auto {
align-self: auto !important;
}
.align-self-start {
align-self: flex-start !important;
}
.align-self-end {
align-self: flex-end !important;
}
.align-self-center {
align-self: center !important;
}
.align-self-baseline {
align-self: baseline !important;
}
.align-self-stretch {
align-self: stretch !important;
}
.flex-flow-wrap{
flex-flow: wrap;
}

View File

@ -0,0 +1,73 @@
/* Color
-------------------------- */
/// color|1|Brand Color|0
$color-primary: #409EFF !default;
/// color|1|Background Color|4
$color-white: #FFFFFF !default;
/// color|1|Background Color|4
$color-black: #000000 !default;
/// color|1|Font Color|2
$color-text-primary: #303133 !default;
/// color|1|Font Color|2
$color-text-regular: #606266 !default;
/// color|1|Font Color|2
$color-text-secondary: #909399 !default;
/// color|1|Font Color|2
$color-text-placeholder: #C0C4CC !default;
/// color|1|Border Color|3
$border-color-base: #DCDFE6 !default;
/// color|1|Border Color|3
$border-color-light: #E4E7ED !default;
/// color|1|Border Color|3
$border-color-lighter: #EBEEF5 !default;
/// color|1|Border Color|3
$border-color-extra-light: #F2F6FC !default;
$bg-color-light: #F5F7FA !default;
$color-1960F4: #1960F4;
$color-1890FF: #1890FF;
$color-000000: #000000;
$color-F56C6C: #F56C6C;
// start::菜单选中颜色
$color-menu-active-bg: #E8EFFE;
$color-menu-active-text: $color-1960F4 !default;
// end::菜单选中颜色
// 文字大小
$f12: 12px;
$f14: 14px;
$f16: 16px;
$f18: 18px;
$f20: 20px;
$f22: 22px;
$f24: 24px;
$f32: 32px;
// 高度
$height20: 20px;
$height24: 24px;
$height30: 30px;
$height34: 34px;
$height40: 40px;
$height48: 48px;
$height56: 56px;
$height64: 64px;
$height90: 90px;
$height120:120px;
$height138: 138px;
/* 项目中的尺寸 8的倍数*/
$size8:8px;
$size10:10px;
$size16:16px;
$size22:22px;
$size24:24px;
$size32:32px;
$size40:40px;
$size72:72px;

View File

@ -0,0 +1,46 @@
<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName"/>
</svg>
<!-- 在组建中直接使用示例 icon-class值为svg的文件名-->
<!-- <svg-icon icon-class="user"></svg-icon> -->
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1.3em;
height: 1.3em;
fill: currentColor;
overflow: hidden;
vertical-align: middle;
}
</style>

View File

@ -0,0 +1,184 @@
<template>
<div class="layout-editor-wrap">
<!-- :value="content" -->
<!-- <quill-editor
class="editor"
ref="myQuillEditor"
v-model="content"
:options="editorOption"
@change="onEditorChange"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@ready="onEditorReady($event)"
/> -->
<quill-editor
class="editor"
ref="myQuillEditor"
:options="editorOption"
@change="onEditorChange"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@ready="onEditorReady($event)"
/>
<EditorUpload
ref="editorUpload"
:accept="accept"
@handleUploadSuccess="handleUploadSuccess"
/>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'
import { Quill } from 'vue-quill-editor'
import { ImageDrop } from 'quill-image-drop-module' //
import ImageResize from 'quill-image-resize-module' //
Quill.register('modules/imageDrop', ImageDrop)
Quill.register('modules/imageResize', ImageResize)
import { addQuillTitle } from './module/quill-title'
import { fontFamily, fontSize, toolbar} from './module/editor.config'
//
let Font = Quill.import('attributors/style/font')
Font.whitelist = fontFamily
Quill.register(Font, true)
//
let fontSizeStyle = Quill.import('attributors/style/size')
fontSizeStyle.whitelist = fontSize
Quill.register(fontSizeStyle,true) //
console.log(Font)
export default {
components: {
quillEditor,
EditorUpload: () => import('./module/EditorUpload.vue'),
},
props: {
editorHtml: {
type: String,
default: () => {
return "";
},
}
},
data() {
return {
editorOption: {
placeholder: '在此处输入内容…',
modules: {
imageDrop: true,
imageResize: {
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white',
},
modules: ['Resize', 'DisplaySize', 'Toolbar'],
},
toolbar: toolbar,
},
},
content: '',
accept: '.jpg,.jpeg,.png,.bmp,.gif',
}
},
computed: {
//
editor() {
return this.$refs.myQuillEditor.quill
},
},
// watch: {
// // content
// editorHtml: {
// handler(newVal) {
// console.log(newVal,"newVal")
// this.content = newVal;
// },
// deep: true,
// immediate: true,
// }
// },
mounted() {
console.log(this.editorHtml,"this.editorHtml")
this.content = this.editorHtml;
addQuillTitle()
let imgHandler = async (image) => {
console.log(image)
if (image) {
let fileInput = document.querySelector(
'.editor-upload-wrap .el-upload__input'
)
fileInput.click() //
}
}
this.editor.getModule('toolbar').addHandler('image', imgHandler)
},
methods: {
// onEditorChange(value) {
// this.$emit('onEditorChange', {
// content: this.content
// })
// },
onEditorChange(value) {
this.$emit('onEditorChange', {
content: value.html
})
},
onEditorBlur(editor) {
// console.log('editor blur!', editor)
this.$emit('onEditorBlur', {
editor: editor,
content: this.content
})
},
onEditorFocus(editor) {
// console.log('editor focus!', editor)
},
onEditorReady(editor) {
// console.log('editor ready!', editor)
},
handleUploadSuccess(file) {
if (file.length > 0) {
let Range = this.editor.getSelection();
//()
this.editor.insertEmbed(
Range != null ? Range.index : 0,
"image",
file
);
}
// todo
// if (file.src != null && file.src.length > 0) {
// let Range = this.editor.getSelection();
// let url = file.src.indexOf("http") != -1 ? file.src : "http:" + file.src;
// //()
// this.editor.insertEmbed(
// Range != null ? Range.index : 0,
// "image",
// url
// );
// }
},
},
}
</script>
<style lang="scss">
@import "./module/quill.scss";
.layout-editor-wrap{
.ql-align-right{
text-align: right;
}
}
</style>

View File

@ -0,0 +1,114 @@
<template>
<!-- 富文本编辑器----上传功能 -->
<div class="editor-upload-wrap">
<el-upload
class="upload-demo"
ref="upload"
action=""
:accept="accept"
:show-file-list="false"
:http-request="httpRequest"
>
<i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</template>
<script>
import file from '@/utils/file'
import commonApi from '@/services/fetchApi'
export default {
props: {
title: {
type: String,
default: '',
},
accept: {
type: String,
default: '*',
},
otherId: {
// id[planIdidid]
type: [String, Number],
default: ''
}
},
data() {
return {
file: file,
fileList: [],
activeIndex: -1,
fileIds: [], // id
}
},
created() {
},
methods: {
httpRequest(param) {
let name = file.getFileExtension(param.file.name)
//
if (this.accept != '*') {
if (this.accept.indexOf(name) === '-1') {
this.$message.error(`请上传格式为${this.accept}的文件`)
return
}
}
//
let fileSize = param.file.size / 1024 / 1024 //MB
if (fileSize > 10) {
this.$message.error('允许上传的文件最大尺寸为10MB')
return
}
let formdata = new FormData()
formdata.append('file', param.file)
commonApi.uploadFile(formdata).then((res) => {
// if (!res.cede) {
// this.fileIds.push(res.id)
this.fileList.push(res.url)
this.handleUpalodSuccess(res.url)
// }
})
// this.$emit('handleImport', param.file)
},
handleUpalodSuccess(data) {
this.$emit('handleUploadSuccess', data)
},
handleDelete(item, i) {
console.log(item)
// commonApi.deleteFile({ id: item.id }).then(res => {
// console.log('',res)
// if(!res.code) {
// this.$message.success('')
// this.fileList.splice(i,1)
// }
// })
},
handleDownload(item, i) {
let obj = {
bucketName: 'device-manage',
objectName: item.objectName
}
// commonApi.getMinioToken(obj).then(res => {
// if(!res.code) {
// commonApi.downloadFile({
// ...obj,
// token: res
// }).then(res => {
// file.downloadFileByBlob(res, item.fileName)
// })
// }
// })
},
getFileName: fileName => {
return fileName.substring(0, fileName.lastIndexOf('.'))
}
},
}
</script>
<style lang="scss" scoped>
.editor-upload-wrap{
display: none;
}
</style>

View File

@ -0,0 +1,48 @@
// 编辑器配置文件
// 字体
const fontFamily = [
'SimSun',
'SimHei',
'Microsoft-YaHei',
'幼圆',
'KaiTi',
'FangSong',
'Arial',
'Times-New-Roman',
'serif',
'sans-serif',
// 'Arial-Black',
// 'Arial-Narrow',
'Verdana',
'Georgia',
// 'Comic-Sans-MS',
'monospace',
'cursive'
]
// 字号
const fontSize = ['12px', '14px', '16px' ,'18px', '20px', '22px', '24px', '26px', '32px', '48px']
// 配置项
const toolbar = [
[{ font: fontFamily }], // 字体种类-----[{ font: [] }]
[{ size: fontSize }], // 字体大小-----[{ size: ['small', false, 'large', 'huge'] }]
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题-----[{ header: [1, 2, 3, 4, 5, 6, false] }]
[{ header: 1 }, { header: 2 }], // 1、2 级标题-----[{ header: 1 }, { header: 2 }]
['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线 -----['bold', 'italic', 'underline', 'strike']
['blockquote', 'code-block'], // 引用 代码块-----['blockquote', 'code-block']
[{ align: [] }], // 对齐方式-----[{ align: [] }]
[{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表-----[{ list: 'ordered' }, { list: 'bullet' }]
[{ script: 'sub' }, { script: 'super' }], // 上标/下标-----[{ script: 'sub' }, { script: 'super' }]
[{ indent: '-1' }, { indent: '+1' }], // 缩进-----[{ indent: '-1' }, { indent: '+1' }]
[{ direction: 'rtl' }], // 文本方向-----[{'direction': 'rtl'}]
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色-----[{ color: [] }, { background: [] }]
['clean'], // 清除文本格式-----['clean']
// ['image', 'link'], // 链接、图片、视频-----['link', 'image', 'video']
]
export {
fontFamily,
fontSize,
toolbar
}

View File

@ -0,0 +1,49 @@
const titleConfig = {
"ql-bold": "加粗",
"ql-color": "颜色",
"ql-font": "字体",
"ql-code": "插入代码",
"ql-italic": "斜体",
"ql-link": "添加链接",
"ql-background": "背景颜色",
"ql-size": "字体大小",
"ql-strike": "删除线",
"ql-script": "上标/下标",
"ql-underline": "下划线",
"ql-blockquote": "引用",
"ql-header": "标题",
"ql-indent": "缩进",
"ql-list": "列表",
"ql-align": "文本对齐",
"ql-direction": "文本方向",
"ql-code-block": "代码块",
"ql-formula": "公式",
"ql-image": "图片",
"ql-video": "视频",
"ql-clean": "清除字体样式",
};
export function addQuillTitle() {
const oToolBar = document.querySelector(".ql-toolbar"),
aButton = oToolBar.querySelectorAll("button"),
aSelect = oToolBar.querySelectorAll("select");
aButton.forEach(function(item) {
if (item.className === "ql-script") {
item.value === "sub" ? (item.title = "下标") : (item.title = "上标");
} else if (item.className === "ql-indent") {
item.value === "+1"
? (item.title = "向右缩进")
: (item.title = "向左缩进");
} else {
// console.log(item)
item.title = titleConfig[item.classList[0]];
}
});
aSelect.forEach(function(item) {
console.log(item, item.className)
if(item.className === 'ql-color' || item.className === 'ql-background') {
item.previousSibling.title = titleConfig[item.classList[0]];
} else{
item.parentNode.title = titleConfig[item.classList[0]];
}
});
}

View File

@ -0,0 +1,465 @@
.layout-editor-wrap {
display: flex;
flex-direction: column;
.editor {
line-height: normal !important;
// height: 200px;
height: 350px;
box-sizing: border-box;
tab-size: 4;
outline: none;
white-space: pre-wrap;
word-wrap: break-word;
margin-bottom: 15px;
}
.ql-editor.ql-blank::before {
font-style: normal;
}
.ql-container {
height: calc(100% - 66px);
}
.ql-snow .ql-tooltip[data-mode='link']::before {
content: '请输入链接地址:';
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: '保存';
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode='video']::before {
content: '请输入视频地址:';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
content: '12px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
font-size: 12px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: '14px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
font-size: 14px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: '16px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
font-size: 16px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
content: '18px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: '20px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
font-size: 20px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
content: '22px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
font-size: 22px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
content: '24px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
font-size: 24px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
content: '26px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
font-size: 26px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
content: '32px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
font-size: 32px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="48px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="48px"]::before {
content: '48px';
}
// select选择的字体大小
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="48px"]::before {
font-size: 48px;
}
.ql-editor .ql-size-12px {
font-size: 12px;
}
.ql-editor .ql-size-14px {
font-size: 14px;
}
.ql-editor .ql-size-16px {
font-size: 16px;
}
.ql-editor .ql-size-18px {
font-size: 18px;
}
.ql-editor .ql-size-20px {
font-size: 20px;
}
.ql-editor .ql-size-22px {
font-size: 22px;
}
.ql-editor .ql-size-24px {
font-size: 24px;
}
.ql-editor .ql-size-26px {
font-size: 26px;
}
.ql-editor .ql-size-32px {
font-size: 32px;
}
.ql-editor .ql-size-48px {
font-size: 48px;
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
content: '标题6';
}
.ql-snow .ql-picker.ql-font {
min-width: 150px;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimSun']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimSun']::before {
content: '宋体';
font-family: 'SimSun';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimHei']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimHei']::before {
content: '黑体';
font-family: 'SimHei';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Microsoft-YaHei']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Microsoft-YaHei']::before {
content: '微软雅黑';
font-family: 'Microsoft YaHei';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='幼圆']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='幼圆']::before {
content: '幼圆';
font-family: '幼圆';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='KaiTi']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='KaiTi']::before {
content: '楷体';
font-family: 'KaiTi';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='FangSong']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='FangSong']::before {
content: '仿宋';
font-family: 'FangSong';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='Arial']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='Arial']::before {
content: 'Arial';
font-family: 'Arial';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Times-New-Roman']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Times-New-Roman']::before {
content: 'Times New Roman';
font-family: 'Times New Roman';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='serif']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='serif']::before {
content: 'serif';
font-family: 'serif';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='sans-serif']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='sans-serif']::before {
content: 'sans-serif';
font-family: 'sans-serif';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Arial-Black']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Arial-Black']::before {
content: 'Arial Black';
font-family: 'Arial Black';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Arial-Narrow']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Arial-Narrow']::before {
content: 'Arial Narrow';
font-family: 'Arial Narrow';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Verdana']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Verdana']::before {
content: 'Verdana';
font-family: Verdana;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Georgia']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Georgia']::before {
content: 'Georgia';
font-family: Georgia;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Comic-Sans-MS']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Comic-Sans-MS']::before {
content: 'Comic Sans MS';
font-family: 'Comic Sans MS';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='monospace']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='monospace']::before {
content: 'monospace';
font-family: monospace;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='cursive']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='cursive']::before {
content: 'cursive';
font-family: cursive;
}
.ql-font-SimSun {
font-family: 'SimSun';
}
.ql-font-SimHei {
font-family: 'SimHei';
}
.ql-font-Microsoft-YaHei {
font-family: 'Microsoft YaHei';
}
.ql-font-KaiTi {
font-family: 'KaiTi';
}
.ql-font-FangSong {
font-family: 'FangSong';
}
.ql-font-Arial {
font-family: 'Arial';
}
.ql-font-Times-New-Roman {
font-family: 'Times New Roman';
}
.ql-font-serif {
font-family: 'serif';
}
.ql-font-sans-serif {
font-family: 'sans-serif';
}
.ql-font-Arial-Black {
font-family: 'Arial Black';
}
.ql-font-Arial-Narrow {
font-family: 'Arial Narrow';
}
.ql-font-Verdana {
font-family: Verdana;
}
.ql-font-Georgia {
font-family: Georgia;
}
.ql-font-Comic-Sans-MS {
font-family: 'Comic Sans MS';
}
.ql-font-monospace {
font-family: monospace;
}
.ql-font-cursive {
font-family: cursive;
}
//------------------------------------------修改样式----------------------------------------------
// .ql-toolbar.ql-snow .ql-picker-label {
// border: 1px solid red;
// }
.ql-toolbar.ql-snow .ql-formats {
margin-right: 5px;
border: 1px solid #9e9898;
margin-top: 2px;
}
.ql-toolbar.ql-snow {
font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
padding: 2px 8px 4px 8px;
}
// 边框线
.ql-toolbar.ql-snow {
border-color: #DCDFE6;
}
.ql-container.ql-snow {
border-color: #DCDFE6;
}
// 头部字体颜色
.ql-snow .ql-picker{
// color: #dbdce5;
}
.ql-snow .ql-stroke {
// stroke: #dbdce5;
}
.ql-snow .ql-fill, .ql-snow .ql-stroke.ql-fill{
// fill:#dbdce5
}
// 下拉背景色
.ql-snow .ql-picker-options {
// background-color: #112660;
}
// 下拉边框
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
// border-color: #173659;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
// border-color: #173659;
}
// 下拉选中效果
.ql-snow.ql-toolbar button:hover, .ql-snow .ql-toolbar button:hover, .ql-snow.ql-toolbar button:focus, .ql-snow .ql-toolbar button:focus, .ql-snow.ql-toolbar button.ql-active, .ql-snow .ql-toolbar button.ql-active, .ql-snow.ql-toolbar .ql-picker-label:hover, .ql-snow .ql-toolbar .ql-picker-label:hover, .ql-snow.ql-toolbar .ql-picker-label.ql-active, .ql-snow .ql-toolbar .ql-picker-label.ql-active, .ql-snow.ql-toolbar .ql-picker-item:hover, .ql-snow .ql-toolbar .ql-picker-item:hover, .ql-snow.ql-toolbar .ql-picker-item.ql-selected, .ql-snow .ql-toolbar .ql-picker-item.ql-selected {
// color: #409eff;
}
// 下拉默认字体颜色
.layout-editor-wrap .ql-snow .ql-picker {
// color: #112660;
}
// 输入框内默认的字体颜色
.ql-editor.ql-blank::before {
color: #ffffff96;
}
// .ql-editor p{
// color: #dbdce5;
// }
// .ql-editor u{
// color: #dbdce5;
// }
.ql-snow .ql-editor pre.ql-syntax{
// background-color: #15428d;
}
}

View File

@ -0,0 +1,283 @@
<template>
<div class="upload-file-wrap">
<el-row :gutter="24">
<el-col :span="span" v-if="isInCount">
<div class="el-col-ctn-box">
<div class="el-col-upload-box">
<el-upload
class="el-upload-box"
ref="upload"
action=""
:accept="accept"
:show-file-list="false"
:http-request="httpRequest"
>
<div class="upload-file">
<i class="el-icon-plus uploader-file-icon"></i>
<div class="f14 color-text-secondary text-center">上传材料</div>
</div>
</el-upload>
<div class="f14 text-center color-text-regular line-height-30">{{uploadName}}</div>
</div>
</div>
</el-col>
<!--上传的图片预览-->
<el-col :span="span" v-for="(item,i) in lists" :key="i" >
<div class="el-col-ctn-box "
@click="handlePreview(item)">
<div class="el-col-upload-box">
<div class="upload-preview-box">
<img v-if="item.deletable && !readOnly"
class="upload-delete-icon" src="../assets/image/icon_close.png" alt=""
@click.stop.prevent="handleDelete(item, i)">
<div class="upload-file">
<el-image class="el-image-upload" :src="item.iconFrontSrc" fit="scale-down"></el-image>
</div>
</div>
<div class="f14 text-center color-text-regular line-height-30">
{{showFileName ? item.fileName : uploadName}}
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import projectConfig from "../services/projectConfig";
export default {
name: "uploadFile",
props: {
span: {
// layout
type: Number,
default: 5
},
accept: {
type: String,
default: '*',
},
imageHeight: {
//
type: String,
default: ''
},
imageMode: {
// ,uni image
type: String,
default: 'aspectFit'
},
readOnly: {
// true-false-
type: Boolean,
default: false
},
fileList: {
//
type: [Array, Object],
default: () => {
return [
//{ url:, fileName: }
]
}
},
uploadName: {
//
type: String,
default: '上传'
},
maxCount: {
//
type: Number,
default: 1
},
selectCount: {
//
type: Number,
default: 1
},
customUpload: {
//
type: Boolean,
default: false
},
autoUpload: {
//
type: Boolean,
default: true
},
showFileName: {
//
type: Boolean,
default: false
},
splitFileTitle: {
//
type: Boolean,
default: true
},
},
data() {
return {
lists: [
//{url: , fileName: , deletable: , readStatus: , iconFrontSrc: }
],
srcList: [],
}
},
computed: {
isInCount() {
return (this.lists.length < this.maxCount) && !this.readOnly
},
},
watch: {
//
fileList: {
immediate: true,
handler() {
this.formatFileList()
}
},
},
methods: {
formatFileList() {
let fileList = this.fileList || []
this.srcList = []
fileList = JSON.parse(JSON.stringify(fileList))
// console.log('upload===========formatFileList()==========fileList', fileList)
const lists = fileList.map(item => {
let obj = Object.assign(item)
obj.deletable = typeof(obj.deletable) === 'boolean' ? obj.deletable : true
let text = obj.url || obj.fileName
obj.fileType = this.$util.getFileExtension(text)
// ()
obj.iconFrontSrc = this.$util.getIcon(obj)
// let previewUrl = `${projectConfig.fileHost}${obj.url}`
let previewUrl = `/manage-center/minio/preview/${obj.url}`
if(obj.url.includes('http')){
previewUrl = obj.url
}
obj.previewUrl = previewUrl
if(this.$util.getFileType(text) === 'image') {
//
obj.iconFrontSrc = obj.previewUrl
}
this.srcList.push(obj.iconFrontSrc)
return obj
});
this.lists = lists
// console.log('uploadFile----:', this.lists)
// this.isInCount = (lists.length < this.maxCount) && !this.readOnly
},
async httpRequest(param) {
// console.log('httpRequest',param)
let fileType = this.$util.getFileExtension(param.file.name)
if(this.accept !== '*' && this.accept.indexOf(fileType) === -1) {
this.$message.warning(`不能上传${fileType}格式的文件`)
return
}
try{
let formData = new FormData()
formData.append('file', param.file)
// let uploadFileRes = await fetchApi.uploadFile(formData);
let uploadFileRes = await this.$fetchApi.uploadFile(formData);
// console.log(uploadFileRes)
let fileList = JSON.parse(JSON.stringify(this.fileList))
fileList.push({
url: uploadFileRes.url,
fileSize: uploadFileRes.size
})
this.$emit('handleUploadFile', fileList)
}catch (e) {
this.$message.error(e.msg)
}
},
async handlePreview(item) {
// console.log(item,111111)
try {
let res = await this.$fetchApi.getMinioToken({objectName: item.url})
// console.log(res)
window.open(`${item.previewUrl}?token=${res}`, '_target')
}catch (e) {
this.$message.error(e.msg || e)
}
},
handleDelete(item, i) {
this.lists.splice(i, 1)
let fileList = JSON.parse(JSON.stringify(this.fileList))
fileList.splice(i, 1)
this.$emit('handleUploadFile', fileList)
}
},
}
</script>
<style lang="scss">
.el-col-ctn-box{
width: 100%;
height: 160px;
}
.el-col-upload-box{
width: 120px;
height: 160px;
border-radius: 4px;
overflow: hidden;
}
.el-upload-box{
width: 100%;
height: 120px;
background: #F5F7FA;
border: 1px dashed #EBEEF5;
}
.el-col-ctn-box .el-upload,
.el-col-ctn-box .upload-file{
width: 100% !important;
}
.el-col-ctn-box .upload-preview-box{
position: relative;
height: 120px;
border: 1px dashed #EBEEF5;
}
.el-col-ctn-box .upload-delete-icon{
width: 30px;
height: auto;
position: absolute;
right: 0;
top: 0;
cursor: pointer;
z-index: 11111;
}
.el-col-ctn-box .upload-file{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 120px;
}
.el-col-ctn-box .uploader-file-icon{
font-size: 32px;
color: $color-text-secondary;
}
.el-col-ctn-box .el-image-upload{
border-radius: 4px;
padding: 5px;
box-sizing: border-box;
}
.el-col-ctn-box .txt-center{
height: 40px;
line-height: 20px;
}
.line-height-30{
line-height: 30px;
}
</style>

View File

@ -0,0 +1,308 @@
<template>
<div class="upload-file-wrap">
<el-row :gutter="24">
<el-col :span="span" v-if="isInCount">
<div class="el-col-ctn-box-name">
<div class="el-col-upload-box-name">
<el-upload
class="el-upload-box-name"
ref="upload"
action=""
:accept="accept"
:show-file-list="false"
:http-request="httpRequest"
>
<div class="upload-file">
<i class="el-icon-plus uploader-file-icon"></i>
<div class="f14 color-text-secondary text-center">上传材料</div>
</div>
</el-upload>
<div class="f14 text-center color-text-regular line-height-30">{{uploadName}}</div>
</div>
</div>
</el-col>
<!--上传的图片预览-->
<el-col :span="span" v-for="(item,i) in lists" :key="i" >
<div class="el-col-ctn-box-name ">
<div class="el-col-upload-box-name">
<div class="upload-preview-box" @click="handlePreview(item)">
<img v-if="item.deletable && !readOnly"
class="upload-delete-icon" src="../assets/image/icon_close.png" alt=""
@click.stop.prevent="handleDelete(item, i)">
<div class="upload-file">
<el-image class="el-image-upload" :src="item.iconFrontSrc" fit="scale-down"></el-image>
</div>
</div>
<div class="f14 text-center color-text-regular line-height-30">
<!-- {{showFileName ? item.fileName : uploadName}} -->
<el-input v-model.trim="item.fileName"
size="small"
clearable
@change="handleChangeName(lists)"
>
</el-input>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import projectConfig from "../services/projectConfig";
export default {
name: "uploadFile",
props: {
span: {
// layout
type: Number,
default: 5
},
accept: {
type: String,
default: '*',
},
imageHeight: {
//
type: String,
default: ''
},
imageMode: {
// ,uni image
type: String,
default: 'aspectFit'
},
readOnly: {
// true-false-
type: Boolean,
default: false
},
fileList: {
//
type: [Array, Object],
default: () => {
return [
//{ url:, fileName: }
]
}
},
uploadName: {
//
type: String,
default: '上传'
},
maxCount: {
//
type: Number,
default: 1
},
selectCount: {
//
type: Number,
default: 1
},
customUpload: {
//
type: Boolean,
default: false
},
autoUpload: {
//
type: Boolean,
default: true
},
showFileName: {
//
type: Boolean,
default: false
},
splitFileTitle: {
//
type: Boolean,
default: true
},
},
data() {
return {
lists: [
//{url: , fileName: , deletable: , readStatus: , iconFrontSrc: }
],
srcList: [],
}
},
computed: {
isInCount() {
return (this.lists.length < this.maxCount) && !this.readOnly
},
},
watch: {
//
fileList: {
immediate: true,
handler() {
this.formatFileList()
}
},
},
methods: {
formatFileList() {
let fileList = this.fileList || []
this.srcList = []
fileList = JSON.parse(JSON.stringify(fileList))
console.log('upload===========formatFileList()方法==========fileList', fileList)
const lists = fileList.map(item => {
let obj = Object.assign(item)
obj.deletable = typeof(obj.deletable) === 'boolean' ? obj.deletable : true
let text = obj.url || obj.fileName
obj.fileType = this.$util.getFileExtension(text)
// ()
obj.iconFrontSrc = this.$util.getIcon(obj)
// let previewUrl = `${projectConfig.fileHost}${obj.url}`
let previewUrl = `/manage-center/minio/preview/${obj.url}`
if(obj.url.includes('http')){
previewUrl = obj.url
}
obj.previewUrl = previewUrl
if(this.$util.getFileType(text) === 'image') {
//
obj.iconFrontSrc = obj.previewUrl
}
this.srcList.push(obj.iconFrontSrc)
obj.fileName = item.fileName
return obj
});
this.lists = lists
console.log('uploadFile----:', this.lists)
},
async httpRequest(param) {
console.log('httpRequest上传文件',param)
let fileType = this.$util.getFileExtension(param.file.name)
if(this.accept !== '*' && this.accept.indexOf(fileType) === -1) {
this.$message.warning(`不能上传${fileType}格式的文件`)
return
}
try{
let formData = new FormData()
formData.append('file', param.file)
let uploadFileRes = await this.$fetchApi.uploadFile(formData);
// console.log(uploadFileRes)
let fileList = JSON.parse(JSON.stringify(this.fileList))
// let time = this.$util.getTimestamp()
// let fileType = this.$util.getFileExtension(uploadFileRes.url)
// let fileName = `${time}.${fileType}`
fileList.push({
url: uploadFileRes.url,
fileName:uploadFileRes.fileName
})
this.$emit('handleUploadFile', fileList)
}catch (e) {
this.$message.error(e.msg)
}
},
async handlePreview(item) {
console.log(item)
try {
let res = await this.$fetchApi.getMinioToken({objectName: item.url})
console.log(res)
window.open(`${item.previewUrl}?token=${res}`, '_target')
}catch (e) {
this.$message.error(e.msg || e)
}
},
handleChangeName(list){
console.log('名字===',list)
let listData = list.map((item,i) => {
return {
url: item.url,
fileName:item.fileName
}
})
this.$emit('handleUploadFile', listData)
},
handleDelete(item, i) {
this.lists.splice(i, 1)
let fileList = JSON.parse(JSON.stringify(this.fileList))
fileList.splice(i, 1)
this.$emit('handleUploadFile', fileList)
}
},
}
</script>
<style lang="scss">
.el-col-ctn-box-name{
width: 100%;
height: 180px;
}
.el-col-upload-box-name{
width: 120px;
height: 180px;
border-radius: 4px;
overflow: hidden;
}
.el-upload-box-name{
width: 100%;
height: 120px;
background: #F5F7FA;
border: 1px dashed #EBEEF5;
margin-bottom: 10px;
}
.el-col-ctn-box-name .el-upload,
.el-col-ctn-box-name .upload-file{
width: 100% !important;
}
.el-col-ctn-box-name .upload-preview-box{
position: relative;
height: 120px;
border: 1px dashed #EBEEF5;
margin-bottom: 10px;
}
.el-col-ctn-box-name .upload-delete-icon{
width: 30px;
height: auto;
position: absolute;
right: 0;
top: 0;
cursor: pointer;
z-index: 11111;
}
.el-col-ctn-box-name .upload-file{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 120px;
}
.el-col-ctn-box-name .uploader-file-icon{
font-size: 32px;
color: $color-text-secondary;
}
.el-col-ctn-box-name .el-image-upload{
border-radius: 4px;
padding: 5px;
box-sizing: border-box;
}
.el-col-ctn-box-name .txt-center{
height: 40px;
line-height: 20px;
}
.line-height-30{
line-height: 30px;
}
// .el-input__inner{
// text-align: center;
// }
</style>

View File

@ -0,0 +1,296 @@
<template>
<div class="upload-file-wrap">
<el-row :gutter="24">
<el-col :span="span" v-if="isInCount">
<div class="el-col-ctn-box-import">
<div class="el-col-upload-box">
<el-upload
class="el-upload-box"
ref="upload"
drag
action=""
:accept="accept"
:show-file-list="false"
:http-request="httpRequest"
>
<div class="upload-file">
<div class="f14 color-text-secondary text-center">
<span class="color-1960F4">点击上传</span>
<span class="m-h-8 color-000">/</span>拖拽到此区域
</div>
</div>
</el-upload>
<div class="text-center color-text-secondary f12 p-v-8">请上传Excel文件大小在60M以内</div>
</div>
</div>
</el-col>
<!--上传的图片预览-->
<el-col :span="span" v-for="(item,i) in lists" :key="i" >
<div class="el-col-ctn-box-import"
@click="handlePreview(item)">
<div class="el-col-upload-box">
<div class="upload-preview-box">
<img v-if="item.deletable && !readOnly"
class="upload-delete-icon" src="../assets/image/icon_close.png" alt=""
@click.stop.prevent="handleDelete(item, i)">
<div class="upload-file">
<el-image class="el-image-upload" :src="item.iconFrontSrc" fit="scale-down"></el-image>
</div>
</div>
<div class="f14 text-center color-text-regular line-height-30">
{{showFileName ? item.fileName : uploadName}}
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import projectConfig from "../services/projectConfig";
export default {
name: "uploadFile",
props: {
span: {
// layout
type: Number,
default: 5
},
accept: {
type: String,
default: '*',
},
imageHeight: {
//
type: String,
default: ''
},
imageMode: {
// ,uni image
type: String,
default: 'aspectFit'
},
readOnly: {
// true-false-
type: Boolean,
default: false
},
fileList: {
//
type: [Array, Object],
default: () => {
return [
//{ url:, fileName: }
]
}
},
uploadName: {
//
type: String,
default: '上传'
},
maxCount: {
//
type: Number,
default: 1
},
selectCount: {
//
type: Number,
default: 1
},
customUpload: {
//
type: Boolean,
default: false
},
autoUpload: {
//
type: Boolean,
default: true
},
showFileName: {
//
type: Boolean,
default: false
},
splitFileTitle: {
//
type: Boolean,
default: true
},
},
data() {
return {
lists: [
//{url: , fileName: , deletable: , readStatus: , iconFrontSrc: }
],
srcList: [],
}
},
computed: {
isInCount() {
return (this.lists.length < this.maxCount) && !this.readOnly
},
},
watch: {
//
fileList: {
immediate: true,
handler() {
this.formatFileList()
}
},
},
methods: {
formatFileList() {
let fileList = this.fileList || []
this.srcList = []
fileList = JSON.parse(JSON.stringify(fileList))
// console.log('upload===========formatFileList()==========fileList', fileList)
const lists = fileList.map(item => {
let obj = Object.assign(item)
obj.deletable = typeof(obj.deletable) === 'boolean' ? obj.deletable : true
let text = obj.url || obj.fileName
obj.fileType = this.$util.getFileExtension(text)
// ()
obj.iconFrontSrc = this.$util.getIcon(obj)
let previewUrl = `/manage-center/minio/preview/${obj.url}`
if(obj.url.includes('http')){
previewUrl = obj.url
}
obj.previewUrl = previewUrl
if(this.$util.getFileType(text) === 'image') {
//
obj.iconFrontSrc = obj.previewUrl
}
this.srcList.push(obj.iconFrontSrc)
return obj
});
this.lists = lists
console.log('uploadFile----:', this.lists)
// this.isInCount = (lists.length < this.maxCount) && !this.readOnly
},
async httpRequest(param) {
console.log('httpRequest上传文件',param)
let fileType = this.$util.getFileExtension(param.file.name)
if(this.accept !== '*' && this.accept.indexOf(fileType) === -1) {
this.$message.warning(`不能上传${fileType}格式的文件`)
return
}
let size = param.file.size/1024/1024
if(size > 60){
this.$message.warning(`文件大小不能超过60M`)
return
}
this.$emit('handleImport', param.file)
try{
let formData = new FormData()
console.log('上传时的',param.file)
formData.append('file', param.file)
// let uploadFileRes = await fetchApi.uploadFile(formData);
let uploadFileRes = await this.$fetchApi.uploadFile(formData);
console.log(uploadFileRes)
let fileList = JSON.parse(JSON.stringify(this.fileList))
fileList.push({
url: uploadFileRes.url,
})
this.$emit('handleUploadFile', fileList)
}catch (e) {
this.$message.error(e.msg)
}
},
async handlePreview(item) {
console.log(item)
try {
let res = await this.$fetchApi.getMinioToken({objectName: item.url})
console.log(res)
window.open(`${item.previewUrl}?token=${res}`, '_target')
}catch (e) {
this.$message.error(e.msg || e)
}
},
handleDelete(item, i) {
this.lists.splice(i, 1)
let fileList = JSON.parse(JSON.stringify(this.fileList))
fileList.splice(i, 1)
this.$emit('handleUploadFile', fileList)
}
},
}
</script>
<style lang="scss">
.el-col-ctn-box-import{
width: 344px;
height: 180px;
.el-col-upload-box{
width: 344px;
height: 180px;
border-radius: 4px;
overflow: hidden;
}
.el-upload-dragger{
width: 100%;
height: 144px;
}
.el-upload-box{
width: 100%;
height: 144px;
// border: 2px dashed #EBEEF5;
}
}
.el-col-ctn-box-import .el-upload,
.el-col-ctn-box-import .upload-file{
width: 100% !important;
}
.el-col-ctn-box-import .upload-preview-box{
position: relative;
height: 144px;
border: 1px dashed #EBEEF5;
}
.el-col-ctn-box-import .upload-delete-icon{
width: 30px;
height: auto;
position: absolute;
right: 0;
top: 0;
cursor: pointer;
z-index: 11111;
}
.el-col-ctn-box-import .upload-file{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 144px;
}
.el-col-ctn-box-import .uploader-file-icon{
font-size: 32px;
color: $color-text-secondary;
}
.el-col-ctn-box-import .el-image-upload{
border-radius: 4px;
padding: 5px;
box-sizing: border-box;
}
.el-col-ctn-box-import .txt-center{
height: 40px;
line-height: 20px;
}
.line-height-30{
line-height: 30px;
}
</style>

148
src/filters/index.js Normal file
View File

@ -0,0 +1,148 @@
// 封装过滤器 调用方式 如:姓名脱敏 <!-- nameHide全局过滤器 --> {{ name | nameHide }}
// 用链式调用的方式在一个表达式中使用多个过滤器 {{productOneCost| round}}
// 过滤器同样可以接收参数,在下面这个例子中,输入的字符串会作为第二个参数传递给过滤器函数: {{productOneCost| numToFixed('$')}}
// 根据身份证号码判断男女
let sexIdcardFilter = value => {
if (!value) {
return "";
} else {
let data = value.substr(16, 1) % 2 === 1 ? "男" : "女";
return data;
}
};
// 身份证号脱敏('331082199708094687' 转换成 '33108219********87') 第8位开始替换8个
let IDcardHide = num => {
let data = num.replace(/(\d{8})\d{8}(\d*)/, "$1********$2");
return data;
};
// 手机号脱敏('13912345678' 转换成 '139****5678') 第3位开始替换4个
let telHide = num => {
let data = num.replace(/(\d{3})\d{4}(\d*)/, "$1****$2");
return data;
};
// 姓名脱敏(小明 转换成 *明 李小明 转换成 李*明 欧阳小明 转换成 欧**明)
let nameHide = name => {
if (name.length === 2) {
return new Array(name.length).join("*") + name.substr(-1);
} else {
return (
name.substr(0, 1) + new Array(name.length - 1).join("*") + name.substr(-1)
);
}
};
//字符串循环复制,count->次数
let repeatStr = (value, count) => {
var text = '';
for (var i = 0; i < count; i++) {
text += value;
}
return text;
}
// 数字/浮点数保留n位小数点 num 位数
let numToFixed = (value = 0, num = 2) => {
value = Number(value)
value = isNaN(value) ? 0 : value
return value.toFixed(num)
}
//去除空格 type 1-所有空格 2-前后空格 3-前空格 4-后空格
let trim = (value, trim) => {
switch (trim) {
case 1:
return value.replace(/\s+/g, "");
case 2:
return value.replace(/(^\s*)|(\s*$)/g, "");
case 3:
return value.replace(/(^\s*)/g, "");
case 4:
return value.replace(/(\s*$)/g, "");
default:
return value;
}
}
//现金额大写转换函数
let upDigit = (n) => {
var fraction = ['角', '分', '厘'];
var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
var unit = [['元', '万', '亿'],['', '拾', '佰', '仟']];
var head = n < 0 ? '欠' : '';
n = Math.abs(n);
var s = '';
for (var k = 0; k < fraction.length; k++) {
s += (digit[Math.floor(n * 10 * Math.pow(10, k)) % 10] + fraction[k]).replace(/零./, '');
}
s = s || '整';
n = Math.floor(n);
for (var i = 0; i < unit[0].length && n > 0; i++) {
var p = '';
for (var j = 0; j < unit[1].length && n > 0; j++) {
p = digit[n % 10] + unit[1][j] + p;
n = Math.floor(n / 10);
}
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
//s = p + unit[0][i] + s;
}
return head + s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整');
}
//任意格式日期处理
//使用格式:
// {{ '2021-04-26 11:05' | formaDate('yyyy-MM-dd hh:mm:ss') }}
// {{ '2021-04-26 11:05' | formaDate('yyyy-MM-dd') }}
// {{ '2021-04-26 11:05' | formaDate('MM/dd') }} 等
let formaDate = (value, fmt) => {
var date = new Date(value);
var o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"w+": date.getDay(), //星期
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o) {
if(k === 'w+') {
if(o[k] === 0) {
fmt = fmt.replace('w', '周日');
}else if(o[k] === 1) {
fmt = fmt.replace('w', '周一');
}else if(o[k] === 2) {
fmt = fmt.replace('w', '周二');
}else if(o[k] === 3) {
fmt = fmt.replace('w', '周三');
}else if(o[k] === 4) {
fmt = fmt.replace('w', '周四');
}else if(o[k] === 5) {
fmt = fmt.replace('w', '周五');
}else if(o[k] === 6) {
fmt = fmt.replace('w', '周六');
}
}else if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
}
export default {
sexIdcardFilter,
IDcardHide,
telHide,
nameHide,
repeatStr,
numToFixed,
trim,
upDigit,
formaDate
};

71
src/main.js Normal file
View File

@ -0,0 +1,71 @@
import Vue from 'vue'
import App from './App.vue'
import fetchApi from './services/fetchApi'
import router from './router' /*引入路由设置*/
import store from './store' /*引入store vuex设置*/
import MetaInfo from 'vue-meta-info' /*动态设置meta标签*/
import './assets/icons' // svg图标
import filter from "./filters";
import util from "./utils/util"
import verify from "./utils/verify"
import clickThrottle from "./utils/clickThrottle"
import {Message,Loading} from 'element-ui'
import * as echarts from 'echarts'; /*echarts图表 示例 https://echarts.apache.org/examples/zh/index.html */
import ElementUI from 'element-ui';
import './assets/style/element-ui-variable.scss'
// import 'element-ui/lib/theme-chalk/index.css';
import 'element-ui/lib/theme-chalk/icon.css'
Vue.use(ElementUI);
// 全局导入过滤器
Object.keys(filter).forEach(key => Vue.filter(key, filter[key]));
Vue.prototype.$message = Message;
Vue.prototype.$loading = Loading.service;
Vue.prototype.$fetchApi = fetchApi;
Vue.prototype.$util = util;
Vue.prototype.$verify = verify;
Vue.prototype.$clickThrottle = clickThrottle;
Vue.prototype.$echarts = echarts;
// vue使用vue-meta-info来动态设置标题
Vue.use(MetaInfo)
new Vue({
data(){
return {
keyWords:null,//关键字
description:null,//描述
sitetitle:null,//标题
sitetitleinit:null//
}
},
metaInfo () {
return {
title: this.sitetitle,
meta: [{name: 'keyWords',content: this.keyWords},{name: 'description',content: this.description}]
}
},
router,
store,
render: h => h(App),
watch:{
'$route': function(to, from) {
console.log(to,from,'路由信息')
if(to.meta.title!=null&&to.meta.sitetitleinit!=null)
{
this.sitetitle=to.meta.title+'-'+this.sitetitleinit;
}
if(to.meta.sitetitleinit!=null)
{
this.sitetitle=this.sitetitleinit;
}
else
{
this.sitetitle=to.meta.title;
}
}
}
}).$mount('#app')

View File

@ -0,0 +1,3 @@
<template>
<div class="layout-content-wrap">基本设置</div>
</template>

View File

@ -0,0 +1,196 @@
<template>
<div>
<el-dialog
:title="addDictDialog.title"
:visible="true"
width="600px"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<el-scrollbar class="bor">
<div class="dialog-content">
<el-form ref="ruleForm"
:model="queryParam"
:rules="rulesClient"
label-width="120px"
class="demo-ruleForm">
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="字典标签" prop="type">
<el-select v-model="queryParam.type"
clearable placeholder="请选择"
class="width100">
<el-option
v-for="item in operateMethodOptions"
:key="item.code"
:label="item.desc"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="字典名称" prop="codeName">
<el-input
v-model.trim="queryParam.codeName"
placeholder="请输入字典名称"
clearable maxlength="20"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="字典编码" prop="code">
<el-input
v-model.trim="queryParam.code"
placeholder="请输入字典编码"
clearable maxlength="20"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="排序" prop="seq">
<el-input-number v-model="queryParam.seq" :min="1" :max="999" label="请输入" class="width100"></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
:rows="3"
placeholder="请输入内容"
maxlength="60"
v-model="queryParam.remark">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</el-scrollbar>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose()">取消</el-button>
<el-button type="primary" @click="handleSubmit()">确认</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import api from "@/services/basicManage";
export default {
components: {
uploadFile: () => import('../../../../components/uploadFile.vue'),//
},
props: {
addDictDialog: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {
queryParam:{
type:'',
typeName:'',
code:'',
codeName:'',//
remark:'',
seq:225
},
rulesClient: {
type: [
{ required: true, message: '请选择字典标签', trigger: 'change',},
],
code: [
{ required: true, message: '请输入字典编码', trigger: 'change',},
],
codeName: [
{ required: true, message: '请输入字典名称', trigger: 'change',},
]
},
operateMethodOptions:[{code:"financial",desc:"金融产品类型"}],
};
},
mounted () {
this.getDictTypeList()
if(Object.keys(this.addDictDialog.data).length>0)
{
this.queryParam = JSON.parse(JSON.stringify(this.addDictDialog.data));
}
},
methods: {
getDictTypeList(){
api.getDictTypeEnum({}).then(res => {
if (!res.code) {
this.operateMethodOptions = res;
}
})
},
handleSubmit(){
if(!this.$clickThrottle()) { return }
let _this=this;
this.$refs.ruleForm.validate((valid) => {
if(valid) {
let typeitem=this.operateMethodOptions.find(item => {
return item.code === _this.queryParam.type
})
_this.queryParam.typeName=typeitem.desc;
if(Object.keys(this.addDictDialog.data).length>0)
{
api.updateDictById(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '编辑数据字典成功!',
type: 'success'
});
this.handleClose()
this.$parent.getDictList(1)
})
}
else
{
api.addDict(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '新增数据字典成功!',
type: 'success'
});
this.handleClose()
this.$parent.getDictList(1)
})
}
}
})
},
handleClose() {
this.$emit('update:addDictDialog', null)
}
}
};
</script>
<style scoped>
.dialog-content{
padding: 16px 107px 16px 72px;
max-height:500px
}
</style>

View File

@ -0,0 +1,177 @@
<template>
<div>
<el-dialog
:title="addSpeechcraftDialog.title"
:visible="true"
width="850px"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<el-scrollbar class="bor">
<div class="dialog-content">
<el-form ref="ruleForm"
:model="queryParam"
:rules="rulesClient"
label-width="120px"
class="demo-ruleForm">
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="15">
<el-form-item label="模板名称" prop="name">
<el-input
v-model.trim="queryParam.name"
placeholder="请输入模板名称"
clearable maxlength="20"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="15">
<el-form-item label="产品类型" prop="productTypeId">
<el-select v-model="queryParam.productTypeId"
clearable placeholder="请选择"
class="width100">
<el-option
v-for="item in dictList"
:key="item.code"
:label="item.codeName"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="15">
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
:rows="3"
placeholder="请输入内容"
maxlength="60"
v-model="queryParam.remark">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="话术内容" prop="remark">
<editor ref="editorintroduction" :editorHtml="queryParam.content" @onEditorChange="onEditorChange" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</el-scrollbar>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose()">取消</el-button>
<el-button type="primary" @click="handleSubmit()">确认</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import basicApi from "@/services/basicManage";
export default {
components: {
editor: () => import("@/components/editor")
},
props: {
addSpeechcraftDialog: {
type: Object,
default: () => {
return {}
},
},
dictList: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {
queryParam:{
productTypeId:'',
name:'',//
remark:'',
content:'',
type:2 //1 2
},
rulesClient: {
name: [
{ required: true, message: '请输入模板名称', trigger: 'change',},
],
productTypeId: [
{ required: true, message: '请选择产品类型', trigger: 'change',},
],
},
operateMethodOptions:[],
};
},
mounted () {
//
if(Object.keys(this.addSpeechcraftDialog.data).length>0){
this.queryParam = JSON.parse(JSON.stringify(this.addSpeechcraftDialog.data));
setTimeout(() => {
document.querySelector(".ql-editor").innerHTML = this.queryParam.content;
this.editorHtml=this.queryParam.content
}, 100);
}
},
methods: {
handleSubmit(){
if(!this.$clickThrottle()) { return }
let _this=this;
this.$refs.ruleForm.validate((valid) => {
if (valid) {
if(Object.keys(this.addSpeechcraftDialog.data).length>0)
{
basicApi.updateTemplateById(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '编辑话术模板成功!',
type: 'success'
});
this.handleClose()
this.$parent.getMediateDataList(1)
})
}
else
{
basicApi.addTemplate(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '新增话术模板成功!',
type: 'success'
});
this.handleClose()
this.$parent.getMediateDataList(1)
})
}
}
})
},
handleClose() {
this.$emit('update:addSpeechcraftDialog', null)
},
onEditorChange(data) {
this.queryParam.content = data.content;
}
}
};
</script>
<style scoped>
.dialog-content{
padding: 16px 37px 16px 12px;
max-height:650px
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<div>
<el-dialog
:title="addTemplateDialog.title"
:visible="true"
width="550px"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<el-scrollbar class="bor">
<div class="dialog-content">
<el-form ref="ruleForm"
:model="queryParam"
:rules="rulesClient"
label-width="120px"
class="demo-ruleForm">
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="模板名称" prop="name">
<el-input
v-model.trim="queryParam.name"
placeholder="请输入模板名称"
clearable maxlength="20"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="产品类型" prop="productTypeId">
<el-select v-model="queryParam.productTypeId"
clearable placeholder="请选择"
class="width100">
<el-option
v-for="item in dictList"
:key="item.code"
:label="item.codeName"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
:rows="3"
placeholder="请输入内容"
maxlength="60"
v-model="queryParam.remark">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<el-form-item prop="content">
<!-- <div class="logo-wrap"> -->
<upload-file :file-list="fileList" :max-count="1"
:show-file-name="true"
uploadName="调解协议模板"
accept=".doc,.docx"
@handleUploadFile="handleUploadFile">
</upload-file>
<!-- </div> -->
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- <div class="logo-wrap">
<upload-file :file-list="fileList" :max-count="1"
:show-file-name="true"
uploadName="调解协议模板"
accept=".doc,.docx"
@handleUploadFile="handleUploadFile">
</upload-file>
</div> -->
</div>
</el-scrollbar>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose()">取消</el-button>
<el-button type="primary" @click="handleSubmit()">确认</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import basicApi from "@/services/basicManage";
export default {
components: {
uploadFile: () => import('../../../../components/uploadFile.vue'),//
},
props: {
addTemplateDialog: {
type: Object,
default: () => {
return {}
},
},
dictList: {
type: Array,
default: () => {
return []
},
},
},
data() {
return {
queryParam:{
productTypeId:'',
name:'',//
remark:'',
content:'',
type:1 //1 2
},
rulesClient: {
name: [
{ required: true, message: '请输入模板名称', trigger: 'change',},
],
content: [
{ required: true, message: '请输入上传调解协议模板', trigger: 'change',},
],
},
operateMethodOptions:[],
fileList:[]
};
},
mounted () {
//
if(Object.keys(this.addTemplateDialog.data).length>0){
this.queryParam = JSON.parse(JSON.stringify(this.addTemplateDialog.data));
if(this.queryParam.content!='')this.fileList.push({fileName: "调解协议模板",url:this.queryParam.content})
}
},
methods: {
//
handleUploadFile(fileList){
fileList = JSON.parse(JSON.stringify(fileList))
this.fileList = fileList.map((item,i) => {
return {
url: item.url,
fileName:'调解协议模板'
}
})
if(fileList.length>0)
{
this.queryParam.content = this.fileList[0].url
this.queryParam.fileSize = (fileList[0].fileSize / 1024 / 1024).toFixed(2)
}
else{this.queryParam.content=""}
},
handleSubmit(){
if(!this.$clickThrottle()) { return }
let _this=this;
this.$refs.ruleForm.validate((valid) => {
if (valid) {
if(Object.keys(this.addTemplateDialog.data).length>0)
{
basicApi.updateTemplateById(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '编辑调解模板成功!',
type: 'success'
});
this.handleClose()
this.$parent.getMediateDataList(1)
})
}
else
{
basicApi.addTemplate(_this.queryParam).then(res => {
this.$message({
showClose: true,
message: '新增调解模板成功!',
type: 'success'
});
this.handleClose()
this.$parent.getMediateDataList(1)
})
}
}
})
},
handleClose() {
this.$emit('update:addTemplateDialog', null)
},
}
};
</script>
<style scoped>
.dialog-content{
padding: 16px 107px 16px 72px;
max-height:500px
}
.logo-wrap{
padding: 0 120px;
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<div class="layout-tabs-content-box">
<div class="">
<div class="height-56 flex-row align-items-center justify-content-between">
<div class="f22 color-text-primary">数据字典</div>
<div class="flex-row">
<div class="mr-16">
<el-input
placeholder="请输入搜索内容"
suffix-icon="el-icon-search"
v-model.trim="queryParam.codeName"
size="small"
clearable
@change="handleSearch"
@keydown.enter.native="handleSearch"
>
</el-input>
</div>
<el-button size="small" type="primary" @click="handleAddForm">新增数据字典</el-button>
</div>
</div>
<div class="" >
<el-table :data="tableData" :height="`${contentHeight}`">
<el-table-column type="index" label="序号" width="55"></el-table-column>
<el-table-column prop="typeName" label="字典标签"></el-table-column>
<el-table-column prop="codeName" label="字典名称"></el-table-column>
<el-table-column prop="seq" label="排序"></el-table-column>
<el-table-column prop="remark" label="备注"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<div class="flex-row align-items-center">
<div class="f14 color-1960F4 cursor-pointer mr-8" @click="handleAddForm(scope)">编辑</div>
<div class="f14 color-1960F4 cursor-pointer" @click="handleDelete(scope)">删除</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="text-center pt-16">
<el-pagination
@size-change="getDictList"
@current-change="getDictList"
:current-page="queryParam.current"
:page-size="queryParam.size"
layout="total, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</div>
<!-- 新增数据字典弹框 -->
<addDictDialog v-if="addDictDialog" :addDictDialog.sync="addDictDialog" />
</div>
</template>
<script>
import basicManage from "@/services/basicManage";
export default {
components: {
addDictDialog: () => import('./components/addDictDialog.vue'),
},
data() {
return {
queryParam: {
codeName:'',
current:1,
size:10
},
tableData: [],
total:0,
addDictDialog:null
}
},
created() {
this.getDictList(1)
},
computed:{
// drawer
contentHeight(){
let oh = document.documentElement.clientHeight;
return oh-56-48-56-50-32
}
},
methods: {
getDictList(val){
this.queryParam.current = val
basicManage.getDictList(this.queryParam).then(res => {
if (!res.code) {
this.tableData = res.records;
this.total = res.total;
}
})
},
//
handleSearch() {
this.queryParam.current = 1
this.queryParam.size = 10
this.getDictList(1)
},
//
handleAddForm(scope){
let title = scope.row?'编辑数组字典':'新增数组字典'
let data = scope.row?scope.row:''
this.addDictDialog={
title:title,
data: data
}
},
//
handleDelete(scope){
this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
if(!this.$clickThrottle()) { return }//
basicManage.deleteDictById({ id: scope.row.id }).then((res) => {
this.$message.success("成功");
this.getDictList(1)
});
}).catch(() => {});
},
}
}
</script>

View File

@ -0,0 +1,154 @@
<template>
<div class="layout-tabs-content-box">
<div class="">
<div class="height-56 flex-row align-items-center justify-content-between">
<div class="f22 color-text-primary">调解话术模板</div>
<div class="flex-row">
<div class="mr-16">
<el-input
placeholder="请输入搜索内容"
suffix-icon="el-icon-search"
v-model.trim="queryParam.name"
size="small"
clearable
@change="handleSearch"
@keydown.enter.native="handleSearch"
>
</el-input>
</div>
<el-button size="small" type="primary" @click="handleAddForm">新增话术模板</el-button>
</div>
</div>
<div class="" >
<el-table :data="tableData" :height="`${contentHeight}`">
<el-table-column type="index" label="序号" width="55"></el-table-column>
<el-table-column prop="name" label="模板名称" width="400"></el-table-column>
<el-table-column label="金融产品" width="200">
<template slot-scope="scope">
<div class="flex-row">
{{getDictName(scope.row.productTypeId)}}
</div>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<div class="flex-row align-items-center">
<div class="f14 color-1960F4 cursor-pointer mr-8" @click="handleAddForm(scope)">编辑</div>
<div class="f14 color-1960F4 cursor-pointer" @click="handleDelete(scope)">删除</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="text-center pt-16">
<el-pagination
@size-change="getMediateDataList"
@current-change="getMediateDataList"
:current-page="queryParam.current"
:page-size="queryParam.size"
layout="total, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</div>
<!-- 新增金融机构弹框 -->
<addSpeechcraftDialog v-if="addSpeechcraftDialog" :dictList.sync="dictList" :addSpeechcraftDialog.sync="addSpeechcraftDialog" />
</div>
</template>
<script>
import basicApi from "@/services/basicManage";
export default {
components: {
addSpeechcraftDialog: () => import('./components/addSpeechcraftDialog.vue'),
},
data() {
return {
queryParam: {
type:2,
name: '',//
current:1,
size:10
},
tableData: [],
total:0,
addSpeechcraftDialog:null,
dictList:[]
}
},
created() {
this.getDictDataList()
this.getMediateDataList(1)
},
computed:{
// drawer
contentHeight(){
let oh = document.documentElement.clientHeight;
return oh-56-48-56-50-32
}
},
methods: {
getDictName(val){
let dictItem= this.dictList.find(item =>{
return item.code === val
})
if(dictItem){return dictItem.codeName;}
else{return '';}
},
getDictDataList(val){
basicApi.getDictList({current:1,size:100}).then(res => {
if (!res.code) {
this.dictList = res.records;
}
})
},
getMediateDataList(val){
this.queryParam.current = val
basicApi.getTemplateList(this.queryParam).then(res => {
if (!res.code) {
this.tableData = res.records;
this.total = res.total;
}
})
},
//
handleSearch() {
this.queryParam.current = 1
this.queryParam.size = 10
this.getMediateDataList(1)
},
//
handleAddForm(scope){
let title = scope.row?'编辑话术模板':'新增话术模板'
let data = scope.row?scope.row:''
this.addSpeechcraftDialog={
title:title,
data: data
}
},
//
handleDelete(scope){
this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
if(!this.$clickThrottle()) { return }//
basicApi.deleteTemplateById({ id: scope.row.id }).then((res) => {
this.$message.success("成功");
this.getMediateDataList(1)
});
}).catch(() => {});
},
}
}
</script>

View File

@ -0,0 +1,194 @@
<template>
<div class="layout-tabs-content-box">
<div class="">
<div class="height-56 flex-row align-items-center justify-content-between">
<div class="f22 color-text-primary">调解协议模板</div>
<div class="flex-row">
<div class="mr-16">
<el-input
placeholder="请输入搜索内容"
suffix-icon="el-icon-search"
v-model.trim="queryParam.name"
size="small"
clearable
@change="handleSearch"
@keydown.enter.native="handleSearch"
>
</el-input>
</div>
<el-button size="small" @click="handleExport">下载模板</el-button>
<el-button size="small" type="primary" @click="handleAddForm">新增调解协议模板</el-button>
</div>
</div>
<div class="" >
<el-table :data="tableData" :height="`${contentHeight}`" @current-change="handleCurrentChange" highlight-current-row>
<!-- <el-table-column type="selection" width="55"></el-table-column> -->
<el-table-column type="index" label="序号" width="55"></el-table-column>
<el-table-column prop="name" label="模板名称" width="400"></el-table-column>
<el-table-column label="金融产品" width="200">
<template slot-scope="scope">
<div class="flex-row">
{{getDictName(scope.row.productTypeId)}}
</div>
</template>
</el-table-column>
<el-table-column label="文件大小" width="150">
<template slot-scope="scope">
<div class="flex-row">
{{scope.row.fileSize}}M
</div>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<div class="flex-row align-items-center">
<div class="f14 color-1960F4 cursor-pointer mr-8" @click="handleAddForm(scope)">编辑</div>
<div class="f14 color-1960F4 cursor-pointer" @click="handleDelete(scope)">删除</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="text-center pt-16" v-if="tableData.length>0">
<el-pagination
@size-change="getMediateDataList"
@current-change="getMediateDataList"
:current-page="queryParam.current"
:page-size="queryParam.size"
layout="total, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</div>
<!-- 新增金融机构弹框 -->
<addTemplateDialog v-if="addTemplateDialog" :dictList.sync="dictList" :addTemplateDialog.sync="addTemplateDialog" />
</div>
</template>
<script>
import basicApi from "@/services/basicManage";
export default {
components: {
addTemplateDialog: () => import('./components/addTemplateDialog.vue'),
},
data() {
return {
queryParam: {
type:1,
name: '',//
current:1,
size:10
},
tableData: [],
total:0,
addTemplateDialog:null,
dictList:[],
multipleSelection:[],
currentRow:null
}
},
created() {
this.getDictDataList()
this.getMediateDataList(1)
},
computed:{
// drawer
contentHeight(){
let oh = document.documentElement.clientHeight;
return oh-56-48-56-50-32
}
},
methods: {
getDictName(val){
let dictItem= this.dictList.find(item =>{
return item.code === val
})
if(dictItem){return dictItem.codeName;}
else{return '';}
},
getDictDataList(val){
basicApi.getDictList({current:1,size:100}).then(res => {
if (!res.code) {
this.dictList = res.records;
}
})
},
getMediateDataList(val){
this.queryParam.current = val
basicApi.getTemplateList(this.queryParam).then(res => {
if (!res.code) {
this.tableData = res.records;
this.total = res.total;
}
})
},
//
handleSearch() {
this.queryParam.current = 1
this.queryParam.size = 10
this.getMediateDataList(1)
},
//
handleAddForm(scope){
let title = scope.row?'编辑调解协议模板':'新增调解协议模板'
let data = scope.row?scope.row:''
this.addTemplateDialog={
title:title,
data: data
}
},
//
handleExport(){
if(!this.$clickThrottle()) { return }//
if(this.currentRow!=null)
{
// this.handlePreview({previewUrl:"/manage-center/minio/preview/"+this.multipleSelection[0].content,url:this.multipleSelection[0].content})
this.handlePreview({previewUrl:"/manage-center/minio/preview/"+this.currentRow.content,url:this.currentRow.content})
}
else
{
this.$message.warning(`请选择下载模板!`)
return
}
},
async handlePreview(item) {
try {
let res = await this.$fetchApi.getMinioToken({objectName: item.url})
console.log(res)
window.open(`${item.previewUrl}?token=${res}`, '_target')
}catch (e) {
this.$message.error(e.msg || e)
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleCurrentChange(val) {
this.currentRow = val;
},
//
handleDelete(scope){
this.$confirm("此操作将永久删除该数据, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
if(!this.$clickThrottle()) { return }//
basicApi.deleteTemplateById({ id: scope.row.id }).then((res) => {
this.$message.success("成功");
this.getMediateDataList(1)
});
}).catch(() => {});
},
}
}
</script>

View File

@ -0,0 +1,30 @@
<template>
<div class="layout-content-wrap">
<el-tabs class="zd-el-tabs-custom zd-el-tabs-custom__left_padding" v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="数据字典" name="dictManage"></el-tab-pane>
<el-tab-pane label="调解协议模板管理" name="templateManagement"></el-tab-pane>
<el-tab-pane label="调解话术管理" name="speechcraftManagement"></el-tab-pane>
</el-tabs>
<components :is="activeName"></components>
</div>
</template>
<script>
export default {
components: {
dictManage: () => import('./components/dictManage'),
templateManagement: () => import('./components/templateManagement'),
speechcraftManagement: () => import('./components/speechcraftManagement'),
},
data() {
return {
activeName: 'dictManage'
};
},
methods: {
handleClick(tab, event) {
console.log(tab, event);
}
}
};
</script>

View File

@ -0,0 +1,750 @@
<template>
<div>
<el-dialog
:title="addCaseDialog.title"
:visible="true"
width="880px"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<div >
<el-steps :active="presentStep" align-center>
<el-step v-for="(item,inx) in transferStep" :key="inx" :title="item.title" :description="item.description"></el-step>
</el-steps>
<!-- 基本信息 -->
<div v-if="presentStep === 1">
<div>
<div class="height-48 line-height-48 f18 color-000 m-v-16 p-h-24">基本信息</div>
<div class="p-h-24">
<el-form ref="ruleFormBase"
:model="baseInfo"
:rules="rulesClient"
label-width="150px"
class="demo-ruleForm">
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="金融机构名称" prop="financialOrgName">
<el-input
v-model.trim="baseInfo.financialOrgName"
placeholder="请输入金融机构名称"
clearable
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="社会统一信用代码" prop="financialOrgCode">
<el-input
v-model.trim="baseInfo.financialOrgCode"
placeholder="请输入社会统一信用代码"
clearable
maxlength="18"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="案件名称" prop="caseName">
<el-input
clearable
placeholder="请输入案件名称"
v-model="baseInfo.caseName">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="案件编号" prop="caseNo">
<el-input
clearable
placeholder="请输入案件编号"
v-model="baseInfo.caseNo">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="金融产品类型" prop="productTypeId">
<el-select v-model="baseInfo.productTypeId"
clearable placeholder="请选择金融产品类型"
class="width100">
<el-option
v-for="item in financialProductsTypeOptions"
:key="item.code"
:label="item.codeName"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标的金额" prop="moneyAmount">
<el-input
clearable
placeholder="请输入内容"
v-model="baseInfo.moneyAmount">
<template slot="append"></template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="逾期次数" prop="overdueTimes">
<!-- <el-select v-model="baseInfo.overdueTimes"
clearable placeholder="请选择逾期次数"
class="width100">
<el-option
v-for="item in operateMethodOptions"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select> -->
<el-input-number v-model="baseInfo.overdueTimes" :min="0" :max="100" class="width100"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="案件描述" prop="caseDescr">
<el-input
clearable
placeholder="请输入内容"
v-model="baseInfo.caseDescr">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
</div>
<!-- 当事人信息 -->
<div v-else-if="presentStep === 2">
<div>
<div class="height-48 line-height-48 f18 color-000 m-v-16 p-h-24">案件当事人</div>
<div class="p-h-24">
<div class="border-solid-lighter-1 p-h-24 mb-16">
<div class="flex-row justify-content-between height-48 line-height-48 f14 border-b-solid-lighter-1 mb-16">
<div class="color-000">债权人</div>
<div class="color-text-regular cursor-pointer" @click="handleReset">清空<i class="el-icon-close"></i></div>
</div>
<el-form ref="ruleFormCreditor"
:model="creditorInfo"
:rules="rulesClientCreditor"
label-width="150px"
class="demo-ruleForm">
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="债权人" prop="creditorName">
<el-input
v-model.trim="creditorInfo.creditorName"
placeholder="请输入债权人"
clearable
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="社会统一信用代码" prop="creditorOrgCode">
<el-input
v-model.trim="creditorInfo.creditorOrgCode"
placeholder="请输入社会统一信用代码"
clearable
maxlength="18"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="法人姓名" prop="creditorLegal">
<el-input
clearable
placeholder="请输入法人姓名"
v-model="creditorInfo.creditorLegal">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="法人身份证号" prop="creditorIdcard">
<el-input
clearable
placeholder="请输入法人身份证号"
v-model="creditorInfo.creditorIdcard"
maxlength="18">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="法人手机号" prop="creditorPhone">
<el-input
clearable
placeholder="请输入法人手机号"
v-model="creditorInfo.creditorPhone"
maxlength="11"
>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="公司地址" prop="creditorAddr">
<el-input
clearable
placeholder="请输入公司地址"
v-model="creditorInfo.creditorAddr">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="邮编" prop="creditorMail">
<el-input
clearable
placeholder="请输入邮编"
v-model="creditorInfo.creditorMail"
maxlength="6"
>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="代理人" prop="creditorAgent">
<el-input
clearable
placeholder="请输入代理人"
v-model="creditorInfo.creditorAgent">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="border-solid-lighter-1 p-h-24">
<div class="flex-row justify-content-between f14 border-b-solid-lighter-1 mb-8 p-v-8 align-items-center">
<div class="color-000">债务人</div>
<el-button size="small" type="primary" @click="handleAdd">新增债务人<i class="el-icon-plus"></i></el-button>
</div>
<div>
<el-form ref="ruleFormObligor"
:model="obligorInfoForm"
label-width="150px"
class="demo-ruleForm">
<div v-for="(item,inx) in obligorInfoForm.debtorEntityList" :key="inx">
<div class="flex-row justify-content-between align-items-center height-40 f14 mb-16">
<div class="color-text-primary">债务人{{inx+1}}</div>
<div class="color-text-regular cursor-pointer" @click="handleRemoveDomain(item)">删除<i class="el-icon-close"></i></div>
</div>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="债务人姓名" :prop="'debtorEntityList.' + inx + '.name'" :rules="{required: true, message: '请输入债权人姓名', trigger: 'blur'}">
<el-input
v-model.trim="obligorInfoForm.debtorEntityList[inx].name"
placeholder="请输入债务人姓名"
clearable
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="证件类型" :prop="'debtorEntityList.' + inx + '.cardTypeId'" :rules="{required: true, message: '请选择证件类型', trigger: 'blur'}">
<el-select v-model="obligorInfoForm.debtorEntityList[inx].cardTypeId"
clearable placeholder="请选择证件类型"
class="width100">
<el-option
v-for="item in idTypeOptions"
:key="item.code"
:label="item.codeName"
:value="item.code">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="证件号码" :prop="'debtorEntityList.' + inx + '.cardNo'"
:rules=" [
{ required: true, message: '请输入证件号', trigger: 'change',},
{ pattern: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, message: '请输入正确的身份证号', trigger: ['blur', 'change']}
]">
<el-input
clearable
placeholder="请输入证件号码"
v-model="obligorInfoForm.debtorEntityList[inx].cardNo"
maxlength="18"
>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" :prop="'debtorEntityList.' + inx + '.phone'" :rules="[
{ required: true, message: '请输入法人手机号', trigger: 'change',},
{ pattern: /^(13[0-9]{9})|(18[0-9]{9})|(14[0-9]{9})|(17[0-9]{9})|(15[0-9]{9})|(19[0-9]{9})$/, message: '请输入正确的手机号码', trigger: ['blur', 'change']}
]">
<el-input
clearable
placeholder="请输入手机号码"
v-model="obligorInfoForm.debtorEntityList[inx].phone"
maxlength="11"
>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="地址" :prop="'debtorEntityList.' + inx + '.addr'" :rules="{ required: true, message: '请输入地址', trigger: 'change',}">
<el-input
clearable
placeholder="请输入地址"
v-model="obligorInfoForm.debtorEntityList[inx].addr">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮编" :prop="'debtorEntityList.' + inx + '.mail'" :rules="{ required: true, message: '请输入邮编', trigger: 'change',}">
<el-input
clearable
placeholder="请输入邮编"
v-model="obligorInfoForm.debtorEntityList[inx].mail"
maxlength="6">
</el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
</div>
</div>
</div>
</div>
<!-- 模板选择 -->
<div v-else-if="presentStep === 3">
<el-form ref="ruleFormTemplate"
:model="queryParam"
:rules="rulesClientTemplate"
label-width="150px"
class="demo-ruleForm">
<div>
<div class="height-48 line-height-48 f18 color-000 m-v-16 p-h-24">模板话术</div>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="话术模板" prop="tpSpeechcraftId">
<el-select v-model="queryParam.tpSpeechcraftId"
clearable placeholder="请选择模板话术"
class="width100">
<el-option
v-for="item in speechcraftTemplateOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
<div>
<div class="height-48 line-height-48 f18 color-000 m-v-16 p-h-24">调解模板</div>
<el-row type="flex" align="middle">
<el-col :span="12">
<el-form-item label="调解模板" prop="tpMediateId">
<el-select v-model="queryParam.tpMediateId"
clearable placeholder="请选择调解模板"
class="width100">
<el-option
v-for="item in mediationTemplateOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
<!-- 材料上传 -->
<div v-else-if="presentStep === 4">
<div class="height-48 line-height-48 f18 color-000 m-v-16 p-h-24">证据材料</div>
<div class="p-h-24">
<upload-file-name :file-list="fileList" :max-count="20"
:show-file-name="true"
@handleUploadFile="handleUploadFile">
</upload-file-name>
</div>
</div>
<!-- 完成 -->
<div v-else-if="presentStep === 5">
<el-result icon="success" title="案件创建完成" subTitle="案件创建完成,继续处理其他案件">
<template slot="extra">
<el-button type="primary" size="medium" @click="handleClose">好的</el-button>
</template>
</el-result>
</div>
</div>
<span slot="footer" class="dialog-footer" v-if="presentStep<5">
<el-button @click="handleClose">取消</el-button>
<el-button
v-if="presentStep > 1 "
type="primary"
@click="presentStep--">上一步</el-button>
<el-button
type="primary"
v-show="presentStep<4"
@click="handleNextStep">下一步</el-button>
<el-button
type="primary"
v-show="presentStep === 4"
@click="handleSubmit">确认
</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import api from "@/services/caseManagement";
export default {
components: {
uploadFileName: () => import('@/components/uploadFileName.vue'),//
},
props: {
addCaseDialog: {
type: Object,
default: () => {
return {}
},
},
},
data() {
const moneyAmountValidate = (rule,value,callback)=>{
if (!value){
callback(new Error('请输入标的金额'));
}else if (!/^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0.\d{1,2}$/.test(value)){
callback(new Error('只能输入两位小数的金额!'));
}else if(!(0<parseInt(value)&&parseInt(value)<100000000)){
callback(new Error('只能输入大于1小于1亿的金额!'));
}else{
callback()
}
};
return {
transferStep:[
{id:1,title:'基本信息',description:'录入案件基本信息'},
{id:2,title:'当事人信息',description:'录入当事人信息'},
{id:3,title:'模板选择',description:'选择模板'},
{id:4,title:'材料上传',description:'上传案件材料'},
{id:5,title:'完成',description:'完成案件创建'},
],
presentStep:1,
//------------------------------------------------------
baseInfo:{
financialOrgName:'',//
financialOrgCode:'',//
caseName:'',//
caseNo:'',//
productTypeId:'',//
moneyAmount:'',//
overdueTimes:0,//
caseDescr:'',//
},
rulesClient: {
financialOrgName: [
{ required: true, message: '请输入机构名称', trigger: 'change',},
],
financialOrgCode: [
{ required: true, message: '请输入社会统一信用代码', trigger: 'change',},
],
caseName: [
{ required: true, message: '请输入案件名称', trigger: 'change',},
],
caseNo: [
{ required: true, message: '请输入案件编号', trigger: 'change',},
],
productTypeId: [
{ required: true, message: '请选择金融产品类型', trigger: 'change',},
],
moneyAmount: [
{ required: true, validator: moneyAmountValidate, trigger: 'change',},
],
caseDescr:[
{ required: true, message: '请输入案件描述', trigger: 'change',},
]
},
financialProductsTypeOptions:[],//
//-----------------------------------------------
//
creditorInfo:{
creditorName:'',//
creditorOrgCode:'',//
creditorLegal:'',//
creditorIdcard:'',//
creditorPhone:'',//
creditorAddr:'',//
creditorMail:'',//
creditorAgent:'',//
},
rulesClientCreditor: {
creditorName: [
{ required: true, message: '请输入债权人', trigger: 'change',},
],
creditorOrgCode: [
{ required: true, message: '请输入债权人机构代码', trigger: 'change',},
],
creditorLegal: [
{ required: true, message: '请输入法人', trigger: 'change',},
],
creditorIdcard: [
{ required: true, message: '请输入法人身份证号', trigger: 'change',},
{ pattern: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, message: '请输入正确的身份证号', trigger: ['blur', 'change']}
],
creditorPhone: [
{ required: true, message: '请输入法人手机号', trigger: 'change',},
{ pattern: /^(13[0-9]{9})|(18[0-9]{9})|(14[0-9]{9})|(17[0-9]{9})|(15[0-9]{9})|(19[0-9]{9})$/, message: '请输入正确的手机号码', trigger: ['blur', 'change']}
],
creditorAddr: [
{ required: true, message: '请输入公司地址', trigger: 'change',},
],
// creditorAgent: [
// { required: true, message: '', trigger: 'change',},
// ],
},
//
idTypeOptions:[],
obligorInfoForm:{
debtorEntityList:[
{
name:'',//
phone:'',//
cardTypeId:'',//
addr:'',//
cardNo:'',//
mail:'',//
}
],
},
obligorRulesClient:{
name: [
{ required: true, message: '请输入债务人姓名', trigger: 'change',},
],
phone: [
{ required: true, message: '请输入法人手机号', trigger: 'change',},
{ pattern: /^(13[0-9]{9})|(18[0-9]{9})|(14[0-9]{9})|(17[0-9]{9})|(15[0-9]{9})|(19[0-9]{9})$/, message: '请输入正确的手机号码', trigger: ['blur', 'change']}
],
cardTypeId: [
{ required: true, message: '请选择证件类型', trigger: 'change',},
],
addr: [
{ required: true, message: '请输入地址', trigger: 'change',},
],
cardNo: [
{ required: true, message: '请输入证件号', trigger: 'change',},
{ pattern: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, message: '请输入正确的身份证号', trigger: ['blur', 'change']}
],
mail: [
{ required: true, message: '请输入邮编', trigger: 'change',},
{ pattern: /^\d{6}$/, message: '请输入正确的邮编', trigger: ['blur', 'change']}
],
},
//------------------------------------------------------------
queryParam:{
tpMediateId:'',//id
tpSpeechcraftId:'',//
},
rulesClientTemplate:{
tpMediateId: [
{ required: true, message: '请选择调解模板', trigger: 'change',},
],
tpSpeechcraftId: [
{ required: true, message: '请选择话术模板', trigger: 'change',},
],
},
fileList:[],//
speechcraftTemplateOptions:[],//
mediationTemplateOptions:[],//
};
},
mounted () {
this.getDict();//
this.getDictIdType();
this.getSpeechcraftTemplateList(),//
this.getTemplateList();//
},
methods: {
//
getDict(){
let data = {
type:'financial'
}
api.getDict(data).then(res => {
if (!res.code) {
this.financialProductsTypeOptions = res;
}
})
},
//
getDictIdType(){
let data = {
type:'certificates'
}
api.getDict(data).then(res => {
if (!res.code) {
this.idTypeOptions = res;
}
})
},
//
handleAdd(){
this.obligorInfoForm.debtorEntityList.push({
name:'',//
phone:'',//
cardTypeId:'',//
addr:'',//
cardNo:'',//
mail:'',//
});
},
//
handleRemoveDomain(item) {
var index = this.obligorInfoForm.debtorEntityList.indexOf(item)
if (index !== -1) {
this.obligorInfoForm.debtorEntityList.splice(index, 1)
}
},
//
handleReset(){
for (let key in this.creditorInfo) {
this.creditorInfo[key] = ''
}
},
//
getSpeechcraftTemplateList(){
let data = {
current: 1,
name: "",
size: 300,
type: 2,
}
api.getTemplateList(data).then(res => {
if (!res.code) {
this.speechcraftTemplateOptions = res.records;
}
})
},
//
getTemplateList(){
let data = {
current: 1,
name: "",
size: 300,
type: 1,
}
api.getTemplateList(data).then(res => {
if (!res.code) {
this.mediationTemplateOptions = res.records;
}
})
},
//
handleNextStep(){
if(this.presentStep === 1){
this.$refs.ruleFormBase.validate((valid) => {
if (valid){this.presentStep++}
})
}else if(this.presentStep === 2){
this.$refs.ruleFormCreditor.validate((valid) => {
if (valid){
this.$refs.ruleFormObligor.validate((valid) => {
if (valid){this.presentStep++}
})
}
})
}else if(this.presentStep === 3){
this.$refs.ruleFormTemplate.validate((valid) => {
if (valid){this.presentStep++}
})
}else{
this.presentStep++
}
},
handleSubmit(){
if(!this.$clickThrottle()) { return }//
let data = {
...this.baseInfo,//
...this.creditorInfo,//
...this.obligorInfoForm,//
...this.queryParam,//
caseFileEntityList:this.fileList//
}
console.log('获取传给后台的信息',data)
api.addCaseInfo(data).then(res => {
this.presentStep++
this.$parent.getCaseInfoList(1)
this.$parent.getCaseCount()
})
},
//
handleUploadFile(fileList){
console.log('获取上传文件信息',fileList)
fileList = JSON.parse(JSON.stringify(fileList))
this.fileList = fileList.map((item,i) => {
return {
url: item.url,
fileName:item.fileName,
name:item.fileName
}
})
},
handleClose() {
this.$emit('update:addCaseDialog', null)
},
}
};
</script>
<style scoped lang="scss">
.dialog-content{
padding: 16px 24px;
// max-height:500px
}
</style>

View File

@ -0,0 +1,432 @@
<template>
<div>
<el-dialog
:title="caseAllocationDialog.title"
:visible="true"
width="880px"
append-to-body
:close-on-click-modal="false"
@close="handleClose"
>
<div class="dialog-content">
<div class="pb-16">
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="24">
<div class="flex-row align-items-center">
<div class="mr-8 flex-shrink-0">部门</div>
<div class="width100">
<el-select v-model="deptIds"
size="medium"
multiple
clearable placeholder="请选择部门"
@change="handleChangeDept"
class="width100">
<el-option
v-for="item in departmentOptions"
:key="item.id"
:label="item.name"
:value="item.id"
class="width100"
>
</el-option>
</el-select>
</div>
</div>
</el-col>
</el-row>
</div>
<el-scrollbar class="bor bg-color-light min-height250">
<div class="department-wrap">
<div v-for="(item,inx) in peopleList" :key="inx" class="department-wrap-list">
<div class="department-dept">
<el-checkbox v-model="checkedAll" :label="item.deptId" @change="handleCheckChange(1,inx,item,item.deptId,$event)">{{item.name}}({{item.count}})</el-checkbox>
</div>
<div class="flex-row justify-content-start flex-flow-wrap ">
<div v-for="(v,i) in item.values" :key="i" class="pt-16" style="flex:0 0 25%">
<el-checkbox v-model="checkedAll" :label="v.id" @change="handleCheckChange(2,inx,v,item.deptId,$event)">{{v.realName}}</el-checkbox>
</div>
</div>
</div>
</div>
</el-scrollbar>
<div class="p-v-24">
<el-form ref="ruleForm"
:model="queryParam"
:rules="rulesClient"
label-width="120px"
class="demo-ruleForm">
<el-row :gutter="20" type="flex" align="middle">
<el-col :span="12">
<el-form-item label="选择开始日期" prop="planStartTime">
<el-date-picker
v-model="queryParam.planStartTime"
type="date"
placeholder="选择日期"
@change="handleChangeDate"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="选择结束日期" prop="planEndTime">
<el-date-picker
v-model="queryParam.planEndTime"
type="date"
placeholder="选择日期"
@change="handleChangeDate"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose()">取消</el-button>
<el-button type="primary" @click="handleSubmit()">确认</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import api from "@/services/caseManagement";
export default {
components: {
},
props: {
caseAllocationDialog: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {
deptIds:[],//id
queryParam:{
planStartTime:'',
planEndTime:'',
},
userList:[],
rulesClient: {
planStartTime: [
{ required: true, message: '请选择开始日期', trigger: 'change',},
],
planEndTime: [
{ required: true, message: '请选择结束日期', trigger: 'change',},
],
},
peopleList:[
{departmentId:1,departmentName:'调解一部12人',
child:[
{id:1,name:'张三' },
{id:2,name:'张三' },
{id:3,name:'张三' },
{id:4,name:'张三' },
{id:5,name:'里面' },
]
},
{departmentId:2,departmentName:'调解二部12人',
child:[
{id:1,name:'张三' },
{id:2,name:'张三' },
{id:3,name:'张三' },
{id:4,name:'张三' },
{id:5,name:'里面' },
]
},
],
departmentOptions:[],//
isIndeterminate:true,
checkedAll:[],
chooseChecked:[],
};
},
mounted () {
this.getDeptList();//
},
methods: {
//
getDeptList(){
let data = {
companyId: this.$store.state.userinfo.companyId,
current: 1,
size: 500,
}
api.getDeptList(data).then(res => {
if (!res.code) {
this.departmentOptions = res.records;
this.deptIds = [this.departmentOptions[0].id]
this.getUserByDeptList()
}
})
},
handleChangeDept(e){
this.checkedAll=[]
this.chooseChecked=[]
// console.log(this.deptIds,'this.deptIds')
if(this.deptIds.length>0)this.getUserByDeptList()
this.peopleList=[]
},
// id
getUserByDeptList(){
let data = {
ids:this.deptIds
}
api.getUserByDeptList(data).then(res => {
if (!res.code) {
// this.peopleList = res;
let selectDept=[];
this.deptIds.forEach((dept)=>{
this.departmentOptions.forEach((item)=>{
if(item.id == dept){
selectDept.push(item)
}
})
})
// console.log('selectDept',selectDept)
this.peopleList =[];
let list = []
selectDept.forEach((opt)=>{
let values= [];
res.forEach((item)=>{
if(item.deptId == opt.id){
values.push({
id:item.id,
realName:item.realName,
checked:false
})
}
})
list.push({
deptId:opt.id,
name:opt.name,
count:opt.count,
checked:false,
values:values
})
})
this.peopleList = list
// console.log('',this.peopleList)
}
})
},
handleCheckChange(type,a=0,chooseItem,deptId,event){
// console.log(chooseItem,event,a,'this.peopleList')
let self = this
if(type==2){//
let index = 0;
self.peopleList[a].values.map((item)=>{
if(self.checkedAll.indexOf(item.id)>-1){
index+=1
}
})
if(index>0){
if(self.checkedAll.indexOf(self.peopleList[a].deptId)<0){
self.checkedAll.push(self.peopleList[a].deptId)
}
}else{
if(self.checkedAll.indexOf(self.peopleList[a].deptId)>0){
self.checkedAll.splice(self.checkedAll.indexOf(self.peopleList[a].deptId),1)
}
}
if(event)
{
if(this.chooseChecked.length==0){self.chooseChecked.push({deptId:deptId,child:[]})}
this.chooseChecked.forEach((item,index) => {
let haveDeptId = self.chooseChecked.find(citem=>{
return citem.deptId===deptId
})
if(haveDeptId != undefined)
{
if(item.deptId==deptId)
{
item.child.push({deptId:deptId,id:chooseItem.id,realName:chooseItem.realName})
}
}
else
{
self.chooseChecked.push({deptId:deptId,child:[{deptId:deptId,id:chooseItem.id,realName:chooseItem.realName}]})
}
});
}
else
{
this.chooseChecked.forEach((item,index) => {
item.child.forEach((itemchild,index) => {
if(itemchild.id==chooseItem.id)
{
item.child.splice(index,1)
}
});
});
}
let childnum = this.chooseChecked.find(item=>{
return item.deptId === deptId
}).child.length;
let allchildnum = this.peopleList.find(item=>{
return item.deptId === deptId
}).values.length;
if(childnum != allchildnum)
{
if(self.checkedAll.indexOf(deptId)>-1){
self.checkedAll.splice(self.checkedAll.indexOf(deptId),1)
}
}
else
{
if(self.checkedAll.indexOf(deptId)<0){
self.checkedAll.push(deptId)
}
}
}else{
if(self.checkedAll.indexOf(self.peopleList[a].deptId)>-1){
self.peopleList[a].values.map((item)=>{
if(self.checkedAll.findIndex((n)=> n==item.id)<0){
self.checkedAll.push(item.id)
// self.checkedAll.push({id:item.id,realName:item.realName,deptId:self.peopleList[a].deptId})
}
})
}else{
self.peopleList[a].values.map((item)=>{
if(self.checkedAll.findIndex((n)=> n==item.id)>-1){
self.checkedAll.splice(self.checkedAll.findIndex((n)=> n==item.id),1)
}
})
}
let haveDeptId=self.chooseChecked.find(citem=>{
return citem.deptId === deptId
})
if(event)
{
if(haveDeptId == undefined)
{
let addchild=[]
self.peopleList.forEach((item,index) => {
if(item.deptId==deptId)
{
item.values.forEach((item,index) => {
addchild.push({deptId:deptId,id:item.id,realName:item.realName})
});
}
});
self.chooseChecked.push({deptId:deptId,child:addchild})
}
}
else
{
if(haveDeptId != undefined)
{
self.chooseChecked.forEach((item,index) => {
if(item.deptId==deptId)
{
self.chooseChecked.splice(index,1)
}
});
}
}
}
// console.log(this.checkedAll,self.chooseChecked,'checkedAll')
},
handleCheckedCitiesChange(){
},
handleSubmit(){
if(!this.$clickThrottle()) { return }//
let chooseUser=[]
this.chooseChecked.forEach((item,index) => {
item.child.forEach((item,index) => {
chooseUser.push({deptId:item.deptId,id:item.id,realName:item.realName})
});
});
if(chooseUser.length==0)
{
this.$message({
showClose: true,
message: '请先选择调解员!',
type: 'warning'
});
}
this.$refs.ruleForm.validate((valid) => {
if(valid) {
let data = {
...this.queryParam,
userList:chooseUser
}
api.dispatchCase(data).then(res => {
this.$message({
showClose: true,
message: '调解案件分配成功!',
type: 'success'
});
this.$parent.getCaseInfoList()
this.handleClose()
})
}
})
},
handleSearch(){
},
handleChangeDate(){
let planStart = new Date(this.queryParam.planStartTime);
let planEnd = new Date(this.queryParam.planEndTime);
if (planEnd < planStart) {
this.$message({
showClose: true,
message: '开始日期不能大于结束日期!',
type: 'warning'
});
this.queryParam.planEndTime=''
}
},
handleClose() {
this.$emit('update:caseAllocationDialog', null)
},
}
};
</script>
<style scoped lang="scss">
.dialog-content{
padding: 16px 24px;
max-height:500px
}
.department-wrap{
padding: 16px 24px;
max-height: 250px;
.department-wrap-list{
margin-bottom:32px;
}
.department-wrap-list:last-child{
margin-bottom:0;
}
}
.min-height250{min-height: 250px;}
.department-dept ::v-deep .el-checkbox__label {color: $color-000000}
</style>

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