fix : 修复实施图片

This commit is contained in:
2025-07-09 22:56:09 +08:00
parent 64e2ff0647
commit 973dc0f2e4
338 changed files with 62195 additions and 62193 deletions

View File

@@ -1,41 +1,41 @@
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
!build
!default.conf
!nginx.conf
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
!build
!default.conf
!nginx.conf

View File

@@ -1,160 +1,160 @@
kind: pipeline
type: docker
name: mosr-web
platform:
os: linux
arch: arm64
steps:
- name: build-package
image: node:18.19.0
volumes:
- name: cache
path: /drone/src/node_modules
commands:
- export CI=false
- mkdir -p /app/build/$DRONE_REPO_NAME
- rm -rf /app/build/$DRONE_REPO_NAME/*
- cp deployment.yml /app/build/$DRONE_REPO_NAME/
- cp Dockerfile /app/build/$DRONE_REPO_NAME/
- cp .dockerignore /app/build/$DRONE_REPO_NAME/
- cp default.conf /app/build/$DRONE_REPO_NAME/
- cp docker.sh /app/build/$DRONE_REPO_NAME/
- cp nginx.conf /app/build/$DRONE_REPO_NAME/
- npm -v
- node -v
- mkdir -p ./node_modules
- export NODE_MODULES_PATH=`pwd`/node_modules
- npm config set registry https://registry.npmmirror.com
- set NODE_OPTIONS=--openssl-legacy-provider
- npm install --legacy-peer-deps
- npm install codemirror
# - npm install patch-package
# - npx patch-package
# - npm info unplugin-icons
- npm list package-manager-detector
# - npm install unplugin-icons@latest @antfu/install-pkg@latest package-manager-detector@latest
- npm run build
- ls /app/build/$DRONE_REPO_NAME/
- echo $NODE_MODULES_PATH
- cp -r dist /app/build/$DRONE_REPO_NAME
- name: build-docker-prod # 制作docker镜像
image: 10.7.127.190:38080/docker/docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: docker
path: /var/run/docker.sock # 挂载宿主机的docker
- name: config
path: /config
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cat Dockerfile
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
- sed -i 's/$PORTS_NAME/'"dasdafas"'/' deployment.yml
- sed -i 's/$PORTS_PORT/'"8081"'/' deployment.yml
- sed -i 's/$PROFILES/'"mosr"'/' nginx.conf
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- cat docker.sh
- sh docker.sh
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
when:
branch:
- prod
- name: build-docker-dm # 制作docker镜像
image: docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: docker
path: /var/run/docker.sock # 挂载宿主机的docker
- name: config
path: /config
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cat Dockerfile
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
- sed -i 's/$PORTS_NAME/'"dasdafas"'/' deployment.yml
- sed -i 's/$PORTS_PORT/'"8082"'/' deployment.yml
- sed -i 's/$PROFILES/'"mosr-dm"'/' nginx.conf
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- cat docker.sh
- sh docker.sh
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
when:
branch:
- dm
- name: drone-rancher-prod # rancher运行
image: bitnami/kubectl:1.26.13-debian-11-r1
volumes: # 将容器内目录挂载到宿主机
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
# 将deployment中定义的变量替换为drone中的内置变量
- kubectl apply -f deployment.yml -n mosr --kubeconfig=/app/config/base-taishan-kubectl.yml
when:
branch:
- prod
- name: drone-rancher-dm # rancher运行
image: bitnami/kubectl:1.26.13-debian-11-r1
volumes: # 将容器内目录挂载到宿主机
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
# 将deployment中定义的变量替换为drone中的内置变量
- kubectl apply -f deployment.yml -n mosr-dm --kubeconfig=/app/config/base-taishan-kubectl.yml
when:
branch:
- dm
volumes:
- name: cache
host:
path: /home/npm/mosr-web
- name: config # k8s对接的配置文件
host:
path: /home/kubect
- name: docker # 宿主机中的docker
host:
path: /var/run/docker.sock
load:
trigger:
branch:
- prod
- dm
event:
- push
kind: pipeline
type: docker
name: mosr-web
platform:
os: linux
arch: arm64
steps:
- name: build-package
image: node:18.19.0
volumes:
- name: cache
path: /drone/src/node_modules
commands:
- export CI=false
- mkdir -p /app/build/$DRONE_REPO_NAME
- rm -rf /app/build/$DRONE_REPO_NAME/*
- cp deployment.yml /app/build/$DRONE_REPO_NAME/
- cp Dockerfile /app/build/$DRONE_REPO_NAME/
- cp .dockerignore /app/build/$DRONE_REPO_NAME/
- cp default.conf /app/build/$DRONE_REPO_NAME/
- cp docker.sh /app/build/$DRONE_REPO_NAME/
- cp nginx.conf /app/build/$DRONE_REPO_NAME/
- npm -v
- node -v
- mkdir -p ./node_modules
- export NODE_MODULES_PATH=`pwd`/node_modules
- npm config set registry https://registry.npmmirror.com
- set NODE_OPTIONS=--openssl-legacy-provider
- npm install --legacy-peer-deps
- npm install codemirror
# - npm install patch-package
# - npx patch-package
# - npm info unplugin-icons
- npm list package-manager-detector
# - npm install unplugin-icons@latest @antfu/install-pkg@latest package-manager-detector@latest
- npm run build
- ls /app/build/$DRONE_REPO_NAME/
- echo $NODE_MODULES_PATH
- cp -r dist /app/build/$DRONE_REPO_NAME
- name: build-docker-prod # 制作docker镜像
image: 10.7.127.190:38080/docker/docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: docker
path: /var/run/docker.sock # 挂载宿主机的docker
- name: config
path: /config
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cat Dockerfile
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
- sed -i 's/$PORTS_NAME/'"dasdafas"'/' deployment.yml
- sed -i 's/$PORTS_PORT/'"8081"'/' deployment.yml
- sed -i 's/$PROFILES/'"mosr"'/' nginx.conf
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- cat docker.sh
- sh docker.sh
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
when:
branch:
- prod
- name: build-docker-dm # 制作docker镜像
image: docker # 使用官方docker镜像
volumes: # 将容器内目录挂载到宿主机
- name: docker
path: /var/run/docker.sock # 挂载宿主机的docker
- name: config
path: /config
environment: # 获取到密文的docker用户名和密码
DOCKER_USERNAME:
from_secret: docker_username
DOCKER_PASSWORD:
from_secret: docker_password
REGISTRY:
from_secret: registry
REGISTRY_NAMESPACE:
from_secret: registry_namespace
commands: # 定义在Docker容器中执行的shell命令
- cat Dockerfile
- sed -i 's/$REGISTRY/'"$REGISTRY"'/' deployment.yml
- sed -i 's/$REGISTRY_NAMESPACE/'"$REGISTRY_NAMESPACE"'/' deployment.yml
- sed -i 's/$DRONE_REPO_NAME/'"$DRONE_REPO_NAME"'/' deployment.yml
- sed -i 's/$DRONE_COMMIT/'"$DRONE_COMMIT"'/' deployment.yml
- sed -i 's/$PORTS_NAME/'"dasdafas"'/' deployment.yml
- sed -i 's/$PORTS_PORT/'"8082"'/' deployment.yml
- sed -i 's/$PROFILES/'"mosr-dm"'/' nginx.conf
# docker登录,不能在脚本中登录,并且不能使用docker login -u -p
- echo $DOCKER_PASSWORD | docker login $REGISTRY --username $DOCKER_USERNAME --password-stdin
- chmod +x docker.sh
- cat docker.sh
- sh docker.sh
# 执行完脚本删除本次制作的docker镜像,避免多次后当前runner空间不足
- docker rmi -f $(docker images | grep $DRONE_REPO_NAME | awk '{print $3}')
when:
branch:
- dm
- name: drone-rancher-prod # rancher运行
image: bitnami/kubectl:1.26.13-debian-11-r1
volumes: # 将容器内目录挂载到宿主机
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
# 将deployment中定义的变量替换为drone中的内置变量
- kubectl apply -f deployment.yml -n mosr --kubeconfig=/app/config/base-taishan-kubectl.yml
when:
branch:
- prod
- name: drone-rancher-dm # rancher运行
image: bitnami/kubectl:1.26.13-debian-11-r1
volumes: # 将容器内目录挂载到宿主机
- name: config
path: /app/config # 将kubectl 配置文件挂载出来
commands: # 定义在Docker容器中执行的shell命令
# 将deployment中定义的变量替换为drone中的内置变量
- kubectl apply -f deployment.yml -n mosr-dm --kubeconfig=/app/config/base-taishan-kubectl.yml
when:
branch:
- dm
volumes:
- name: cache
host:
path: /home/npm/mosr-web
- name: config # k8s对接的配置文件
host:
path: /home/kubect
- name: docker # 宿主机中的docker
host:
path: /var/run/docker.sock
load:
trigger:
branch:
- prod
- dm
event:
- push

View File

@@ -1,2 +1,2 @@
# 开发环境基地址
VITE_BASE_URL='/api'
# 开发环境基地址
VITE_BASE_URL='/api'

View File

@@ -1,3 +1,3 @@
# 生产环境基地址
VITE_BASE_URL='/api'
# 生产环境基地址
VITE_BASE_URL='/api'

56
.gitignore vendored
View File

@@ -1,28 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -1,19 +1,19 @@
FROM 10.7.127.190:38080/nginx:latest
RUN rm -rf /etc/nginx/conf.d/default.conf
RUN rm -rf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d
COPY nginx.conf /etc/nginx/
#COPY mosr.feashow.cn_chain.crt /etc/nginx/
#COPY private.key /etc/nginx/
#RUN useradd -b /home/clay -m -s /bin/bash clay
#RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay
#USER clay
COPY ./dist /home/clay
WORKDIR /home/clay
EXPOSE 80
FROM 10.7.127.190:38080/nginx:latest
RUN rm -rf /etc/nginx/conf.d/default.conf
RUN rm -rf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d
COPY nginx.conf /etc/nginx/
#COPY mosr.feashow.cn_chain.crt /etc/nginx/
#COPY private.key /etc/nginx/
#RUN useradd -b /home/clay -m -s /bin/bash clay
#RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay
#USER clay
COPY ./dist /home/clay
WORKDIR /home/clay
EXPOSE 80

View File

@@ -1,2 +1,2 @@
# 科技创新项目管理平台
# 科技创新项目管理平台

View File

@@ -1,19 +1,19 @@
server {
listen 80;
listen [::]:80;
location /api {
proxy_pass http://gateway.dev.svc.cluster.local:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
#proxy_set_header Host $host;
rewrite "^/api/(.*)$" /$1 break;
}
location / {
root /home/clay;
index index.html index.htm;
}
}
server {
listen 80;
listen [::]:80;
location /api {
proxy_pass http://gateway.dev.svc.cluster.local:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
#proxy_set_header Host $host;
rewrite "^/api/(.*)$" /$1 break;
}
location / {
root /home/clay;
index index.html index.htm;
}
}

View File

@@ -1,51 +1,51 @@
apiVersion: v1
kind: Service
metadata:
name: $DRONE_REPO_NAME
spec:
type: NodePort
ports:
- name: $PORTS_NAME
nodePort: $PORTS_PORT
port: 80
protocol: TCP
targetPort: 80
selector:
app: $DRONE_REPO_NAME
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: $DRONE_REPO_NAME
spec:
replicas: 1
selector:
matchLabels:
app: $DRONE_REPO_NAME
template:
metadata:
labels:
app: $DRONE_REPO_NAME
spec:
imagePullSecrets:
- name: harbor
containers:
- image: $REGISTRY/$REGISTRY_NAMESPACE/$DRONE_REPO_NAME:$DRONE_COMMIT
name: $DRONE_REPO_NAME
imagePullPolicy: Always
env:
- name: TIME_ZONE
value: Asia/Shanghai
- name: REF_NAME
value: dev
resources:
requests:
memory: 0.1Gi
cpu: 0.1
limits:
memory: 2Gi
cpu: 2
ports:
- containerPort: 80
name: app-port
apiVersion: v1
kind: Service
metadata:
name: $DRONE_REPO_NAME
spec:
type: NodePort
ports:
- name: $PORTS_NAME
nodePort: $PORTS_PORT
port: 80
protocol: TCP
targetPort: 80
selector:
app: $DRONE_REPO_NAME
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: $DRONE_REPO_NAME
spec:
replicas: 1
selector:
matchLabels:
app: $DRONE_REPO_NAME
template:
metadata:
labels:
app: $DRONE_REPO_NAME
spec:
imagePullSecrets:
- name: harbor
containers:
- image: $REGISTRY/$REGISTRY_NAMESPACE/$DRONE_REPO_NAME:$DRONE_COMMIT
name: $DRONE_REPO_NAME
imagePullPolicy: Always
env:
- name: TIME_ZONE
value: Asia/Shanghai
- name: REF_NAME
value: dev
resources:
requests:
memory: 0.1Gi
cpu: 0.1
limits:
memory: 2Gi
cpu: 2
ports:
- containerPort: 80
name: app-port

View File

@@ -1,15 +1,15 @@
#!/bin/sh
# 定义应用组名
group_name='clay'
# 定义应用名称
app_name=$DRONE_REPO_NAME
# 定义应用版本
app_version=$DRONE_COMMIT
echo ${app_version}
# 打包编译docker镜像
echo '----build image start----'
docker build -t ${group_name}/${app_name} .
echo '----build image success----'
docker tag ${group_name}/${app_name} $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
docker push $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
echo 'push success'
#!/bin/sh
# 定义应用组名
group_name='clay'
# 定义应用名称
app_name=$DRONE_REPO_NAME
# 定义应用版本
app_version=$DRONE_COMMIT
echo ${app_version}
# 打包编译docker镜像
echo '----build image start----'
docker build -t ${group_name}/${app_name} .
echo '----build image success----'
docker tag ${group_name}/${app_name} $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
docker push $REGISTRY/$REGISTRY_NAMESPACE/${app_name}:${app_version}
echo 'push success'

View File

@@ -1,13 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>科技创新项目管理平台</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>科技创新项目管理平台</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@@ -1,72 +1,72 @@
-----BEGIN CERTIFICATE-----
MIIG3DCCBMSgAwIBAgIQDzIS+rldpl8FKv9qt1IuQDANBgkqhkiG9w0BAQsFADBb
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg
SW5jLjElMCMGA1UEAxMcVHJ1c3RBc2lhIERWIFRMUyBSU0EgQ0EgMjAyNTAeFw0y
NTAzMTkwMDAwMDBaFw0yNTA2MTcyMzU5NTlaMBoxGDAWBgNVBAMTD21vc3IuZmVh
c2hvdy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK92bSayd6Wo
wFJz+ldX8QEgQiUjEPyQB0rV+Op9/eZSmpC6y+DuS/CddOPaXs+t1fV9L2kQ1yWD
Byc7cZK2PnzGb8+Uh9BR3UtVaCxISGqxjvt2V1lIwXbBDOUjtkVVlchhGR+BrNzP
YGyMLhgdBDxhKK4ogBNOx23AzCpTGFsU7sL996qwYo2rhIE8UuYcw3deS4RtfMUx
zt58wn1s+9kki6Qti7dLw3Bg0eCXop+7/FC09fg5Nh3EygMlZvLyvNOFig+o/Fk3
6ibp2N56yFLEfe+WNj4xPCad/3Cevh5BIgTsSAPBh6J5Jk4IXoL8PuCSc96d79Bg
SVGNGhRuCgcCAwEAAaOCAtswggLXMB8GA1UdIwQYMBaAFLQSKKW0wB2fKXFpPNkR
lkp1aVDAMB0GA1UdDgQWBBTL9/e/QUue1NxlPXspxQ/RzXhzxTAaBgNVHREEEzAR
gg9tb3NyLmZlYXNob3cuY24wPgYDVR0gBDcwNTAzBgZngQwBAgEwKTAnBggrBgEF
BQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIF
oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIweQYIKwYBBQUHAQEEbTBr
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUH
MAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9UcnVzdEFzaWFEVlRMU1JT
QUNBMjAyNS5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIB
awFpAHYATnWjJ1yaEMM4W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGVrKDPywAA
BAMARzBFAiAJkC1pvmPIhgdAkRoyPCItM4oRM5Bb8OI3zVzNvdNTkQIhAN1Fq4mU
GJYrJkOmwvJ2Mb5upB50Ic8C7KatpMdKEFM7AHYAfVkeEuF4KnscYWd8Xv340Idc
FKBOlZ65Ay/ZDowuebgAAAGVrKDQBwAABAMARzBFAiAT9jfX08uN94aIeK84IySz
jUPDa1MSWjJKsA3XusY3GAIhAJ9PvGtFx9+UM9YNNT7BZUq6hhVvhYWhlf+d0qpy
uEl9AHcAzxFW7tUufK/zh1vZaS6b6RpxZ0qwF+ysAdJbd87MOwgAAAGVrKDP+AAA
BAMASDBGAiEA0c9dt1JwyAMzQtv7UsPaKEJ5sp6HDaSWe5BGIYWsYrcCIQDjS6L1
9TF6SpcEWHH6bl952VQb6Xvt1JmmKUNX6iK2xTANBgkqhkiG9w0BAQsFAAOCAgEA
0E2VWQjWgEBz968xq2cpYGv2Enfs2TWpynuoPTwY83V7h2ejNbpjgyW1gT/kQkxa
G5k4jpkVmNMaj3CAvK4IA5jOPh6dhzBG35Qc0PwRm0eovcUdUNUd0g4EOv82p2s1
ab1SWNYoxGdS+y+LHhfFZ7CoVcSvBz+LHBlPTVTkLA0SWLA0fhS3pl5oGIilMtSM
znCUUuMBtMQBv7sFX2gDEYwxGaMn3lpoqBGkpx4UBc51z/U3+X9zLqu6n/GpLC72
+qz6QtQVm0Np8gcjul0ebQqAPwDG4U+9jYEmdwVHZ0iUKgyZPECPU+TTtHx0TFS3
B5JXy8vbGJBqpwq6hMnu/SFm+GY3iPk7N0Aj5+9QNcl2FTF8k/nCoK3MuY71ZmxR
E1NY6Hl5KpKzBqc7JG4iqQxJ0dD9Racn4wegGDlX0Vr2U+ohHYeETNJXOX+JT4tc
1PBdfiywbX+FCdE2ZPehWa6dt4fnPBC/9lSywrzOWLNt9z1a/Mh73N5F6ndaXq1p
v/N3Q0qnXpW1RZa6Baqlfvk2vqhraRbT9YH5Y+f51DhtVB6fbELO/pJr1H5kh0XI
CczHkGTGD7xZloNfTMLP2AVguIXJ0EASAAMw/MBRWvSd4He2lLHvujEqTXsTISgv
v+/5bZP8qBk3/oEgdLjlmqWY1sesBH84tiMZcxCkPNM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIQCSYyO0lk42hGFRLe8aXVLDANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yNTAxMDgwMDAwMDBaFw0zNTAxMDcyMzU5NTlaMFsxCzAJBgNVBAYTAkNO
MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSUwIwYDVQQD
ExxUcnVzdEFzaWEgRFYgVExTIFJTQSBDQSAyMDI1MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEA0fuEmuBIsN6ZZVq+gRobMorOGIilTCIfQrxNpR8FUZ9R
/GfbiekbiIKphQXEZ7N1uBnn6tXUuZ32zl6jPkZpHzN/Bmgk1BWSIzVc0npMzrWq
/hrbk5+KddXJdsNpeG1+Q8lc8uVMBrztnxaPb7Rh7yQCsMrcO4hgVaqLJWkVvEfW
ULtoCHQnNaj4IroG6VxQf1oArQ8bPbwpI02lieSahRa78FQuXdoGVeQcrkhtVjZs
ON98vq5fPWZX2LFv7e5J6P9IHbzvOl8yyQjv+2/IOwhNSkaXX3bI+//bqF9XW/p7
+gsUmHiK5YsvLjmXcvDmoDEGrXMzgX31Zl2nJ+umpRbLjwP8rxYIUsKoEwEdFoto
Aid59UEBJyw/GibwXQ5xTyKD/N6C8SFkr1+myOo4oe1UB+YgvRu6qSxIABo5kYdX
FodLP4IgoVJdeUFs1Usa6bxYEO6EgMf5lCWt9hGZszvXYZwvyZGq3ogNXM7eKyi2
20WzJXYMmi9TYFq2Fa95aZe4wki6YhDhhOO1g0sjITGVaB73G+JOCI9yJhv6+REN
D40ZpboUHE8JNgMVWbG1isAMVCXqiADgXtuC+tmJWPEH9cR6OuJLEpwOzPfgAbnn
2MRu7Tsdr8jPjTPbD0FxblX1ydW3RG30vwLF5lkTTRkHG9epMgpPMdYP7nY/08MC
AwEAAaOCAVYwggFSMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLQSKKW0
wB2fKXFpPNkRlkp1aVDAMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
dgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
dC5jb20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
aWdpQ2VydEdsb2JhbFJvb3RHMi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDARBgNV
HSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAJ4a3svh316GY2+Z7EYx
mBIsOwjJSnyoEfzx2T699ctLLrvuzS79Mg3pPjxSLlUgyM8UzrFc5tgVU3dZ1sFQ
I4RM+ysJdvIAX/7Yx1QbooVdKhkdi9X7QN7yVkjqwM3fY3WfQkRTzhIkM7mYIQbR
r+y2Vkju61BLqh7OCRpPMiudjEpP1kEtRyGs2g0aQpEIqKBzxgitCXSayO1hoO6/
71ts801OzYlqYW9OQQQ2GCJyFbD6XHDjdpn+bWUxTKWaMY0qedSCbHE3Kl2QEF0C
ynZ7SbC03yR+gKZQDeTXrNP1kk5Qhe7jSXgw+nhbspe0q/M1ZcNCz+sPxeOwdCcC
gJE=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIG3DCCBMSgAwIBAgIQDzIS+rldpl8FKv9qt1IuQDANBgkqhkiG9w0BAQsFADBb
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg
SW5jLjElMCMGA1UEAxMcVHJ1c3RBc2lhIERWIFRMUyBSU0EgQ0EgMjAyNTAeFw0y
NTAzMTkwMDAwMDBaFw0yNTA2MTcyMzU5NTlaMBoxGDAWBgNVBAMTD21vc3IuZmVh
c2hvdy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK92bSayd6Wo
wFJz+ldX8QEgQiUjEPyQB0rV+Op9/eZSmpC6y+DuS/CddOPaXs+t1fV9L2kQ1yWD
Byc7cZK2PnzGb8+Uh9BR3UtVaCxISGqxjvt2V1lIwXbBDOUjtkVVlchhGR+BrNzP
YGyMLhgdBDxhKK4ogBNOx23AzCpTGFsU7sL996qwYo2rhIE8UuYcw3deS4RtfMUx
zt58wn1s+9kki6Qti7dLw3Bg0eCXop+7/FC09fg5Nh3EygMlZvLyvNOFig+o/Fk3
6ibp2N56yFLEfe+WNj4xPCad/3Cevh5BIgTsSAPBh6J5Jk4IXoL8PuCSc96d79Bg
SVGNGhRuCgcCAwEAAaOCAtswggLXMB8GA1UdIwQYMBaAFLQSKKW0wB2fKXFpPNkR
lkp1aVDAMB0GA1UdDgQWBBTL9/e/QUue1NxlPXspxQ/RzXhzxTAaBgNVHREEEzAR
gg9tb3NyLmZlYXNob3cuY24wPgYDVR0gBDcwNTAzBgZngQwBAgEwKTAnBggrBgEF
BQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIF
oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIweQYIKwYBBQUHAQEEbTBr
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUH
MAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9UcnVzdEFzaWFEVlRMU1JT
QUNBMjAyNS5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIB
awFpAHYATnWjJ1yaEMM4W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGVrKDPywAA
BAMARzBFAiAJkC1pvmPIhgdAkRoyPCItM4oRM5Bb8OI3zVzNvdNTkQIhAN1Fq4mU
GJYrJkOmwvJ2Mb5upB50Ic8C7KatpMdKEFM7AHYAfVkeEuF4KnscYWd8Xv340Idc
FKBOlZ65Ay/ZDowuebgAAAGVrKDQBwAABAMARzBFAiAT9jfX08uN94aIeK84IySz
jUPDa1MSWjJKsA3XusY3GAIhAJ9PvGtFx9+UM9YNNT7BZUq6hhVvhYWhlf+d0qpy
uEl9AHcAzxFW7tUufK/zh1vZaS6b6RpxZ0qwF+ysAdJbd87MOwgAAAGVrKDP+AAA
BAMASDBGAiEA0c9dt1JwyAMzQtv7UsPaKEJ5sp6HDaSWe5BGIYWsYrcCIQDjS6L1
9TF6SpcEWHH6bl952VQb6Xvt1JmmKUNX6iK2xTANBgkqhkiG9w0BAQsFAAOCAgEA
0E2VWQjWgEBz968xq2cpYGv2Enfs2TWpynuoPTwY83V7h2ejNbpjgyW1gT/kQkxa
G5k4jpkVmNMaj3CAvK4IA5jOPh6dhzBG35Qc0PwRm0eovcUdUNUd0g4EOv82p2s1
ab1SWNYoxGdS+y+LHhfFZ7CoVcSvBz+LHBlPTVTkLA0SWLA0fhS3pl5oGIilMtSM
znCUUuMBtMQBv7sFX2gDEYwxGaMn3lpoqBGkpx4UBc51z/U3+X9zLqu6n/GpLC72
+qz6QtQVm0Np8gcjul0ebQqAPwDG4U+9jYEmdwVHZ0iUKgyZPECPU+TTtHx0TFS3
B5JXy8vbGJBqpwq6hMnu/SFm+GY3iPk7N0Aj5+9QNcl2FTF8k/nCoK3MuY71ZmxR
E1NY6Hl5KpKzBqc7JG4iqQxJ0dD9Racn4wegGDlX0Vr2U+ohHYeETNJXOX+JT4tc
1PBdfiywbX+FCdE2ZPehWa6dt4fnPBC/9lSywrzOWLNt9z1a/Mh73N5F6ndaXq1p
v/N3Q0qnXpW1RZa6Baqlfvk2vqhraRbT9YH5Y+f51DhtVB6fbELO/pJr1H5kh0XI
CczHkGTGD7xZloNfTMLP2AVguIXJ0EASAAMw/MBRWvSd4He2lLHvujEqTXsTISgv
v+/5bZP8qBk3/oEgdLjlmqWY1sesBH84tiMZcxCkPNM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIQCSYyO0lk42hGFRLe8aXVLDANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yNTAxMDgwMDAwMDBaFw0zNTAxMDcyMzU5NTlaMFsxCzAJBgNVBAYTAkNO
MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSUwIwYDVQQD
ExxUcnVzdEFzaWEgRFYgVExTIFJTQSBDQSAyMDI1MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEA0fuEmuBIsN6ZZVq+gRobMorOGIilTCIfQrxNpR8FUZ9R
/GfbiekbiIKphQXEZ7N1uBnn6tXUuZ32zl6jPkZpHzN/Bmgk1BWSIzVc0npMzrWq
/hrbk5+KddXJdsNpeG1+Q8lc8uVMBrztnxaPb7Rh7yQCsMrcO4hgVaqLJWkVvEfW
ULtoCHQnNaj4IroG6VxQf1oArQ8bPbwpI02lieSahRa78FQuXdoGVeQcrkhtVjZs
ON98vq5fPWZX2LFv7e5J6P9IHbzvOl8yyQjv+2/IOwhNSkaXX3bI+//bqF9XW/p7
+gsUmHiK5YsvLjmXcvDmoDEGrXMzgX31Zl2nJ+umpRbLjwP8rxYIUsKoEwEdFoto
Aid59UEBJyw/GibwXQ5xTyKD/N6C8SFkr1+myOo4oe1UB+YgvRu6qSxIABo5kYdX
FodLP4IgoVJdeUFs1Usa6bxYEO6EgMf5lCWt9hGZszvXYZwvyZGq3ogNXM7eKyi2
20WzJXYMmi9TYFq2Fa95aZe4wki6YhDhhOO1g0sjITGVaB73G+JOCI9yJhv6+REN
D40ZpboUHE8JNgMVWbG1isAMVCXqiADgXtuC+tmJWPEH9cR6OuJLEpwOzPfgAbnn
2MRu7Tsdr8jPjTPbD0FxblX1ydW3RG30vwLF5lkTTRkHG9epMgpPMdYP7nY/08MC
AwEAAaOCAVYwggFSMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLQSKKW0
wB2fKXFpPNkRlkp1aVDAMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
dgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
dC5jb20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
aWdpQ2VydEdsb2JhbFJvb3RHMi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDARBgNV
HSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAJ4a3svh316GY2+Z7EYx
mBIsOwjJSnyoEfzx2T699ctLLrvuzS79Mg3pPjxSLlUgyM8UzrFc5tgVU3dZ1sFQ
I4RM+ysJdvIAX/7Yx1QbooVdKhkdi9X7QN7yVkjqwM3fY3WfQkRTzhIkM7mYIQbR
r+y2Vkju61BLqh7OCRpPMiudjEpP1kEtRyGs2g0aQpEIqKBzxgitCXSayO1hoO6/
71ts801OzYlqYW9OQQQ2GCJyFbD6XHDjdpn+bWUxTKWaMY0qedSCbHE3Kl2QEF0C
ynZ7SbC03yR+gKZQDeTXrNP1kk5Qhe7jSXgw+nhbspe0q/M1ZcNCz+sPxeOwdCcC
gJE=
-----END CERTIFICATE-----

View File

@@ -1,52 +1,52 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' '*';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
listen [::]:80;
location /api {
proxy_pass http://gateway.$PROFILES.svc.cluster.local:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Host $host;
rewrite "^/api/(.*)$" /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
client_max_body_size 30m;
}
location / {
root /home/clay;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
}
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' '*';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
listen [::]:80;
location /api {
proxy_pass http://gateway.$PROFILES.svc.cluster.local:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Host $host;
rewrite "^/api/(.*)$" /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
client_max_body_size 30m;
}
location / {
root /home/clay;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
}

View File

@@ -1,59 +1,59 @@
{
"name": "mosr-web",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build --config vite.config.mjs",
"preview": "vite preview"
},
"overrides": {
"package-manager-detector": "1.0.0",
"@iconify/utils": "2.2.1"
},
"dependencies": {
"@antv/g6": "^3.5.7",
"@tinymce/tinymce-vue": "^4.0.7",
"axios": "^1.4.0",
"d3": "^7.8.5",
"docx-preview": "^0.3.2",
"echarts": "^5.4.2",
"element-plus": "^2.6.0",
"file-saver": "^2.0.5",
"highlight.js": "9.18.5",
"jquery": "^3.6.0",
"js-cookie": "^3.0.5",
"nprogress": "^0.2.0",
"pinia": "^2.0.35",
"sass": "^1.62.1",
"scss": "^0.2.4",
"sql-formatter": "^2.3.4",
"tinymce": "^5.0.4",
"unplugin-icons": "^0.16.1",
"vite-plugin-inspect": "^0.7.26",
"vue": "^3.2.47",
"vue-clipboard3": "^2.0.0",
"vue-codemirror": "^6.1.1",
"vue-json-viewer": "^3.0.4",
"vue-router": "^4.1.6",
"vue3-pdf-app": "^1.0.3",
"vue3-print-nb": "^0.1.4",
"vuedraggable": "^4.1.0",
"xlsx": "^0.18.5",
"xlsx-style-vite": "^0.0.2"
},
"devDependencies": {
"@codemirror/lang-java": "^6.0.1",
"@codemirror/lang-javascript": "^6.1.9",
"@codemirror/lang-sql": "^6.5.4",
"@vitejs/plugin-vue": "^4.2.1",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"lodash": "^4.17.21",
"unplugin-auto-import": "^0.15.3",
"unplugin-vue-components": "^0.24.1",
"vite": "^4.3.4",
"vite-plugin-svg-icons": "^0.4.0"
}
}
{
"name": "mosr-web",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build --config vite.config.mjs",
"preview": "vite preview"
},
"overrides": {
"package-manager-detector": "1.0.0",
"@iconify/utils": "2.2.1"
},
"dependencies": {
"@antv/g6": "^3.5.7",
"@tinymce/tinymce-vue": "^4.0.7",
"axios": "^1.4.0",
"d3": "^7.8.5",
"docx-preview": "^0.3.2",
"echarts": "^5.4.2",
"element-plus": "^2.6.0",
"file-saver": "^2.0.5",
"highlight.js": "9.18.5",
"jquery": "^3.6.0",
"js-cookie": "^3.0.5",
"nprogress": "^0.2.0",
"pinia": "^2.0.35",
"sass": "^1.62.1",
"scss": "^0.2.4",
"sql-formatter": "^2.3.4",
"tinymce": "^5.0.4",
"unplugin-icons": "^0.16.1",
"vite-plugin-inspect": "^0.7.26",
"vue": "^3.2.47",
"vue-clipboard3": "^2.0.0",
"vue-codemirror": "^6.1.1",
"vue-json-viewer": "^3.0.4",
"vue-router": "^4.1.6",
"vue3-pdf-app": "^1.0.3",
"vue3-print-nb": "^0.1.4",
"vuedraggable": "^4.1.0",
"xlsx": "^0.18.5",
"xlsx-style-vite": "^0.0.2"
},
"devDependencies": {
"@codemirror/lang-java": "^6.0.1",
"@codemirror/lang-javascript": "^6.1.9",
"@codemirror/lang-sql": "^6.5.4",
"@vitejs/plugin-vue": "^4.2.1",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"lodash": "^4.17.21",
"unplugin-auto-import": "^0.15.3",
"unplugin-vue-components": "^0.24.1",
"vite": "^4.3.4",
"vite-plugin-svg-icons": "^0.4.0"
}
}

View File

@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvdm0msnelqMBS
c/pXV/EBIEIlIxD8kAdK1fjqff3mUpqQusvg7kvwnXTj2l7PrdX1fS9pENclgwcn
O3GStj58xm/PlIfQUd1LVWgsSEhqsY77dldZSMF2wQzlI7ZFVZXIYRkfgazcz2Bs
jC4YHQQ8YSiuKIATTsdtwMwqUxhbFO7C/feqsGKNq4SBPFLmHMN3XkuEbXzFMc7e
fMJ9bPvZJIukLYu3S8NwYNHgl6Kfu/xQtPX4OTYdxMoDJWby8rzThYoPqPxZN+om
6djeeshSxH3vljY+MTwmnf9wnr4eQSIE7EgDwYeieSZOCF6C/D7gknPene/QYElR
jRoUbgoHAgMBAAECggEABmJQMV6/9LKRoM5gduoXtjtGvNQsS4wv/7yOTHXeFZG+
1vI89cel0rDf7mRlG7hO9xohbfizY0WDrp0+kiB4YJDVw587W8yGuTV3z1in7d3c
/nA9WF3J0DjQ78tfV+F3zC0gPWG5+OTAtOJa0PzJSSsd0Exf8JPmtKsVopqYYcPv
RL2uP+NfcsxIEPz7rBBqiTGbOgsoKIpVZWiV6dmGOHLnI3ktWE8GXyIFv0VO6kp2
fk/Z2uU9rfS9Qc9NijVdZ5AejdSh70iWNdiVMTSXZ69XLQCiY1h/376mraAPZTC1
T0fYAtaOdyRrYLIW3yuznZa6hz351+t4TjJHQGjAUQKBgQDe8FS3yM85Ve3qlNaV
pzjpjkv8cn8u43Hyk88owNACxkvzUXx15YE+AGjjycVO5rbyC1mtdE2MKX8cd5T/
cA75RoSDxBTR7xi9eqBzJpQ7hm2rTaZSkHhu4P9KsthgQFFYQB6EkZgYczLOs/OV
UmPMuKwL7HcwuRf00jjAOoJPdwKBgQDJe7R4PS0VBAWnh3lC9R/NEbEoFQ6LUwPh
Qgmgj6LRB/1NgaC7ekDCSyfFlTtpnRDD+WqCrZDiB1ZZehyUObvr0Y0Cb4Y77Fjh
lPVG0kfcKUldMpJIfeex0LPBwYHC62Y0ztNQmtgTldDjX04b4gAEgpUReHVTJtDr
6S1wRPVd8QKBgHIL0+roqUmVcc5NMbEBCJZCGxEbqYBdDg+gGZupdz/UHUpt5xOQ
wprrLr1InM0OLYyIzelz06/eEo6HhgteUeqnbmbRyizS+X8E2kvN8oq47CVz5Z/b
FCD0rOSTtSkX/gT9WB9NM9deJyGi4PsEWNWDq0+2OgsMxPqTCEEeLUdlAoGAHNmB
tdXMpr20sZBMZLIEo7Bs1XhuZLS2UYLLLhpjDds/AeIVycJvk2J/h2Me5rh+thD4
l02S+Upjqtw5S2AY8GNI9ZhSeDIXZ/WUSVfCwluHDbk4CPk+O8/ObWfv1KEwOU+E
In6JggRprKTw4j0yE3M/NQkyg32DXMQ+pVy6ZYECgYEAmW/+vm3X2NMj8yjr0Io2
P3F/9EHPkrGHNC3Qj6Q2mFus6oDe6NwOQg5Su0fFC77spHFi1g/MlGUxbzoxjVxH
1wQmwCHBJuJ97H9MOJ9K2v88/pkvfFGthkTLpbcJLqX57WVEVnVKBMNhpLrlp+0r
T3tV8tN010INwiQkaoqCsuw=
-----END PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvdm0msnelqMBS
c/pXV/EBIEIlIxD8kAdK1fjqff3mUpqQusvg7kvwnXTj2l7PrdX1fS9pENclgwcn
O3GStj58xm/PlIfQUd1LVWgsSEhqsY77dldZSMF2wQzlI7ZFVZXIYRkfgazcz2Bs
jC4YHQQ8YSiuKIATTsdtwMwqUxhbFO7C/feqsGKNq4SBPFLmHMN3XkuEbXzFMc7e
fMJ9bPvZJIukLYu3S8NwYNHgl6Kfu/xQtPX4OTYdxMoDJWby8rzThYoPqPxZN+om
6djeeshSxH3vljY+MTwmnf9wnr4eQSIE7EgDwYeieSZOCF6C/D7gknPene/QYElR
jRoUbgoHAgMBAAECggEABmJQMV6/9LKRoM5gduoXtjtGvNQsS4wv/7yOTHXeFZG+
1vI89cel0rDf7mRlG7hO9xohbfizY0WDrp0+kiB4YJDVw587W8yGuTV3z1in7d3c
/nA9WF3J0DjQ78tfV+F3zC0gPWG5+OTAtOJa0PzJSSsd0Exf8JPmtKsVopqYYcPv
RL2uP+NfcsxIEPz7rBBqiTGbOgsoKIpVZWiV6dmGOHLnI3ktWE8GXyIFv0VO6kp2
fk/Z2uU9rfS9Qc9NijVdZ5AejdSh70iWNdiVMTSXZ69XLQCiY1h/376mraAPZTC1
T0fYAtaOdyRrYLIW3yuznZa6hz351+t4TjJHQGjAUQKBgQDe8FS3yM85Ve3qlNaV
pzjpjkv8cn8u43Hyk88owNACxkvzUXx15YE+AGjjycVO5rbyC1mtdE2MKX8cd5T/
cA75RoSDxBTR7xi9eqBzJpQ7hm2rTaZSkHhu4P9KsthgQFFYQB6EkZgYczLOs/OV
UmPMuKwL7HcwuRf00jjAOoJPdwKBgQDJe7R4PS0VBAWnh3lC9R/NEbEoFQ6LUwPh
Qgmgj6LRB/1NgaC7ekDCSyfFlTtpnRDD+WqCrZDiB1ZZehyUObvr0Y0Cb4Y77Fjh
lPVG0kfcKUldMpJIfeex0LPBwYHC62Y0ztNQmtgTldDjX04b4gAEgpUReHVTJtDr
6S1wRPVd8QKBgHIL0+roqUmVcc5NMbEBCJZCGxEbqYBdDg+gGZupdz/UHUpt5xOQ
wprrLr1InM0OLYyIzelz06/eEo6HhgteUeqnbmbRyizS+X8E2kvN8oq47CVz5Z/b
FCD0rOSTtSkX/gT9WB9NM9deJyGi4PsEWNWDq0+2OgsMxPqTCEEeLUdlAoGAHNmB
tdXMpr20sZBMZLIEo7Bs1XhuZLS2UYLLLhpjDds/AeIVycJvk2J/h2Me5rh+thD4
l02S+Upjqtw5S2AY8GNI9ZhSeDIXZ/WUSVfCwluHDbk4CPk+O8/ObWfv1KEwOU+E
In6JggRprKTw4j0yE3M/NQkyg32DXMQ+pVy6ZYECgYEAmW/+vm3X2NMj8yjr0Io2
P3F/9EHPkrGHNC3Qj6Q2mFus6oDe6NwOQg5Su0fFC77spHFi1g/MlGUxbzoxjVxH
1wQmwCHBJuJ97H9MOJ9K2v88/pkvfFGthkTLpbcJLqX57WVEVnVKBMNhpLrlp+0r
T3tV8tN010INwiQkaoqCsuw=
-----END PRIVATE KEY-----

File diff suppressed because one or more lines are too long

View File

@@ -1,61 +1,61 @@
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.4;
margin: 1rem;
}
table {
border-collapse: collapse;
}
/* Apply a default padding if legacy cellpadding attribute is missing */
table:not([cellpadding]) th,
table:not([cellpadding]) td {
padding: 0.4rem;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-width"]) th,
table[border]:not([border="0"]):not([style*="border-width"]) td {
border-width: 1px;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-style"]) th,
table[border]:not([border="0"]):not([style*="border-style"]) td {
border-style: solid;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-color"]) th,
table[border]:not([border="0"]):not([style*="border-color"]) td {
border-color: #ccc;
}
figure {
display: table;
margin: 1rem auto;
}
figure figcaption {
color: #999;
display: block;
margin-top: 0.25rem;
text-align: center;
}
hr {
border-color: #ccc;
border-style: solid;
border-width: 1px 0 0 0;
}
code {
background-color: #e8e8e8;
border-radius: 3px;
padding: 0.1rem 0.2rem;
}
.mce-content-body:not([dir=rtl]) blockquote {
border-left: 2px solid #ccc;
margin-left: 1.5rem;
padding-left: 1rem;
}
.mce-content-body[dir=rtl] blockquote {
border-right: 2px solid #ccc;
margin-right: 1.5rem;
padding-right: 1rem;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.4;
margin: 1rem;
}
table {
border-collapse: collapse;
}
/* Apply a default padding if legacy cellpadding attribute is missing */
table:not([cellpadding]) th,
table:not([cellpadding]) td {
padding: 0.4rem;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-width"]) th,
table[border]:not([border="0"]):not([style*="border-width"]) td {
border-width: 1px;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-style"]) th,
table[border]:not([border="0"]):not([style*="border-style"]) td {
border-style: solid;
}
/* Set default table styles if a table has a positive border attribute
and no inline css */
table[border]:not([border="0"]):not([style*="border-color"]) th,
table[border]:not([border="0"]):not([style*="border-color"]) td {
border-color: #ccc;
}
figure {
display: table;
margin: 1rem auto;
}
figure figcaption {
color: #999;
display: block;
margin-top: 0.25rem;
text-align: center;
}
hr {
border-color: #ccc;
border-style: solid;
border-width: 1px 0 0 0;
}
code {
background-color: #e8e8e8;
border-radius: 3px;
padding: 0.1rem 0.2rem;
}
.mce-content-body:not([dir=rtl]) blockquote {
border-left: 2px solid #ccc;
margin-left: 1.5rem;
padding-left: 1rem;
}
.mce-content-body[dir=rtl] blockquote {
border-right: 2px solid #ccc;
margin-right: 1.5rem;
padding-right: 1rem;
}

View File

@@ -1 +1 @@
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,211 +1,211 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>axupimgs</title>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection" content="telephone=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<style>
html,body{height:100%;margin:0;padding:0;background:#fff;}
ul{margin:0;padding:0;list-style:none;}
#wrap{padding:10px;}
#topbar{padding:10px 0;border-bottom:1px solid #ccc;text-align:right;}
#topbar button {margin:0;margin-left:5px;outline:none;padding: 4px 16px;box-sizing: border-box;
display:inline-block;border:none;border-radius:3px;text-align:center;cursor:pointer;
font-size:14px;line-height:1.5;background-color:#f0f0f0;color:#223;
}
#topbar button.primary{background-color:#3d97d4;color:#fff;}
#topbar button:hover{background-color:#207ab7;color:#fff;}
#topbar button.removeall{float:left}
#file_list {display:grid;grid-gap:10px;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));padding-top:10px;}
#file_list:empty:after{content:'可以直接拖拽文件到这里';color:#777;font-size:0.8em;}
#file_list li{position:relative;display:block;vertical-align:top;padding:5px 5px;border-radius:5px;}
#file_list li.up-over {}
#file_list li.up-now {}
#file_list li.up-now:after{content:'';position:absolute;top:0;left:0;display:block;width:100%;height:100%;background:rgba(255,255,255,0.8) url(loading.gif) center center no-repeat;border-radius:5px;z-index:999;}
#file_list li:hover{background-color:#ddd;}
#file_list li .picbox {display:flex;flex:0 0 auto;justify-content:center;overflow:hidden;position:relative;width:100%;padding-top:100%;align-items:center;}
#file_list li .picbox img {display:block;max-width:100%;max-height:100%;position:absolute;
top:50%;left:50%;transform:translateX(-50%) translateY(-50%);}
#file_list li.up-over .picbox:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M512%200C229.376%200%200%20229.376%200%20512s229.376%20512%20512%20512%20512-229.376%20512-512S794.624%200%20512%200z%22%20fill%3D%22%234AC711%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22M855.552%20394.752l-358.4%20358.4a50.9952%2050.9952%200%200%201-72.192%200l-204.8-204.8c-18.944-19.968-18.944-51.2%200-71.168a50.5344%2050.5344%200%200%201%2072.192-1.024L460.8%20644.608l322.048-322.048c19.968-18.944%2051.2-18.944%2071.168%200%2020.48%2019.456%2020.992%2051.712%201.536%2072.192z%22%20fill%3D%22%23FFFFFF%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E');position:absolute;bottom:2px;right:2px;z-index:9;}
#file_list li .tools {display:none;position:absolute;bottom:5px;right:5px;z-index:99;}
#file_list li:hover .tools {display:block;}
#file_list li .tools .remove{cursor:pointer;}
#file_list li .tools .remove:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20width=%2224%22%20height=%2224%22%20viewBox=%220%200%2024%2024%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20d=%22M17%206h3a1%201%200%200%201%200%202h-1v11a3%203%200%200%201-3%203H8a3%203%200%200%201-3-3V8H4a1%201%200%201%201%200-2h3V5a3%203%200%200%201%203-3h4a3%203%200%200%201%203%203v1zm-2%200V5a1%201%200%200%200-1-1h-4a1%201%200%200%200-1%201v1h6zm2%202H7v11a1%201%200%200%200%201%201h8a1%201%200%200%200%201-1V8zm-8%203a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6zm4%200a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6z%22%3E%3C/path%3E%3C/svg%3E');}
#file_list li .namebox {font-size:14px;line-height:20px;max-height:40px;overflow:hidden;padding:5px 10px;text-align:center;display:flex;justify-content:center;align-items:flex-start;}
#file_list li .namebox span{word-break:break-all;vertical-align:top;}
</style>
</head>
<body>
<div id="wrap">
<div id="topbar"><button class="addfile primary">+ 添加文件</button><button class="removeall">清空列表</button></div>
<ul id="file_list"></ul>
</div>
<script>
var editor=parent.tinymce.activeEditor;
var axupimgs=parent.axupimgs;
axupimgs.res = []; //存放本地文件的数组
var blobInfo = {file:null}
blobInfo.blob = function(){return this.file;}
var upload_handler = axupimgs.images_upload_handler;
var upload_base_path = axupimgs.images_upload_base_path;
//为列表添加排序
function reSort(){
document.querySelectorAll('#file_list li').forEach((el,i)=>{
el.setAttribute('data-num',i);
});
}
function addList(files){
var files_sum = files.length;
var vDom = document.createDocumentFragment();
for(let i=0;i<files_sum;i++){
let file = files[i];
let blobUrl = window.URL.createObjectURL(file)
axupimgs.res.push({file:file,blobUrl:blobUrl,url:''});
let li = document.createElement('li');
li.setAttribute('class','up-no');
li.setAttribute('data-time',file.lastModified);
li.innerHTML='<div class="picbox"><img src="'+blobUrl+'"></div><div class="namebox"><span>'+file.name+'</span></div><div class="tools"><a class="remove"></a></div>';
vDom.appendChild(li);
}
document.querySelector('#file_list').appendChild(vDom);
if(axupimgs.res.length>0){
document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
el.classList ? el.classList.add('up-now') : el.className+=' up-now';
});
upAllFiles(0);
}
//reSort();
}
//清空列表
document.querySelector('#topbar .removeall').addEventListener('click',()=>{
axupimgs.res=[]
document.querySelectorAll('#file_list li').forEach((el,i)=>{
el.parentNode.removeChild(el)
});
});
//拖拽添加
document.addEventListener('dragover', (e)=>{
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
document.addEventListener('drop', (e)=>{
e.stopPropagation();
e.preventDefault();
if(!e.dataTransfer.files){return false;}
var dropfiles = e.dataTransfer.files;
if(!(dropfiles.length>0)){return false;}
var exts=axupimgs.axupimgs_filetype.replace(/(\s)+/g,'').toLowerCase().split(',');
var files=[];
for( let file of dropfiles ){
ext = file.name.split('.');
ext = '.'+ext[ext.length-1];
for(let s of exts){
if(s==ext){
files.push(file);
break;
}
}
}
if(files.length>0){ addList(files) }
});
//添加文件
document.querySelector('#topbar .addfile').addEventListener('click',()=>{
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('multiple', 'multiple');
input.setAttribute('accept', axupimgs.axupimgs_filetype);
input.click();
input.onchange = function() {
var files = this.files;
addList(files);
}
});
var file_i = 0;
function upAllFiles(n){
var len = axupimgs.res.length;
file_i = n;
if(len == n){
file_i=0;
// document.querySelector('#topbar .upall').innerText='全部上传';
return true;
}
if( axupimgs.res[n].url!='' ){
n++;
upAllFiles(n)
}else{
blobInfo.file=axupimgs.res[n].file;
upload_handler(blobInfo,function(url,name){
if(upload_base_path){
if(upload_base_path.slice(-1)=='/' && url.substr(0,1)=='/' ){
url = upload_base_path + url.slice(1);
}else if(upload_base_path.slice(-1)!='/' && url.substr(0,1)!='/' ){
url = upload_base_path + '/' + url;
}else{
url = upload_base_path + url;
}
}
axupimgs.res[file_i].url = url;
// filename = url.split('/').pop();
filename = name
var li = document.querySelectorAll('#file_list li')[file_i];
li.setAttribute('class','up-over');
li.querySelector('.namebox span').innerText = filename;
n++
upAllFiles(n);
},function(err){
// document.querySelector('#topbar .upall').innerText='全部上传';
// document.querySelectorAll('#file_list li.up-now').forEach((el,i)=>{
// el.setAttribute('class','up-no');
// });
// alert(err);
});
}
}
//
// document.querySelector('#topbar .upall').addEventListener('click',(e)=>{
// if(e.target.innerText!='全部上传'){return false;}
// if(axupimgs.res.length>0){
// document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
// el.classList ? el.classList.add('up-now') : el.className+=' up-now';
// });
// e.target.innerText='上传中...';
// upAllFiles(0);
// }
// });
var observ_flist = new MutationObserver( (muList,observe)=>{
if(muList[0].addedNodes.length>0){
muList[0].addedNodes.forEach((el)=>{
el.querySelector('.remove').addEventListener('click',(e)=>{
var li = e.target.parentNode.parentNode;
var n = li.getAttribute('data-num');
var el = document.querySelectorAll('#file_list li')[n];
el.parentNode.removeChild(el);
axupimgs.res.splice(n,1);
});
});
}
reSort();
});
observ_flist.observe(document.querySelector('#file_list'),{childList:true});
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>axupimgs</title>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection" content="telephone=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<style>
html,body{height:100%;margin:0;padding:0;background:#fff;}
ul{margin:0;padding:0;list-style:none;}
#wrap{padding:10px;}
#topbar{padding:10px 0;border-bottom:1px solid #ccc;text-align:right;}
#topbar button {margin:0;margin-left:5px;outline:none;padding: 4px 16px;box-sizing: border-box;
display:inline-block;border:none;border-radius:3px;text-align:center;cursor:pointer;
font-size:14px;line-height:1.5;background-color:#f0f0f0;color:#223;
}
#topbar button.primary{background-color:#3d97d4;color:#fff;}
#topbar button:hover{background-color:#207ab7;color:#fff;}
#topbar button.removeall{float:left}
#file_list {display:grid;grid-gap:10px;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));padding-top:10px;}
#file_list:empty:after{content:'可以直接拖拽文件到这里';color:#777;font-size:0.8em;}
#file_list li{position:relative;display:block;vertical-align:top;padding:5px 5px;border-radius:5px;}
#file_list li.up-over {}
#file_list li.up-now {}
#file_list li.up-now:after{content:'';position:absolute;top:0;left:0;display:block;width:100%;height:100%;background:rgba(255,255,255,0.8) url(loading.gif) center center no-repeat;border-radius:5px;z-index:999;}
#file_list li:hover{background-color:#ddd;}
#file_list li .picbox {display:flex;flex:0 0 auto;justify-content:center;overflow:hidden;position:relative;width:100%;padding-top:100%;align-items:center;}
#file_list li .picbox img {display:block;max-width:100%;max-height:100%;position:absolute;
top:50%;left:50%;transform:translateX(-50%) translateY(-50%);}
#file_list li.up-over .picbox:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M512%200C229.376%200%200%20229.376%200%20512s229.376%20512%20512%20512%20512-229.376%20512-512S794.624%200%20512%200z%22%20fill%3D%22%234AC711%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22M855.552%20394.752l-358.4%20358.4a50.9952%2050.9952%200%200%201-72.192%200l-204.8-204.8c-18.944-19.968-18.944-51.2%200-71.168a50.5344%2050.5344%200%200%201%2072.192-1.024L460.8%20644.608l322.048-322.048c19.968-18.944%2051.2-18.944%2071.168%200%2020.48%2019.456%2020.992%2051.712%201.536%2072.192z%22%20fill%3D%22%23FFFFFF%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E');position:absolute;bottom:2px;right:2px;z-index:9;}
#file_list li .tools {display:none;position:absolute;bottom:5px;right:5px;z-index:99;}
#file_list li:hover .tools {display:block;}
#file_list li .tools .remove{cursor:pointer;}
#file_list li .tools .remove:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20width=%2224%22%20height=%2224%22%20viewBox=%220%200%2024%2024%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20d=%22M17%206h3a1%201%200%200%201%200%202h-1v11a3%203%200%200%201-3%203H8a3%203%200%200%201-3-3V8H4a1%201%200%201%201%200-2h3V5a3%203%200%200%201%203-3h4a3%203%200%200%201%203%203v1zm-2%200V5a1%201%200%200%200-1-1h-4a1%201%200%200%200-1%201v1h6zm2%202H7v11a1%201%200%200%200%201%201h8a1%201%200%200%200%201-1V8zm-8%203a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6zm4%200a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6z%22%3E%3C/path%3E%3C/svg%3E');}
#file_list li .namebox {font-size:14px;line-height:20px;max-height:40px;overflow:hidden;padding:5px 10px;text-align:center;display:flex;justify-content:center;align-items:flex-start;}
#file_list li .namebox span{word-break:break-all;vertical-align:top;}
</style>
</head>
<body>
<div id="wrap">
<div id="topbar"><button class="addfile primary">+ 添加文件</button><button class="removeall">清空列表</button></div>
<ul id="file_list"></ul>
</div>
<script>
var editor=parent.tinymce.activeEditor;
var axupimgs=parent.axupimgs;
axupimgs.res = []; //存放本地文件的数组
var blobInfo = {file:null}
blobInfo.blob = function(){return this.file;}
var upload_handler = axupimgs.images_upload_handler;
var upload_base_path = axupimgs.images_upload_base_path;
//为列表添加排序
function reSort(){
document.querySelectorAll('#file_list li').forEach((el,i)=>{
el.setAttribute('data-num',i);
});
}
function addList(files){
var files_sum = files.length;
var vDom = document.createDocumentFragment();
for(let i=0;i<files_sum;i++){
let file = files[i];
let blobUrl = window.URL.createObjectURL(file)
axupimgs.res.push({file:file,blobUrl:blobUrl,url:''});
let li = document.createElement('li');
li.setAttribute('class','up-no');
li.setAttribute('data-time',file.lastModified);
li.innerHTML='<div class="picbox"><img src="'+blobUrl+'"></div><div class="namebox"><span>'+file.name+'</span></div><div class="tools"><a class="remove"></a></div>';
vDom.appendChild(li);
}
document.querySelector('#file_list').appendChild(vDom);
if(axupimgs.res.length>0){
document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
el.classList ? el.classList.add('up-now') : el.className+=' up-now';
});
upAllFiles(0);
}
//reSort();
}
//清空列表
document.querySelector('#topbar .removeall').addEventListener('click',()=>{
axupimgs.res=[]
document.querySelectorAll('#file_list li').forEach((el,i)=>{
el.parentNode.removeChild(el)
});
});
//拖拽添加
document.addEventListener('dragover', (e)=>{
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
});
document.addEventListener('drop', (e)=>{
e.stopPropagation();
e.preventDefault();
if(!e.dataTransfer.files){return false;}
var dropfiles = e.dataTransfer.files;
if(!(dropfiles.length>0)){return false;}
var exts=axupimgs.axupimgs_filetype.replace(/(\s)+/g,'').toLowerCase().split(',');
var files=[];
for( let file of dropfiles ){
ext = file.name.split('.');
ext = '.'+ext[ext.length-1];
for(let s of exts){
if(s==ext){
files.push(file);
break;
}
}
}
if(files.length>0){ addList(files) }
});
//添加文件
document.querySelector('#topbar .addfile').addEventListener('click',()=>{
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('multiple', 'multiple');
input.setAttribute('accept', axupimgs.axupimgs_filetype);
input.click();
input.onchange = function() {
var files = this.files;
addList(files);
}
});
var file_i = 0;
function upAllFiles(n){
var len = axupimgs.res.length;
file_i = n;
if(len == n){
file_i=0;
// document.querySelector('#topbar .upall').innerText='全部上传';
return true;
}
if( axupimgs.res[n].url!='' ){
n++;
upAllFiles(n)
}else{
blobInfo.file=axupimgs.res[n].file;
upload_handler(blobInfo,function(url,name){
if(upload_base_path){
if(upload_base_path.slice(-1)=='/' && url.substr(0,1)=='/' ){
url = upload_base_path + url.slice(1);
}else if(upload_base_path.slice(-1)!='/' && url.substr(0,1)!='/' ){
url = upload_base_path + '/' + url;
}else{
url = upload_base_path + url;
}
}
axupimgs.res[file_i].url = url;
// filename = url.split('/').pop();
filename = name
var li = document.querySelectorAll('#file_list li')[file_i];
li.setAttribute('class','up-over');
li.querySelector('.namebox span').innerText = filename;
n++
upAllFiles(n);
},function(err){
// document.querySelector('#topbar .upall').innerText='全部上传';
// document.querySelectorAll('#file_list li.up-now').forEach((el,i)=>{
// el.setAttribute('class','up-no');
// });
// alert(err);
});
}
}
//
// document.querySelector('#topbar .upall').addEventListener('click',(e)=>{
// if(e.target.innerText!='全部上传'){return false;}
// if(axupimgs.res.length>0){
// document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
// el.classList ? el.classList.add('up-now') : el.className+=' up-now';
// });
// e.target.innerText='上传中...';
// upAllFiles(0);
// }
// });
var observ_flist = new MutationObserver( (muList,observe)=>{
if(muList[0].addedNodes.length>0){
muList[0].addedNodes.forEach((el)=>{
el.querySelector('.remove').addEventListener('click',(e)=>{
var li = e.target.parentNode.parentNode;
var n = li.getAttribute('data-num');
var el = document.querySelectorAll('#file_list li')[n];
el.parentNode.removeChild(el);
axupimgs.res.splice(n,1);
});
});
}
reSort();
});
observ_flist.observe(document.querySelector('#file_list'),{childList:true});
</script>
</body>
</html>

View File

@@ -1,13 +1,13 @@
<template>
<RouterView />
</template>
<script setup>
import {usePermisstionStroe} from '@/stores/permisstion.js'
window.addEventListener('beforeunload', e=>beforeunload(e))
const beforeunload = (()=>{
const permisstionStore = usePermisstionStroe()
permisstionStore.setIsLoadRoutes(true)
permisstionStore.setIsSuccessReq()
})
</script>
<template>
<RouterView />
</template>
<script setup>
import {usePermisstionStroe} from '@/stores/permisstion.js'
window.addEventListener('beforeunload', e=>beforeunload(e))
const beforeunload = (()=>{
const permisstionStore = usePermisstionStroe()
permisstionStore.setIsLoadRoutes(true)
permisstionStore.setIsSuccessReq()
})
</script>

View File

@@ -1,36 +1,36 @@
import request from '@/utils/request.js'
export const getArticle = (params) => {
return request({
url: '/workflow/mosr/article/list',
method: "get",
params
});
};
export const getArticleDetail = (articleId) => {
return request({
url: `/workflow/mosr/article/${articleId}`,
method: "get"
});
};
export const addArticle= (data) => {
return request({
url: '/workflow/mosr/article/add',
method: "post",
data
});
};
export const editArticle= (data) => {
return request({
url: '/workflow/mosr/article/update',
method: "post",
data
});
};
export const deleteArticle = (articleIds) => {
return request({
url: `/workflow/mosr/article/${articleIds}`,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getArticle = (params) => {
return request({
url: '/workflow/mosr/article/list',
method: "get",
params
});
};
export const getArticleDetail = (articleId) => {
return request({
url: `/workflow/mosr/article/${articleId}`,
method: "get"
});
};
export const addArticle= (data) => {
return request({
url: '/workflow/mosr/article/add',
method: "post",
data
});
};
export const editArticle= (data) => {
return request({
url: '/workflow/mosr/article/update',
method: "post",
data
});
};
export const deleteArticle = (articleIds) => {
return request({
url: `/workflow/mosr/article/${articleIds}`,
method: "delete"
});
};

View File

@@ -1,31 +1,31 @@
import request from "@/utils/request.js";
export const initPassword=(data)=>{
return request({
url:'/admin/mosr/user/init/password',
method:'post',
data
})
}
export const editPassword=(data)=>{
return request({
url:'/admin/mosr/user/update/password',
method:'post',
data
})
}
export const getAgentInfo=()=>{
return request({
url:'/admin/mosr/user/self/approval/agent',
method:'get'
})
}
export const editAgentInfo=(data)=>{
return request({
url:'/admin/mosr/user/self/approval/agent',
method:'post',
data
})
}
import request from "@/utils/request.js";
export const initPassword=(data)=>{
return request({
url:'/admin/mosr/user/init/password',
method:'post',
data
})
}
export const editPassword=(data)=>{
return request({
url:'/admin/mosr/user/update/password',
method:'post',
data
})
}
export const getAgentInfo=()=>{
return request({
url:'/admin/mosr/user/self/approval/agent',
method:'get'
})
}
export const editAgentInfo=(data)=>{
return request({
url:'/admin/mosr/user/self/approval/agent',
method:'post',
data
})
}

View File

@@ -1,15 +1,15 @@
import request from '@/utils/request.js'
export const getCacheOpt = (cacheKey) => {
return request({
url: '/admin/dict/data/option/'+ cacheKey,
method: 'get',
})
}
export const getCacheType = (cacheKey) => {
return request({
url: '/admin/dict/data/type/'+ cacheKey,
method: 'get',
})
import request from '@/utils/request.js'
export const getCacheOpt = (cacheKey) => {
return request({
url: '/admin/dict/data/option/'+ cacheKey,
method: 'get',
})
}
export const getCacheType = (cacheKey) => {
return request({
url: '/admin/dict/data/type/'+ cacheKey,
method: 'get',
})
}

View File

@@ -1,9 +1,9 @@
import request from '@/utils/request.js'
export const requestList = ( api, params, method = 'get' ) => {
return request({
url: api,
method,
params
})
import request from '@/utils/request.js'
export const requestList = ( api, params, method = 'get' ) => {
return request({
url: api,
method,
params
})
}

View File

@@ -1,54 +1,54 @@
import request from '@/utils/request.js'
//获取部门信息
export const getDeptList = (params) => {
return request({
url: '/admin/dept',
method: 'get',
params
})
}
//获取增加时的部门列表
export const getDeptOption = () => {
return request({
url: '/admin/dept/option',
method: 'get'
})
}
//获取修改时的部门列表
export const getDeptExcludeOption = (deptId) => {
return request({
url: `/admin/dept/option/exclude/${deptId}`,
method: 'get'
})
}
//新增部门
export const addDept = (data) => {
return request({
url: '/admin/dept',
method: 'post',
data
})
}
//编辑部门
export const editDept = (data) => {
return request({
url: '/admin/dept',
method: 'put',
data
})
}
//查询部门详情
export const getDeptDetail = (deptId) => {
return request({
url: `/admin/dept/${deptId}`,
method: "get"
});
};
//删除部门
export const deleteDept = (deptId) => {
return request({
url: `/admin/dept/${deptId}`,
method: "delete"
});
};
import request from '@/utils/request.js'
//获取部门信息
export const getDeptList = (params) => {
return request({
url: '/admin/dept',
method: 'get',
params
})
}
//获取增加时的部门列表
export const getDeptOption = () => {
return request({
url: '/admin/dept/option',
method: 'get'
})
}
//获取修改时的部门列表
export const getDeptExcludeOption = (deptId) => {
return request({
url: `/admin/dept/option/exclude/${deptId}`,
method: 'get'
})
}
//新增部门
export const addDept = (data) => {
return request({
url: '/admin/dept',
method: 'post',
data
})
}
//编辑部门
export const editDept = (data) => {
return request({
url: '/admin/dept',
method: 'put',
data
})
}
//查询部门详情
export const getDeptDetail = (deptId) => {
return request({
url: `/admin/dept/${deptId}`,
method: "get"
});
};
//删除部门
export const deleteDept = (deptId) => {
return request({
url: `/admin/dept/${deptId}`,
method: "delete"
});
};

View File

@@ -1,107 +1,107 @@
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
export const addAllocation = (data) => {
return request({
url:'/workflow/mosr/cost/allocation',
method: "post",
data
});
};
export const addShare = (data) => {
return request({
url:'/workflow/mosr/cost/share',
method: "post",
data
});
};
export const getAllocationDetail = (allocationId) => {
return request({
url: `/workflow/mosr/cost/allocation/info/${allocationId}`,
method: "get"
});
};
export const getAllocationDetails = (allocationId) => {
return request({
url: `/workflow/mosr/cost/allocation/usr/detail/${allocationId}`,
method: "get"
});
};
export const getAllocationSummaryDetails = (params) => {
return request({
url: '/workflow/mosr/cost/allocation/collect',
method: "get",
params:params
});
};
export const getAllocationProcess = () => {
return request({
url: '/workflow/mosr/cost/allocation/process',
method: "get"
});
};
export const getAllocationDetailList = (params) => {
return request({
url: '/workflow/mosr/cost/allocation/usr',
method: "get",
params:params
});
};
export const getResearchUser = () => {
return request({
url: '/admin/mosr/user/research',
method: "get"
});
};
export const getProjectOption = () => {
return request({
url: '/workflow/mosr/project/implementation/in/implementation/option',
method: "get"
});
};
export const editAllocation = (data) => {
return request({
url: '/workflow/mosr/cost/allocation/edit',
method: "post",
data
});
};
export const applyCcSend = (data) => {
return request({
url: '/workflow/mosr/cc/send',
method: "post",
data
});
};
export const deleteAllocation = (id) => {
return request({
url: `/workflow/mosr/cost/allocation/${id}`,
method: "delete"
});
};
export const shareExportExcel = (allocationId) => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/allocation/collect/${allocationId}`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
export const shareDetailExport= (data) => {
return axios.post(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/share/export`,
data, {
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
export const addAllocation = (data) => {
return request({
url:'/workflow/mosr/cost/allocation',
method: "post",
data
});
};
export const addShare = (data) => {
return request({
url:'/workflow/mosr/cost/share',
method: "post",
data
});
};
export const getAllocationDetail = (allocationId) => {
return request({
url: `/workflow/mosr/cost/allocation/info/${allocationId}`,
method: "get"
});
};
export const getAllocationDetails = (allocationId) => {
return request({
url: `/workflow/mosr/cost/allocation/usr/detail/${allocationId}`,
method: "get"
});
};
export const getAllocationSummaryDetails = (params) => {
return request({
url: '/workflow/mosr/cost/allocation/collect',
method: "get",
params:params
});
};
export const getAllocationProcess = () => {
return request({
url: '/workflow/mosr/cost/allocation/process',
method: "get"
});
};
export const getAllocationDetailList = (params) => {
return request({
url: '/workflow/mosr/cost/allocation/usr',
method: "get",
params:params
});
};
export const getResearchUser = () => {
return request({
url: '/admin/mosr/user/research',
method: "get"
});
};
export const getProjectOption = () => {
return request({
url: '/workflow/mosr/project/implementation/in/implementation/option',
method: "get"
});
};
export const editAllocation = (data) => {
return request({
url: '/workflow/mosr/cost/allocation/edit',
method: "post",
data
});
};
export const applyCcSend = (data) => {
return request({
url: '/workflow/mosr/cc/send',
method: "post",
data
});
};
export const deleteAllocation = (id) => {
return request({
url: `/workflow/mosr/cost/allocation/${id}`,
method: "delete"
});
};
export const shareExportExcel = (allocationId) => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/allocation/collect/${allocationId}`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
export const shareDetailExport= (data) => {
return axios.post(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/share/export`,
data, {
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};

View File

@@ -1,31 +1,31 @@
import request from '@/utils/request.js'
export const getHomeTaskInfo = () => {
return request({
url: '/workflow/mosr/process/task',
method: "get"
});
};
//获取已办数据
export const getDoneTaskInfo = () => {
return request({
url: '/workflow/mosr/process/task/about',
method: "get"
});
};
//获取专项资金饼图数据
export const getSpecialFundChart = () => {
return request({
url: '/workflow/home/page/statistic',
method: "get"
});
};
//获取首页四个统计数量
export const getHomeStatistics = () => {
return request({
url: '/workflow/mosr/process/task/statistics',
method: "get"
});
};
import request from '@/utils/request.js'
export const getHomeTaskInfo = () => {
return request({
url: '/workflow/mosr/process/task',
method: "get"
});
};
//获取已办数据
export const getDoneTaskInfo = () => {
return request({
url: '/workflow/mosr/process/task/about',
method: "get"
});
};
//获取专项资金饼图数据
export const getSpecialFundChart = () => {
return request({
url: '/workflow/home/page/statistic',
method: "get"
});
};
//获取首页四个统计数量
export const getHomeStatistics = () => {
return request({
url: '/workflow/mosr/process/task/statistics',
method: "get"
});
};

View File

@@ -1,44 +1,44 @@
import request from '@/utils/request.js'
// 获取list
export const getIPBlackList = (params) => {
return request({
url: '/admin/ip/back',
method: 'get',
params
})
}
// 新增
export const addIPBlack = (data) => {
return request({
url: '/admin/ip/back',
method: 'post',
data
})
}
// 修改
export const editIPBlack = (data) => {
return request({
url: '/admin/ip/back',
method: 'put',
data
})
}
// 删除
export const delIPBlack = (ids) => {
return request({
url: '/admin/ip/back/'+ids,
method: 'delete'
})
}
// 详情
export const getIPBlackDetail = (id) => {
return request({
url: '/admin/ip/back/'+id,
method: 'get'
})
import request from '@/utils/request.js'
// 获取list
export const getIPBlackList = (params) => {
return request({
url: '/admin/ip/back',
method: 'get',
params
})
}
// 新增
export const addIPBlack = (data) => {
return request({
url: '/admin/ip/back',
method: 'post',
data
})
}
// 修改
export const editIPBlack = (data) => {
return request({
url: '/admin/ip/back',
method: 'put',
data
})
}
// 删除
export const delIPBlack = (ids) => {
return request({
url: '/admin/ip/back/'+ids,
method: 'delete'
})
}
// 详情
export const getIPBlackDetail = (id) => {
return request({
url: '/admin/ip/back/'+id,
method: 'get'
})
}

View File

@@ -1,24 +1,24 @@
import request from "@/utils/request.js";
//查询登录日志
export const getLoginLogList = (params) => {
return request({
url: "/log/login-info/list",
method: "get",
params
});
};
//查询登录日志详情
export const getLoginLogDetail = (infoId) => {
return request({
url: `/log/login-info/${infoId}`,
method: "get"
});
};
//删除登录日志
export const deleteLoginLog = (infoIds) => {
return request({
url: `/log/login-info/${infoIds}`,
method: "delete"
});
};
import request from "@/utils/request.js";
//查询登录日志
export const getLoginLogList = (params) => {
return request({
url: "/log/login-info/list",
method: "get",
params
});
};
//查询登录日志详情
export const getLoginLogDetail = (infoId) => {
return request({
url: `/log/login-info/${infoId}`,
method: "get"
});
};
//删除登录日志
export const deleteLoginLog = (infoIds) => {
return request({
url: `/log/login-info/${infoIds}`,
method: "delete"
});
};

View File

@@ -1,24 +1,24 @@
import request from "@/utils/request.js";
//查询操作日志
export const getOperateLog = (params) => {
return request({
url: "/log/log/list",
method: "get",
params
});
};
//查询操作日志详情
export const getOperateLogDetail = (operId) => {
return request({
url: `/log/log/${operId}`,
method: "get"
});
};
//删除操作日志
export const deleteOperateLog = (operIds) => {
return request({
url: `/log/log/${operIds}`,
method: "delete"
});
};
import request from "@/utils/request.js";
//查询操作日志
export const getOperateLog = (params) => {
return request({
url: "/log/log/list",
method: "get",
params
});
};
//查询操作日志详情
export const getOperateLogDetail = (operId) => {
return request({
url: `/log/log/${operId}`,
method: "get"
});
};
//删除操作日志
export const deleteOperateLog = (operIds) => {
return request({
url: `/log/log/${operIds}`,
method: "delete"
});
};

View File

@@ -1,36 +1,36 @@
import request from '@/utils/request.js'
export const getCodeImg = () => {
return request({
url: '/auth/captchaImage',
method: 'get'
})
}
export const login = (data) => {
return request({
url: '/auth/login',
method: 'post',
data
})
}
export const switchAccount = (userId) => {
return request({
url: `/auth/switch/account/${userId}`,
method: 'post',
})
}
export const getUserInfo = () => {
return request({
url: '/auth/info',
method: 'get',
})
}
export const getAuthInfo = () => {
return request({
url: '/admin/mosr/user/detail/info',
method: 'get',
})
}
import request from '@/utils/request.js'
export const getCodeImg = () => {
return request({
url: '/auth/captchaImage',
method: 'get'
})
}
export const login = (data) => {
return request({
url: '/auth/login',
method: 'post',
data
})
}
export const switchAccount = (userId) => {
return request({
url: `/auth/switch/account/${userId}`,
method: 'post',
})
}
export const getUserInfo = () => {
return request({
url: '/auth/info',
method: 'get',
})
}
export const getAuthInfo = () => {
return request({
url: '/admin/mosr/user/detail/info',
method: 'get',
})
}

View File

@@ -1,30 +1,30 @@
import request from '@/utils/request.js'
export const getNoticeList = (params) => {
return request({
url: '/notice/notice',
method: 'get',
params
})
}
export const getNoticeDetail = (noticeId) => {
return request({
url: '/notice/notice/'+noticeId,
method: "get"
});
};
export const addNotice = (data) => {
return request({
url: '/notice/notice',
method: 'post',
data
})
}
export const deleteNotice = (noticeId) => {
return request({
url: `/notice/notice/${noticeId}`,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getNoticeList = (params) => {
return request({
url: '/notice/notice',
method: 'get',
params
})
}
export const getNoticeDetail = (noticeId) => {
return request({
url: '/notice/notice/'+noticeId,
method: "get"
});
};
export const addNotice = (data) => {
return request({
url: '/notice/notice',
method: 'post',
data
})
}
export const deleteNotice = (noticeId) => {
return request({
url: `/notice/notice/${noticeId}`,
method: "delete"
});
};

View File

@@ -1,43 +1,43 @@
import request from '@/utils/request.js'
export const getNotifyList = (params) => {
return request({
url: '/notice/notify',
method: 'get',
params
})
}
export const getNotifyDetail = (noticeId) => {
return request({
url: '/notice/notify/'+noticeId,
method: "get"
});
};
//已读单个消息
export const readSingleNotify = (noticeId) => {
return request({
url: '/notice/notify/read/'+noticeId,
method: 'put'
})
}
//已读全部消息
export const readAllNotify = () => {
return request({
url: '/notice/notify/read/all',
method: 'put'
})
}
//删除单个消息
export const deleteSingleNotify = (noticeId) => {
return request({
url: '/notice/notify/'+noticeId,
method: "delete"
});
};
//删除多个消息
export const deleteMoreNotify = (noticeIds) => {
return request({
url: '/notice/notify/batch/'+noticeIds,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getNotifyList = (params) => {
return request({
url: '/notice/notify',
method: 'get',
params
})
}
export const getNotifyDetail = (noticeId) => {
return request({
url: '/notice/notify/'+noticeId,
method: "get"
});
};
//已读单个消息
export const readSingleNotify = (noticeId) => {
return request({
url: '/notice/notify/read/'+noticeId,
method: 'put'
})
}
//已读全部消息
export const readAllNotify = () => {
return request({
url: '/notice/notify/read/all',
method: 'put'
})
}
//删除单个消息
export const deleteSingleNotify = (noticeId) => {
return request({
url: '/notice/notify/'+noticeId,
method: "delete"
});
};
//删除多个消息
export const deleteMoreNotify = (noticeIds) => {
return request({
url: '/notice/notify/batch/'+noticeIds,
method: "delete"
});
};

View File

@@ -1,17 +1,17 @@
import request from "@/utils/request.js";
//查询在线用户
export const getOnlineList = (params) => {
return request({
url: "/admin/online/user",
method: "get",
params
});
};
//强制退出用户
export const deleteOnlineUser= (tokenId) => {
return request({
url: '/admin/online/user/'+tokenId,
method: "delete"
});
};
import request from "@/utils/request.js";
//查询在线用户
export const getOnlineList = (params) => {
return request({
url: "/admin/online/user",
method: "get",
params
});
};
//强制退出用户
export const deleteOnlineUser= (tokenId) => {
return request({
url: '/admin/online/user/'+tokenId,
method: "delete"
});
};

View File

@@ -1,48 +1,48 @@
import request from '@/utils/request.js'
//获取岗位信息
export const getPostList = (params) => {
return request({
url: '/admin/post',
method: 'get',
params
})
}
//查询岗位详情
export const getPostDetail = (postId) => {
return request({
url: `/admin/post/info/${postId}`,
method: "get"
});
};
//新增岗位
export const addPost = (data) => {
return request({
url: '/admin/post',
method: 'post',
data
})
}
//编辑岗位
export const editPost = (data) => {
return request({
url: '/admin/post',
method: 'put',
data
})
}
//获取select下拉框数据
export const getSelectOption = () => {
return request({
url: '/admin/post/option',
method: 'get'
})
}
//删除角色信息
export const deletePost = (postId) => {
return request({
url: `/admin/post/${postId}`,
method: "delete"
});
};
import request from '@/utils/request.js'
//获取岗位信息
export const getPostList = (params) => {
return request({
url: '/admin/post',
method: 'get',
params
})
}
//查询岗位详情
export const getPostDetail = (postId) => {
return request({
url: `/admin/post/info/${postId}`,
method: "get"
});
};
//新增岗位
export const addPost = (data) => {
return request({
url: '/admin/post',
method: 'post',
data
})
}
//编辑岗位
export const editPost = (data) => {
return request({
url: '/admin/post',
method: 'put',
data
})
}
//获取select下拉框数据
export const getSelectOption = () => {
return request({
url: '/admin/post/option',
method: 'get'
})
}
//删除角色信息
export const deletePost = (postId) => {
return request({
url: `/admin/post/${postId}`,
method: "delete"
});
};

View File

@@ -1,128 +1,128 @@
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
//需求征集
export const getDemandInfo = (param) => {
return request({
url: '/workflow/mosr/requirement',
method: "get",
params: param
});
};
export const filterRequirementName = (requirementName) => {
return request({
url: `/workflow/mosr/requirement/match/${requirementName}`,
method: "get"
});
};
export const getWorkflowInfo = () => {
return request({
url: '/workflow/mosr/requirement/process',
method: "get"
});
};
export const getInfo = (requirementId) => {
return request({
url: `/workflow/mosr/requirement/info/${requirementId}`,
method: "get"
});
};
export const getFormInfo = (requirementId) => {
return request({
url: `/workflow/mosr/requirement/form/${requirementId}`,
method: "get"
});
};
export const agreeTask = (data) => {
return request({
url: `/workflow/mosr/process/task/agree`,
method: "post",
data: data
});
};
export const rejectTask = (data) => {
return request({
url: `/workflow/mosr/process/task/reject`,
method: "post",
data: data
});
};
export const addRequirement = (data) => {
return request({
url: '/workflow/mosr/requirement',
method: "post",
data: data
});
};
export const resubmit = (data) => {
return request({
url: '/workflow/mosr/requirement/resubmit',
method: "post",
data: data
});
};
export const deleteFile = (fileId) => {
return request({
url: `/workflow/process/file/delete/${fileId}`,
method: "delete"
});
};
export const downloadFile = (fileId) => {
return request({
url: '/workflow/process/file/download',
method: "get",
responseType:'blob',
params:{
fileId:fileId
}
});
};
export const getCompanyOption = () => {
return request({
url: '/admin/mosr/sub/company/companyOption',
method: "get"
});
};
export const deleteDemand = (id) => {
return request({
url: `/workflow/mosr/requirement/${id}`,
method: "delete"
});
};
export const getRequirementStatePerm = () => {
return request({
url: '/workflow/mosr/requirement/prem/state',
method: "get"
});
};
export const downloadTemplate = (type) => {
return request({
url: '/workflow/mosr/attachment/download/template',
method: "get",
responseType:'blob',
params:{
type:type
}
});
};
export const downloadTemplateZip = (typeList) => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/attachment/download/pack?typeList=${typeList}`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
},
}
);
// return request({
// url: '/workflow/mosr/attachment/download/pack',
// method: "get",
// responseType:'blob',
// params:{
// typeList:typeList
// }
// });
};
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
//需求征集
export const getDemandInfo = (param) => {
return request({
url: '/workflow/mosr/requirement',
method: "get",
params: param
});
};
export const filterRequirementName = (requirementName) => {
return request({
url: `/workflow/mosr/requirement/match/${requirementName}`,
method: "get"
});
};
export const getWorkflowInfo = () => {
return request({
url: '/workflow/mosr/requirement/process',
method: "get"
});
};
export const getInfo = (requirementId) => {
return request({
url: `/workflow/mosr/requirement/info/${requirementId}`,
method: "get"
});
};
export const getFormInfo = (requirementId) => {
return request({
url: `/workflow/mosr/requirement/form/${requirementId}`,
method: "get"
});
};
export const agreeTask = (data) => {
return request({
url: `/workflow/mosr/process/task/agree`,
method: "post",
data: data
});
};
export const rejectTask = (data) => {
return request({
url: `/workflow/mosr/process/task/reject`,
method: "post",
data: data
});
};
export const addRequirement = (data) => {
return request({
url: '/workflow/mosr/requirement',
method: "post",
data: data
});
};
export const resubmit = (data) => {
return request({
url: '/workflow/mosr/requirement/resubmit',
method: "post",
data: data
});
};
export const deleteFile = (fileId) => {
return request({
url: `/workflow/process/file/delete/${fileId}`,
method: "delete"
});
};
export const downloadFile = (fileId) => {
return request({
url: '/workflow/process/file/download',
method: "get",
responseType:'blob',
params:{
fileId:fileId
}
});
};
export const getCompanyOption = () => {
return request({
url: '/admin/mosr/sub/company/companyOption',
method: "get"
});
};
export const deleteDemand = (id) => {
return request({
url: `/workflow/mosr/requirement/${id}`,
method: "delete"
});
};
export const getRequirementStatePerm = () => {
return request({
url: '/workflow/mosr/requirement/prem/state',
method: "get"
});
};
export const downloadTemplate = (type) => {
return request({
url: '/workflow/mosr/attachment/download/template',
method: "get",
responseType:'blob',
params:{
type:type
}
});
};
export const downloadTemplateZip = (typeList) => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/attachment/download/pack?typeList=${typeList}`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
},
}
);
// return request({
// url: '/workflow/mosr/attachment/download/pack',
// method: "get",
// responseType:'blob',
// params:{
// typeList:typeList
// }
// });
};

View File

@@ -1,123 +1,123 @@
import request from '@/utils/request'
export const fileUp = (url, data) => {
return request({
url,
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
export const requirementReported = (data) => {
return request({
url: '/workflow/mosr/requirement/reported',
method: "post",
data: data
});
};
//需求汇总-征集名称关键词匹配
export const getRequirementName = (requirementName) => {
return request({
url: `/workflow/mosr/requirement/collect/project/match/${requirementName}`,
method: "get"
});
};
//需求汇总-项目名称关键词匹配
export const getProjectName = (projectName) => {
return request({
url: `workflow/mosr/requirement/collect`,
method: "get",
params:{
projectName:projectName
}
});
};
//获取需求上报 流程信息
export const getProcessInfo = (specialFund) => {
return request({
url: `/workflow/mosr/requirement/collect/process/${specialFund}`,
method: "get"
});
};
export const getDetail = (projectId) => {
return request({
url: `/workflow/mosr/requirement/collect/info/${projectId}`,
method: "get"
});
};
export const resubmitReported = (data) => {
return request({
url: '/workflow/mosr/requirement/collect/resubmit',
method: "post",
data: data
});
};
export const getCollectAttachment = (params) => {
return request({
url: '/workflow/mosr/requirement/collect/attachments',
method: "get",
params:params
});
};
export const uploadCollectAttachment= (data) => {
return request({
url: '/workflow/mosr/requirement/collect/upload',
method: "post",
data: data
});
};
// 年度计划
export const addPlan= (data) => {
return request({
url: '/workflow/annual/plan',
method: "post",
data: data
});
};
export const editPlan= (data) => {
return request({
url: '/workflow/annual/plan',
method: "put",
data: data
});
};
export const getPlan= (annualPlanId) => {
return request({
url: `/workflow/annual/plan/info/${annualPlanId}`,
method: "get"
});
};
export const deletePlan= (annualPlanId) => {
return request({
url: `/workflow/annual/plan/${annualPlanId}`,
method: "delete"
});
};
export const approvePlan= (data) => {
return request({
url: '/workflow/annual/plan/approve',
method: "post",
data: data
});
};
export const getProjectOption = () => {
return request({
url: '/workflow/mosr/requirement/master',
method: "get"
});
};
export const getRequirementOption = () => {
return request({
url: '/workflow/mosr/requirement/option',
method: "get"
});
};
import request from '@/utils/request'
export const fileUp = (url, data) => {
return request({
url,
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
export const requirementReported = (data) => {
return request({
url: '/workflow/mosr/requirement/reported',
method: "post",
data: data
});
};
//需求汇总-征集名称关键词匹配
export const getRequirementName = (requirementName) => {
return request({
url: `/workflow/mosr/requirement/collect/project/match/${requirementName}`,
method: "get"
});
};
//需求汇总-项目名称关键词匹配
export const getProjectName = (projectName) => {
return request({
url: `workflow/mosr/requirement/collect`,
method: "get",
params:{
projectName:projectName
}
});
};
//获取需求上报 流程信息
export const getProcessInfo = (specialFund) => {
return request({
url: `/workflow/mosr/requirement/collect/process/${specialFund}`,
method: "get"
});
};
export const getDetail = (projectId) => {
return request({
url: `/workflow/mosr/requirement/collect/info/${projectId}`,
method: "get"
});
};
export const resubmitReported = (data) => {
return request({
url: '/workflow/mosr/requirement/collect/resubmit',
method: "post",
data: data
});
};
export const getCollectAttachment = (params) => {
return request({
url: '/workflow/mosr/requirement/collect/attachments',
method: "get",
params:params
});
};
export const uploadCollectAttachment= (data) => {
return request({
url: '/workflow/mosr/requirement/collect/upload',
method: "post",
data: data
});
};
// 年度计划
export const addPlan= (data) => {
return request({
url: '/workflow/annual/plan',
method: "post",
data: data
});
};
export const editPlan= (data) => {
return request({
url: '/workflow/annual/plan',
method: "put",
data: data
});
};
export const getPlan= (annualPlanId) => {
return request({
url: `/workflow/annual/plan/info/${annualPlanId}`,
method: "get"
});
};
export const deletePlan= (annualPlanId) => {
return request({
url: `/workflow/annual/plan/${annualPlanId}`,
method: "delete"
});
};
export const approvePlan= (data) => {
return request({
url: '/workflow/annual/plan/approve',
method: "post",
data: data
});
};
export const getProjectOption = () => {
return request({
url: '/workflow/mosr/requirement/master',
method: "get"
});
};
export const getRequirementOption = () => {
return request({
url: '/workflow/mosr/requirement/option',
method: "get"
});
};

View File

@@ -1,38 +1,38 @@
import request from '@/utils/request.js'
export const searchFileList = (params) => {
return request({
url: `/workflow/mosr/attachment/list`,
method: "get",
params: params
});
};
export const searchAllFileList = (params) => {
return request({
url: '/workflow/mosr/attachment/all',
method: "get",
params: params
});
};
export const uploadFileList = (data) => {
return request({
url: '/workflow/mosr/attachment/upload',
method: "post",
data: data
});
};
export const searchImplementationFileList = (params) => {
return request({
url: '/workflow/mosr/attachment/implementation/list',
method: "get",
params: params
});
};
export const switchAttachmentState = (data) => {
return request({
url: '/workflow/mosr/project/filing/attachment/switch',
method: "post",
data
});
};
import request from '@/utils/request.js'
export const searchFileList = (params) => {
return request({
url: `/workflow/mosr/attachment/list`,
method: "get",
params: params
});
};
export const searchAllFileList = (params) => {
return request({
url: '/workflow/mosr/attachment/all',
method: "get",
params: params
});
};
export const uploadFileList = (data) => {
return request({
url: '/workflow/mosr/attachment/upload',
method: "post",
data: data
});
};
export const searchImplementationFileList = (params) => {
return request({
url: '/workflow/mosr/attachment/implementation/list',
method: "get",
params: params
});
};
export const switchAttachmentState = (data) => {
return request({
url: '/workflow/mosr/project/filing/attachment/switch',
method: "post",
data
});
};

View File

@@ -1,240 +1,240 @@
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
//项目立项
export const getApplyProcess = (projectId) => {
return request({
url: `/workflow/mosr/project/approval/initiation/process/${projectId}`,
method: "get"
});
};
export const filterProjectName = (projectName,targetState) => {
return request({
url: `/workflow/mosr/project/approval/match/${projectName}/${targetState}`,
method: "get"
});
};
export const projectApply = (data) => {
return request({
url: '/workflow/mosr/project/approval/initiation/apply',
method: "post",
data: data
});
};
export const getApplyDetail = (ProjectId) => {
return request({
url: `/workflow/mosr/project/approval/info/${ProjectId}`,
method: "get"
});
};
export const resubmitApply = (data) => {
return request({
url: '/workflow/mosr/project/approval/initiation/resubmit',
method: "post",
data: data
});
};
export const getInitiationAttachment = (params) => {
return request({
url: '/workflow/mosr/project/approval/attachments',
method: "get",
params: params
});
};
//项目实施
export const getCheckDetail = (projectId) => {
return request({
url: `/workflow/mosr/project/implementation/info/${projectId}`,
method: "get"
});
};
export const resubmitCheck = (data) => {
return request({
url: '/workflow/mosr/project/implementation/resubmit',
method: "post",
data: data
});
};
export const projectCheck = (data) => {
return request({
url: '/workflow/mosr/project/implementation/initiation/check',
method: "post",
data: data
});
};
export const getProjectCheckProcess = (projectId) => {
return request({
url: `/workflow/mosr/project/implementation/process/${projectId}`,
method: "get"
});
};
export const addLedger = (data) => {
return request({
url: '/workflow/mosr/expense/ledger',
method: "post",
data: data
});
};
export const getTags = (projectId) => {
return request({
url: `/workflow/mosr/attachment/option/${projectId}`,
method: "get"
});
};
export const getTagList = (projectId) => {
return request({
url: `/workflow/mosr/file/tag/list`,
method: "get",
params:{
projectId: projectId
}
});
};
export const addTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/add',
method: "post",
data:data
});
};
export const updateTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/update',
method: "post",
data:data
});
};
export const delTag = (tageId) => {
return request({
url: `/workflow/mosr/file/tag/${tageId}`,
method: "delete"
});
};
export const getPhaseProcess = () => {
return request({
url: '/workflow/phase/change/process',
method: "get"
});
};
export const submitPhaseChange = (data) => {
return request({
url: '/workflow/phase/change',
method: "post",
data: data
});
};
export const getPhaseDetail = (projectId) => {
return request({
url: `/workflow/phase/change/info/${projectId}`,
method: "get"
});
};
export const getPhaseForm = (projectId) => {
return request({
url: `/workflow/phase/change/from/${projectId}`,
method: "get"
});
};
export const resubmitPhaseForm = (data) => {
return request({
url: '/workflow/phase/change/resubmit',
method: "post",
data: data
});
};
//项目归档
export const getConclusionDetail = (ProjectId) => {
return request({
url: `/workflow/mosr/project/filing/info/${ProjectId}`,
method: "get"
});
};
export const resubmitConclusion = (data) => {
return request({
url: '/workflow/mosr/project/filing/resubmit',
method: "post",
data: data
});
};
export const projectConclusion = (data) => {
return request({
url: '/workflow/mosr/project/filing/project/entry',
method: "post",
data: data
});
};
export const getProjectConclusionProcess = () => {
return request({
url: '/workflow/mosr/project/filing/process',
method: "get"
});
};
//获取前置流程
export const getPreProcess = () => {
return request({
url: '/workflow/details/pre/process',
method: "get"
});
};
export const updateLedger = (data) => {
return request({
url: '/workflow/mosr/expense/ledger/replenishment',
method: "post",
data: data
});
};
export const searchUpdateLedgerData = (projectId) => {
return request({
url: `/workflow/mosr/expense/ledger/${projectId}`,
method: "get"
});
};
//
// export const searchUpdateLedgerData = (projectId) => {
// return request({
// url: '/workflow/mosr/expense/ledger/import',
// method: "get"
// });
// };
export const exportExcel = (data) => {
return axios.post(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/project/implementation/export`,
data, {
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
//台账模板下载
export const ledgerTemplateDownload = () => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/project/implementation/download/template`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
//费用明细模板下载
export const costTemplateDownload = () => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/rd/expense/download/template`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
import request from '@/utils/request.js'
import axios from "axios";
import {getToken} from "@/utils/auth";
//项目立项
export const getApplyProcess = (projectId) => {
return request({
url: `/workflow/mosr/project/approval/initiation/process/${projectId}`,
method: "get"
});
};
export const filterProjectName = (projectName,targetState) => {
return request({
url: `/workflow/mosr/project/approval/match/${projectName}/${targetState}`,
method: "get"
});
};
export const projectApply = (data) => {
return request({
url: '/workflow/mosr/project/approval/initiation/apply',
method: "post",
data: data
});
};
export const getApplyDetail = (ProjectId) => {
return request({
url: `/workflow/mosr/project/approval/info/${ProjectId}`,
method: "get"
});
};
export const resubmitApply = (data) => {
return request({
url: '/workflow/mosr/project/approval/initiation/resubmit',
method: "post",
data: data
});
};
export const getInitiationAttachment = (params) => {
return request({
url: '/workflow/mosr/project/approval/attachments',
method: "get",
params: params
});
};
//项目实施
export const getCheckDetail = (projectId) => {
return request({
url: `/workflow/mosr/project/implementation/info/${projectId}`,
method: "get"
});
};
export const resubmitCheck = (data) => {
return request({
url: '/workflow/mosr/project/implementation/resubmit',
method: "post",
data: data
});
};
export const projectCheck = (data) => {
return request({
url: '/workflow/mosr/project/implementation/initiation/check',
method: "post",
data: data
});
};
export const getProjectCheckProcess = (projectId) => {
return request({
url: `/workflow/mosr/project/implementation/process/${projectId}`,
method: "get"
});
};
export const addLedger = (data) => {
return request({
url: '/workflow/mosr/expense/ledger',
method: "post",
data: data
});
};
export const getTags = (projectId) => {
return request({
url: `/workflow/mosr/attachment/option/${projectId}`,
method: "get"
});
};
export const getTagList = (projectId) => {
return request({
url: `/workflow/mosr/file/tag/list`,
method: "get",
params:{
projectId: projectId
}
});
};
export const addTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/add',
method: "post",
data:data
});
};
export const updateTag = (data) => {
return request({
url: '/workflow/mosr/file/tag/update',
method: "post",
data:data
});
};
export const delTag = (tageId) => {
return request({
url: `/workflow/mosr/file/tag/${tageId}`,
method: "delete"
});
};
export const getPhaseProcess = () => {
return request({
url: '/workflow/phase/change/process',
method: "get"
});
};
export const submitPhaseChange = (data) => {
return request({
url: '/workflow/phase/change',
method: "post",
data: data
});
};
export const getPhaseDetail = (projectId) => {
return request({
url: `/workflow/phase/change/info/${projectId}`,
method: "get"
});
};
export const getPhaseForm = (projectId) => {
return request({
url: `/workflow/phase/change/from/${projectId}`,
method: "get"
});
};
export const resubmitPhaseForm = (data) => {
return request({
url: '/workflow/phase/change/resubmit',
method: "post",
data: data
});
};
//项目归档
export const getConclusionDetail = (ProjectId) => {
return request({
url: `/workflow/mosr/project/filing/info/${ProjectId}`,
method: "get"
});
};
export const resubmitConclusion = (data) => {
return request({
url: '/workflow/mosr/project/filing/resubmit',
method: "post",
data: data
});
};
export const projectConclusion = (data) => {
return request({
url: '/workflow/mosr/project/filing/project/entry',
method: "post",
data: data
});
};
export const getProjectConclusionProcess = () => {
return request({
url: '/workflow/mosr/project/filing/process',
method: "get"
});
};
//获取前置流程
export const getPreProcess = () => {
return request({
url: '/workflow/details/pre/process',
method: "get"
});
};
export const updateLedger = (data) => {
return request({
url: '/workflow/mosr/expense/ledger/replenishment',
method: "post",
data: data
});
};
export const searchUpdateLedgerData = (projectId) => {
return request({
url: `/workflow/mosr/expense/ledger/${projectId}`,
method: "get"
});
};
//
// export const searchUpdateLedgerData = (projectId) => {
// return request({
// url: '/workflow/mosr/expense/ledger/import',
// method: "get"
// });
// };
export const exportExcel = (data) => {
return axios.post(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/project/implementation/export`,
data, {
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
//台账模板下载
export const ledgerTemplateDownload = () => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/project/implementation/download/template`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};
//费用明细模板下载
export const costTemplateDownload = () => {
return axios.get(
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/rd/expense/download/template`,
{
responseType: 'blob',
headers: {
Authorization: getToken()
}
}
);
};

View File

@@ -1,68 +1,68 @@
import request from '@/utils/request.js'
export const getTableList = (params) => {
return request({
url: '/code-gen/table',
method: 'get',
params
})
}
export const getDynamicTable = (params) => {
return request({
url: '/code-gen/dynamic-table',
method: 'get',
params
})
}
export const getTableDetail = (tableId) => {
return request({
url: `/code-gen/table/${tableId}`,
method: 'get',
})
}
export const previewCode = (tableId) => {
return request({
url: `/code-gen/table/preview/${tableId}`,
method: 'get',
})
}
export const deleteMoreTable = (params) => {
return request({
url: '/code-gen/table',
method: 'delete',
params
})
}
export const deleteTable = (tableId) => {
return request({
url: `/code-gen/table/${tableId}`,
method: 'delete',
})
}
export const importTable = (data) => {
return request({
url: "/code-gen/table/import-table",
method: 'post',
data
})
}
export const editCodeGen = (data) => {
return request({
url: '/code-gen/table',
method: 'put',
data
})
}
export const syncDatabase = (tableId) => {
return request({
url: '/code-gen/table/sync/'+tableId,
method: 'put'
})
}
import request from '@/utils/request.js'
export const getTableList = (params) => {
return request({
url: '/code-gen/table',
method: 'get',
params
})
}
export const getDynamicTable = (params) => {
return request({
url: '/code-gen/dynamic-table',
method: 'get',
params
})
}
export const getTableDetail = (tableId) => {
return request({
url: `/code-gen/table/${tableId}`,
method: 'get',
})
}
export const previewCode = (tableId) => {
return request({
url: `/code-gen/table/preview/${tableId}`,
method: 'get',
})
}
export const deleteMoreTable = (params) => {
return request({
url: '/code-gen/table',
method: 'delete',
params
})
}
export const deleteTable = (tableId) => {
return request({
url: `/code-gen/table/${tableId}`,
method: 'delete',
})
}
export const importTable = (data) => {
return request({
url: "/code-gen/table/import-table",
method: 'post',
data
})
}
export const editCodeGen = (data) => {
return request({
url: '/code-gen/table',
method: 'put',
data
})
}
export const syncDatabase = (tableId) => {
return request({
url: '/code-gen/table/sync/'+tableId,
method: 'put'
})
}

View File

@@ -1,54 +1,54 @@
import request from '@/utils/request.js'
export const getDataSourceList = (params) => {
return request({
url: '/code-gen/data-source',
method: 'get',
params
})
}
export const getDataSourceOption = () => {
return request({
url: '/code-gen/data-source/option',
method: 'get'
})
}
export const getDataSourceOptionType=()=>{
return request({
url:'/code-gen/data-source/option/type',
method:'get'
})
}
export const getDataSource = (dsId) => {
return request({
url: `/code-gen/data-source/${dsId}`,
method: 'get'
})
}
export const addDataSource = (data) => {
return request({
url: '/code-gen/data-source',
method: 'post',
data
})
}
export const editDataSource = (data) => {
return request({
url: '/code-gen/data-source',
method: 'put',
data
})
}
export const deleteDataSource = (dsId) => {
return request({
url: `/code-gen/data-source/${dsId}`,
method: 'delete'
})
}
import request from '@/utils/request.js'
export const getDataSourceList = (params) => {
return request({
url: '/code-gen/data-source',
method: 'get',
params
})
}
export const getDataSourceOption = () => {
return request({
url: '/code-gen/data-source/option',
method: 'get'
})
}
export const getDataSourceOptionType=()=>{
return request({
url:'/code-gen/data-source/option/type',
method:'get'
})
}
export const getDataSource = (dsId) => {
return request({
url: `/code-gen/data-source/${dsId}`,
method: 'get'
})
}
export const addDataSource = (data) => {
return request({
url: '/code-gen/data-source',
method: 'post',
data
})
}
export const editDataSource = (data) => {
return request({
url: '/code-gen/data-source',
method: 'put',
data
})
}
export const deleteDataSource = (dsId) => {
return request({
url: `/code-gen/data-source/${dsId}`,
method: 'delete'
})
}

View File

@@ -1,52 +1,52 @@
import request from '@/utils/request.js'
// 请求校验规则表list
export const getRegularList = (params) => {
return request({
url: '/code-gen/rapid/regular',
method: 'get',
params
})
}
// 获取校验规则表详情
export const getRegularDetails = (regularId) => {
return request({
url: '/code-gen/rapid/regular/' + regularId,
method: 'get'
})
}
// 获取校验规则选项列表
export const getRegularOpt = (regularId) => {
return request({
url: '/code-gen/rapid/regular/option',
method: 'get'
})
}
// 新增校验规则表
export const addRegular = (data) => {
return request({
url: '/code-gen/rapid/regular',
method: 'post',
data
})
}
// 修改校验规则表
export const editRegular = (data) => {
return request({
url: '/code-gen/rapid/regular',
method: 'put',
data
})
}
// 删除校验规则表
export const delRegular =(regularId) => {
return request({
url: '/code-gen/rapid/regular/' + regularId,
method: 'delete'
})
import request from '@/utils/request.js'
// 请求校验规则表list
export const getRegularList = (params) => {
return request({
url: '/code-gen/rapid/regular',
method: 'get',
params
})
}
// 获取校验规则表详情
export const getRegularDetails = (regularId) => {
return request({
url: '/code-gen/rapid/regular/' + regularId,
method: 'get'
})
}
// 获取校验规则选项列表
export const getRegularOpt = (regularId) => {
return request({
url: '/code-gen/rapid/regular/option',
method: 'get'
})
}
// 新增校验规则表
export const addRegular = (data) => {
return request({
url: '/code-gen/rapid/regular',
method: 'post',
data
})
}
// 修改校验规则表
export const editRegular = (data) => {
return request({
url: '/code-gen/rapid/regular',
method: 'put',
data
})
}
// 删除校验规则表
export const delRegular =(regularId) => {
return request({
url: '/code-gen/rapid/regular/' + regularId,
method: 'delete'
})
}

View File

@@ -1,36 +1,36 @@
import request from '@/utils/request.js'
export const getResearchFundChart = (year) => {
return request({
url: '/workflow/mosr/rd/home',
method: 'get',
params: {year:year}
})
}
export const getResearchFundDetail = (rdFundId) => {
return request({
url: `/workflow/mosr/rd/${rdFundId}`,
method: "get"
});
};
export const addResearchFund= (data) => {
return request({
url: '/workflow/mosr/rd/add',
method: "post",
data
});
};
export const editResearchFund= (data) => {
return request({
url: '/workflow/mosr/rd/update',
method: "post",
data
});
};
export const deleteResearchFund = (rdFundIds) => {
return request({
url: `/workflow/mosr/rd/${rdFundIds}`,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getResearchFundChart = (year) => {
return request({
url: '/workflow/mosr/rd/home',
method: 'get',
params: {year:year}
})
}
export const getResearchFundDetail = (rdFundId) => {
return request({
url: `/workflow/mosr/rd/${rdFundId}`,
method: "get"
});
};
export const addResearchFund= (data) => {
return request({
url: '/workflow/mosr/rd/add',
method: "post",
data
});
};
export const editResearchFund= (data) => {
return request({
url: '/workflow/mosr/rd/update',
method: "post",
data
});
};
export const deleteResearchFund = (rdFundIds) => {
return request({
url: `/workflow/mosr/rd/${rdFundIds}`,
method: "delete"
});
};

View File

@@ -1,110 +1,110 @@
import request from '@/utils/request.js'
export const getRoleList = (params) => {
return request({
url: '/admin/role',
method: 'get',
params
})
}
//查询角色option
export const getRoleOption = () => {
return request({
url: '/admin/role/option',
method: "get"
});
};
export const getTemRoleOption = () => {
return request({
url: '/admin/role/option/template',
method: "get"
});
};
//查询角色信息
export const getRoleDetail = (roleId) => {
return request({
url: `/admin/role/${roleId}`,
method: "get"
});
};
//根据菜单id获取分配的角色信息
export const getRoleInfoByMenuId = (params) => {
return request({
url: '/admin/role/menu',
method: 'get',
params
})
}
//获取排除在外的角色
export const getRoleExcludeMenuId = (params) => {
return request({
url: '/admin/role/menu/list',
method: "get",
params
});
};
// 新增修改
export const operate = (data) => {
if(data.roleId) return editRole(data)
return addRole(data)
}
// 新增角色
export const addRole = (data) => {
return request({
url: '/admin/role',
method: 'post',
data
})
}
// 修改角色
export const editRole = (data) => {
return request({
url: '/admin/role',
method: 'put',
data
})
}
//解除当前角色对应的所有菜单的绑定关系
export const unbindAllRole = (menuId) => {
return request({
url: '/admin/role/all/unbind/menu',
method: 'put',
data: {
id: menuId
}
})
}
// 解除角色与菜单之间的绑定状态
export const cancelAuthorization = (menuId, roleIds) => {
return request({
url: '/admin/role/unbind/menu',
method: 'put',
data: {
id: menuId,
ids: roleIds
}
})
}
//建立角色用户绑定关系
export const bindRoleAndMenu = (menuId, roleIds) => {
return request({
url: '/admin/role/bind/menu',
method: 'put',
data: {
id: menuId,
ids: roleIds
}
})
}
//删除角色信息
export const deleteRole = (roleId) => {
return request({
url: `/admin/role/${roleId}`,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getRoleList = (params) => {
return request({
url: '/admin/role',
method: 'get',
params
})
}
//查询角色option
export const getRoleOption = () => {
return request({
url: '/admin/role/option',
method: "get"
});
};
export const getTemRoleOption = () => {
return request({
url: '/admin/role/option/template',
method: "get"
});
};
//查询角色信息
export const getRoleDetail = (roleId) => {
return request({
url: `/admin/role/${roleId}`,
method: "get"
});
};
//根据菜单id获取分配的角色信息
export const getRoleInfoByMenuId = (params) => {
return request({
url: '/admin/role/menu',
method: 'get',
params
})
}
//获取排除在外的角色
export const getRoleExcludeMenuId = (params) => {
return request({
url: '/admin/role/menu/list',
method: "get",
params
});
};
// 新增修改
export const operate = (data) => {
if(data.roleId) return editRole(data)
return addRole(data)
}
// 新增角色
export const addRole = (data) => {
return request({
url: '/admin/role',
method: 'post',
data
})
}
// 修改角色
export const editRole = (data) => {
return request({
url: '/admin/role',
method: 'put',
data
})
}
//解除当前角色对应的所有菜单的绑定关系
export const unbindAllRole = (menuId) => {
return request({
url: '/admin/role/all/unbind/menu',
method: 'put',
data: {
id: menuId
}
})
}
// 解除角色与菜单之间的绑定状态
export const cancelAuthorization = (menuId, roleIds) => {
return request({
url: '/admin/role/unbind/menu',
method: 'put',
data: {
id: menuId,
ids: roleIds
}
})
}
//建立角色用户绑定关系
export const bindRoleAndMenu = (menuId, roleIds) => {
return request({
url: '/admin/role/bind/menu',
method: 'put',
data: {
id: menuId,
ids: roleIds
}
})
}
//删除角色信息
export const deleteRole = (roleId) => {
return request({
url: `/admin/role/${roleId}`,
method: "delete"
});
};

View File

@@ -1,46 +1,46 @@
import request from '@/utils/request.js'
export const getFundDetail = (specialFundId) => {
return request({
url: `/workflow/mosr/special/fund/from/${specialFundId}`,
method: "get"
});
};
export const getFundDetailProcess = (specialFundId) => {
return request({
url: `/workflow/mosr/special/fund/info/${specialFundId}`,
method: "get"
});
};
export const getFundOption = () => {
return request({
url: '/workflow/mosr/special/fund/option',
method: "get"
});
};
export const getFundProcess = (specialFundId) => {
return request({
url: '/workflow/mosr/special/fund/process',
method: "get"
});
};
export const addFund= (data) => {
return request({
url: '/workflow/mosr/special/fund',
method: "post",
data
});
};
export const resubmitFund= (data) => {
return request({
url: '/workflow/mosr/special/fund/resubmit',
method: "post",
data
});
};
export const deleteFund = (id) => {
return request({
url: `/workflow/mosr/special/fund/${id}`,
method: "delete"
});
};
import request from '@/utils/request.js'
export const getFundDetail = (specialFundId) => {
return request({
url: `/workflow/mosr/special/fund/from/${specialFundId}`,
method: "get"
});
};
export const getFundDetailProcess = (specialFundId) => {
return request({
url: `/workflow/mosr/special/fund/info/${specialFundId}`,
method: "get"
});
};
export const getFundOption = () => {
return request({
url: '/workflow/mosr/special/fund/option',
method: "get"
});
};
export const getFundProcess = (specialFundId) => {
return request({
url: '/workflow/mosr/special/fund/process',
method: "get"
});
};
export const addFund= (data) => {
return request({
url: '/workflow/mosr/special/fund',
method: "post",
data
});
};
export const resubmitFund= (data) => {
return request({
url: '/workflow/mosr/special/fund/resubmit',
method: "post",
data
});
};
export const deleteFund = (id) => {
return request({
url: `/workflow/mosr/special/fund/${id}`,
method: "delete"
});
};

View File

@@ -1,30 +1,30 @@
import request from "@/utils/request.js";
export const getSubCompanyList=(params)=>{
return request({
url:'/admin/mosr/sub/company',
method:'get',
params
})
}
export const getDepartmentList=(params)=>{
return request({
url:'/admin/mosr/department',
method:'get',
params
})
}
export const getCompanyDetail=(companyId)=>{
return request({
url:`/admin/mosr/sub/company/info/${companyId}`,
method:'get'
})
}
export const setCompanyLeader=(data)=>{
return request({
url:'/admin/mosr/sub/company/leader',
method:'post',
data:data
})
}
import request from "@/utils/request.js";
export const getSubCompanyList=(params)=>{
return request({
url:'/admin/mosr/sub/company',
method:'get',
params
})
}
export const getDepartmentList=(params)=>{
return request({
url:'/admin/mosr/department',
method:'get',
params
})
}
export const getCompanyDetail=(companyId)=>{
return request({
url:`/admin/mosr/sub/company/info/${companyId}`,
method:'get'
})
}
export const setCompanyLeader=(data)=>{
return request({
url:'/admin/mosr/sub/company/leader',
method:'post',
data:data
})
}

View File

@@ -1,54 +1,54 @@
import request from '@/utils/request.js'
// 请求参数配置表list
export const getConfigList = (params) => {
return request({
url: '/admin/config',
method: 'get',
params
})
}
//获取到option列表
// 获取参数配置表详情
export const getConfigDetails = (configId) => {
return request({
url: '/admin/config/' + configId,
method: 'get'
})
}
// 获取参数配置表详情
export const getConfigByKey = (configKey) => {
return request({
url: '/admin/config/key/' + configKey,
method: 'get'
})
}
// 新增参数配置表
export const addConfig = (data) => {
return request({
url: '/admin/config',
method: 'post',
data
})
}
// 修改参数配置表
export const editConfig = (data) => {
return request({
url: '/admin/config',
method: 'put',
data
})
}
// 删除参数配置表
export const delConfig =(configId) => {
return request({
url: '/admin/config/' + configId,
method: 'delete'
})
}
import request from '@/utils/request.js'
// 请求参数配置表list
export const getConfigList = (params) => {
return request({
url: '/admin/config',
method: 'get',
params
})
}
//获取到option列表
// 获取参数配置表详情
export const getConfigDetails = (configId) => {
return request({
url: '/admin/config/' + configId,
method: 'get'
})
}
// 获取参数配置表详情
export const getConfigByKey = (configKey) => {
return request({
url: '/admin/config/key/' + configKey,
method: 'get'
})
}
// 新增参数配置表
export const addConfig = (data) => {
return request({
url: '/admin/config',
method: 'post',
data
})
}
// 修改参数配置表
export const editConfig = (data) => {
return request({
url: '/admin/config',
method: 'put',
data
})
}
// 删除参数配置表
export const delConfig =(configId) => {
return request({
url: '/admin/config/' + configId,
method: 'delete'
})
}

View File

@@ -1,44 +1,44 @@
import request from '@/utils/request.js'
// 请求字典类型表list
export const getDictDataList = (params) => {
return request({
url: '/admin/dict/data',
method: 'get',
params
})
}
// 获取字典数据表详情
export const getDictDataDetails = (dictCode) => {
return request({
url: '/admin/dict/data/' + dictCode,
method: 'get'
})
}
// 新增字典数据表
export const addDictData = (data) => {
return request({
url: '/admin/dict/data',
method: 'post',
data
})
}
// 修改字典类型表
export const editDictData = (data) => {
return request({
url: '/admin/dict/data',
method: 'put',
data
})
}
// 删除字典类型表
export const delDictData = (dictCode) => {
return request({
url: `/admin/dict/data/${dictCode}`,
method: 'delete'
})
}
import request from '@/utils/request.js'
// 请求字典类型表list
export const getDictDataList = (params) => {
return request({
url: '/admin/dict/data',
method: 'get',
params
})
}
// 获取字典数据表详情
export const getDictDataDetails = (dictCode) => {
return request({
url: '/admin/dict/data/' + dictCode,
method: 'get'
})
}
// 新增字典数据表
export const addDictData = (data) => {
return request({
url: '/admin/dict/data',
method: 'post',
data
})
}
// 修改字典类型表
export const editDictData = (data) => {
return request({
url: '/admin/dict/data',
method: 'put',
data
})
}
// 删除字典类型表
export const delDictData = (dictCode) => {
return request({
url: `/admin/dict/data/${dictCode}`,
method: 'delete'
})
}

View File

@@ -1,58 +1,58 @@
import request from '@/utils/request.js'
export const getDictOption = () => {
return request({
url: '/admin/dict/type/option',
method: 'get'
})
}
// 请求字典类型表list
export const getDictTypeList = (params) => {
return request({
url: '/admin/dict/type',
method: 'get',
params
})
}
// 获取字典类型表详情
export const getDictTypeDetails = (dictTypeId) => {
return request({
url: '/admin/dict/type/' + dictTypeId,
method: 'get'
})
}
// 新增字典类型表
export const addDictType = (data) => {
return request({
url: '/admin/dict/type',
method: 'post',
data
})
}
// 修改字典类型表
export const editDictType = (data) => {
return request({
url: '/admin/dict/type',
method: 'put',
data
})
}
// 删除字典类型表
export const delDictType =(dictTypeId) => {
return request({
url: '/admin/dict/type/' + dictTypeId,
method: 'delete'
})
}
//字典刷新缓存
export const refreshDict =() => {
return request({
url: 'admin/dict/type/refresh',
method: 'post'
})
}
import request from '@/utils/request.js'
export const getDictOption = () => {
return request({
url: '/admin/dict/type/option',
method: 'get'
})
}
// 请求字典类型表list
export const getDictTypeList = (params) => {
return request({
url: '/admin/dict/type',
method: 'get',
params
})
}
// 获取字典类型表详情
export const getDictTypeDetails = (dictTypeId) => {
return request({
url: '/admin/dict/type/' + dictTypeId,
method: 'get'
})
}
// 新增字典类型表
export const addDictType = (data) => {
return request({
url: '/admin/dict/type',
method: 'post',
data
})
}
// 修改字典类型表
export const editDictType = (data) => {
return request({
url: '/admin/dict/type',
method: 'put',
data
})
}
// 删除字典类型表
export const delDictType =(dictTypeId) => {
return request({
url: '/admin/dict/type/' + dictTypeId,
method: 'delete'
})
}
//字典刷新缓存
export const refreshDict =() => {
return request({
url: 'admin/dict/type/refresh',
method: 'post'
})
}

View File

@@ -1,16 +1,16 @@
import request from '@/utils/request.js'
export const getMappingList = (params) => {
return request({
url: '/admin/mapping/switch',
method: 'get',
params
})
}
export const editMappingSwitch = (data) => {
return request({
url: '/admin/mapping/switch',
method: 'put',
data
})
}
import request from '@/utils/request.js'
export const getMappingList = (params) => {
return request({
url: '/admin/mapping/switch',
method: 'get',
params
})
}
export const editMappingSwitch = (data) => {
return request({
url: '/admin/mapping/switch',
method: 'put',
data
})
}

View File

@@ -1,8 +1,8 @@
import request from '@/utils/request'
export const getRouters = () => {
return request({
url: '/auth/router',
method: 'get'
})
import request from '@/utils/request'
export const getRouters = () => {
return request({
url: '/auth/router',
method: 'get'
})
}

View File

@@ -1,53 +1,53 @@
import request from '@/utils/request.js'
export const getMenuList = (params) => {
return request({
url: '/admin/menu',
method: 'get',
params
})
}
export const editMenu = (data) => {
return request({
url: '/admin/menu',
method: 'put',
data
})
}
export const addMenu = (data) => {
return request({
url: '/admin/menu',
method: 'post',
data
})
}
export const delMenu = (menuId) => {
return request({
url: '/admin/menu/'+menuId,
method: 'delete'
})
}
export const getMenuInfo = (menuId) => {
return request({
url: '/admin/menu/info/'+menuId,
method: 'get'
})
}
export const getMenuOpt = (excludeId=0) => {
return request({
url: '/admin/menu/option/'+excludeId,
method: 'get'
})
}
export const getMenuOptRole = (roleId) => {
return request({
url: '/admin/menu/option/role/'+roleId,
method: 'get'
})
}
import request from '@/utils/request.js'
export const getMenuList = (params) => {
return request({
url: '/admin/menu',
method: 'get',
params
})
}
export const editMenu = (data) => {
return request({
url: '/admin/menu',
method: 'put',
data
})
}
export const addMenu = (data) => {
return request({
url: '/admin/menu',
method: 'post',
data
})
}
export const delMenu = (menuId) => {
return request({
url: '/admin/menu/'+menuId,
method: 'delete'
})
}
export const getMenuInfo = (menuId) => {
return request({
url: '/admin/menu/info/'+menuId,
method: 'get'
})
}
export const getMenuOpt = (excludeId=0) => {
return request({
url: '/admin/menu/option/'+excludeId,
method: 'get'
})
}
export const getMenuOptRole = (roleId) => {
return request({
url: '/admin/menu/option/role/'+roleId,
method: 'get'
})
}

View File

@@ -1,251 +1,251 @@
import request from '@/utils/request.js'
// 根据角色或者部门id获取对应数据
export const getDeptOpt = (params = {}) => {
return request({
url: `/admin/mosr/department/option`,
method: 'get',
params
})
}
export const getSubCompOpt = () => {
return request({
url: `/admin/mosr/sub/company/option`,
method: 'get'
})
}
export const getUserAccount = () => {
return request({
url: `/admin/mosr/user/account/list`,
method: 'get'
})
}
export const judgeIsSameRole = (userId) => {
return request({
url: `/admin/mosr/user/company/same/${userId}`,
method: 'get'
})
}
// 查询角色信息
export const getRolesOpt = () => {
return request({
url: '/admin/role/option',
method: 'get',
})
}
// 获取岗位下拉
export const getJobOpt = () => {
return request({
url: '/admin/job/option',
method: 'get',
})
}
export const getMosrUserList = (params) => {
return request({
url: '/admin/mosr/user',
method: 'get',
params
})
}
export const getUserList = (params) => {
return request({
url: '/admin/user',
method: 'get',
params
})
}
//获取用户详情
export const getUserDetail = (userId) => {
return request({
url: `/admin/mosr/user/info/${userId}`,
method: "get"
});
};
// 操作
export const operate = (data, type) => {
// console.log(type ,'type');
if (data.userId && type !== '0') return editUser(data)
else if (type == '0') return editUserOA(data)
return addUser(data)
}
// 新增用户
export const addUser = (data) => {
return request({
url: '/admin/mosr/user',
method: 'post',
data
})
}
// 修改用户
export const editUser = (data) => {
return request({
url: '/admin/mosr/user',
method: 'put',
data
})
}
// 修改OA用户
export const editUserOA = (data) => {
return request({
url: '/admin/mosr/user/oa',
method: 'put',
data
})
}
//删除用户信息
export const deleteUser = (userId) => {
return request({
url: `/admin/user/${userId}`,
method: "delete"
});
};
//根据roleId获取用户信息
export const getUserByRoleId = (roleId, params) => {
return request({
url: `/admin/user/role/${roleId}`,
method: "get",
params
});
};
//排除角色id获取用户信息
export const getUserExcludeRoleId = (roleId, params) => {
return request({
url: `/admin/user/role/exclude/${roleId}`,
method: "get",
params
});
};
//建立角色用户绑定关系
export const roleBindUser = (data) => {
return request({
url: '/admin/user/bind/role',
method: 'put',
data
})
}
// 解除角色与用户之间的绑定状态
export const cancelAuthorization = (data) => {
return request({
url: '/admin/user/unbind/role',
method: 'put',
data
})
}
//解除当前角色对应的所有用户的绑定关系
export const unbindAllUser = (roleId) => {
return request({
url: '/admin/user/all/unbind/role',
method: 'put',
data: {
id: roleId
}
})
}
//根据岗位id获取分配的用户信息
export const getUserInfoByPostId = (postId, params) => {
return request({
url: `/admin/user/post/${postId}`,
method: 'get',
params
})
}
//排除岗位id获取用户信息
export const getUserExcludePostId = (postId, params) => {
return request({
url: `/admin/user/post/exclude/${postId}`,
method: "get",
params
});
};
//建立岗位与用户绑定关系
export const postBindUser = (userIds, postId) => {
return request({
url: '/admin/user/bind/post',
method: 'put',
data: {
ids: userIds,
id: postId
}
})
}
// 解除岗位与用户之间的绑定状态
export const cancelPostAndUserAuthorization = (userIds, postId) => {
return request({
url: '/admin/user/unbind/post',
method: 'put',
data: {
ids: userIds,
id: postId
}
})
}
//解除当前岗位对应的所有用户的绑定关系
export const unbindAllUserByPost = (postId) => {
return request({
url: '/admin/user/all/unbind/post',
method: 'put',
data: {
id: postId
}
})
}
export const bindAccount = (data) => {
return request({
url: '/admin/mosr/user/bind/account',
method: 'post',
data
})
}
export const getBindAccount = (userId) => {
return request({
url: `/admin/mosr/user/bind/account/info/${userId}`,
method: 'get'
})
}
export const checkMatrix = (userId) => {
return request({
url: `/admin/mosr/user/matrix?userId=` + userId,
method: 'get'
})
}
export const getAgentInfo=(userId)=>{
return request({
url: `/admin/mosr/user/approval/agent/${userId}`,
method:'get'
})
}
export const editAgentInfo=(data)=>{
return request({
url:'/admin/mosr/user/approval/agent',
method:'post',
data
})
}
export const addWhiteUser=(data)=>{
return request({
url:'/admin/approve/white',
method:'post',
data
})
}
export const delWhiteUser=(data)=>{
return request({
url:'/admin/approve/white',
method:'delete',
data
})
}
import request from '@/utils/request.js'
// 根据角色或者部门id获取对应数据
export const getDeptOpt = (params = {}) => {
return request({
url: `/admin/mosr/department/option`,
method: 'get',
params
})
}
export const getSubCompOpt = () => {
return request({
url: `/admin/mosr/sub/company/option`,
method: 'get'
})
}
export const getUserAccount = () => {
return request({
url: `/admin/mosr/user/account/list`,
method: 'get'
})
}
export const judgeIsSameRole = (userId) => {
return request({
url: `/admin/mosr/user/company/same/${userId}`,
method: 'get'
})
}
// 查询角色信息
export const getRolesOpt = () => {
return request({
url: '/admin/role/option',
method: 'get',
})
}
// 获取岗位下拉
export const getJobOpt = () => {
return request({
url: '/admin/job/option',
method: 'get',
})
}
export const getMosrUserList = (params) => {
return request({
url: '/admin/mosr/user',
method: 'get',
params
})
}
export const getUserList = (params) => {
return request({
url: '/admin/user',
method: 'get',
params
})
}
//获取用户详情
export const getUserDetail = (userId) => {
return request({
url: `/admin/mosr/user/info/${userId}`,
method: "get"
});
};
// 操作
export const operate = (data, type) => {
// console.log(type ,'type');
if (data.userId && type !== '0') return editUser(data)
else if (type == '0') return editUserOA(data)
return addUser(data)
}
// 新增用户
export const addUser = (data) => {
return request({
url: '/admin/mosr/user',
method: 'post',
data
})
}
// 修改用户
export const editUser = (data) => {
return request({
url: '/admin/mosr/user',
method: 'put',
data
})
}
// 修改OA用户
export const editUserOA = (data) => {
return request({
url: '/admin/mosr/user/oa',
method: 'put',
data
})
}
//删除用户信息
export const deleteUser = (userId) => {
return request({
url: `/admin/user/${userId}`,
method: "delete"
});
};
//根据roleId获取用户信息
export const getUserByRoleId = (roleId, params) => {
return request({
url: `/admin/user/role/${roleId}`,
method: "get",
params
});
};
//排除角色id获取用户信息
export const getUserExcludeRoleId = (roleId, params) => {
return request({
url: `/admin/user/role/exclude/${roleId}`,
method: "get",
params
});
};
//建立角色用户绑定关系
export const roleBindUser = (data) => {
return request({
url: '/admin/user/bind/role',
method: 'put',
data
})
}
// 解除角色与用户之间的绑定状态
export const cancelAuthorization = (data) => {
return request({
url: '/admin/user/unbind/role',
method: 'put',
data
})
}
//解除当前角色对应的所有用户的绑定关系
export const unbindAllUser = (roleId) => {
return request({
url: '/admin/user/all/unbind/role',
method: 'put',
data: {
id: roleId
}
})
}
//根据岗位id获取分配的用户信息
export const getUserInfoByPostId = (postId, params) => {
return request({
url: `/admin/user/post/${postId}`,
method: 'get',
params
})
}
//排除岗位id获取用户信息
export const getUserExcludePostId = (postId, params) => {
return request({
url: `/admin/user/post/exclude/${postId}`,
method: "get",
params
});
};
//建立岗位与用户绑定关系
export const postBindUser = (userIds, postId) => {
return request({
url: '/admin/user/bind/post',
method: 'put',
data: {
ids: userIds,
id: postId
}
})
}
// 解除岗位与用户之间的绑定状态
export const cancelPostAndUserAuthorization = (userIds, postId) => {
return request({
url: '/admin/user/unbind/post',
method: 'put',
data: {
ids: userIds,
id: postId
}
})
}
//解除当前岗位对应的所有用户的绑定关系
export const unbindAllUserByPost = (postId) => {
return request({
url: '/admin/user/all/unbind/post',
method: 'put',
data: {
id: postId
}
})
}
export const bindAccount = (data) => {
return request({
url: '/admin/mosr/user/bind/account',
method: 'post',
data
})
}
export const getBindAccount = (userId) => {
return request({
url: `/admin/mosr/user/bind/account/info/${userId}`,
method: 'get'
})
}
export const checkMatrix = (userId) => {
return request({
url: `/admin/mosr/user/matrix?userId=` + userId,
method: 'get'
})
}
export const getAgentInfo=(userId)=>{
return request({
url: `/admin/mosr/user/approval/agent/${userId}`,
method:'get'
})
}
export const editAgentInfo=(data)=>{
return request({
url:'/admin/mosr/user/approval/agent',
method:'post',
data
})
}
export const addWhiteUser=(data)=>{
return request({
url:'/admin/approve/white',
method:'post',
data
})
}
export const delWhiteUser=(data)=>{
return request({
url:'/admin/approve/white',
method:'delete',
data
})
}

View File

@@ -1,78 +1,78 @@
import request from '@/utils/request.js'
export function getProcessDefinitionList(param) {
return request({
url: "/workflow/process/definition",
method: "get",
params: param
})
}
export function getProcessDefinitionInfo(deploymentId) {
return request({
url: "/workflow/process/definition/" + deploymentId,
method: "get",
})
}
export function getInitiateInfo(processDefinitionKey) {
return request({
url: "/workflow/process/definition/key/" + processDefinitionKey,
method: "get",
})
}
export function getHistoryVersion(processDefinitionKey) {
return request({
url: "/workflow/process/definition/history/" + processDefinitionKey,
method: "get",
})
}
export function deleteHistoryVersion(deploymentId) {
return request({
url: "/workflow/process/definition/" + deploymentId,
method: "delete",
})
}
export function suspendProcessDefinition(processDefinitionId) {
return request({
url: "/workflow/process/definition/suspend",
method: "put",
data: processDefinitionId
})
}
export function activateProcessDefinition(processDefinitionId) {
return request({
url: "/workflow/process/definition/activate",
method: "put",
data: processDefinitionId
})
}
export function addProcessDefinition(param) {
return request({
url: "/workflow/process/definition",
method: "post",
data: param
})
}
export function getTypeOption() {
return request({
url: "/workflow/process/definition/type/option",
method: "get",
})
}
export function getFromPerm(processKey) {
return request({
url: "/workflow/process/definition/from/perm/"+processKey,
method: "get",
})
}
import request from '@/utils/request.js'
export function getProcessDefinitionList(param) {
return request({
url: "/workflow/process/definition",
method: "get",
params: param
})
}
export function getProcessDefinitionInfo(deploymentId) {
return request({
url: "/workflow/process/definition/" + deploymentId,
method: "get",
})
}
export function getInitiateInfo(processDefinitionKey) {
return request({
url: "/workflow/process/definition/key/" + processDefinitionKey,
method: "get",
})
}
export function getHistoryVersion(processDefinitionKey) {
return request({
url: "/workflow/process/definition/history/" + processDefinitionKey,
method: "get",
})
}
export function deleteHistoryVersion(deploymentId) {
return request({
url: "/workflow/process/definition/" + deploymentId,
method: "delete",
})
}
export function suspendProcessDefinition(processDefinitionId) {
return request({
url: "/workflow/process/definition/suspend",
method: "put",
data: processDefinitionId
})
}
export function activateProcessDefinition(processDefinitionId) {
return request({
url: "/workflow/process/definition/activate",
method: "put",
data: processDefinitionId
})
}
export function addProcessDefinition(param) {
return request({
url: "/workflow/process/definition",
method: "post",
data: param
})
}
export function getTypeOption() {
return request({
url: "/workflow/process/definition/type/option",
method: "get",
})
}
export function getFromPerm(processKey) {
return request({
url: "/workflow/process/definition/from/perm/"+processKey,
method: "get",
})
}

View File

@@ -1,9 +1,9 @@
import request from '@/utils/request.js'
export function deleteFile(fileId) {
// 删除文件
return request({
url: '/workflow/process/file/' + fileId,
method: 'delete',
})
}
import request from '@/utils/request.js'
export function deleteFile(fileId) {
// 删除文件
return request({
url: '/workflow/process/file/' + fileId,
method: 'delete',
})
}

View File

@@ -1,53 +1,53 @@
import request from '@/utils/request.js'
/**
* 开始实例流程
* @param param
* @returns {*}
*/
export function startProcessInstance(param) {
return request({
url: "/workflow/process/instance/start",
method: "post",
data: param
})
}
export function restartProcessInstance(param) {
return request({
url: "/workflow/process/instance/restart",
method: "post",
data: param
})
}
export function getAboutInstanceList(param) {
return request({
url: "/workflow/process/instance/about",
method: "get",
params: param
})
}
export function getInitiatedInstanceList(param) {
return request({
url: "/workflow/process/instance/self",
method: "get",
params: param
})
}
export function getInitiatedInstanceInfo(processInstanceId) {
return request({
url: "/workflow/process/instance/info/"+processInstanceId,
method: "get",
})
}
export function getInitiatedInstanceReInfo(instanceId) {
return request({
url: "/workflow/process/instance/re/info/"+instanceId,
method: "get",
})
}
import request from '@/utils/request.js'
/**
* 开始实例流程
* @param param
* @returns {*}
*/
export function startProcessInstance(param) {
return request({
url: "/workflow/process/instance/start",
method: "post",
data: param
})
}
export function restartProcessInstance(param) {
return request({
url: "/workflow/process/instance/restart",
method: "post",
data: param
})
}
export function getAboutInstanceList(param) {
return request({
url: "/workflow/process/instance/about",
method: "get",
params: param
})
}
export function getInitiatedInstanceList(param) {
return request({
url: "/workflow/process/instance/self",
method: "get",
params: param
})
}
export function getInitiatedInstanceInfo(processInstanceId) {
return request({
url: "/workflow/process/instance/info/"+processInstanceId,
method: "get",
})
}
export function getInitiatedInstanceReInfo(instanceId) {
return request({
url: "/workflow/process/instance/re/info/"+instanceId,
method: "get",
})
}

View File

@@ -1,46 +1,46 @@
import request from '@/utils/request.js'
// 请求系统内置监听器list
export const getProcessListenerList = (params) => {
return request({
url: '/workflow/process/listener',
method: 'get',
params
})
}
//获取到option列表
// 获取系统内置监听器详情
export const getProcessListenerDetails = (processListenerId) => {
return request({
url: '/workflow/process/listener/' + processListenerId,
method: 'get'
})
}
// 新增系统内置监听器
export const addProcessListener = (data) => {
return request({
url: '/workflow/process/listener',
method: 'post',
data
})
}
// 修改系统内置监听器
export const editProcessListener = (data) => {
return request({
url: '/workflow/process/listener',
method: 'put',
data
})
}
// 删除系统内置监听器
export const delProcessListener =(processListenerId) => {
return request({
url: '/workflow/process/listener/' + processListenerId,
method: 'delete'
})
}
import request from '@/utils/request.js'
// 请求系统内置监听器list
export const getProcessListenerList = (params) => {
return request({
url: '/workflow/process/listener',
method: 'get',
params
})
}
//获取到option列表
// 获取系统内置监听器详情
export const getProcessListenerDetails = (processListenerId) => {
return request({
url: '/workflow/process/listener/' + processListenerId,
method: 'get'
})
}
// 新增系统内置监听器
export const addProcessListener = (data) => {
return request({
url: '/workflow/process/listener',
method: 'post',
data
})
}
// 修改系统内置监听器
export const editProcessListener = (data) => {
return request({
url: '/workflow/process/listener',
method: 'put',
data
})
}
// 删除系统内置监听器
export const delProcessListener =(processListenerId) => {
return request({
url: '/workflow/process/listener/' + processListenerId,
method: 'delete'
})
}

View File

@@ -1,45 +1,45 @@
import request from '@/utils/request.js'
export function getTaskList() {
return request({
url: "/workflow/process/task",
method: "get",
})
}
export function getTaskInfo(taskId) {
return request({
url: "/workflow/process/task/"+taskId,
method: "get",
})
}
export function completeTask(params) {
return request({
url: "/workflow/process/task/complete",
method: "put",
data: params
})
}
export function refuseTask(params) {
return request({
url: "/workflow/process/task/refuse",
method: "put",
data: params
})
}
export function rollBackTask(params) {
return request({
url: "/workflow/process/task/rollback",
method: "put",
data: params
})
}
export function addComment(params) {
return request({
url: "/workflow/process/task/comment",
method: "post",
data: params
})
}
import request from '@/utils/request.js'
export function getTaskList() {
return request({
url: "/workflow/process/task",
method: "get",
})
}
export function getTaskInfo(taskId) {
return request({
url: "/workflow/process/task/"+taskId,
method: "get",
})
}
export function completeTask(params) {
return request({
url: "/workflow/process/task/complete",
method: "put",
data: params
})
}
export function refuseTask(params) {
return request({
url: "/workflow/process/task/refuse",
method: "put",
data: params
})
}
export function rollBackTask(params) {
return request({
url: "/workflow/process/task/rollback",
method: "put",
data: params
})
}
export function addComment(params) {
return request({
url: "/workflow/process/task/comment",
method: "post",
data: params
})
}

View File

@@ -1,47 +1,47 @@
import request from '@/utils/request.js'
//根据角色或者部门获取到对应的数据
export function getUserTree(type,chooseId){
return request({
url:`/admin/user/choose/${type}/${chooseId}`,
method:'get'
})
}
// 查询系统角色
export function getRole() {
return request({
url: 'admin/role/option',
method: 'get'
})
}
//获取采取树形控件的部门option
export function getDepartmentTree() {
return request({
url: 'admin/dept/option',
method: 'get'
})
}
export function getMosrUser(params) {
return request({
url: '/admin/mosr/user/choose',
method: 'get',
params:params
})
}
export function getOrganizationStructure(params) {
return request({
url: '/admin/organizational/structure/choose',
method: 'get',
params:params
})
}
export function getOrganizationStructureTree(params) {
return request({
url: '/admin/organizational/structure/tree',
method: 'get',
params: params
})
}
import request from '@/utils/request.js'
//根据角色或者部门获取到对应的数据
export function getUserTree(type,chooseId){
return request({
url:`/admin/user/choose/${type}/${chooseId}`,
method:'get'
})
}
// 查询系统角色
export function getRole() {
return request({
url: 'admin/role/option',
method: 'get'
})
}
//获取采取树形控件的部门option
export function getDepartmentTree() {
return request({
url: 'admin/dept/option',
method: 'get'
})
}
export function getMosrUser(params) {
return request({
url: '/admin/mosr/user/choose',
method: 'get',
params:params
})
}
export function getOrganizationStructure(params) {
return request({
url: '/admin/organizational/structure/choose',
method: 'get',
params:params
})
}
export function getOrganizationStructureTree(params) {
return request({
url: '/admin/organizational/structure/tree',
method: 'get',
params: params
})
}

View File

@@ -1,77 +1,77 @@
tinymce.PluginManager.add('axupimgs', function (editor, url) {
var pluginName = '多图片上传';
window.axupimgs = {}; //扔外部公共变量,也可以扔一个自定义的位置
const baseURL = import.meta.env.VITE_BASE_URL
// var baseURL=tinymce.baseURL;
var iframe1 = '/upfiles.html';
console.log('editor',editor)
axupimgs.images_upload_handler = editor.getParam('images_upload_handler_not_loading', undefined, 'function');
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
axupimgs.res = [];
var openDialog = function () {
return editor.windowManager.openUrl({
title: pluginName,
size: 'large',
url: iframe1,
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'custom',
text: 'Save',
name: 'save',
primary: true
},
],
onAction: function (api, details) {
switch (details.name) {
case 'save':
var html = '';
var imgs = axupimgs.res;
var len = imgs.length;
for (let i = 0; i < len; i++) {
if (imgs[i].url) {
html += '<img src="' + imgs[i].url + '" />';
}
}
editor.insertContent(html);
axupimgs.res = [];
api.close();
break;
default:
break;
}
}
});
};
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs', '<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
editor.ui.registry.addButton('axupimgs', {
icon: 'axupimgs',
tooltip: pluginName,
onAction: function () {
openDialog();
}
});
editor.ui.registry.addMenuItem('axupimgs', {
icon: 'axupimgs',
text: '图片批量上传...',
onAction: function () {
openDialog();
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
};
}
};
});
tinymce.PluginManager.add('axupimgs', function (editor, url) {
var pluginName = '多图片上传';
window.axupimgs = {}; //扔外部公共变量,也可以扔一个自定义的位置
const baseURL = import.meta.env.VITE_BASE_URL
// var baseURL=tinymce.baseURL;
var iframe1 = '/upfiles.html';
console.log('editor',editor)
axupimgs.images_upload_handler = editor.getParam('images_upload_handler_not_loading', undefined, 'function');
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
axupimgs.res = [];
var openDialog = function () {
return editor.windowManager.openUrl({
title: pluginName,
size: 'large',
url: iframe1,
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'custom',
text: 'Save',
name: 'save',
primary: true
},
],
onAction: function (api, details) {
switch (details.name) {
case 'save':
var html = '';
var imgs = axupimgs.res;
var len = imgs.length;
for (let i = 0; i < len; i++) {
if (imgs[i].url) {
html += '<img src="' + imgs[i].url + '" />';
}
}
editor.insertContent(html);
axupimgs.res = [];
api.close();
break;
default:
break;
}
}
});
};
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs', '<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
editor.ui.registry.addButton('axupimgs', {
icon: 'axupimgs',
tooltip: pluginName,
onAction: function () {
openDialog();
}
});
editor.ui.registry.addMenuItem('axupimgs', {
icon: 'axupimgs',
text: '图片批量上传...',
onAction: function () {
openDialog();
}
});
return {
getMetadata: function () {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
};
}
};
});

View File

@@ -1,75 +1,75 @@
tinymce.PluginManager.add('axupimgs', function(editor, url) {
var pluginName='Ax多图片上传';
window.axupimgs={}; //扔外部公共变量,也可以扔一个自定义的位置
var baseURL=tinymce.baseURL;
var iframe1 = baseURL+'/plugins/axupimgs/upfiles.html';
axupimgs.images_upload_handler = editor.getParam('images_upload_handler', undefined, 'function');
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
axupimgs.res=[];
var openDialog = function() {
return editor.windowManager.openUrl({
title: pluginName,
size: 'large',
url:iframe1,
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'custom',
text: 'Save',
name: 'save',
primary: true
},
],
onAction: function (api, details) {
switch (details.name) {
case 'save':
var html = '';
var imgs = axupimgs.res;
var len = imgs.length;
for(let i=0;i<len;i++){
if( imgs[i].url ){
html += '<img src="'+imgs[i].url+'" />';
}
}
editor.insertContent(html);
axupimgs.res=[];
api.close();
break;
default:
break;
}
}
});
};
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs','<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
editor.ui.registry.addButton('axupimgs', {
icon: 'axupimgs',
tooltip: pluginName,
onAction: function() {
openDialog();
}
});
editor.ui.registry.addMenuItem('axupimgs', {
icon: 'axupimgs',
text: '图片批量上传...',
onAction: function() {
openDialog();
}
});
return {
getMetadata: function() {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
};
}
};
});
tinymce.PluginManager.add('axupimgs', function(editor, url) {
var pluginName='Ax多图片上传';
window.axupimgs={}; //扔外部公共变量,也可以扔一个自定义的位置
var baseURL=tinymce.baseURL;
var iframe1 = baseURL+'/plugins/axupimgs/upfiles.html';
axupimgs.images_upload_handler = editor.getParam('images_upload_handler', undefined, 'function');
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
axupimgs.res=[];
var openDialog = function() {
return editor.windowManager.openUrl({
title: pluginName,
size: 'large',
url:iframe1,
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'custom',
text: 'Save',
name: 'save',
primary: true
},
],
onAction: function (api, details) {
switch (details.name) {
case 'save':
var html = '';
var imgs = axupimgs.res;
var len = imgs.length;
for(let i=0;i<len;i++){
if( imgs[i].url ){
html += '<img src="'+imgs[i].url+'" />';
}
}
editor.insertContent(html);
axupimgs.res=[];
api.close();
break;
default:
break;
}
}
});
};
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs','<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
editor.ui.registry.addButton('axupimgs', {
icon: 'axupimgs',
tooltip: pluginName,
onAction: function() {
openDialog();
}
});
editor.ui.registry.addMenuItem('axupimgs', {
icon: 'axupimgs',
text: '图片批量上传...',
onAction: function() {
openDialog();
}
});
return {
getMetadata: function() {
return {
name: pluginName,
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
};
}
};
});

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

Before

Width:  |  Height:  |  Size: 276 B

After

Width:  |  Height:  |  Size: 277 B

View File

@@ -1,144 +1,144 @@
* {
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
}
/* ==============X轴/Y轴区域样式=============*/
.box-card-h {
height: 390px !important;
}
.box-card::-webkit-scrollbar {
width: 6px;
}
// 滚动条轨道
.box-card::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
// 小滑块
.box-card::-webkit-scrollbar-thumb {
background: rgba(80, 81, 82, 0.29);
border-radius: 10px;
}
.box-card {
font-size: 15px;
height: 350px;
overflow-y: auto;
.el-card__body {
padding: 15px;
}
.x-y-axis {
margin-bottom: 10px;
}
.list-group {
height: 100%;
}
.cards {
margin-bottom: 10px;
span:last-child {
color: #2a99ff;
}
.update-color {
display: flex;
align-items: center;
justify-content: space-around;
> span{
white-space: pre
}
}
}
.card-active {
outline: none; /* 隐藏默认的蓝色外边框 */
box-shadow: 0 0 5px blue; /* 添加阴影效果,颜色为蓝色 */
}
.x-y-cards {
.el-card__body {
display: flex;
justify-content: space-around;
align-items: center;
height: 50px;
}
.cards-right {
display: flex;
align-items: center;
justify-content: flex-end;
> span:first-child {
color: #2a99ff;
}
}
}
}
//扩大拖拽区域
.drag-block {
height: 329px;
}
.red-bgc {
background-color: red;
}
.yellow-bgc {
background-color: yellow;
}
/* ==============基础设置样式=============*/
.basic-setup {
font-weight: bold;
font-size: 18px;
margin-bottom: 10px;
}
.setting {
display: flex;
flex-direction: column;
margin-bottom: 10px;
.setting-title {
font-weight: bold;
font-size: 16px;
margin-bottom: 5px;
}
.setting-item {
margin-bottom: 10px;
}
}
/* ==============高级设置样式=============*/
.advanced-setting{
.el-form-item {
display: block;
.el-form-item__label {
font-weight: bold;
font-size: 18px;
}
.el-form-item__content {
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 15px;
}
}
}
/* ==============echarts样式=============*/
#container {
box-sizing: border-box;
height: 450px;
width: 80%;
margin: 0 auto;
}
* {
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
}
/* ==============X轴/Y轴区域样式=============*/
.box-card-h {
height: 390px !important;
}
.box-card::-webkit-scrollbar {
width: 6px;
}
// 滚动条轨道
.box-card::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
// 小滑块
.box-card::-webkit-scrollbar-thumb {
background: rgba(80, 81, 82, 0.29);
border-radius: 10px;
}
.box-card {
font-size: 15px;
height: 350px;
overflow-y: auto;
.el-card__body {
padding: 15px;
}
.x-y-axis {
margin-bottom: 10px;
}
.list-group {
height: 100%;
}
.cards {
margin-bottom: 10px;
span:last-child {
color: #2a99ff;
}
.update-color {
display: flex;
align-items: center;
justify-content: space-around;
> span{
white-space: pre
}
}
}
.card-active {
outline: none; /* 隐藏默认的蓝色外边框 */
box-shadow: 0 0 5px blue; /* 添加阴影效果,颜色为蓝色 */
}
.x-y-cards {
.el-card__body {
display: flex;
justify-content: space-around;
align-items: center;
height: 50px;
}
.cards-right {
display: flex;
align-items: center;
justify-content: flex-end;
> span:first-child {
color: #2a99ff;
}
}
}
}
//扩大拖拽区域
.drag-block {
height: 329px;
}
.red-bgc {
background-color: red;
}
.yellow-bgc {
background-color: yellow;
}
/* ==============基础设置样式=============*/
.basic-setup {
font-weight: bold;
font-size: 18px;
margin-bottom: 10px;
}
.setting {
display: flex;
flex-direction: column;
margin-bottom: 10px;
.setting-title {
font-weight: bold;
font-size: 16px;
margin-bottom: 5px;
}
.setting-item {
margin-bottom: 10px;
}
}
/* ==============高级设置样式=============*/
.advanced-setting{
.el-form-item {
display: block;
.el-form-item__label {
font-weight: bold;
font-size: 18px;
}
.el-form-item__content {
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 15px;
}
}
}
/* ==============echarts样式=============*/
#container {
box-sizing: border-box;
height: 450px;
width: 80%;
margin: 0 auto;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +1,53 @@
.el-side {
border-radius: 10px;
}
.logo {
height: 65px;
background-color: #BEA266;
color: #ffffff;
font-weight: bold;
font-size: 26px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: 10px;
& > img {
object-fit: scale-down;
width: 100%;
height: 40px;
}
}
.port-link{
display: block;
width: 200px;
height: 50px;
margin-left: -40px;
padding-left: 40px;
}
.el-menu {
border: none !important;
.el-sub-menu {
.el-sub-menu__title {
display: block;
font-size: 14px;
&:hover{
//background-color: #1F315F;
}
}
.el-menu-item {
font-size: 14px;
justify-content: flex-start;
align-items: center;
&:hover {
//background-color: #373350 !important;
//color: #EDC49A;
}
}
.el-menu-item.is-active {
background: rgba(190,162,102,0.5);
//background-color: #373350 !important;
}
}
}
.el-side {
border-radius: 10px;
}
.logo {
height: 65px;
background-color: #BEA266;
color: #ffffff;
font-weight: bold;
font-size: 26px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: 10px;
& > img {
object-fit: scale-down;
width: 100%;
height: 40px;
}
}
.port-link{
display: block;
width: 200px;
height: 50px;
margin-left: -40px;
padding-left: 40px;
}
.el-menu {
border: none !important;
.el-sub-menu {
.el-sub-menu__title {
display: block;
font-size: 14px;
&:hover{
//background-color: #1F315F;
}
}
.el-menu-item {
font-size: 14px;
justify-content: flex-start;
align-items: center;
&:hover {
//background-color: #373350 !important;
//color: #EDC49A;
}
}
.el-menu-item.is-active {
background: rgba(190,162,102,0.5);
//background-color: #373350 !important;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +1,110 @@
<template>
<el-button color="#DED0B2" style="float: right;margin: 0 10px 10px 0" @click="exportExcelHandler">导出</el-button>
<el-table ref="table" :data="tableData" style="width: 100%;height: 479px" :show-summary="true" border
:summary-method="getSummaries" v-loading="loading" :header-cell-style="{background:'#f5f7fa'}">
<el-table-column type="index" label="序号" align="center" width="60"/>
<el-table-column prop="projectName" label="项目名称" align="center"/>
<el-table-column prop="projectCost" label="费用性质" align="center">
<template #default="scope">
<div v-if="scope.row.projectCost !== null">
<Tag dictType="project_cost" :value="scope.row.projectCost"/>
</div>
<div v-else>--</div>
</template>
</el-table-column>
<el-table-column prop="researchStage" label="研发阶段" align="center">
<template #default="scope">
<div v-if="scope.row.researchStage !== null && scope.row.researchStage !== null && scope.row.researchStage !== undefined">
<el-tag effect="plain">{{scope.row.researchStage==1?'开发阶段':'研究阶段'}}</el-tag>
</div>
<div v-else>--</div>
</template>
</el-table-column>
<el-table-column prop="afterTax" label="分摊金额" align="center">
<template #default="scope">
<div v-if="scope.row.afterTax !== null">
<!-- {{ toThousands(scope.row.afterTax) }}-->
{{ scope.row.afterTax }}
</div>
</template>
</el-table-column>
</el-table>
<!-- <Tag dictType="research_stage" :value="scope.row.researchStage"/>-->
</template>
<script setup>
import {getAllocationSummaryDetails} from "@/api/expense-manage";
import {shareExportExcel} from "@/api/expense-manage";
const props = defineProps({
allocationName :{
type: String,
default: ''
}
})
const tableData = ref()
const loading = ref(false)
const table = ref()
const route = useRoute()
const getSummaries = (param) => {
const {columns, data} = param
const sums = []
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '小计'
} else if (index === 4) {
const values = data.map((item) => Number(item[column.property]))
if (!values.every((value) => Number.isNaN(value))) {
sums[index] = `${values.reduce((prev, curr) => {
const value = Number(curr)
if (!Number.isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)}`
sums[index] = parseFloat(sums[index]).toFixed(2)
// sums[index] = toThousands(sums[index])
} else {
sums[index] = '-'
}
}
})
return sums
}
// const exportTable = () => {
// const $e = table.value.$el
// let $table = $e.querySelector('.el-table__fixed')
// if (!$table) {
// $table = $e
// }
// exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目费用分摊表", 2)
// }
const exportExcelHandler = () => {
shareExportExcel(route.query.id).then(res => {
let fileName = `科技创新项目费用分摊表-${props.allocationName}.zip`
const blob = new Blob([res.data])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = fileName
a.click()
})
}
const init = () => {
loading.value = true
let params = {
allocationId: route.query.id
}
getAllocationSummaryDetails(params).then(res => {
tableData.value = res.data
loading.value = false
})
}
init()
</script>
<style scoped>
</style>
<template>
<el-button color="#DED0B2" style="float: right;margin: 0 10px 10px 0" @click="exportExcelHandler">导出</el-button>
<el-table ref="table" :data="tableData" style="width: 100%;height: 479px" :show-summary="true" border
:summary-method="getSummaries" v-loading="loading" :header-cell-style="{background:'#f5f7fa'}">
<el-table-column type="index" label="序号" align="center" width="60"/>
<el-table-column prop="projectName" label="项目名称" align="center"/>
<el-table-column prop="projectCost" label="费用性质" align="center">
<template #default="scope">
<div v-if="scope.row.projectCost !== null">
<Tag dictType="project_cost" :value="scope.row.projectCost"/>
</div>
<div v-else>--</div>
</template>
</el-table-column>
<el-table-column prop="researchStage" label="研发阶段" align="center">
<template #default="scope">
<div v-if="scope.row.researchStage !== null && scope.row.researchStage !== null && scope.row.researchStage !== undefined">
<el-tag effect="plain">{{scope.row.researchStage==1?'开发阶段':'研究阶段'}}</el-tag>
</div>
<div v-else>--</div>
</template>
</el-table-column>
<el-table-column prop="afterTax" label="分摊金额" align="center">
<template #default="scope">
<div v-if="scope.row.afterTax !== null">
<!-- {{ toThousands(scope.row.afterTax) }}-->
{{ scope.row.afterTax }}
</div>
</template>
</el-table-column>
</el-table>
<!-- <Tag dictType="research_stage" :value="scope.row.researchStage"/>-->
</template>
<script setup>
import {getAllocationSummaryDetails} from "@/api/expense-manage";
import {shareExportExcel} from "@/api/expense-manage";
const props = defineProps({
allocationName :{
type: String,
default: ''
}
})
const tableData = ref()
const loading = ref(false)
const table = ref()
const route = useRoute()
const getSummaries = (param) => {
const {columns, data} = param
const sums = []
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '小计'
} else if (index === 4) {
const values = data.map((item) => Number(item[column.property]))
if (!values.every((value) => Number.isNaN(value))) {
sums[index] = `${values.reduce((prev, curr) => {
const value = Number(curr)
if (!Number.isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)}`
sums[index] = parseFloat(sums[index]).toFixed(2)
// sums[index] = toThousands(sums[index])
} else {
sums[index] = '-'
}
}
})
return sums
}
// const exportTable = () => {
// const $e = table.value.$el
// let $table = $e.querySelector('.el-table__fixed')
// if (!$table) {
// $table = $e
// }
// exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目费用分摊表", 2)
// }
const exportExcelHandler = () => {
shareExportExcel(route.query.id).then(res => {
let fileName = `科技创新项目费用分摊表-${props.allocationName}.zip`
const blob = new Blob([res.data])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = fileName
a.click()
})
}
const init = () => {
loading.value = true
let params = {
allocationId: route.query.id
}
getAllocationSummaryDetails(params).then(res => {
tableData.value = res.data
loading.value = false
})
}
init()
</script>
<style scoped>
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,208 +1,208 @@
<template>
<div v-loading="loading" :style="type==='singleDetail'?'padding: 0 30px':''">
<baseTitle title="需求征集信息" v-if="type!=='singleDetail'"></baseTitle>
<el-form :model="formData" >
<el-row gutter="20" style="margin-left: 5px">
<el-col :span="6">
<el-form-item label="征集名称">
<span>{{ formData.requirementName }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="征集类型">
<span>{{ formData.collectType }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="需求上报截止时间">
<span>{{ formData.deadline }}</span>
</el-form-item>
</el-col>
<el-col :span="6" v-if="formData.isSpecialFund">
<el-form-item label="专项资金名称">
<span>{{ formData.specialFund }}</span>
</el-form-item>
</el-col>
<el-col :span="24" v-if="type==='singleDetail'">
<el-form-item label="征集公司">
<span :class="showExpendClass(showMoreCompany,formData.companyIds)">{{
getCompanyName(formData.companyIds)
}}</span>
<div style="color: #2a99ff;text-align: center;width: 100%;font-size: 15px;cursor: pointer"
@click="handleExpend">{{ showExpendText }}
</div>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-bottom: -15px">
<el-form-item label="征集说明">
<div v-if="formData.collectExplain" v-html="formData.collectExplain" style="white-space: pre-wrap;">
</div>
<div v-else>--</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件文件" style="margin-bottom: 0"></baseTitle>
<file-component title="" tag="需求征集"
v-model:value="formData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/>
</el-col>
<el-col :span="24" style="margin-top: -15px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record" style="margin-top: -15px">
<div class="approval-title">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266; --el-switch-off-color:#cecdcd"
/>
</div>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="collectionProcess"/>
</div>
</div>
</el-form>
</div>
</template>
<script setup lang="jsx">
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {downloadFile} from "@/api/project-demand";
const emit = defineEmits(['update:value'])
const showExpendText = ref('')
const showMoreCompany = ref(false)
const props = defineProps({
formData: {
type: Array,
default: []
},
data: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
companyOption: {
type: Array,
default: []
},
loading: {
type: Boolean,
default: false
},
fileListShow: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
value: {
type: String,
default: ''
}
})
const changeDiagram = ref(false)
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const getCompanyName = (data) => {
if (data) {
return data.join('')
}
}
const handleExpend = () => {
showMoreCompany.value = !showMoreCompany.value;
showExpendClass(showMoreCompany.value, props.formData.companyIds)
}
const showExpendClass = (showMoreCompany, data) => {
if (!showMoreCompany) {
if (data && data.length > 14) {
showExpendText.value = '展开'
return 'company-style'
}
} else {
showExpendText.value = '收缩'
return ''
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-empty__description) {
margin-top: 0;
}
.company-style {
//width: 98%;
min-height: 30px;
max-height: 60px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -53px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -26px !important;
}
}
}
</style>
<template>
<div v-loading="loading" :style="type==='singleDetail'?'padding: 0 30px':''">
<baseTitle title="需求征集信息" v-if="type!=='singleDetail'"></baseTitle>
<el-form :model="formData" >
<el-row gutter="20" style="margin-left: 5px">
<el-col :span="6">
<el-form-item label="征集名称">
<span>{{ formData.requirementName }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="征集类型">
<span>{{ formData.collectType }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="需求上报截止时间">
<span>{{ formData.deadline }}</span>
</el-form-item>
</el-col>
<el-col :span="6" v-if="formData.isSpecialFund">
<el-form-item label="专项资金名称">
<span>{{ formData.specialFund }}</span>
</el-form-item>
</el-col>
<el-col :span="24" v-if="type==='singleDetail'">
<el-form-item label="征集公司">
<span :class="showExpendClass(showMoreCompany,formData.companyIds)">{{
getCompanyName(formData.companyIds)
}}</span>
<div style="color: #2a99ff;text-align: center;width: 100%;font-size: 15px;cursor: pointer"
@click="handleExpend">{{ showExpendText }}
</div>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-bottom: -15px">
<el-form-item label="征集说明">
<div v-if="formData.collectExplain" v-html="formData.collectExplain" style="white-space: pre-wrap;">
</div>
<div v-else>--</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件文件" style="margin-bottom: 0"></baseTitle>
<file-component title="" tag="需求征集"
v-model:value="formData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/>
</el-col>
<el-col :span="24" style="margin-top: -15px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record" style="margin-top: -15px">
<div class="approval-title">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266; --el-switch-off-color:#cecdcd"
/>
</div>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="collectionProcess"/>
</div>
</div>
</el-form>
</div>
</template>
<script setup lang="jsx">
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {downloadFile} from "@/api/project-demand";
const emit = defineEmits(['update:value'])
const showExpendText = ref('')
const showMoreCompany = ref(false)
const props = defineProps({
formData: {
type: Array,
default: []
},
data: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
companyOption: {
type: Array,
default: []
},
loading: {
type: Boolean,
default: false
},
fileListShow: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
value: {
type: String,
default: ''
}
})
const changeDiagram = ref(false)
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const getCompanyName = (data) => {
if (data) {
return data.join('')
}
}
const handleExpend = () => {
showMoreCompany.value = !showMoreCompany.value;
showExpendClass(showMoreCompany.value, props.formData.companyIds)
}
const showExpendClass = (showMoreCompany, data) => {
if (!showMoreCompany) {
if (data && data.length > 14) {
showExpendText.value = '展开'
return 'company-style'
}
} else {
showExpendText.value = '收缩'
return ''
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-empty__description) {
margin-top: 0;
}
.company-style {
//width: 98%;
min-height: 30px;
max-height: 60px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -53px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -26px !important;
}
}
}
</style>

View File

@@ -1,424 +1,424 @@
<template>
<el-dialog custom-class="custom-dialog" class="border" :border="false" width="1000px" style="height: 676px"
:title="title" :show-close="false" :visible.sync="visible" v-model="visible" append-to-body :close-on-click-modal="false" @close="closeDialog">
<div class="picker">
<div class="candidate" v-loading="loading">
<el-input v-model="filterText"
clearable placeholder="输入公司进行搜索">
<template #append>
<el-button @click="getList()">搜索</el-button>
</template>
</el-input>
<fvCheckbox style="margin-left: 10px" :options="checkOptions" v-model="checkList" @change="checkBoxChange"/>
<!-- 人员选择 -->
<el-empty :image-size="100" description="似乎没有数据" v-show="dataList.length === 0"/>
<el-scrollbar style="height:87%;">
<div class="tree">
<el-tree :data="dataList" ref="tree" :props="defaultProps" empty-text="" node-key="value"
:show-checkbox="showCheckbox" highlight-current default-expand-all
:default-checked-keys="defaultChecked" :disabled="disabled"
:check-strictly="!checkStrictly" @node-click="(node,check)=>handleNodeClick(node,check)"
@check-change="handleCheckClick" :filter-node-method="filterNode">
<template #default="{ node, data }">
<div class="tree-node">
<div style="display: flex;align-items: center;padding: 3px 0">
{{ node.label }}
</div>
</div>
</template>
</el-tree>
</div>
</el-scrollbar>
</div>
<div class="selected">
<div class="count">
<span>已选 {{ selectList.length }} 项</span>
<span @click="clearSelected">清空</span>
</div>
<div class="org-items">
<el-empty :image-size="100" description="请点击左侧列表选择数据" v-show="selectList.length === 0"/>
<div v-for="(selectItem, selectIndex) in selectList" :key="selectIndex" class="org-item">
{{ selectItem.label }}
<el-icon @click="removeSingleSelected(selectItem)" size="20" style="margin-left: 10px;cursor: pointer;">
<CircleClose/>
</el-icon>
</div>
</div>
</div>
</div>
<div class="footer">
<el-button size="mini" @click="cancelUserPicker">取 消</el-button>
<el-button size="mini" color="#DED0B2" @click="selectConfirm">确 定</el-button>
</div>
</el-dialog>
</template>
<script setup>
import {ElMessageBox} from "element-plus";
import {getSubCompOpt} from "@/api/user/user";
const checkList = ref(['1'])
const checkStrictly = ref(false)
const isExpand = ref('展开')
const expandedKeys = ref(['-1']);
const checkOptions = ref([
{
label: isExpand.value,
value: '1'
},
// {
// label: '父子联动',
// value: '2'
// },
])
const props = defineProps({
value: {
type: Array,
default: () => {
return [];
}
},
multiple: { //是否多选
default: true,
type: Boolean
},
showCheckbox: { //是否显示左侧选择框
default: true,
type: Boolean
}
});
let selectItem = reactive({
type: -1,
value: "0"
});
const visible = ref(false);
const loading = ref(false);
const title = ref("请选择");
const selectList = ref([]);
const filterText = ref("");
const dataList = ref([]);
const defaultChecked = ref([]);
const tree = ref([]);
const defaultProps = {
value: "value",
label: "label",
children: "children",
disabled: "disabled",
};
const isRemoveSingleSelected = ref(false);
const emit = defineEmits(['update:modelValue'])
const _value = computed({
get() {
return props.value;
},
set(value) {
emit('update:modelValue', value)
}
});
watch(() => filterText.value, (newVal) => {
tree.value.filter(newVal);
});
const closeDialog=()=>{
console.log('关闭')
visible.value=false
filterText.value=''
}
const checkBoxChange = (val) => {
checkStrictly.value = val.includes('2')
let nodes = tree.value.store.nodesMap
if (val.includes('1')) {
for (const node in nodes) {
nodes[node].expanded = true;
}
isExpand.value = '折叠'
} else {
for (const node in nodes) {
nodes[node].expanded = false;
}
isExpand.value = '展开'
}
}
const getList = () => {
getSubCompOpt().then(res => {
dataList.value = [
{
label: "所有公司",
value: -1,
},
...res.data
]
});
};
//通过关键字过滤树节点
const filterNode = (value, data) => {
//通过关键字过滤树节点
if (!value) return true;
return data.label.indexOf(value) !== -1;
};
//用于用户选择
const show = () => {
//用于弹开部门选择
visible.value = true;
selectList.value = _value.value
defaultChecked.value = _value.value.map(item => item.value)
getList()
};
const updateTreeCheck = (list, flag) => {
list.forEach(item => {
if (item.value !== -1) {
tree.value.setChecked(item, flag)
if (item.children !== undefined) {
updateTreeCheck(item.children, flag)
}
}
})
}
const handleCheckClick = (data, checked) => {
if (data.value == -1) {
if(checked){
updateTreeCheck(dataList.value, false)
tree.value.setChecked(data,true);
}
}
if(tree.value.getCheckedKeys().length>1&&tree.value.getCheckedKeys().indexOf(-1)!==-1){
tree.value.setChecked(-1,false);
}
// 左侧有选择框 + 多选
if (props.multiple) {
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === data.value) {
selectList.value.splice(i, 1);
break;
}
}
if (checked) {
// if (data.children === undefined) {
selectList.value.push(data);
// }
} else if (data === "1") {
tree.value.setCheckedKeys([]);
selectList.value = [];
}
} else {// 左侧有选择框 + 单选
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === data.value) {
selectList.value.splice(i, 1);
break;
}
}
if (checked) {
tree.value.setCheckedNodes([data]);
selectList.value = [data];
} else if (data === "1") {
selectList.value = [];
tree.value.setCheckedKeys([]);
}
}
};
const handleNodeClick = (node, check) => {
if (check.isLeaf !== false) {
if (props.multiple) {
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === node.value) {
selectList.value.splice(i, 1);
break;
}
}
check.checked = true;
selectList.value.push(node);
} else {
check.checked = true;
selectList.value = [node];
}
}
// _value.value = selectList.value
};
const removeSingleSelected = (selectItem) => {
//左侧无选择框时,右侧显示×
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === selectItem.value) {
tree.value.setChecked(selectList.value[i].value, false);
selectList.value.splice(i, 1);
break;
}
}
if (props.showCheckbox) {
// 左侧有选择框 + 单选
if (props.multiple === false) {
tree.value.setCheckedKeys([]);
}
}
// isRemoveSingleSelected.value = true
};
const clearSelected = () => {
//清空
ElMessageBox.confirm("您确定要清空已选中的项?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
// isRemoveSingleSelected.value = true
if (!props.showCheckbox) {
selectList.value = [];
} else {
handleCheckClick("1");
}
});
};
const cancelUserPicker = () => {
if (localStorage.getItem('originallyCompanySelectedList')) {
selectList.value = JSON.parse(localStorage.getItem('originallyCompanySelectedList'))
}else{
selectList.value=[]
handleCheckClick("1");
}
emit("cancelOrClear", selectList.value);
visible.value = false;
// nextTick(()=>{
// isRemoveSingleSelected.value=false
// })
}
const selectConfirm = () => {
//确定按钮
emit("ok", selectList.value);
dataList.value = []
visible.value = false;
localStorage.setItem('originallyCompanySelectedList', JSON.stringify(selectList.value))
};
defineExpose({
show
});
getList()
</script>
<style lang="scss" scoped>
$containWidth: 480px;
:deep(.tree) {
.el-tree-node__content {
height: 34px;
.tree-node {
font-size: 18px;
}
}
//.el-tree-node {
// .is-leaf + .el-checkbox .el-checkbox__inner {
// display: inline-block;
// }
//
// .el-checkbox .el-checkbox__inner {
// display: none;
// }
//}
}
.footer {
float: right;
margin-top: 10px;
}
.picker {
height: 560px;
position: relative;
text-align: left;
.candidate {
position: absolute;
display: block;
width: $containWidth;
height: 100%;
border: 1px solid #e8e8e8;
:deep(.el-input) {
height: 40px;
.el-input__inner, .el-input-group__append {
font-size: 16px;
}
}
}
.selected {
right: 0;
top: 0;
position: absolute;
display: inline-block;
width: 450px;
height: 100%;
border: 1px solid #e8e8e8;
.count {
width: 100%;
padding: 10px;
display: inline-block;
border-bottom: 1px solid #e8e8e8;
margin-bottom: 5px;
font-size: 16px;
> span:nth-child(2) {
float: right;
color: #c75450;
cursor: pointer;
margin-left: 10px;
}
}
.org-items {
overflow-y: auto;
height: 90%;
.el-icon-close {
position: absolute;
right: 5px;
cursor: pointer;
font-size: larger;
}
.org-item {
margin: 0 5px;
border-radius: 5px;
position: relative;
padding: 7px 5px;
display: flex;
align-items: center;
font-size: 16px;
&:hover {
background: #f1f1f1;
}
> span {
margin-left: 5px;
}
}
}
}
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
::-webkit-scrollbar {
float: right;
width: 4px;
height: 4px;
background-color: white;
}
::-webkit-scrollbar-thumb {
border-radius: 16px;
background-color: #efefef;
}
</style>
<template>
<el-dialog custom-class="custom-dialog" class="border" :border="false" width="1000px" style="height: 676px"
:title="title" :show-close="false" :visible.sync="visible" v-model="visible" append-to-body :close-on-click-modal="false" @close="closeDialog">
<div class="picker">
<div class="candidate" v-loading="loading">
<el-input v-model="filterText"
clearable placeholder="输入公司进行搜索">
<template #append>
<el-button @click="getList()">搜索</el-button>
</template>
</el-input>
<fvCheckbox style="margin-left: 10px" :options="checkOptions" v-model="checkList" @change="checkBoxChange"/>
<!-- 人员选择 -->
<el-empty :image-size="100" description="似乎没有数据" v-show="dataList.length === 0"/>
<el-scrollbar style="height:87%;">
<div class="tree">
<el-tree :data="dataList" ref="tree" :props="defaultProps" empty-text="" node-key="value"
:show-checkbox="showCheckbox" highlight-current default-expand-all
:default-checked-keys="defaultChecked" :disabled="disabled"
:check-strictly="!checkStrictly" @node-click="(node,check)=>handleNodeClick(node,check)"
@check-change="handleCheckClick" :filter-node-method="filterNode">
<template #default="{ node, data }">
<div class="tree-node">
<div style="display: flex;align-items: center;padding: 3px 0">
{{ node.label }}
</div>
</div>
</template>
</el-tree>
</div>
</el-scrollbar>
</div>
<div class="selected">
<div class="count">
<span>已选 {{ selectList.length }} 项</span>
<span @click="clearSelected">清空</span>
</div>
<div class="org-items">
<el-empty :image-size="100" description="请点击左侧列表选择数据" v-show="selectList.length === 0"/>
<div v-for="(selectItem, selectIndex) in selectList" :key="selectIndex" class="org-item">
{{ selectItem.label }}
<el-icon @click="removeSingleSelected(selectItem)" size="20" style="margin-left: 10px;cursor: pointer;">
<CircleClose/>
</el-icon>
</div>
</div>
</div>
</div>
<div class="footer">
<el-button size="mini" @click="cancelUserPicker">取 消</el-button>
<el-button size="mini" color="#DED0B2" @click="selectConfirm">确 定</el-button>
</div>
</el-dialog>
</template>
<script setup>
import {ElMessageBox} from "element-plus";
import {getSubCompOpt} from "@/api/user/user";
const checkList = ref(['1'])
const checkStrictly = ref(false)
const isExpand = ref('展开')
const expandedKeys = ref(['-1']);
const checkOptions = ref([
{
label: isExpand.value,
value: '1'
},
// {
// label: '父子联动',
// value: '2'
// },
])
const props = defineProps({
value: {
type: Array,
default: () => {
return [];
}
},
multiple: { //是否多选
default: true,
type: Boolean
},
showCheckbox: { //是否显示左侧选择框
default: true,
type: Boolean
}
});
let selectItem = reactive({
type: -1,
value: "0"
});
const visible = ref(false);
const loading = ref(false);
const title = ref("请选择");
const selectList = ref([]);
const filterText = ref("");
const dataList = ref([]);
const defaultChecked = ref([]);
const tree = ref([]);
const defaultProps = {
value: "value",
label: "label",
children: "children",
disabled: "disabled",
};
const isRemoveSingleSelected = ref(false);
const emit = defineEmits(['update:modelValue'])
const _value = computed({
get() {
return props.value;
},
set(value) {
emit('update:modelValue', value)
}
});
watch(() => filterText.value, (newVal) => {
tree.value.filter(newVal);
});
const closeDialog=()=>{
console.log('关闭')
visible.value=false
filterText.value=''
}
const checkBoxChange = (val) => {
checkStrictly.value = val.includes('2')
let nodes = tree.value.store.nodesMap
if (val.includes('1')) {
for (const node in nodes) {
nodes[node].expanded = true;
}
isExpand.value = '折叠'
} else {
for (const node in nodes) {
nodes[node].expanded = false;
}
isExpand.value = '展开'
}
}
const getList = () => {
getSubCompOpt().then(res => {
dataList.value = [
{
label: "所有公司",
value: -1,
},
...res.data
]
});
};
//通过关键字过滤树节点
const filterNode = (value, data) => {
//通过关键字过滤树节点
if (!value) return true;
return data.label.indexOf(value) !== -1;
};
//用于用户选择
const show = () => {
//用于弹开部门选择
visible.value = true;
selectList.value = _value.value
defaultChecked.value = _value.value.map(item => item.value)
getList()
};
const updateTreeCheck = (list, flag) => {
list.forEach(item => {
if (item.value !== -1) {
tree.value.setChecked(item, flag)
if (item.children !== undefined) {
updateTreeCheck(item.children, flag)
}
}
})
}
const handleCheckClick = (data, checked) => {
if (data.value == -1) {
if(checked){
updateTreeCheck(dataList.value, false)
tree.value.setChecked(data,true);
}
}
if(tree.value.getCheckedKeys().length>1&&tree.value.getCheckedKeys().indexOf(-1)!==-1){
tree.value.setChecked(-1,false);
}
// 左侧有选择框 + 多选
if (props.multiple) {
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === data.value) {
selectList.value.splice(i, 1);
break;
}
}
if (checked) {
// if (data.children === undefined) {
selectList.value.push(data);
// }
} else if (data === "1") {
tree.value.setCheckedKeys([]);
selectList.value = [];
}
} else {// 左侧有选择框 + 单选
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === data.value) {
selectList.value.splice(i, 1);
break;
}
}
if (checked) {
tree.value.setCheckedNodes([data]);
selectList.value = [data];
} else if (data === "1") {
selectList.value = [];
tree.value.setCheckedKeys([]);
}
}
};
const handleNodeClick = (node, check) => {
if (check.isLeaf !== false) {
if (props.multiple) {
//不添加重复的数据到右边
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === node.value) {
selectList.value.splice(i, 1);
break;
}
}
check.checked = true;
selectList.value.push(node);
} else {
check.checked = true;
selectList.value = [node];
}
}
// _value.value = selectList.value
};
const removeSingleSelected = (selectItem) => {
//左侧无选择框时,右侧显示×
for (let i = 0; i < selectList.value.length; i++) {
if (selectList.value[i].value === selectItem.value) {
tree.value.setChecked(selectList.value[i].value, false);
selectList.value.splice(i, 1);
break;
}
}
if (props.showCheckbox) {
// 左侧有选择框 + 单选
if (props.multiple === false) {
tree.value.setCheckedKeys([]);
}
}
// isRemoveSingleSelected.value = true
};
const clearSelected = () => {
//清空
ElMessageBox.confirm("您确定要清空已选中的项?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
// isRemoveSingleSelected.value = true
if (!props.showCheckbox) {
selectList.value = [];
} else {
handleCheckClick("1");
}
});
};
const cancelUserPicker = () => {
if (localStorage.getItem('originallyCompanySelectedList')) {
selectList.value = JSON.parse(localStorage.getItem('originallyCompanySelectedList'))
}else{
selectList.value=[]
handleCheckClick("1");
}
emit("cancelOrClear", selectList.value);
visible.value = false;
// nextTick(()=>{
// isRemoveSingleSelected.value=false
// })
}
const selectConfirm = () => {
//确定按钮
emit("ok", selectList.value);
dataList.value = []
visible.value = false;
localStorage.setItem('originallyCompanySelectedList', JSON.stringify(selectList.value))
};
defineExpose({
show
});
getList()
</script>
<style lang="scss" scoped>
$containWidth: 480px;
:deep(.tree) {
.el-tree-node__content {
height: 34px;
.tree-node {
font-size: 18px;
}
}
//.el-tree-node {
// .is-leaf + .el-checkbox .el-checkbox__inner {
// display: inline-block;
// }
//
// .el-checkbox .el-checkbox__inner {
// display: none;
// }
//}
}
.footer {
float: right;
margin-top: 10px;
}
.picker {
height: 560px;
position: relative;
text-align: left;
.candidate {
position: absolute;
display: block;
width: $containWidth;
height: 100%;
border: 1px solid #e8e8e8;
:deep(.el-input) {
height: 40px;
.el-input__inner, .el-input-group__append {
font-size: 16px;
}
}
}
.selected {
right: 0;
top: 0;
position: absolute;
display: inline-block;
width: 450px;
height: 100%;
border: 1px solid #e8e8e8;
.count {
width: 100%;
padding: 10px;
display: inline-block;
border-bottom: 1px solid #e8e8e8;
margin-bottom: 5px;
font-size: 16px;
> span:nth-child(2) {
float: right;
color: #c75450;
cursor: pointer;
margin-left: 10px;
}
}
.org-items {
overflow-y: auto;
height: 90%;
.el-icon-close {
position: absolute;
right: 5px;
cursor: pointer;
font-size: larger;
}
.org-item {
margin: 0 5px;
border-radius: 5px;
position: relative;
padding: 7px 5px;
display: flex;
align-items: center;
font-size: 16px;
&:hover {
background: #f1f1f1;
}
> span {
margin-left: 5px;
}
}
}
}
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
::-webkit-scrollbar {
float: right;
width: 4px;
height: 4px;
background-color: white;
}
::-webkit-scrollbar-thumb {
border-radius: 16px;
background-color: #efefef;
}
</style>

View File

@@ -1,255 +1,255 @@
<template>
<el-button color="#DED0B2" style="float: right;margin: 0 10px 10px 0" @click="exportTable">导出</el-button>
<el-table ref="reportTable" :data="tableData" style="width: 100%;height: 479px"
:span-method="objectSpanMethod" v-loading="loading">
<el-table-column label="四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表" align="center">
<el-table-column v-for="column in columnInfo" :prop="column.prop" :label="column.label" align="center"
:fixed="(!column.children) ? ((column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') ? 'right' : 'left') : false"
:width="(column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') ? 160:130">
<template #default="scope">
<template v-if="column.children">
<el-table-column v-for="childColumn in column.children"
:prop="column.prop + '.'+ childColumn.prop"
:label="childColumn.label"
:width="childColumn.prop === 'subtotal' ? 160 : 130">
<template #default="columnScope">
<template v-if="(tableData.length -1) !== columnScope.$index">
{{
columnScope.row[column.prop][childColumn.prop] ? columnScope.row[column.prop][childColumn.prop] : '/'
}}
</template>
<template v-else>
{{ columnScope.row[column.prop][childColumn.prop] }}
</template>
</template>
</el-table-column>
</template>
<template v-else>
<!--分摊金额合计与分摊金额总计计算-->
<template
v-if="(column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') && (tableData.length -1) !== scope.$index">
{{ getTotalSeparation(scope.row, column.prop) }}
</template>
<template
v-else-if="(tableData.length -1) === scope.$index && (column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost')">
{{ getTotalSummary(scope.row, column.prop) }}
</template>
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</template>
</el-table-column>
</el-table-column>
</el-table>
</template>
<script setup lang="jsx">
import {getResearchUser, getAllocationDetails} from "@/api/expense-manage";
import {exportExcel} from "@/utils/export-excel";
import {ElNotification} from "element-plus";
const route = useRoute()
const tableIns = ref()
const reportTable = ref({});
const columnInfo = ref([])
const monthConcat = new Map()
const tableData = ref([])
const loading = ref(false)
const researchOptions = ref([])
const objectSpanMethod = ({row, column, rowIndex, columnIndex}) => {
if (columnIndex === 0) {
if (monthConcat.has(rowIndex)) {
return {
rowspan: monthConcat.get(rowIndex),
colspan: 1,
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
} else {
let length = Object.keys(row).length
// console.log(length)
if (length > 5) {
if (concatColumn(columnIndex, length, rowIndex)) {
if (rowIndex % 5 === 0) {
return {
rowspan: 5,
colspan: 1,
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
}
}
}
}
const getTotalSeparation = (row, prop) => {
let totalSeparation = 0.00
for (let key of Object.keys(row)) {
if (key.startsWith('personInfo')) {
let value = prop === 'totalSeparation' ? (row[key].separationAmount ? row[key].separationAmount : 0) : row[key].subtotal
if ("/" !== value) {
try {
totalSeparation += parseFloat(value)
} catch (e) {
}
}
}
}
if (totalSeparation !== 0) {
return totalSeparation.toFixed(2);
} else {
return "/"
}
}
const getTotalSummary = (row, prop) => {
let key;
if (prop === 'totalSeparation') {
key = 'separationAmount'
} else {
key = 'subtotal'
}
let result = 0
for (const rowKey of Object.keys(row)) {
if (rowKey.startsWith('personInfo')) {
let value = row[rowKey][key]
if (value && "/" !== value) {
try {
result += parseFloat(value)
} catch (e) {
}
}
}
}
return result.toFixed(2);
}
const concatColumn = (columnIndex, length, rowIndex) => {
if (rowIndex === tableData.value.length - 1) {
return false
}
let columnLength = 5 + (length - 5) * 5
if (columnIndex === 1
|| columnIndex === columnLength - 1) {
return true;
}
for (let i = 0; i < length - 5; i++) {
if (columnIndex === 4 + (i * 5)
|| columnIndex === 5 + (i * 5)
|| columnIndex === 7 + (i * 5)) {
return true
}
}
return false
}
const init = () => {
loading.value = true
getAllocationDetails(route.query.id).then(res => {
if (res.code !== 1000) {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
columnInfo.value = res.data.columns
let tableDataLet = res.data.tableData;
let personInfoKey = []
columnInfo.value.forEach(item => {
if (item.prop.startsWith('personInfo')) {
personInfoKey.push(item.prop)
}
})
tableData.value = []
let rowIndex = 0;
let summary = {
month: "",
salaryType: '',
projectName: "合计",
totalSeparation: 10,
totalSeparationCost: 10
}
for (const key of personInfoKey) {
summary[key] = {
researchDuration: "",
separationAmount: 0,
subtotal: 0,
wagesPayable: "",
workday: "",
}
}
tableDataLet.forEach((tableDatum) => {
let rowspan = tableDatum.rows.length * 5
monthConcat.set(rowIndex, rowspan)
rowIndex += rowspan
for (const tableDatumElement of tableDatum.rows) {
tableData.value = tableData.value.concat(tableDatumElement)
let row = tableDatumElement[0]
for (const key of personInfoKey) {
try {
if (row[key].subtotal && '/' !== row[key].subtotal) {
summary[key].subtotal += parseFloat(row[key].subtotal)
}
} catch (e) {
}
}
}
})
for (const row of tableData.value) {
for (const key of personInfoKey) {
try {
if (row[key].separationAmount && '/' !== row[key].separationAmount) {
summary[key].separationAmount += parseFloat(row[key].separationAmount)
}
} catch (e) {
}
}
}
for (const key of personInfoKey) {
summary[key].subtotal = summary[key].subtotal.toFixed(2)
summary[key].separationAmount = summary[key].separationAmount.toFixed(2)
}
monthConcat.set(rowIndex, 1)
tableData.value.push(summary)
loading.value = false
})
}
const getResearchOptions = async () => {
const res = await getResearchUser()
researchOptions.value = res.data
}
const search = (val) => {
tableConfig.params = {
allocationId: route.query.id,
...val
}
tableIns.value.refresh()
}
getResearchOptions()
init()
const exportTable = () => {
const $e = reportTable.value.$el
let $table = $e.querySelector('.el-table__fixed')
if (!$table) {
$table = $e
}
exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表", 2)
}
</script>
<template>
<el-button color="#DED0B2" style="float: right;margin: 0 10px 10px 0" @click="exportTable">导出</el-button>
<el-table ref="reportTable" :data="tableData" style="width: 100%;height: 479px"
:span-method="objectSpanMethod" v-loading="loading">
<el-table-column label="四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表" align="center">
<el-table-column v-for="column in columnInfo" :prop="column.prop" :label="column.label" align="center"
:fixed="(!column.children) ? ((column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') ? 'right' : 'left') : false"
:width="(column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') ? 160:130">
<template #default="scope">
<template v-if="column.children">
<el-table-column v-for="childColumn in column.children"
:prop="column.prop + '.'+ childColumn.prop"
:label="childColumn.label"
:width="childColumn.prop === 'subtotal' ? 160 : 130">
<template #default="columnScope">
<template v-if="(tableData.length -1) !== columnScope.$index">
{{
columnScope.row[column.prop][childColumn.prop] ? columnScope.row[column.prop][childColumn.prop] : '/'
}}
</template>
<template v-else>
{{ columnScope.row[column.prop][childColumn.prop] }}
</template>
</template>
</el-table-column>
</template>
<template v-else>
<!--分摊金额合计与分摊金额总计计算-->
<template
v-if="(column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost') && (tableData.length -1) !== scope.$index">
{{ getTotalSeparation(scope.row, column.prop) }}
</template>
<template
v-else-if="(tableData.length -1) === scope.$index && (column.prop === 'totalSeparation' || column.prop === 'totalSeparationCost')">
{{ getTotalSummary(scope.row, column.prop) }}
</template>
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</template>
</el-table-column>
</el-table-column>
</el-table>
</template>
<script setup lang="jsx">
import {getResearchUser, getAllocationDetails} from "@/api/expense-manage";
import {exportExcel} from "@/utils/export-excel";
import {ElNotification} from "element-plus";
const route = useRoute()
const tableIns = ref()
const reportTable = ref({});
const columnInfo = ref([])
const monthConcat = new Map()
const tableData = ref([])
const loading = ref(false)
const researchOptions = ref([])
const objectSpanMethod = ({row, column, rowIndex, columnIndex}) => {
if (columnIndex === 0) {
if (monthConcat.has(rowIndex)) {
return {
rowspan: monthConcat.get(rowIndex),
colspan: 1,
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
} else {
let length = Object.keys(row).length
// console.log(length)
if (length > 5) {
if (concatColumn(columnIndex, length, rowIndex)) {
if (rowIndex % 5 === 0) {
return {
rowspan: 5,
colspan: 1,
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
}
}
}
}
const getTotalSeparation = (row, prop) => {
let totalSeparation = 0.00
for (let key of Object.keys(row)) {
if (key.startsWith('personInfo')) {
let value = prop === 'totalSeparation' ? (row[key].separationAmount ? row[key].separationAmount : 0) : row[key].subtotal
if ("/" !== value) {
try {
totalSeparation += parseFloat(value)
} catch (e) {
}
}
}
}
if (totalSeparation !== 0) {
return totalSeparation.toFixed(2);
} else {
return "/"
}
}
const getTotalSummary = (row, prop) => {
let key;
if (prop === 'totalSeparation') {
key = 'separationAmount'
} else {
key = 'subtotal'
}
let result = 0
for (const rowKey of Object.keys(row)) {
if (rowKey.startsWith('personInfo')) {
let value = row[rowKey][key]
if (value && "/" !== value) {
try {
result += parseFloat(value)
} catch (e) {
}
}
}
}
return result.toFixed(2);
}
const concatColumn = (columnIndex, length, rowIndex) => {
if (rowIndex === tableData.value.length - 1) {
return false
}
let columnLength = 5 + (length - 5) * 5
if (columnIndex === 1
|| columnIndex === columnLength - 1) {
return true;
}
for (let i = 0; i < length - 5; i++) {
if (columnIndex === 4 + (i * 5)
|| columnIndex === 5 + (i * 5)
|| columnIndex === 7 + (i * 5)) {
return true
}
}
return false
}
const init = () => {
loading.value = true
getAllocationDetails(route.query.id).then(res => {
if (res.code !== 1000) {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
columnInfo.value = res.data.columns
let tableDataLet = res.data.tableData;
let personInfoKey = []
columnInfo.value.forEach(item => {
if (item.prop.startsWith('personInfo')) {
personInfoKey.push(item.prop)
}
})
tableData.value = []
let rowIndex = 0;
let summary = {
month: "",
salaryType: '',
projectName: "合计",
totalSeparation: 10,
totalSeparationCost: 10
}
for (const key of personInfoKey) {
summary[key] = {
researchDuration: "",
separationAmount: 0,
subtotal: 0,
wagesPayable: "",
workday: "",
}
}
tableDataLet.forEach((tableDatum) => {
let rowspan = tableDatum.rows.length * 5
monthConcat.set(rowIndex, rowspan)
rowIndex += rowspan
for (const tableDatumElement of tableDatum.rows) {
tableData.value = tableData.value.concat(tableDatumElement)
let row = tableDatumElement[0]
for (const key of personInfoKey) {
try {
if (row[key].subtotal && '/' !== row[key].subtotal) {
summary[key].subtotal += parseFloat(row[key].subtotal)
}
} catch (e) {
}
}
}
})
for (const row of tableData.value) {
for (const key of personInfoKey) {
try {
if (row[key].separationAmount && '/' !== row[key].separationAmount) {
summary[key].separationAmount += parseFloat(row[key].separationAmount)
}
} catch (e) {
}
}
}
for (const key of personInfoKey) {
summary[key].subtotal = summary[key].subtotal.toFixed(2)
summary[key].separationAmount = summary[key].separationAmount.toFixed(2)
}
monthConcat.set(rowIndex, 1)
tableData.value.push(summary)
loading.value = false
})
}
const getResearchOptions = async () => {
const res = await getResearchUser()
researchOptions.value = res.data
}
const search = (val) => {
tableConfig.params = {
allocationId: route.query.id,
...val
}
tableIns.value.refresh()
}
getResearchOptions()
init()
const exportTable = () => {
const $e = reportTable.value.$el
let $table = $e.querySelector('.el-table__fixed')
if (!$table) {
$table = $e
}
exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表", 2)
}
</script>

View File

@@ -1,212 +1,212 @@
<template>
<el-form :label-position="labelAlign">
<el-form-item :label="title" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :style="{marginTop: '10px',marginLeft: tag!=='需求上报'?'15px':'0'}">
<file-upload @getFile="getOtherFile" v-if="fileListShow === 'EDIT'"/>
<!-- :style="{width:isOpenPrint?'610px': '100%'}" table-layout="auto" id="printTable"-->
<fvTable style="width:100%;" :height="tag=='项目立项'?'160':'160'" :style="{maxHeight:tag=='项目立项'?'160px':'160px',height:tag=='项目立项'?'160px':'160px'}" v-if="processViewer" :scrollbar-always-on="true" :tableConfig="tableConfig"
:data="_value" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-form>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</template>
<script setup lang="jsx">
import {downloadFile, deleteFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
import FilePreview from "../filePreview/index.vue";
const props = defineProps({
title: {
type: String,
default: ''
},
tag: {
type: String,
default: ''
},
fileNameTableWidth: {
type: String,
default: '400'
},
fileListShow: {
type: String,
default: 'READ'
},
value: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
labelAlign: {
type: String,
default: 'right'
},
//弹窗是否铺满全屏
fullscreen: {
type: Boolean,
default: false
},
//是否开始打印
isOpenPrint: {
type: Boolean,
default: false
},
})
const emit = defineEmits(['update:value'])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: 85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: props.fileNameTableWidth,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center',
showOverflowTooltip: false,
minWidth: props.fileNameTableWidth,
},
{
prop: 'size',
label: '文件大小',
align: 'center',
width: 150,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link>
{item.label}
</el-button>
))
}
{
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const getOtherFile = (val) => {
props.processViewer = false
let fileObj = compositeParam(val)
_value.value.push(fileObj)
nextTick(() => {
props.processViewer = true
})
}
const compositeParam = (item, type) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: props.tag
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const handleDelete = (row) => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
_value.value.splice(_value.value.findIndex((item) => item.fileId === row.fileId), 1);
}
});
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-table--fit ) {
height: 160px !important;
}
@media print {
//#printTable{
// width: 400px!important;
//}
}
</style>
<template>
<el-form :label-position="labelAlign">
<el-form-item :label="title" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :style="{marginTop: '10px',marginLeft: tag!=='需求上报'?'15px':'0'}">
<file-upload @getFile="getOtherFile" v-if="fileListShow === 'EDIT'"/>
<!-- :style="{width:isOpenPrint?'610px': '100%'}" table-layout="auto" id="printTable"-->
<fvTable style="width:100%;" :height="tag=='项目立项'?'160':'160'" :style="{maxHeight:tag=='项目立项'?'160px':'160px',height:tag=='项目立项'?'160px':'160px'}" v-if="processViewer" :scrollbar-always-on="true" :tableConfig="tableConfig"
:data="_value" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-form>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</template>
<script setup lang="jsx">
import {downloadFile, deleteFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
import FilePreview from "../filePreview/index.vue";
const props = defineProps({
title: {
type: String,
default: ''
},
tag: {
type: String,
default: ''
},
fileNameTableWidth: {
type: String,
default: '400'
},
fileListShow: {
type: String,
default: 'READ'
},
value: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
labelAlign: {
type: String,
default: 'right'
},
//弹窗是否铺满全屏
fullscreen: {
type: Boolean,
default: false
},
//是否开始打印
isOpenPrint: {
type: Boolean,
default: false
},
})
const emit = defineEmits(['update:value'])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: 85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: props.fileNameTableWidth,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center',
showOverflowTooltip: false,
minWidth: props.fileNameTableWidth,
},
{
prop: 'size',
label: '文件大小',
align: 'center',
width: 150,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link>
{item.label}
</el-button>
))
}
{
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const getOtherFile = (val) => {
props.processViewer = false
let fileObj = compositeParam(val)
_value.value.push(fileObj)
nextTick(() => {
props.processViewer = true
})
}
const compositeParam = (item, type) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: props.tag
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const handleDelete = (row) => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
_value.value.splice(_value.value.findIndex((item) => item.fileId === row.fileId), 1);
}
});
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-table--fit ) {
height: 160px !important;
}
@media print {
//#printTable{
// width: 400px!important;
//}
}
</style>

View File

@@ -1,242 +1,242 @@
<template>
<!-- <baseTitle title="审核意见"></baseTitle>-->
<!-- <fvForm :schema="schema" @getInstance="(e)=>form = e"></fvForm>-->
<div class="oper-page-btn" style="display: flex">
<el-button type="danger" @click="handleReject">驳回</el-button>
<el-button color="#DED0B2" @click="handleAgree">同意</el-button>
</div>
<div class="opinion-dialog">
<el-dialog v-model="showBackNode" title="请选择退回节点" width="400">
<el-table :data="taskUserOptionList" style="width: 100%"
:header-cell-style="{background:'#f5f7fa'}">
<el-table-column width="55">
<template #default="scope">
<el-radio
class="radio"
:label="scope.row"
v-model="backNode"
>&emsp;&emsp;&emsp;
</el-radio>
</template>
</el-table-column>
<el-table-column
prop="nodeName"
label="节点名称">
<!-- <template #default="scope">-->
<!-- {{scope.row.nodeId==-1?'发起节点':scope.row.nodeName}}-->
<!-- </template>-->
</el-table-column>
<el-table-column
prop="name"
label="操作者">
<template #default="scope">
<el-tag v-if="scope.row.userInfo" type="success">{{ scope.row.userInfo.name }}</el-tag>
</template>
</el-table-column>
</el-table>
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
<el-button type="danger" @click="rollbackHandler">确定</el-button>
<el-button @click="showBackNode=false">取消</el-button>
</div>
<!-- <el-select v-if="taskUserOptionList?.length>0" v-model="backNode" placeholder="请选择退回节点" clearable>-->
<!-- <el-option-->
<!-- v-for="item in taskUserOptionList"-->
<!-- :key="item.nodeId"-->
<!-- :label="item.nodeName + (item.userInfo ? ':' + item.userInfo.name : '')"-->
<!-- :value="item.nodeId">-->
<!-- </el-option>-->
<!-- </el-select>-->
<!-- <el-button type="danger" @click="rollbackHandler">确认</el-button>-->
</el-dialog>
</div>
</template>
<script setup lang="jsx">
import {ElNotification} from 'element-plus';
import {agreeTask, rejectTask} from "@/api/project-demand/index.js";
import {useTagsView} from '@/stores/tagsview.js'
const tagsViewStore = useTagsView()
const route = useRoute()
const router = useRouter()
const props = defineProps({
taskId: {
type: String,
default: ''
},
formData: {
type: Object,
default: {}
},
value: {
type: String,
default: ''
},
//退回节点选择框数据
taskUserOptionList: {
type: Array,
default: []
}
})
const form = ref()
const backNode = ref({})
const showBackNode = ref(false)
const schema = computed(() => {
return [
{
label: '',
prop: 'auditOpinion',
component: 'el-input',
colProps: {
span: 24
},
props: {
placeholder: '请输入审核意见',
type: 'textarea',
rows: 3
}
}
]
})
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const back = () => {
switch (route.name) {
case 'Initiation/detail':
router.push({name: 'Initiation'})
break;
case 'Filing/detail':
router.push({name: 'Filing'})
break;
case 'Implementation/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
if (route.query.step === '10') {
router.push({name: 'Summary'})
} else if (route.query.step === '20') {
router.push({name: 'Initiation'})
} else if (route.query.step === '40') {
router.push({name: 'Implementation'})
} else if (route.query.step === '50') {
router.push({name: 'Filing'})
} else if (route.query.step === '00') {
router.push({name: 'Requirement'})
}
}
break;
// case 'Summary/detail':
// if (route.query.source === 'home') {
// router.push('/home')
// } else {
// router.push({name: 'Summary'})
// }
// break;
case 'Requirement/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Requirement'})
}
break;
case 'Fund/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Fund'})
}
break;
case 'Share/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Expense/share'})
}
break;
case 'Phase/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Implementation'})
}
break;
}
}
// 驳回
const handleReject = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
showBackNode.value = true
backNode.value = {}
}
//回退节点
const rollbackHandler = async () => {
// const values = form.value.getValues()
const params = {
taskId: props.taskId,
// ...values
auditOpinion: _value.value,
rollBackId: backNode.value.nodeId
}
// console.log('params', params)
const res = await rejectTask(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
back()
}
}
const handleAgree = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
// const values = form.value.getValues()
const params = {
taskId: props.taskId,
formData: props.formData,
auditOpinion: _value.value
}
const res = await agreeTask(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
back()
}
}
</script>
<style lang="scss">
.opinion-dialog {
.el-dialog__body {
padding: 0 !important;
}
}
</style>
<template>
<!-- <baseTitle title="审核意见"></baseTitle>-->
<!-- <fvForm :schema="schema" @getInstance="(e)=>form = e"></fvForm>-->
<div class="oper-page-btn" style="display: flex">
<el-button type="danger" @click="handleReject">驳回</el-button>
<el-button color="#DED0B2" @click="handleAgree">同意</el-button>
</div>
<div class="opinion-dialog">
<el-dialog v-model="showBackNode" title="请选择退回节点" width="400">
<el-table :data="taskUserOptionList" style="width: 100%"
:header-cell-style="{background:'#f5f7fa'}">
<el-table-column width="55">
<template #default="scope">
<el-radio
class="radio"
:label="scope.row"
v-model="backNode"
>&emsp;&emsp;&emsp;
</el-radio>
</template>
</el-table-column>
<el-table-column
prop="nodeName"
label="节点名称">
<!-- <template #default="scope">-->
<!-- {{scope.row.nodeId==-1?'发起节点':scope.row.nodeName}}-->
<!-- </template>-->
</el-table-column>
<el-table-column
prop="name"
label="操作者">
<template #default="scope">
<el-tag v-if="scope.row.userInfo" type="success">{{ scope.row.userInfo.name }}</el-tag>
</template>
</el-table-column>
</el-table>
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
<el-button type="danger" @click="rollbackHandler">确定</el-button>
<el-button @click="showBackNode=false">取消</el-button>
</div>
<!-- <el-select v-if="taskUserOptionList?.length>0" v-model="backNode" placeholder="请选择退回节点" clearable>-->
<!-- <el-option-->
<!-- v-for="item in taskUserOptionList"-->
<!-- :key="item.nodeId"-->
<!-- :label="item.nodeName + (item.userInfo ? ':' + item.userInfo.name : '')"-->
<!-- :value="item.nodeId">-->
<!-- </el-option>-->
<!-- </el-select>-->
<!-- <el-button type="danger" @click="rollbackHandler">确认</el-button>-->
</el-dialog>
</div>
</template>
<script setup lang="jsx">
import {ElNotification} from 'element-plus';
import {agreeTask, rejectTask} from "@/api/project-demand/index.js";
import {useTagsView} from '@/stores/tagsview.js'
const tagsViewStore = useTagsView()
const route = useRoute()
const router = useRouter()
const props = defineProps({
taskId: {
type: String,
default: ''
},
formData: {
type: Object,
default: {}
},
value: {
type: String,
default: ''
},
//退回节点选择框数据
taskUserOptionList: {
type: Array,
default: []
}
})
const form = ref()
const backNode = ref({})
const showBackNode = ref(false)
const schema = computed(() => {
return [
{
label: '',
prop: 'auditOpinion',
component: 'el-input',
colProps: {
span: 24
},
props: {
placeholder: '请输入审核意见',
type: 'textarea',
rows: 3
}
}
]
})
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const back = () => {
switch (route.name) {
case 'Initiation/detail':
router.push({name: 'Initiation'})
break;
case 'Filing/detail':
router.push({name: 'Filing'})
break;
case 'Implementation/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
if (route.query.step === '10') {
router.push({name: 'Summary'})
} else if (route.query.step === '20') {
router.push({name: 'Initiation'})
} else if (route.query.step === '40') {
router.push({name: 'Implementation'})
} else if (route.query.step === '50') {
router.push({name: 'Filing'})
} else if (route.query.step === '00') {
router.push({name: 'Requirement'})
}
}
break;
// case 'Summary/detail':
// if (route.query.source === 'home') {
// router.push('/home')
// } else {
// router.push({name: 'Summary'})
// }
// break;
case 'Requirement/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Requirement'})
}
break;
case 'Fund/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Fund'})
}
break;
case 'Share/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Expense/share'})
}
break;
case 'Phase/detail':
if (route.query.source === 'home') {
router.push('/home')
} else {
router.push({name: 'Implementation'})
}
break;
}
}
// 驳回
const handleReject = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
showBackNode.value = true
backNode.value = {}
}
//回退节点
const rollbackHandler = async () => {
// const values = form.value.getValues()
const params = {
taskId: props.taskId,
// ...values
auditOpinion: _value.value,
rollBackId: backNode.value.nodeId
}
// console.log('params', params)
const res = await rejectTask(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
back()
}
}
const handleAgree = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
// const values = form.value.getValues()
const params = {
taskId: props.taskId,
formData: props.formData,
auditOpinion: _value.value
}
const res = await agreeTask(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
back()
}
}
</script>
<style lang="scss">
.opinion-dialog {
.el-dialog__body {
padding: 0 !important;
}
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,275 +1,275 @@
<template>
<div v-loading="loading" style="padding: 0 30px">
<baseTitle title="专项资金详情"></baseTitle>
<el-form :model="formData" ref="form" >
<el-row style="margin-left: 15px;margin-bottom: -18px">
<el-col :span="6">
<el-form-item label="专项名称">
<span>{{ formData.name }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="金额(元)">
<span>{{ toThousands(formData.fundAmount) }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="剩余金额(元)">
<span>{{ toThousands(formData.residualAmount) }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="专项资金情况说明" >
<div style="white-space: pre-wrap">{{formData.introduce}}
</div>
</el-form-item>
</el-col>
</el-row>
<el-row style="margin-bottom: -18px" class="projects">
<baseTitle title="关联项目" v-if="!data.taskId"></baseTitle>
<el-col :span="24" v-if="!data.taskId" >
<el-form-item >
<fvTable style="width: 100%;max-height:160px" height="160" v-if="showTable" :tableConfig="projectTable"
:data="formData.projects" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-col>
<baseTitle title="附件文件"></baseTitle>
<el-col :span="24">
<el-form-item>
<fvTable style="width: 100%;max-height: 160px;" height="160" v-if="showTable" :tableConfig="fileTable"
:data="formData.files" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-top: -18px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="auditOpinion">
<el-input
v-model="formData.auditOpinion"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record">
<div class="approval-title">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/>
</div>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="fundProcess"/>
</div>
</div>
</el-form>
<opinion v-if="data.taskId" :formData="data.formData" :taskId="data.taskId"
:taskUserOptionList="data.taskUserOptionList"
v-model:value="formData.auditOpinion"></opinion>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import {toThousands} from '@/utils/changePrice.js'
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {downloadFile} from "@/api/project-demand";
const changeDiagram = ref(false)
const emit = defineEmits(['getInfo', "update:formData"])
const form = ref()
const router = useRouter()
const props = defineProps({
formData: {
type: Array,
default: []
},
data: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
}, showTable: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
}
})
const projectTable = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'projectName',
label: '项目名称',
align: 'center',
width: 400
},
{
prop: 'specialFundAmount',
label: '项目金额',
align: 'center',
currentRender:({row})=>{
return <span>{toThousands(row.specialFundAmount)}</span>
}
},
{
prop: 'startTime',
label: '项目时间',
align: 'center'
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<el-button type="primary" link onClick={() => handleView(row)}>查看</el-button>
)
}
}
]
})
const fileTable = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: 400,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const handleView=(row)=>{
router.push({
name: 'Implementation/detail',
query: {
id: row.requirementId,
projectId: row.projectId,
step: '10'
}
})
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
watch(() => props.showTable, (newVal) => {
props.showTable = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
.projects{
:deep(.el-table--fit ) {
height: 300px !important;
}
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -20px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -10px !important;
}
}
}
</style>
<template>
<div v-loading="loading" style="padding: 0 30px">
<baseTitle title="专项资金详情"></baseTitle>
<el-form :model="formData" ref="form" >
<el-row style="margin-left: 15px;margin-bottom: -18px">
<el-col :span="6">
<el-form-item label="专项名称">
<span>{{ formData.name }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="金额(元)">
<span>{{ toThousands(formData.fundAmount) }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="剩余金额(元)">
<span>{{ toThousands(formData.residualAmount) }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="专项资金情况说明" >
<div style="white-space: pre-wrap">{{formData.introduce}}
</div>
</el-form-item>
</el-col>
</el-row>
<el-row style="margin-bottom: -18px" class="projects">
<baseTitle title="关联项目" v-if="!data.taskId"></baseTitle>
<el-col :span="24" v-if="!data.taskId" >
<el-form-item >
<fvTable style="width: 100%;max-height:160px" height="160" v-if="showTable" :tableConfig="projectTable"
:data="formData.projects" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-col>
<baseTitle title="附件文件"></baseTitle>
<el-col :span="24">
<el-form-item>
<fvTable style="width: 100%;max-height: 160px;" height="160" v-if="showTable" :tableConfig="fileTable"
:data="formData.files" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-top: -18px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="auditOpinion">
<el-input
v-model="formData.auditOpinion"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record">
<div class="approval-title">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/>
</div>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="fundProcess"/>
</div>
</div>
</el-form>
<opinion v-if="data.taskId" :formData="data.formData" :taskId="data.taskId"
:taskUserOptionList="data.taskUserOptionList"
v-model:value="formData.auditOpinion"></opinion>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import {toThousands} from '@/utils/changePrice.js'
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {downloadFile} from "@/api/project-demand";
const changeDiagram = ref(false)
const emit = defineEmits(['getInfo', "update:formData"])
const form = ref()
const router = useRouter()
const props = defineProps({
formData: {
type: Array,
default: []
},
data: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
}, showTable: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
}
})
const projectTable = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'projectName',
label: '项目名称',
align: 'center',
width: 400
},
{
prop: 'specialFundAmount',
label: '项目金额',
align: 'center',
currentRender:({row})=>{
return <span>{toThousands(row.specialFundAmount)}</span>
}
},
{
prop: 'startTime',
label: '项目时间',
align: 'center'
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<el-button type="primary" link onClick={() => handleView(row)}>查看</el-button>
)
}
}
]
})
const fileTable = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: 400,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const handleView=(row)=>{
router.push({
name: 'Implementation/detail',
query: {
id: row.requirementId,
projectId: row.projectId,
step: '10'
}
})
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
watch(() => props.showTable, (newVal) => {
props.showTable = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
.projects{
:deep(.el-table--fit ) {
height: 300px !important;
}
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -20px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -10px !important;
}
}
}
</style>

View File

@@ -1,442 +1,442 @@
<template>
<div class="detail-block" v-loading="loading">
<el-form :model="localFormData" ref="summaryForm" :rules="rules">
<baseTitle title="预期知识产权"></baseTitle>
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px">
<!-- <el-col :span="6">-->
<!-- <el-form-item label="预期成果形式" prop="resultForm">-->
<!-- <span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6">
<el-form-item label="知识产权归属" prop="intellectualProperty">
<span>{{
filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty)
}}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估专利(项)" prop="newPatent">
<span>{{ localFormData.newPatent }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
<span>{{ localFormData.softwareCopyright }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估技术标准(项)" prop="technicalNorms">
<span>{{ localFormData.technicalNorms }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新产品(项)" prop="newProduct">
<span>{{ localFormData.newProduct }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新工艺(项)" prop="newProcess">
<span>{{ localFormData.newProcess }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新装置(项)" prop="newDevice">
<span>{{ localFormData.newDevice }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新材料(项)" prop="newMaterials">
<span>{{ localFormData.newMaterials }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
<span>{{ localFormData.computerSoftware }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估论文论著(项)" prop="thesis">
<span>{{ localFormData.thesis }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估研究报告(项)" prop="researchReport">
<span>{{ localFormData.researchReport }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估商标(项)" prop="trademark">
<span>{{ localFormData.trademark }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估其他(项)" prop="other">
<span style="white-space: pre-wrap">{{ localFormData.other }}</span>
</el-form-item>
</el-col>
</el-row>
<baseTitle title="项目描述"></baseTitle>
<el-row gutter="20" style="margin-left: 5px;margin-bottom: -18px;">
<el-col :span="24">
<el-form-item label="现有业务描述" prop="serviceDescription">
<span style="white-space: pre-wrap">{{ localFormData.serviceDescription }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="建设目标描述" prop="contentDescription">
<span style="white-space: pre-wrap">{{ localFormData.contentDescription }}</span>
</el-form-item>
</el-col>
</el-row>
<baseTitle title="需求上报申请书" style="margin-bottom: -3px;"></baseTitle>
<!-- <el-row gutter="20" style="margin-bottom: -15px;">-->
<!-- <el-col :span="24">-->
<!-- <single-file-component tag="需求上报" v-model:value="localFormData.singleFile" :processViewer="processViewer"/>-->
<!-- &lt;!&ndash; <el-form-item>&ndash;&gt;-->
<!-- &lt;!&ndash; {{localFormData.singleFile}}&ndash;&gt;-->
<!-- &lt;!&ndash; <el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">&ndash;&gt;-->
<!-- &lt;!&ndash; {{ localFormData.singleFile?.originalFileName }}&ndash;&gt;-->
<!-- &lt;!&ndash; </el-button>&ndash;&gt;-->
<!-- &lt;!&ndash; </el-form-item>&ndash;&gt;-->
<!-- </el-col>-->
<!-- </el-row>-->
<!--/* <baseTitle title="附件文件" style="margin-bottom: 0"></baseTitle>*/-->
<el-row gutter="20" style="margin-bottom: -18px;">
<el-col :span="24" class="file-table-style">
<file-component tag="需求上报"
v-model:value="localFormData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/>
</el-col>
<el-col :span="24" style="margin-top: -15px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
<div v-if="data.state==='5'" style="margin-bottom: 15px">
<baseTitle title="前置流程" v-if="localFormData.preProcess"></baseTitle>
<div style="display: flex;align-items: center;flex-wrap: wrap;">
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
<a :href="item.baseUrl" target="_blank"
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
v-if="index != localFormData.preProcess.length -1"></span>
</a>
</div>
</div>
</div>
<div v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<!-- <baseTitle title="前置流程"></baseTitle>-->
<!-- <select-pre-process :formData="localFormData"/>-->
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record">
<div class="approval-title" style="margin-top: -12px">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/>
</div>
<el-button color="#DED0B2" style="margin-left: 10px"
@click="handleCarbonCopy()">立即抄送
</el-button>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:step="'report'"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="summaryProcess"/>
</div>
</div>
</el-form>
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
@cancelOrClear="carbonCopyUserPickerOk"/>
<div class="oper-page-btn" v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<el-button type="danger" @click="handleRejectPlan">驳回年度计划</el-button>
<el-button color="#DED0B2" @click="handleAgreePlan">通过年度计划</el-button>
</div>
</div>
</template>
<script setup lang="jsx">
import {toThousands} from '@/utils/changePrice.js'
import {downloadFile, deleteFile} from "@/api/project-demand";
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {useTagsView} from '@/stores/tagsview.js'
import {getFundOption} from "@/api/special-fund";
import {useCacheStore} from '@/stores/cache.js'
import {getSubCompOpt} from "@/api/user/user";
import FileComponent from "./FileComponent.vue";
import {ElNotification} from "element-plus";
import {approvePlan} from "@/api/project-demand/summary";
import SelectPreProcess from "@/components/SelectPreProcess.vue";
import {applyCcSend} from "@/api/expense-manage";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
const emit = defineEmits(['update:value','ccSend'])
const tagsViewStore = useTagsView()
const cacheStore = useCacheStore()
const props = defineProps({
formData: {
type: Object,
default: {}
},
data: {
type: Object,
default: {
state: '1'
}
},
processViewer: {
type: Boolean,
default: false
},
fileListShow: {
type: String,
default: 'READ'
},
loading: {
type: Boolean,
default: false
},
value: {
type: String,
default: ''
}
})
const changeDiagram = ref(false)
const localFormData = ref({})
const route = useRoute()
const router = useRouter()
const fundOption = ref([])
const companyOption = ref([])
const dictName = ref({})
const carbonCopyUserList = ref([])
const carbonCopyUserRef = ref()
const rules = reactive({
auditOpinion: [{required: true, message: '请输入审核意见', trigger: 'blur'}],
})
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const handleCarbonCopy = () => {
carbonCopyUserRef.value.showUserPicker()
}
const carbonCopyUserPickerOk = (userList) => {
carbonCopyUserList.value = userList.map(item => item.id)
console.log('localFormData.value', props.data)
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
addUser()
}
const addUser = async () => {
const res = await applyCcSend({
instanceId: props.data.processInstanceId,
projectId: route.query.projectId,
state: route.query.step,
userIds: carbonCopyUserList.value
})
console.log('res', res)
if (res.code === 1000) {
ElNotification({
title: '提示',
message: '抄送成功',
type: 'success'
})
emit('ccSend')
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
}
const handleRejectPlan = async () => {
// const values = form.value.getValues()
// console.log('route',route.query.projectId)
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = {
auditOpinion: _value.value,
projectId: parseInt(route.query.projectId),
state: false
}
// console.log('params', params)
const res = await approvePlan(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Summary'
})
}
const handleAgreePlan = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = {
auditOpinion: _value.value,
projectId: parseInt(route.query.projectId),
preProcess: JSON.stringify(localFormData.value.preProcess),
state: true
}
const res = await approvePlan(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Summary'
})
}
const filterDict = (data, value) => {
if (data === undefined || value === undefined) return;
let label = ''
let result = []
if (value instanceof Array) {
value.forEach(item1 => {
data.find(item => {
if (item.value == item1) {
result.push(item.label)
}
})
})
label = result.map(item => item).join('')
} else {
if (data instanceof Array) {
data.find(item => {
if (item.value == value) {
label = item.label
}
})
}
}
return label
}
const getFundOptions = async () => {
const resFund = await getFundOption()
fundOption.value = resFund.data
const res = await getSubCompOpt()
companyOption.value = res.data
}
const changeName = (option, value) => {
let name = ''
option.forEach(item => {
if (item.value == value) {
name = item.label
}
})
return name
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watchEffect(() => {
props.formData.singleFile = [props.formData.singleFile]
return Object.keys(props.formData).length && (localFormData.value = props.formData)
})
getFundOptions()
</script>
<style scoped lang="scss">
.detail-block {
overflow-x: hidden;
overflow-y: auto;
padding-bottom: 0 !important;
}
.file-table-style {
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
}
</style>
<template>
<div class="detail-block" v-loading="loading">
<el-form :model="localFormData" ref="summaryForm" :rules="rules">
<baseTitle title="预期知识产权"></baseTitle>
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px">
<!-- <el-col :span="6">-->
<!-- <el-form-item label="预期成果形式" prop="resultForm">-->
<!-- <span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6">
<el-form-item label="知识产权归属" prop="intellectualProperty">
<span>{{
filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty)
}}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估专利(项)" prop="newPatent">
<span>{{ localFormData.newPatent }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
<span>{{ localFormData.softwareCopyright }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估技术标准(项)" prop="technicalNorms">
<span>{{ localFormData.technicalNorms }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新产品(项)" prop="newProduct">
<span>{{ localFormData.newProduct }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新工艺(项)" prop="newProcess">
<span>{{ localFormData.newProcess }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新装置(项)" prop="newDevice">
<span>{{ localFormData.newDevice }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估新材料(项)" prop="newMaterials">
<span>{{ localFormData.newMaterials }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
<span>{{ localFormData.computerSoftware }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估论文论著(项)" prop="thesis">
<span>{{ localFormData.thesis }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估研究报告(项)" prop="researchReport">
<span>{{ localFormData.researchReport }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估商标(项)" prop="trademark">
<span>{{ localFormData.trademark }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="预估其他(项)" prop="other">
<span style="white-space: pre-wrap">{{ localFormData.other }}</span>
</el-form-item>
</el-col>
</el-row>
<baseTitle title="项目描述"></baseTitle>
<el-row gutter="20" style="margin-left: 5px;margin-bottom: -18px;">
<el-col :span="24">
<el-form-item label="现有业务描述" prop="serviceDescription">
<span style="white-space: pre-wrap">{{ localFormData.serviceDescription }}</span>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="建设目标描述" prop="contentDescription">
<span style="white-space: pre-wrap">{{ localFormData.contentDescription }}</span>
</el-form-item>
</el-col>
</el-row>
<baseTitle title="需求上报申请书" style="margin-bottom: -3px;"></baseTitle>
<!-- <el-row gutter="20" style="margin-bottom: -15px;">-->
<!-- <el-col :span="24">-->
<!-- <single-file-component tag="需求上报" v-model:value="localFormData.singleFile" :processViewer="processViewer"/>-->
<!-- &lt;!&ndash; <el-form-item>&ndash;&gt;-->
<!-- &lt;!&ndash; {{localFormData.singleFile}}&ndash;&gt;-->
<!-- &lt;!&ndash; <el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">&ndash;&gt;-->
<!-- &lt;!&ndash; {{ localFormData.singleFile?.originalFileName }}&ndash;&gt;-->
<!-- &lt;!&ndash; </el-button>&ndash;&gt;-->
<!-- &lt;!&ndash; </el-form-item>&ndash;&gt;-->
<!-- </el-col>-->
<!-- </el-row>-->
<!--/* <baseTitle title="附件文件" style="margin-bottom: 0"></baseTitle>*/-->
<el-row gutter="20" style="margin-bottom: -18px;">
<el-col :span="24" class="file-table-style">
<file-component tag="需求上报"
v-model:value="localFormData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/>
</el-col>
<el-col :span="24" style="margin-top: -15px">
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
<div v-if="data.state==='5'" style="margin-bottom: 15px">
<baseTitle title="前置流程" v-if="localFormData.preProcess"></baseTitle>
<div style="display: flex;align-items: center;flex-wrap: wrap;">
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
<a :href="item.baseUrl" target="_blank"
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
v-if="index != localFormData.preProcess.length -1"></span>
</a>
</div>
</div>
</div>
<div v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<!-- <baseTitle title="前置流程"></baseTitle>-->
<!-- <select-pre-process :formData="localFormData"/>-->
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<div class="approval-record">
<div class="approval-title" style="margin-top: -12px">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/>
</div>
<el-button color="#DED0B2" style="margin-left: 10px"
@click="handleCarbonCopy()">立即抄送
</el-button>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:step="'report'"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" id-name="summaryProcess"/>
</div>
</div>
</el-form>
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
@cancelOrClear="carbonCopyUserPickerOk"/>
<div class="oper-page-btn" v-perm="['annual:plan:approve']" v-if="data.state==='4'">
<el-button type="danger" @click="handleRejectPlan">驳回年度计划</el-button>
<el-button color="#DED0B2" @click="handleAgreePlan">通过年度计划</el-button>
</div>
</div>
</template>
<script setup lang="jsx">
import {toThousands} from '@/utils/changePrice.js'
import {downloadFile, deleteFile} from "@/api/project-demand";
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue'
import {useTagsView} from '@/stores/tagsview.js'
import {getFundOption} from "@/api/special-fund";
import {useCacheStore} from '@/stores/cache.js'
import {getSubCompOpt} from "@/api/user/user";
import FileComponent from "./FileComponent.vue";
import {ElNotification} from "element-plus";
import {approvePlan} from "@/api/project-demand/summary";
import SelectPreProcess from "@/components/SelectPreProcess.vue";
import {applyCcSend} from "@/api/expense-manage";
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
const emit = defineEmits(['update:value','ccSend'])
const tagsViewStore = useTagsView()
const cacheStore = useCacheStore()
const props = defineProps({
formData: {
type: Object,
default: {}
},
data: {
type: Object,
default: {
state: '1'
}
},
processViewer: {
type: Boolean,
default: false
},
fileListShow: {
type: String,
default: 'READ'
},
loading: {
type: Boolean,
default: false
},
value: {
type: String,
default: ''
}
})
const changeDiagram = ref(false)
const localFormData = ref({})
const route = useRoute()
const router = useRouter()
const fundOption = ref([])
const companyOption = ref([])
const dictName = ref({})
const carbonCopyUserList = ref([])
const carbonCopyUserRef = ref()
const rules = reactive({
auditOpinion: [{required: true, message: '请输入审核意见', trigger: 'blur'}],
})
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const handleCarbonCopy = () => {
carbonCopyUserRef.value.showUserPicker()
}
const carbonCopyUserPickerOk = (userList) => {
carbonCopyUserList.value = userList.map(item => item.id)
console.log('localFormData.value', props.data)
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
addUser()
}
const addUser = async () => {
const res = await applyCcSend({
instanceId: props.data.processInstanceId,
projectId: route.query.projectId,
state: route.query.step,
userIds: carbonCopyUserList.value
})
console.log('res', res)
if (res.code === 1000) {
ElNotification({
title: '提示',
message: '抄送成功',
type: 'success'
})
emit('ccSend')
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
}
const handleRejectPlan = async () => {
// const values = form.value.getValues()
// console.log('route',route.query.projectId)
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = {
auditOpinion: _value.value,
projectId: parseInt(route.query.projectId),
state: false
}
// console.log('params', params)
const res = await approvePlan(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Summary'
})
}
const handleAgreePlan = async () => {
if (!_value.value) {
ElNotification({
title: '提示',
message: '请填写审核意见',
type: 'warning'
})
return
}
const params = {
auditOpinion: _value.value,
projectId: parseInt(route.query.projectId),
preProcess: JSON.stringify(localFormData.value.preProcess),
state: true
}
const res = await approvePlan(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Summary'
})
}
const filterDict = (data, value) => {
if (data === undefined || value === undefined) return;
let label = ''
let result = []
if (value instanceof Array) {
value.forEach(item1 => {
data.find(item => {
if (item.value == item1) {
result.push(item.label)
}
})
})
label = result.map(item => item).join('')
} else {
if (data instanceof Array) {
data.find(item => {
if (item.value == value) {
label = item.label
}
})
}
}
return label
}
const getFundOptions = async () => {
const resFund = await getFundOption()
fundOption.value = resFund.data
const res = await getSubCompOpt()
companyOption.value = res.data
}
const changeName = (option, value) => {
let name = ''
option.forEach(item => {
if (item.value == value) {
name = item.label
}
})
return name
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
watchEffect(() => {
props.formData.singleFile = [props.formData.singleFile]
return Object.keys(props.formData).length && (localFormData.value = props.formData)
})
getFundOptions()
</script>
<style scoped lang="scss">
.detail-block {
overflow-x: hidden;
overflow-y: auto;
padding-bottom: 0 !important;
}
.file-table-style {
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
}
</style>

View File

@@ -1,209 +1,209 @@
<template>
<el-form :label-position="labelAlign">
<el-form-item :label="title?'其他文件':''" :label-position="labelAlign" :label-width="title?95:''">
<fvTable style="width: 100%;max-height: 80px;" v-if="processViewer" height="80" :tableConfig="tableConfig"
:data="_value" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-form>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</template>
<script setup lang="jsx">
import {downloadFile, deleteFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
const props = defineProps({
title: {
type: String,
default: ''
},
tag: {
type: String,
default: ''
},
fileNameTableWidth: {
type: String,
default: '400'
},
value: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
labelAlign: {
type: String,
default: 'right'
},
//弹窗是否铺满全屏
fullscreen: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:value'])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: 85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: props.fileNameTableWidth,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
width: 150,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link>
{item.label}
</el-button>
))
}
{
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const getOtherFile = (val) => {
props.processViewer = false
let fileObj = compositeParam(val)
_value.value.push(fileObj)
nextTick(() => {
props.processViewer = true
})
}
const compositeParam = (item, type) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: props.tag
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const handleDelete = (row) => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
_value.value.splice(_value.value.findIndex((item) => item.fileId === row.fileId), 1);
}
});
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-table--fit ) {
height: 80px !important;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
</style>
<template>
<el-form :label-position="labelAlign">
<el-form-item :label="title?'其他文件':''" :label-position="labelAlign" :label-width="title?95:''">
<fvTable style="width: 100%;max-height: 80px;" v-if="processViewer" height="80" :tableConfig="tableConfig"
:data="_value" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-form>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</template>
<script setup lang="jsx">
import {downloadFile, deleteFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
const props = defineProps({
title: {
type: String,
default: ''
},
tag: {
type: String,
default: ''
},
fileNameTableWidth: {
type: String,
default: '400'
},
value: {
type: Array,
default: []
},
processViewer: {
type: Boolean,
default: false
},
labelAlign: {
type: String,
default: 'right'
},
//弹窗是否铺满全屏
fullscreen: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:value'])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: 85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: props.fileNameTableWidth,
showOverflowTooltip: false,
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
width: 150,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link>
{item.label}
</el-button>
))
}
{
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const getOtherFile = (val) => {
props.processViewer = false
let fileObj = compositeParam(val)
_value.value.push(fileObj)
nextTick(() => {
props.processViewer = true
})
}
const compositeParam = (item, type) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: props.tag
}
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
const handleDelete = (row) => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
_value.value.splice(_value.value.findIndex((item) => item.fileId === row.fileId), 1);
}
});
}
watch(() => props.processViewer, (newVal) => {
props.processViewer = newVal
}, {deep: true})
</script>
<style scoped lang="scss">
:deep(.el-table--fit ) {
height: 80px !important;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -25px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -13px !important;
}
}
}
</style>

View File

@@ -1,210 +1,210 @@
<template>
<el-upload :file-list="_value" ref="uploadRef"
action="#"
:headers="headers"
:limit="maxSize"
with-credentials
:multiple="multiple"
:data="uploadParams" :on-change="handleChange"
:http-request="customUpload"
:show-file-list="showFileList"
:auto-upload="false"
:before-upload="beforeUpload"
:on-error="uploadError"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<!-- :on-success="handleUploadSuccess"-->
<el-button color="#DED0B2" :loading="loading" :disabled="disabled">上传文件</el-button>
</el-upload>
</template>
<script setup>
import {ElLoading, ElMessage, ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import {nextTick} from "vue";
import axios from "axios";
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload")
const headers = reactive({
'Content-Type': 'multipart/form-data',
authorization: getToken()
})
const loading = ref(false)
const showTable = ref(false)
const uploadIndex = ref(0)
const uploadParams = ref({})
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 999999
},
showFileList: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: true
}
})
const uploadRef = ref(null); // el-upload 的 ref
const uploadPromises = ref([]); // 跟踪每个文件的上传状态
const emit = defineEmits(["input", "beforeUpload", "getFile", "delete"])
const fileList = ref([])
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("input", val);
}
})
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const uploadLoading = ref(false)
const uploadFile = ref([])
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
// 文件选择变化时触发
const handleChange = (file, files) => {
const deleteFileRow = JSON.parse(localStorage.getItem('deleteFileRow'));
console.log("🚀 ~ file:deleteFileRow ", deleteFileRow, uploadFile.value)
let deleteIndex = null
if (deleteFileRow) {
deleteIndex = uploadFile.value.findIndex((item) => item.name === deleteFileRow.originalFileName && item.size === deleteFileRow.size)
console.log("🚀 ~ file:deleteIndex ", deleteIndex)
if (deleteIndex != -1) {
uploadFile.value.splice(deleteIndex, 1);
}
}
console.log(file, files, 'files')
uploadIndex.value++
uploadFile.value.push(file)
console.log("🚀 ~ file:uploadFile.value ", uploadFile.value)
localStorage.removeItem('deleteFileRow')
};
watch(() => uploadIndex.value, (newVal) => {
console.log('newVal', newVal)
startUpload(uploadFile.value); // 自动触发上传
}, {
deep: true
})
// 自定义上传逻辑
const customUpload = async (options) => {
const formData = new FormData();
formData.append('file', options.raw);
try {
const response = await axios.post(uploadFileUrl.value, formData, {
headers: headers,
});
fileList.value.push(response.data.data)
emit("getFile", response.data.data)
return response.data; // 成功时返回响应
} catch (error) {
throw new Error('上传失败'); // 失败时抛出错误
}
};
// 触发所有文件上传
const startUpload = (files) => {
uploadLoading.value = ElLoading.service({
fullscreen: true,
text: '文件上传中...',
})
if (files.length === 0) {
return; // 没有文件时直接返回
}
uploadPromises.value = []; // 重置 Promise 数组
files.forEach((file) => {
// 触发每个文件的上传
const promise = new Promise((resolve, reject) => {
customUpload(file).then(resolve)
.catch(reject);
});
uploadPromises.value.push(promise);
});
// 使用 Promise.all 监听所有文件上传完成
Promise.all(uploadPromises.value)
.then(() => {
ElNotification({
title: '提示',
message: '所有文件上传完成!',
type: 'success'
})
files = []; // 清空文件列表
uploadRef.value.clearFiles(); // 清空上传组件
uploadFile.value = [] // 清空文件列表
nextTick(() => {
uploadLoading.value.close()
uploadLoading.value = null
})
})
};
const beforeUpload = () => {
loading.value = true
return true
}
const handleUploadSuccess = (res) => {
ElNotification({
title: '提示',
message: res.code === 1000 ? '上传成功' : '上传失败',
type: res.code === 1000 ? 'success' : 'error'
})
loading.value = false
showTable.value = true
let data = res.data
fileList.value.push(data)
// emit("getFile", res.data)
}
const uploadError = () => {
loading.value = false
ElNotification({
title: '提示',
message: "上传失败,请稍后再试!",
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
:deep(.el-upload-list) {
width: 400px;
}
</style>
<template>
<el-upload :file-list="_value" ref="uploadRef"
action="#"
:headers="headers"
:limit="maxSize"
with-credentials
:multiple="multiple"
:data="uploadParams" :on-change="handleChange"
:http-request="customUpload"
:show-file-list="showFileList"
:auto-upload="false"
:before-upload="beforeUpload"
:on-error="uploadError"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<!-- :on-success="handleUploadSuccess"-->
<el-button color="#DED0B2" :loading="loading" :disabled="disabled">上传文件</el-button>
</el-upload>
</template>
<script setup>
import {ElLoading, ElMessage, ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import {nextTick} from "vue";
import axios from "axios";
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload")
const headers = reactive({
'Content-Type': 'multipart/form-data',
authorization: getToken()
})
const loading = ref(false)
const showTable = ref(false)
const uploadIndex = ref(0)
const uploadParams = ref({})
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 999999
},
showFileList: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: true
}
})
const uploadRef = ref(null); // el-upload 的 ref
const uploadPromises = ref([]); // 跟踪每个文件的上传状态
const emit = defineEmits(["input", "beforeUpload", "getFile", "delete"])
const fileList = ref([])
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("input", val);
}
})
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const uploadLoading = ref(false)
const uploadFile = ref([])
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
// 文件选择变化时触发
const handleChange = (file, files) => {
const deleteFileRow = JSON.parse(localStorage.getItem('deleteFileRow'));
console.log("🚀 ~ file:deleteFileRow ", deleteFileRow, uploadFile.value)
let deleteIndex = null
if (deleteFileRow) {
deleteIndex = uploadFile.value.findIndex((item) => item.name === deleteFileRow.originalFileName && item.size === deleteFileRow.size)
console.log("🚀 ~ file:deleteIndex ", deleteIndex)
if (deleteIndex != -1) {
uploadFile.value.splice(deleteIndex, 1);
}
}
console.log(file, files, 'files')
uploadIndex.value++
uploadFile.value.push(file)
console.log("🚀 ~ file:uploadFile.value ", uploadFile.value)
localStorage.removeItem('deleteFileRow')
};
watch(() => uploadIndex.value, (newVal) => {
console.log('newVal', newVal)
startUpload(uploadFile.value); // 自动触发上传
}, {
deep: true
})
// 自定义上传逻辑
const customUpload = async (options) => {
const formData = new FormData();
formData.append('file', options.raw);
try {
const response = await axios.post(uploadFileUrl.value, formData, {
headers: headers,
});
fileList.value.push(response.data.data)
emit("getFile", response.data.data)
return response.data; // 成功时返回响应
} catch (error) {
throw new Error('上传失败'); // 失败时抛出错误
}
};
// 触发所有文件上传
const startUpload = (files) => {
uploadLoading.value = ElLoading.service({
fullscreen: true,
text: '文件上传中...',
})
if (files.length === 0) {
return; // 没有文件时直接返回
}
uploadPromises.value = []; // 重置 Promise 数组
files.forEach((file) => {
// 触发每个文件的上传
const promise = new Promise((resolve, reject) => {
customUpload(file).then(resolve)
.catch(reject);
});
uploadPromises.value.push(promise);
});
// 使用 Promise.all 监听所有文件上传完成
Promise.all(uploadPromises.value)
.then(() => {
ElNotification({
title: '提示',
message: '所有文件上传完成!',
type: 'success'
})
files = []; // 清空文件列表
uploadRef.value.clearFiles(); // 清空上传组件
uploadFile.value = [] // 清空文件列表
nextTick(() => {
uploadLoading.value.close()
uploadLoading.value = null
})
})
};
const beforeUpload = () => {
loading.value = true
return true
}
const handleUploadSuccess = (res) => {
ElNotification({
title: '提示',
message: res.code === 1000 ? '上传成功' : '上传失败',
type: res.code === 1000 ? 'success' : 'error'
})
loading.value = false
showTable.value = true
let data = res.data
fileList.value.push(data)
// emit("getFile", res.data)
}
const uploadError = () => {
loading.value = false
ElNotification({
title: '提示',
message: "上传失败,请稍后再试!",
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
:deep(.el-upload-list) {
width: 400px;
}
</style>

View File

@@ -1,43 +1,43 @@
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
Youve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
Youve successfully created a project with
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>

View File

@@ -1,114 +1,114 @@
<template>
<el-upload :file-list="[]"
:limit="maxSize"
with-credentials
:multiple="multiple"
:http-request="httpRequestHandle"
:data="uploadParams"
:auto-upload="true"
:show-file-list="false"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-button color="#DED0B2" style="margin-right: 10px;" :disabled="disabled">导入</el-button>
</el-upload>
</template>
<script setup>
import {ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
})
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/mosr/rd/expense/import")
const headers = reactive({
authorization: getToken()
})
// const loading = ref(false)
const uploadParams = ref({})
const emit = defineEmits(["input", "getFile", "delete"])
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
const beforeUpload = () => {
// loading.value = true
return true
}
const httpRequestHandle = (param) => {
let file = param.file
axios.post(uploadFileUrl.value, {
file: file
}, {
headers: {
'Content-Type': 'multipart/form-data',
...headers
}
}).then(res => {
handleUploadSuccess(res)
}).catch(error => {
uploadError(error)
})
}
const handleUploadSuccess = (res) => {
let data = res.data
ElNotification({
title: '提示',
message: data.code === 1000 ? '上传成功' : '上传失败',
type: data.code === 1000 ? 'success' : 'error'
})
emit("success")
}
const uploadError = (error) => {
console.log("🚀 ~ file:'error ", error.response.data.msg)
// loading.value = false
ElNotification({
title: '提示',
message: error.response.data.msg,
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
</style>
<template>
<el-upload :file-list="[]"
:limit="maxSize"
with-credentials
:multiple="multiple"
:http-request="httpRequestHandle"
:data="uploadParams"
:auto-upload="true"
:show-file-list="false"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-button color="#DED0B2" style="margin-right: 10px;" :disabled="disabled">导入</el-button>
</el-upload>
</template>
<script setup>
import {ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
})
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/mosr/rd/expense/import")
const headers = reactive({
authorization: getToken()
})
// const loading = ref(false)
const uploadParams = ref({})
const emit = defineEmits(["input", "getFile", "delete"])
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
const beforeUpload = () => {
// loading.value = true
return true
}
const httpRequestHandle = (param) => {
let file = param.file
axios.post(uploadFileUrl.value, {
file: file
}, {
headers: {
'Content-Type': 'multipart/form-data',
...headers
}
}).then(res => {
handleUploadSuccess(res)
}).catch(error => {
uploadError(error)
})
}
const handleUploadSuccess = (res) => {
let data = res.data
ElNotification({
title: '提示',
message: data.code === 1000 ? '上传成功' : '上传失败',
type: data.code === 1000 ? 'success' : 'error'
})
emit("success")
}
const uploadError = (error) => {
console.log("🚀 ~ file:'error ", error.response.data.msg)
// loading.value = false
ElNotification({
title: '提示',
message: error.response.data.msg,
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
</style>

View File

@@ -1,116 +1,116 @@
<template>
<el-upload :file-list="[]"
:limit="maxSize"
with-credentials
:multiple="multiple"
:http-request="httpRequestHandle"
:data="uploadParams"
:auto-upload="true"
:show-file-list="false"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-button color="#DED0B2" style="margin-left: 10px; margin-right: 10px;" :disabled="disabled">导入</el-button>
</el-upload>
</template>
<script setup>
import {ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
projectId: {
type: Number,
default: 0
}
})
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/mosr/expense/ledger/import?projectId=" + props.projectId)
const headers = reactive({
authorization: getToken()
})
// const loading = ref(false)
const uploadParams = ref({})
const emit = defineEmits(["input", "getFile", "delete"])
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
const beforeUpload = () => {
// loading.value = true
return true
}
const httpRequestHandle = (param) => {
let file = param.file
axios.post(uploadFileUrl.value, {
file: file
}, {
headers: {
'Content-Type': 'multipart/form-data',
...headers
}
}).then(res => {
handleUploadSuccess(res)
}).catch(error => {
uploadError(error)
})
}
const handleUploadSuccess = (res) => {
let data = res.data
ElNotification({
title: '提示',
message: data.code === 1000 ? '上传成功' : '上传失败',
type: data.code === 1000 ? 'success' : 'error'
})
emit("success")
}
const uploadError = (error) => {
// loading.value = false
ElNotification({
title: '提示',
message: "上传失败,请稍后再试!",
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
</style>
<template>
<el-upload :file-list="[]"
:limit="maxSize"
with-credentials
:multiple="multiple"
:http-request="httpRequestHandle"
:data="uploadParams"
:auto-upload="true"
:show-file-list="false"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-button color="#DED0B2" style="margin-left: 10px; margin-right: 10px;" :disabled="disabled">导入</el-button>
</el-upload>
</template>
<script setup>
import {ElMessageBox, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
const props = defineProps({
value: {
type: Array,
default: () => {
return []
}
},
maxSize: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
projectId: {
type: Number,
default: 0
}
})
const baseURL = import.meta.env.VITE_BASE_URL
const uploadFileUrl = ref(baseURL + "/workflow/mosr/expense/ledger/import?projectId=" + props.projectId)
const headers = reactive({
authorization: getToken()
})
// const loading = ref(false)
const uploadParams = ref({})
const emit = defineEmits(["input", "getFile", "delete"])
const beforeRemove = (file) => {
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => true)
}
const handleRemove = (file) => {
emit("delete", file.response.data.id)
}
const beforeUpload = () => {
// loading.value = true
return true
}
const httpRequestHandle = (param) => {
let file = param.file
axios.post(uploadFileUrl.value, {
file: file
}, {
headers: {
'Content-Type': 'multipart/form-data',
...headers
}
}).then(res => {
handleUploadSuccess(res)
}).catch(error => {
uploadError(error)
})
}
const handleUploadSuccess = (res) => {
let data = res.data
ElNotification({
title: '提示',
message: data.code === 1000 ? '上传成功' : '上传失败',
type: data.code === 1000 ? 'success' : 'error'
})
emit("success")
}
const uploadError = (error) => {
// loading.value = false
ElNotification({
title: '提示',
message: "上传失败,请稍后再试!",
type: 'error'
})
}
defineExpose({
handleRemove
})
</script>
<style lang="scss" scoped>
a {
font-size: 14px;
color: #2a99ff;
}
</style>

View File

@@ -1,133 +1,133 @@
<template>
<div style="display: block">
<slot name="pre"></slot>
<div class="user-audit">
<div class="circle-user">
<Tooltip v-if="userName" :content="userName" placement="bottom-start" width="45px"/>
<Tooltip v-else :content="user.name" placement="bottom-start" width="45px"/>
<!-- :style="{-->
<!-- backgroundColor: '#fff'-->
<!-- }">-->
<div v-if="user.icon"
class="el-timeline-item__node">
<div v-if="user.isAgent&&!showIcon">
</div>
<el-icon v-else size="15" :color="user.color" :class="user.class">
<component :is="user.icon"/>
</el-icon>
</div>
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
row: {
type: Number,
default: 1
},
hoverTip: {
type: Boolean,
default: false
},
showIcon: {
type: Boolean,
default: false
},
user: {
type: Object,
default: {}
},
userName: {
type: String,
default: ''
},
mode: {
type: String,
default: 'design'
},
type: {
type: String,
default: ''
},
})
const init = () => {
// for (let user of props.userInfo) {
initUser(props.user)
// }
}
const initUser = (user) => {
let state = user.state
//创建节点
if (state === 'CREATE') {
user["icon"] = 'CircleCheckFilled'
user["color"] = "#0bbd87"
}
//审批通过
if (state === 'AGREE' || state === 'AUTO_PASS') {
user["icon"] = 'CircleCheckFilled'
user["color"] = "#0bbd87"
}
if (props.type === "CC") {
user["icon"] = "Promotion"
user["color"] = "#3395f8"
}
//审批处理中
if (state === 'RUNNING') {
user["icon"] = 'Loading'
user["color"] = "#f78f5f"
user["class"] = 'is-loading'
}
//拒绝后评论
if (state === 'REFUSE' || state === 'ROLLBACK') {
// user["icon"] = 'Close'
// user["color"] = "#f56c6c"
user["icon"] = 'CircleCloseFilled'
user["color"] = "#f56c6c"
}
if (state === 'PASS') {
user["icon"] = 'MoreFilled'
user["color"] = "#c0c4cc"
}
// if (state === 'ROLLBACK') {
// // user["icon"] = 'RefreshLeft'
// // user["color"] = "#f78f5f"
// user["icon"] = 'CircleCloseFilled'
// user["color"] = "#f56c6c"
// }
return user;
}
init()
</script>
<style scoped lang="scss">
.user-audit {
display: flex;
flex-direction: column;
align-items: center;
.circle-user {
width: 46px;
height: 46px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
border: 1px solid #ACACAC;
position: relative;
background-color: #8a7243;
color: #fff;
.el-timeline-item__node {
position: absolute;
bottom: 0;
right: 1px;
}
}
}
</style>
<template>
<div style="display: block">
<slot name="pre"></slot>
<div class="user-audit">
<div class="circle-user">
<Tooltip v-if="userName" :content="userName" placement="bottom-start" width="45px"/>
<Tooltip v-else :content="user.name" placement="bottom-start" width="45px"/>
<!-- :style="{-->
<!-- backgroundColor: '#fff'-->
<!-- }">-->
<div v-if="user.icon"
class="el-timeline-item__node">
<div v-if="user.isAgent&&!showIcon">
</div>
<el-icon v-else size="15" :color="user.color" :class="user.class">
<component :is="user.icon"/>
</el-icon>
</div>
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
row: {
type: Number,
default: 1
},
hoverTip: {
type: Boolean,
default: false
},
showIcon: {
type: Boolean,
default: false
},
user: {
type: Object,
default: {}
},
userName: {
type: String,
default: ''
},
mode: {
type: String,
default: 'design'
},
type: {
type: String,
default: ''
},
})
const init = () => {
// for (let user of props.userInfo) {
initUser(props.user)
// }
}
const initUser = (user) => {
let state = user.state
//创建节点
if (state === 'CREATE') {
user["icon"] = 'CircleCheckFilled'
user["color"] = "#0bbd87"
}
//审批通过
if (state === 'AGREE' || state === 'AUTO_PASS') {
user["icon"] = 'CircleCheckFilled'
user["color"] = "#0bbd87"
}
if (props.type === "CC") {
user["icon"] = "Promotion"
user["color"] = "#3395f8"
}
//审批处理中
if (state === 'RUNNING') {
user["icon"] = 'Loading'
user["color"] = "#f78f5f"
user["class"] = 'is-loading'
}
//拒绝后评论
if (state === 'REFUSE' || state === 'ROLLBACK') {
// user["icon"] = 'Close'
// user["color"] = "#f56c6c"
user["icon"] = 'CircleCloseFilled'
user["color"] = "#f56c6c"
}
if (state === 'PASS') {
user["icon"] = 'MoreFilled'
user["color"] = "#c0c4cc"
}
// if (state === 'ROLLBACK') {
// // user["icon"] = 'RefreshLeft'
// // user["color"] = "#f78f5f"
// user["icon"] = 'CircleCloseFilled'
// user["color"] = "#f56c6c"
// }
return user;
}
init()
</script>
<style scoped lang="scss">
.user-audit {
display: flex;
flex-direction: column;
align-items: center;
.circle-user {
width: 46px;
height: 46px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
border: 1px solid #ACACAC;
position: relative;
background-color: #8a7243;
color: #fff;
.el-timeline-item__node {
position: absolute;
bottom: 0;
right: 1px;
}
}
}
</style>

View File

@@ -1,3 +1,3 @@
<template>
<router-view></router-view>
<template>
<router-view></router-view>
</template>

View File

@@ -1,101 +1,101 @@
<template>
<div style="display: flex;justify-content: center">
<span class="stateIcon" :style="{backgroundColor: filterDictClass(cacheStore.getDict(dictType), value)}"></span>
<span>{{tagConfig.label}}</span>
<span> {{ filterDict(cacheStore.getDict(dictType), value) }}</span>
</div>
</template>
<script setup>
import {defineProps} from "vue";
import {useCacheStore} from "@/stores/cache.js";
const cacheStore = useCacheStore();
const props = defineProps({
dictType: {
type: String,
default: ""
},
value: {
type: Object,
default: null
}
});
const tagConfig = reactive({
listClass: "green",
isType: true,
label: ""
});
const filterDictClass = (data, value) => {
if (!data|| value == null) return 'gray'
if (data instanceof Array) {
tagConfig.value = data.find(item => item.value == value)
if (!tagConfig.value) {
return '#409EFF'
} else {
if (tagConfig.value?.isType) {
return changeParams(tagConfig.value.listClass)
} else {
return tagConfig.value.listClass
}
}
}
}
const filterDict = (data, value) => {
if (!data || value == null) return '未知'
if (data instanceof Array) {
if (value == true || value == false) {
tagConfig.value = data.find(item => item.value == value.toString())
} else if (typeof value === "object") {
if (value !== null) {
tagConfig.value = data.find(item => item.value == value[0])
} else {
tagConfig.value = {}
}
} else {
tagConfig.value = data.find(item => item.value == value)
}
}
return tagConfig.value?.label || '未知'
}
/**
* 根据接口返回的listClass切换成对应的颜色
* @param listClass 后端返回的listClass字段
* @returns {string}
*/
const changeParams = (listClass) => {
switch (listClass) {
case 'danger':
return 'red'
case 'success':
return '#67C23A'
case 'info':
return '#909399'
case 'primary':
return '#409EFF'
case 'warning':
return '#E6A23C'
default:
return listClass
}
}
// dictFormat()
</script>
<style scoped lang="scss">
//.dot{
// width:8px;
// height: 20px;
// margin-left: -5px;
// background-color: green;
// z-index: 99999;
//}
:deep(.el-tag){
position: relative;
margin-top: 9px;
margin-right: 7px;
height: 8px;
}
</style>
<template>
<div style="display: flex;justify-content: center">
<span class="stateIcon" :style="{backgroundColor: filterDictClass(cacheStore.getDict(dictType), value)}"></span>
<span>{{tagConfig.label}}</span>
<span> {{ filterDict(cacheStore.getDict(dictType), value) }}</span>
</div>
</template>
<script setup>
import {defineProps} from "vue";
import {useCacheStore} from "@/stores/cache.js";
const cacheStore = useCacheStore();
const props = defineProps({
dictType: {
type: String,
default: ""
},
value: {
type: Object,
default: null
}
});
const tagConfig = reactive({
listClass: "green",
isType: true,
label: ""
});
const filterDictClass = (data, value) => {
if (!data|| value == null) return 'gray'
if (data instanceof Array) {
tagConfig.value = data.find(item => item.value == value)
if (!tagConfig.value) {
return '#409EFF'
} else {
if (tagConfig.value?.isType) {
return changeParams(tagConfig.value.listClass)
} else {
return tagConfig.value.listClass
}
}
}
}
const filterDict = (data, value) => {
if (!data || value == null) return '未知'
if (data instanceof Array) {
if (value == true || value == false) {
tagConfig.value = data.find(item => item.value == value.toString())
} else if (typeof value === "object") {
if (value !== null) {
tagConfig.value = data.find(item => item.value == value[0])
} else {
tagConfig.value = {}
}
} else {
tagConfig.value = data.find(item => item.value == value)
}
}
return tagConfig.value?.label || '未知'
}
/**
* 根据接口返回的listClass切换成对应的颜色
* @param listClass 后端返回的listClass字段
* @returns {string}
*/
const changeParams = (listClass) => {
switch (listClass) {
case 'danger':
return 'red'
case 'success':
return '#67C23A'
case 'info':
return '#909399'
case 'primary':
return '#409EFF'
case 'warning':
return '#E6A23C'
default:
return listClass
}
}
// dictFormat()
</script>
<style scoped lang="scss">
//.dot{
// width:8px;
// height: 20px;
// margin-left: -5px;
// background-color: green;
// z-index: 99999;
//}
:deep(.el-tag){
position: relative;
margin-top: 9px;
margin-right: 7px;
height: 8px;
}
</style>

View File

@@ -1,81 +1,81 @@
<template>
<el-popconfirm
confirm-button-text="确认"
cancel-button-text="取消"
icon="WarningFilled"
icon-color="#E6A23C"
:title="title"
@confirm="handleDelete"
@cancel="handleCancel"
>
<template #reference>
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-if="perm" v-perm="perm" :icon="btnIcon" :plain="isPlain" :link="link">
{{ btnText }}
</el-button>
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-else :icon="btnIcon" :plain="isPlain" :link="link">
{{ btnText }}
</el-button>
</template>
</el-popconfirm>
</template>
<script setup>
const props = defineProps({
name: {
type: Object,
default: null
},
btnType: {
type: String,
default: 'danger'
},
type: {
type: String,
default: ''
},
link: {
type: Boolean,
default: true
},
btnIcon: {
type: String,
default: ''
},
btnText: {
type: String,
default: '删除'
},
perm: {
type: Array,
default: null
},
isDisabled: {
type: Boolean,
default: false
},
isPlain: {
type: Boolean,
default: false
},
})
const emit = defineEmits()
const title = ref(`确认${props.btnText}名称为"${props.name}"的${props.type}吗!`)
const visible = ref(false)
watch(() => props.name, (newVal) => {
title.value = "确认" + props.btnText + "名称为" + '"' + props.name + '"' + "的" + props.type + "吗!"
})
const handleCancel = () => {
visible.value = false
}
const handleDelete = () => {
emit("delete")
}
</script>
<style lang="scss">
.el-popconfirm__main {
display: flex;
word-break: break-all;
align-items: center;
}
</style>
<template>
<el-popconfirm
confirm-button-text="确认"
cancel-button-text="取消"
icon="WarningFilled"
icon-color="#E6A23C"
:title="title"
@confirm="handleDelete"
@cancel="handleCancel"
>
<template #reference>
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-if="perm" v-perm="perm" :icon="btnIcon" :plain="isPlain" :link="link">
{{ btnText }}
</el-button>
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-else :icon="btnIcon" :plain="isPlain" :link="link">
{{ btnText }}
</el-button>
</template>
</el-popconfirm>
</template>
<script setup>
const props = defineProps({
name: {
type: Object,
default: null
},
btnType: {
type: String,
default: 'danger'
},
type: {
type: String,
default: ''
},
link: {
type: Boolean,
default: true
},
btnIcon: {
type: String,
default: ''
},
btnText: {
type: String,
default: '删除'
},
perm: {
type: Array,
default: null
},
isDisabled: {
type: Boolean,
default: false
},
isPlain: {
type: Boolean,
default: false
},
})
const emit = defineEmits()
const title = ref(`确认${props.btnText}名称为"${props.name}"的${props.type}吗!`)
const visible = ref(false)
watch(() => props.name, (newVal) => {
title.value = "确认" + props.btnText + "名称为" + '"' + props.name + '"' + "的" + props.type + "吗!"
})
const handleCancel = () => {
visible.value = false
}
const handleDelete = () => {
emit("delete")
}
</script>
<style lang="scss">
.el-popconfirm__main {
display: flex;
word-break: break-all;
align-items: center;
}
</style>

View File

@@ -1,275 +1,275 @@
<template>
<div v-loading="_value">
<el-form :model="attachment" inline style="margin-left: 15px" @submit.prevent="handleSearch">
<el-form-item label="名称" prop="fileName">
<el-input v-model="attachment.fileName" placeholder="请输入文件名查询" clearable filterable style="width: 300px"/>
</el-form-item>
<el-form-item label="项目阶段" prop="targetState" v-if="allFile">
<el-select v-model="attachment.targetState" placeholder="请选择项目阶段" clearable filterable style="width: 300px">
<el-option
v-for="item in cacheStore.getDict('archive_file_type')"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="标签" prop="tag" v-if="type==='30'">
<el-select v-model="attachment.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
<el-option
v-for="item in tagsOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleSearch" color="#DED0B2">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
<el-button v-if="uploadState&&!allFile" color="#DED0B2" @click="handleUpload">上传附件</el-button>
</el-form-item>
</el-form>
<el-card style="width: 100%;overflow-y: hidden">
<fvTable style="width: 100%;max-height: 318px" v-if="showTable" height="318" :tableConfig="allFile?tableConfigAll:tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="99" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-card>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import {downloadFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
import {getTags} from "@/api/project-manage";
import {computed, ref} from "vue";
import {useCacheStore} from '@/stores/cache.js'
const route = useRoute()
const router = useRouter()
const cacheStore = useCacheStore()
const attachment = reactive({})
const emit = defineEmits(['search','update:modelValue'])
const props = defineProps({
fileList: {
type: Array,
default: []
},
type: {
type: String,
default: '00'
},
uploadState: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: true
},
allFile: {
type: Boolean,
default: false
}
})
const tagsOption = ref([])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width:85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label:'标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'createTime',
label: '上传时间',
align: 'center',
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const tableConfigAll = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width:85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'targetState',
label:'项目阶段',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
if (row.targetState&&row.targetState !== null&&row.targetState!==undefined) {
return (<Tag dictType={'archive_file_type'} value={row.targetState}/>)
} else {
return '--'
}
}
},
{
prop: 'tag',
label:'标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'createTime',
label: '上传时间',
align: 'center',
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const showTable = ref(true)
const _value = computed({
get() {
return props.loading || ""
},
set(value) {
emit('update:modelValue', value)
}
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const getTagsOption = () => {
if (!route.query.id) return
getTags(route.query.id).then(res => {
if (res.code === 1000) {
tagsOption.value = res.data
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleSearch = () => {
emit('search', attachment)
}
const handleReset=()=>{
attachment.fileName=''
attachment.targetState=''
attachment.tag=null
emit('search', {})
}
const handleUpload = () => {
emit('upload')
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.type, (val) => {
props.type = val
})
watch(() => props.fileList, (val) => {
showTable.value = false
nextTick(() => {
showTable.value = true
})
props.fileList = val
})
if (props.type === '30') {
getTagsOption()
}
onActivated(()=>{
if (props.type === '30') {
getTagsOption()
}
handleSearch()
})
</script>
<style scoped>
:deep(.el-table--fit ) {
height: 318px !important;
}
</style>
<template>
<div v-loading="_value">
<el-form :model="attachment" inline style="margin-left: 15px" @submit.prevent="handleSearch">
<el-form-item label="名称" prop="fileName">
<el-input v-model="attachment.fileName" placeholder="请输入文件名查询" clearable filterable style="width: 300px"/>
</el-form-item>
<el-form-item label="项目阶段" prop="targetState" v-if="allFile">
<el-select v-model="attachment.targetState" placeholder="请选择项目阶段" clearable filterable style="width: 300px">
<el-option
v-for="item in cacheStore.getDict('archive_file_type')"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="标签" prop="tag" v-if="type==='30'">
<el-select v-model="attachment.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
<el-option
v-for="item in tagsOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleSearch" color="#DED0B2">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
<el-button v-if="uploadState&&!allFile" color="#DED0B2" @click="handleUpload">上传附件</el-button>
</el-form-item>
</el-form>
<el-card style="width: 100%;overflow-y: hidden">
<fvTable style="width: 100%;max-height: 318px" v-if="showTable" height="318" :tableConfig="allFile?tableConfigAll:tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="99" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-card>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import {downloadFile} from "@/api/project-demand";
import {ElNotification} from "element-plus";
import {getTags} from "@/api/project-manage";
import {computed, ref} from "vue";
import {useCacheStore} from '@/stores/cache.js'
const route = useRoute()
const router = useRouter()
const cacheStore = useCacheStore()
const attachment = reactive({})
const emit = defineEmits(['search','update:modelValue'])
const props = defineProps({
fileList: {
type: Array,
default: []
},
type: {
type: String,
default: '00'
},
uploadState: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: true
},
allFile: {
type: Boolean,
default: false
}
})
const tagsOption = ref([])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width:85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label:'标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'createTime',
label: '上传时间',
align: 'center',
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const tableConfigAll = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width:85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'targetState',
label:'项目阶段',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
if (row.targetState&&row.targetState !== null&&row.targetState!==undefined) {
return (<Tag dictType={'archive_file_type'} value={row.targetState}/>)
} else {
return '--'
}
}
},
{
prop: 'tag',
label:'标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'createTime',
label: '上传时间',
align: 'center',
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const showTable = ref(true)
const _value = computed({
get() {
return props.loading || ""
},
set(value) {
emit('update:modelValue', value)
}
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const clickToPreview=(row)=>{
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
}
const getTagsOption = () => {
if (!route.query.id) return
getTags(route.query.id).then(res => {
if (res.code === 1000) {
tagsOption.value = res.data
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleSearch = () => {
emit('search', attachment)
}
const handleReset=()=>{
attachment.fileName=''
attachment.targetState=''
attachment.tag=null
emit('search', {})
}
const handleUpload = () => {
emit('upload')
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
watch(() => props.type, (val) => {
props.type = val
})
watch(() => props.fileList, (val) => {
showTable.value = false
nextTick(() => {
showTable.value = true
})
props.fileList = val
})
if (props.type === '30') {
getTagsOption()
}
onActivated(()=>{
if (props.type === '30') {
getTagsOption()
}
handleSearch()
})
</script>
<style scoped>
:deep(.el-table--fit ) {
height: 318px !important;
}
</style>

View File

@@ -1,226 +1,226 @@
<template>
<div style="display: flex;align-items: center;flex-wrap: wrap;">
<el-button color="#DED0B2" @click="handleShowPreTable" style="margin-right: 10px">
{{
localFormData.preProcess && localFormData.preProcess.length > 0 ? '更改' : '请选择前置流程'
}}
</el-button>
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
<a :href="item.baseUrl" target="_blank"
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
v-if="index != localFormData.preProcess.length -1"></span>
</a>
</div>
</div>
<el-dialog v-if="showPreTable" title="前置流程" v-model="showPreTable" width="80%">
<el-form :model="preProcessForm" inline @submit.prevent="getPreProcessList">
<el-form-item label="请求名称">
<el-input v-model="preProcessForm.requestName" placeholder="请输入请求名称" clearable>
</el-input>
</el-form-item>
<el-form-item>
<el-button color="#DED0B2" @click="getPreProcessList">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
<el-form-item>
<el-tag type="danger" style="font-size: 16px;color: red;" >特别提示{{ getPreProcessTag(localFormData.projectImpact,basicData.projectImpact) }}</el-tag>
</el-form-item>
</el-form>
<el-table :data="preProcessList" v-loading="loading"
@select="handleSelect" @select-all="handleSelect" row-key="requestId" ref="preProcessTable">
<el-table-column type="selection" width="55" :reserve-selection="true"
:selectable="checkSelectable"/>
<el-table-column prop="requestId" label="请求id"></el-table-column>
<el-table-column prop="requestName" label="请求名称"></el-table-column>
<el-table-column prop="lastOperatorName" label="最后操作人名称"></el-table-column>
<el-table-column prop="lastOperateTime" label="最后操作时间"></el-table-column>
<el-table-column prop="currentNodeName" label="当前节点"></el-table-column>
<el-table-column prop="creatorName" label="创建人"></el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<a :href="scope.row.baseUrl" target="_blank" style="color: #2a99ff;margin-left: 10px">查看流程</a>
</template>
</el-table-column>
</el-table>
<paging :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :page-sizes="[10, 20, 30, 40,50]"
:total="total" @changeSize="handleSizeChange" @goPage="handleCurrentChange"/>
<div class="oper">
<el-button color="#DED0B2" @click="choosePreProcess">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</el-dialog>
</template>
<script setup>
import {
getPreProcess
} from "@/api/project-manage";
import Paging from "@/components/pagination/index.vue";
const props = defineProps({
formData: {
type: Object,
default: {}
},
basicData: {
type: Object,
default: {}
},
})
const loading = ref(false)
//暂存数据
const originalProcess = ref([])
const currentList = ref([])
const showPreTable = ref(false)
const selectRows = ref([])
const preProcessList = ref([])
const total = ref(0)
const preProcessTable = ref()
const localFormData = ref({
projectPersonIds: [],
projectChargePerson: null,
preProcess: [
// {
// requestId: null,
// requestName: '',
// baseUrl: ''
// }
]
})
const preProcessForm = reactive({
requestName: ''
})
const pageInfo = reactive({
pageNum: 1,
pageSize: 10,
})
const getPreProcessTag = (impact,basicImpact) => {
let data=''
if(impact){
data= impact
}else if(basicImpact){
data= basicImpact
}
if (data == 1) {
//一般项目
return '研发费用20万元以下科技创新项目报总经理审批'
} else if (data == 2) {
//重大项目
return '重大项目20万元到500万元之间要总办会审批'
} else if (data == 3) {
//特别重大项目
return '特别重大项目500万元以上要董事会审批'
}
}
const handleReset = () => {
preProcessForm.requestName = ''
getPreProcessList()
}
const handleSelect = async (selection) => {
selectRows.value = selection
}
const checkSelectable=(row)=>{
const detailProcessStr = localStorage.getItem('detailProcess');
let preProcessArray = []
if (detailProcessStr) {
try {
preProcessArray = JSON.parse(detailProcessStr)
} catch (e) {
preProcessArray=[]
}
if (preProcessArray&&preProcessArray.length > 0) {
for (let i = 0; i < preProcessArray.length; i++) {
return preProcessArray[i].requestId !== row.requestId;
}
}else{
return true
}
}
}
const handleShowPreTable = () => {
showPreTable.value = true
nextTick(() => {
localFormData.value.preProcess?.forEach((item) => {
if (preProcessTable.value) {
preProcessTable.value.toggleRowSelection(item, true)
}
})
})
getPreProcessList()
}
const handleCancel = () => {
showPreTable.value = false
}
const choosePreProcess = () => {
let preProcessObj = {}
let preProcessArray = []
const detailProcessStr = localStorage.getItem('detailProcess');
try {
originalProcess.value = JSON.parse(detailProcessStr)
} catch (e) {
originalProcess.value=[]
}
selectRows.value.forEach((item) => {
const exists = originalProcess.value?.some(dp => dp.requestId === item.requestId)
if (!exists) {
preProcessObj = {
requestId: item.requestId,
requestName: item.requestName,
baseUrl: item.baseUrl
}
preProcessArray.push(preProcessObj)
}
})
if(props.formData.mode === 'view'||props.formData.mode === 'resubmit'){
localFormData.value.preProcess = [...originalProcess.value,...preProcessArray]
}else{
localFormData.value.preProcess = preProcessArray
}
localStorage.setItem('preProcess', JSON.stringify(preProcessArray))
showPreTable.value = false
}
const getPreProcessList = () => {
loading.value = true
getPreProcess().then(res => {
loading.value = false
let searchArray = []
let regexPattern = ("%" + preProcessForm.requestName + "%").replace(/%/g, '.*').replace(/_/g, '.');
let regex = new RegExp('^' + regexPattern + '$');
res.data.filter((item) => {
if (regex.test(item.requestName)) {
searchArray.push(item)
}
})
total.value = searchArray.length
currentList.value = searchArray
preProcessList.value = currentList.value.slice(0, 10)
})
}
//切换每页显示条数
const handleSizeChange = (val) => {
pageInfo.pageSize = val;
preProcessList.value = currentList.value.slice((pageInfo.pageNum - 1) * val, pageInfo.pageNum * val)
};
//点击页码进行分页功能
const handleCurrentChange = (val) => {
pageInfo.pageNum = val;
preProcessList.value = currentList.value.slice((val - 1) * pageInfo.pageSize, val * pageInfo.pageSize)
};
watchEffect(() => {
return Object.keys(props.formData).length && (localFormData.value = props.formData)
})
</script>
<style scoped>
.oper {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
</style>
<template>
<div style="display: flex;align-items: center;flex-wrap: wrap;">
<el-button color="#DED0B2" @click="handleShowPreTable" style="margin-right: 10px">
{{
localFormData.preProcess && localFormData.preProcess.length > 0 ? '更改' : '请选择前置流程'
}}
</el-button>
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
<a :href="item.baseUrl" target="_blank"
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
v-if="index != localFormData.preProcess.length -1"></span>
</a>
</div>
</div>
<el-dialog v-if="showPreTable" title="前置流程" v-model="showPreTable" width="80%">
<el-form :model="preProcessForm" inline @submit.prevent="getPreProcessList">
<el-form-item label="请求名称">
<el-input v-model="preProcessForm.requestName" placeholder="请输入请求名称" clearable>
</el-input>
</el-form-item>
<el-form-item>
<el-button color="#DED0B2" @click="getPreProcessList">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
<el-form-item>
<el-tag type="danger" style="font-size: 16px;color: red;" >特别提示{{ getPreProcessTag(localFormData.projectImpact,basicData.projectImpact) }}</el-tag>
</el-form-item>
</el-form>
<el-table :data="preProcessList" v-loading="loading"
@select="handleSelect" @select-all="handleSelect" row-key="requestId" ref="preProcessTable">
<el-table-column type="selection" width="55" :reserve-selection="true"
:selectable="checkSelectable"/>
<el-table-column prop="requestId" label="请求id"></el-table-column>
<el-table-column prop="requestName" label="请求名称"></el-table-column>
<el-table-column prop="lastOperatorName" label="最后操作人名称"></el-table-column>
<el-table-column prop="lastOperateTime" label="最后操作时间"></el-table-column>
<el-table-column prop="currentNodeName" label="当前节点"></el-table-column>
<el-table-column prop="creatorName" label="创建人"></el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<a :href="scope.row.baseUrl" target="_blank" style="color: #2a99ff;margin-left: 10px">查看流程</a>
</template>
</el-table-column>
</el-table>
<paging :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :page-sizes="[10, 20, 30, 40,50]"
:total="total" @changeSize="handleSizeChange" @goPage="handleCurrentChange"/>
<div class="oper">
<el-button color="#DED0B2" @click="choosePreProcess">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</el-dialog>
</template>
<script setup>
import {
getPreProcess
} from "@/api/project-manage";
import Paging from "@/components/pagination/index.vue";
const props = defineProps({
formData: {
type: Object,
default: {}
},
basicData: {
type: Object,
default: {}
},
})
const loading = ref(false)
//暂存数据
const originalProcess = ref([])
const currentList = ref([])
const showPreTable = ref(false)
const selectRows = ref([])
const preProcessList = ref([])
const total = ref(0)
const preProcessTable = ref()
const localFormData = ref({
projectPersonIds: [],
projectChargePerson: null,
preProcess: [
// {
// requestId: null,
// requestName: '',
// baseUrl: ''
// }
]
})
const preProcessForm = reactive({
requestName: ''
})
const pageInfo = reactive({
pageNum: 1,
pageSize: 10,
})
const getPreProcessTag = (impact,basicImpact) => {
let data=''
if(impact){
data= impact
}else if(basicImpact){
data= basicImpact
}
if (data == 1) {
//一般项目
return '研发费用20万元以下科技创新项目报总经理审批'
} else if (data == 2) {
//重大项目
return '重大项目20万元到500万元之间要总办会审批'
} else if (data == 3) {
//特别重大项目
return '特别重大项目500万元以上要董事会审批'
}
}
const handleReset = () => {
preProcessForm.requestName = ''
getPreProcessList()
}
const handleSelect = async (selection) => {
selectRows.value = selection
}
const checkSelectable=(row)=>{
const detailProcessStr = localStorage.getItem('detailProcess');
let preProcessArray = []
if (detailProcessStr) {
try {
preProcessArray = JSON.parse(detailProcessStr)
} catch (e) {
preProcessArray=[]
}
if (preProcessArray&&preProcessArray.length > 0) {
for (let i = 0; i < preProcessArray.length; i++) {
return preProcessArray[i].requestId !== row.requestId;
}
}else{
return true
}
}
}
const handleShowPreTable = () => {
showPreTable.value = true
nextTick(() => {
localFormData.value.preProcess?.forEach((item) => {
if (preProcessTable.value) {
preProcessTable.value.toggleRowSelection(item, true)
}
})
})
getPreProcessList()
}
const handleCancel = () => {
showPreTable.value = false
}
const choosePreProcess = () => {
let preProcessObj = {}
let preProcessArray = []
const detailProcessStr = localStorage.getItem('detailProcess');
try {
originalProcess.value = JSON.parse(detailProcessStr)
} catch (e) {
originalProcess.value=[]
}
selectRows.value.forEach((item) => {
const exists = originalProcess.value?.some(dp => dp.requestId === item.requestId)
if (!exists) {
preProcessObj = {
requestId: item.requestId,
requestName: item.requestName,
baseUrl: item.baseUrl
}
preProcessArray.push(preProcessObj)
}
})
if(props.formData.mode === 'view'||props.formData.mode === 'resubmit'){
localFormData.value.preProcess = [...originalProcess.value,...preProcessArray]
}else{
localFormData.value.preProcess = preProcessArray
}
localStorage.setItem('preProcess', JSON.stringify(preProcessArray))
showPreTable.value = false
}
const getPreProcessList = () => {
loading.value = true
getPreProcess().then(res => {
loading.value = false
let searchArray = []
let regexPattern = ("%" + preProcessForm.requestName + "%").replace(/%/g, '.*').replace(/_/g, '.');
let regex = new RegExp('^' + regexPattern + '$');
res.data.filter((item) => {
if (regex.test(item.requestName)) {
searchArray.push(item)
}
})
total.value = searchArray.length
currentList.value = searchArray
preProcessList.value = currentList.value.slice(0, 10)
})
}
//切换每页显示条数
const handleSizeChange = (val) => {
pageInfo.pageSize = val;
preProcessList.value = currentList.value.slice((pageInfo.pageNum - 1) * val, pageInfo.pageNum * val)
};
//点击页码进行分页功能
const handleCurrentChange = (val) => {
pageInfo.pageNum = val;
preProcessList.value = currentList.value.slice((val - 1) * pageInfo.pageSize, val * pageInfo.pageSize)
};
watchEffect(() => {
return Object.keys(props.formData).length && (localFormData.value = props.formData)
})
</script>
<style scoped>
.oper {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
</style>

View File

@@ -1,63 +1,63 @@
<template>
<div class="tag-style">
<el-tag v-if="tagConfig?.isType" :type="tagConfig?.listClass" :effect="tagConfig?.theme || 'plain'">
{{ filterDict(cacheStore.getDict(dictType), value) }}
</el-tag>
<el-tag v-else :color="tagConfig?.listClass" :effect="tagConfig?.theme || 'plain'"
:class="{'null-tag':filterDict(cacheStore.getDict(dictType), value)===undefined}">
{{ filterDict(cacheStore.getDict(dictType), value) }}
</el-tag>
</div>
</template>
<script setup>
import {useCacheStore} from "@/stores/cache.js";
import {defineProps, nextTick} from "vue";
const cacheStore = useCacheStore();
const props = defineProps({
dictType: {
type: String,
default: "",
required: true
},
value: {
type: String || Number,
default: null
}
});
const tagConfig = ref({})
const filterDict = (data, value) => {
if (!data || value == null) return
if (data instanceof Array) {
if (value == true || value == false) {
tagConfig.value = data.find(item => item.value == value.toString())
} else if (typeof value === "object") {
if (value !== null) {
tagConfig.value = data.find(item => item.value == value[0])
} else {
tagConfig.value = {}
}
} else {
tagConfig.value = data.find(item => item.value == value)
}
}
return tagConfig.value?.label || '未知'
}
</script>
<style scoped lang="scss">
.tag-style {
:deep(.el-tag.el-tag--dark) {
border-color: transparent !important;
}
.null-tag {
border-color: transparent;
background-color: transparent;
}
}
</style>
<template>
<div class="tag-style">
<el-tag v-if="tagConfig?.isType" :type="tagConfig?.listClass" :effect="tagConfig?.theme || 'plain'">
{{ filterDict(cacheStore.getDict(dictType), value) }}
</el-tag>
<el-tag v-else :color="tagConfig?.listClass" :effect="tagConfig?.theme || 'plain'"
:class="{'null-tag':filterDict(cacheStore.getDict(dictType), value)===undefined}">
{{ filterDict(cacheStore.getDict(dictType), value) }}
</el-tag>
</div>
</template>
<script setup>
import {useCacheStore} from "@/stores/cache.js";
import {defineProps, nextTick} from "vue";
const cacheStore = useCacheStore();
const props = defineProps({
dictType: {
type: String,
default: "",
required: true
},
value: {
type: String || Number,
default: null
}
});
const tagConfig = ref({})
const filterDict = (data, value) => {
if (!data || value == null) return
if (data instanceof Array) {
if (value == true || value == false) {
tagConfig.value = data.find(item => item.value == value.toString())
} else if (typeof value === "object") {
if (value !== null) {
tagConfig.value = data.find(item => item.value == value[0])
} else {
tagConfig.value = {}
}
} else {
tagConfig.value = data.find(item => item.value == value)
}
}
return tagConfig.value?.label || '未知'
}
</script>
<style scoped lang="scss">
.tag-style {
:deep(.el-tag.el-tag--dark) {
border-color: transparent !important;
}
.null-tag {
border-color: transparent;
background-color: transparent;
}
}
</style>

View File

@@ -1,120 +1,120 @@
<template>
<baseTitle title="标签名称"></baseTitle>
<el-form :model="formData" ref="tagForm" label-width="auto" :rules="rules">
<el-form-item label="标签名称" prop="tagName">
<el-input v-model="formData.tagName" placeholder="请输入标签名称" style="width: 300px" v-if="showInput"/>
<el-select v-model="formData.tagName" placeholder="请选择标签" remote clearable filterable style="width: 300px" v-else>
<el-option
v-for="item in tagsOption"
:key="item.label"
:label="item.value"
:value="item.label"
/>
</el-select>
</el-form-item>
</el-form>
<baseTitle title="其他文件"></baseTitle>
<el-card style="width: 100%;margin: 15px 0">
<file-upload @getFile="getFiles"/>
<fvTable style="width: 100%;max-height: 160px;height: 160px" height="160" v-if="showTable" :tableConfig="tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-card>
<div class="oper-page-btn">
<el-button color="#DED0B2" @click="handleSubmit(tagForm)">提交</el-button>
</div>
</template>
<script setup lang="jsx">
const props = defineProps({
tagsOption: {
type: Array,
default: []
}, formData: {
type: Array,
default: []
}, showInput: {
type: Boolean,
default: true
},
})
const rules = reactive({
tagName: [{required: true, message: '请输入标签名称', trigger: ['blur', 'change']}],
})
const tagForm = ref()
const showTable = ref(true)
const emits = defineEmits(['getFile'])
const fileList = ref([])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'tag',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const compositeParam = (item) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: formData.value.tagName,
}
}
const getFiles = (val) => {
showTable.value = false
let fileObj = compositeParam(val)
// emit("getFile", fileObj)
fileList.value.push(fileObj)
nextTick(() => {
showTable.value = true
})
}
watch(() => fileList.value, (val) => {
fileList.value = val
})
defineExpose({
fileList
})
</script>
<style scoped>
</style>
<template>
<baseTitle title="标签名称"></baseTitle>
<el-form :model="formData" ref="tagForm" label-width="auto" :rules="rules">
<el-form-item label="标签名称" prop="tagName">
<el-input v-model="formData.tagName" placeholder="请输入标签名称" style="width: 300px" v-if="showInput"/>
<el-select v-model="formData.tagName" placeholder="请选择标签" remote clearable filterable style="width: 300px" v-else>
<el-option
v-for="item in tagsOption"
:key="item.label"
:label="item.value"
:value="item.label"
/>
</el-select>
</el-form-item>
</el-form>
<baseTitle title="其他文件"></baseTitle>
<el-card style="width: 100%;margin: 15px 0">
<file-upload @getFile="getFiles"/>
<fvTable style="width: 100%;max-height: 160px;height: 160px" height="160" v-if="showTable" :tableConfig="tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-card>
<div class="oper-page-btn">
<el-button color="#DED0B2" @click="handleSubmit(tagForm)">提交</el-button>
</div>
</template>
<script setup lang="jsx">
const props = defineProps({
tagsOption: {
type: Array,
default: []
}, formData: {
type: Array,
default: []
}, showInput: {
type: Boolean,
default: true
},
})
const rules = reactive({
tagName: [{required: true, message: '请输入标签名称', trigger: ['blur', 'change']}],
})
const tagForm = ref()
const showTable = ref(true)
const emits = defineEmits(['getFile'])
const fileList = ref([])
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'tag',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const compositeParam = (item) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: formData.value.tagName,
}
}
const getFiles = (val) => {
showTable.value = false
let fileObj = compositeParam(val)
// emit("getFile", fileObj)
fileList.value.push(fileObj)
nextTick(() => {
showTable.value = true
})
}
watch(() => fileList.value, (val) => {
fileList.value = val
})
defineExpose({
fileList
})
</script>
<style scoped>
</style>

View File

@@ -1,86 +1,86 @@
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vues
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
you need to test your components and web pages, check out
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
<a href="https://on.cypress.io/component" target="_blank">Cypress Component Testing</a>.
<br />
More instructions are available in <code>README.md</code>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
you need more resources, we suggest paying
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
Discord server, or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
>StackOverflow</a
>. You should also subscribe to
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
the official
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
twitter account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
</WelcomeItem>
</template>
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vues
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
you need to test your components and web pages, check out
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
<a href="https://on.cypress.io/component" target="_blank">Cypress Component Testing</a>.
<br />
More instructions are available in <code>README.md</code>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
you need more resources, we suggest paying
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
Discord server, or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
>StackOverflow</a
>. You should also subscribe to
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
the official
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
twitter account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
</WelcomeItem>
</template>

View File

@@ -1,286 +1,286 @@
<template>
<div class="tinymce-boxz" style="width: 100%">
<Editor v-model="content" :init="init"/>
</div>
</template>
<script setup>
import tinymce from 'tinymce'
import Editor from "@tinymce/tinymce-vue";
import {defineProps} from "vue";
import {ElLoading, ElMessage, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
import 'tinymce/themes/silver'
import 'tinymce/icons/default/icons'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/visualchars'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/media'
import 'tinymce/plugins/template'
import 'tinymce/plugins/code'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/table'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/autosave'
import '@/assets/axupimgs/plugin.js'//多图上传插件
const emit = defineEmits(['update:value','getFiles'])
const props = defineProps({
//默认值
value: {
type: String,
default: "",
},
imageUrl: {
type: String,
default: "",
},
fileUrl: {
type: String,
default: "",
},
plugins: {
type: [String, Array],
default:
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image axupimgs link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave",
},
toolbar: {
type: [String, Array],
default: [
"fullscreen undo redo | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ",
"styleselect formatselect fontselect fontsizeselect | table image axupimgs media pagebreak insertdatetime selectall visualblocks searchreplace | code preview | indent2em lineheight formatpainter",
],
},
fontFormats: {
type: [String, Array],
default: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;"
},
width: {
type: String,
default: 'auto'
},
height: {
type: Number,
default: 500
}
})
const fileLists=ref([])
const content = ref(props.value);
const imgUrl = ref();
// const apiKey = reactive("v4zo4n22oanvco29ws5drh0pecuf3gh53clx53cccj3grjwg");
const init = reactive({
language_url: '/langs/zh_CN.js', //汉化路径是自定义的
skin_url: '/skins/ui/oxide', //皮肤
content_css: '/skins/content/default/content.css',
language: 'zh_CN',
placeholder: "在这里输入文字", //textarea中的提示信息
min_width: 300,
min_height: 200,
width: props.width,
height: props.height, //注引入autoresize插件时此属性失效
resize: "both", //编辑器宽高是否可变false-否,true-高可变,'both'-宽高均可,注意引号
promotion: false,
branding: false, //tiny技术支持信息是否显示
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
elementpath: false, //元素路径是否显示
font_formats: props.fontFormats, //字体样式
plugins: props.plugins, //插件配置 axupimgs indent2em
toolbar: props.toolbar, //工具栏配置设为false则隐藏
menubar: "file edit view format table tools", //菜单栏配置设为false则隐藏不配置则默认显示全部菜单也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
images_upload_url: '/workflow/process/file/upload', //后端处理程序的url建议直接自定义上传函数image_upload_handler这个就可以不用了
// images_upload_base_path: '/demo', //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
paste_data_images: true, //图片是否可粘贴
file_picker_types: "file image", //file image media分别对应三个类型文件的上传link插件image和axupimgs插件media插件。想屏蔽某个插件的上传就去掉对应的参数
// 文件上传处理函数
setup: function (editor) {
editor.on('change', function (e) {
tinymce.activeEditor.save();//执行自动保存
});
},
//此处为图片上传处理函数
images_upload_handler: (blobInfo, success) => {
// new Promise((resolve, reject) => {
let formData = new FormData()
formData.append('file', blobInfo.blob())
//上传图片接口 上传成功后返回图片地址,用于显示在富文本中
uploadFile(formData, props.imageUrl, success, true)
// }),
},
images_upload_handler_not_loading: (blobInfo, success) => {
let formData = new FormData()
formData.append('file', blobInfo.blob())
//上传图片接口
uploadFile(formData, props.imageUrl, success, false)
},
file_picker_callback: (callback, value, meta) => {
// 使用案例http://tinymce.ax-z.cn/general/upload-images.php
// meta.filetype //根据这个判断点击的是什么file image media
let filetype; //限制文件的上传类型,需要什么就添加什么的后缀
if (meta.filetype == "image") {
filetype = ".jpg, .jpeg, .png, .gif, .ico, .svg";
} else if (meta.filetype == "media") {
filetype = ".mp3, .mp4, .avi, .mov";
} else {
filetype =
".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4, .jpg, .jpeg, .png, .gif, .ico, .svg";
}
let inputElem = document.createElement("input"); //创建文件选择
inputElem.setAttribute("type", "file");
inputElem.setAttribute("accept", filetype);
inputElem.click();
inputElem.onchange = () => {
let file = inputElem.files[0]; //获取文件信息
let xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', import.meta.env.VITE_BASE_URL + props.imageUrl);
xhr.setRequestHeader(
'Authorization', getToken()
)
let loading = ElLoading.service({
lock: true,
text: '文件上传中...',
background: 'rgba(0, 0, 0, 0.7)',
})
xhr.onload = function () {
let res;
// if (xhr.status != 200) {
// failure('HTTP Error: ' + xhr.status);
// return;
// }
res = JSON.parse(xhr.responseText);
ElNotification({
title: '提示',
message: res.code === 1000 ? '上传成功' : '上传失败',
type: res.code === 1000 ? 'success' : 'error'
})
loading.close()
console.log("🚀 ~ file:res.data ", res.data)
res.data.originalFileName=res.data.originalFilename
console.log("🚀 ~ file:'meta.filetype ",meta.filetype )
if (res && res.data && res.data.fileType &&
!["png", "jpg", "jpeg","gif", "svg","ico"].includes(res.data.fileType.toLowerCase())){
fileLists.value.push(res.data)
emit('getFiles',fileLists.value)
}
const fileUrl = res.data.url;
// '?fileId='+res.data.id+
callback(fileUrl + '?fileName=' + res.data.originalFilename, {text: file.name, title: file.name});
};
formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
//
// let reader = new FileReader();
// reader.readAsDataURL(file);
// reader.onload = function () {
// let formData;
// let id = "blobid" + new Date().getTime();
// let blobCache = tinymce.activeEditor.editorUpload.blobCache;
// let base64 = reader.result.split(",")[1];
// let blobInfo = blobCache.create(id, file, base64);
// blobCache.add(blobInfo);
// // callback(blobInfo.blobUri(), {alt: file.name});
// formData = new FormData();
// formData.append('file', file, file.name );
// uploadFile(formData, props.imageUrl,callback)
// };
};
},
});
//内容有变化,就更新内容,将值返回给父组件
watch(() => {
emit("update:value", content.value);
});
const uploadFile = (formData, url, success, isLoading) => {
let loading = null
if (isLoading) {
loading = ElLoading.service({
lock: true,
text: '图片上传中...',
background: 'rgba(0, 0, 0, 0.7)',
})
}
axios.post(
import.meta.env.VITE_BASE_URL + url,
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
Authorization: getToken()
}
}
).then(res => {
// if (res.status !== 200) {
// ElMessage.error("上传失败!")
// }
let data = res.data
if (data.code !== 1000) {
ElMessage.error(data.msg)
if (loading) {
loading.close()
}
} else {
if (isLoading) {
success(data.data.url)
} else {
success(data.data.url, data.data.originalFilename)
}
if (loading) {
loading.close()
}
}
})
}
</script>
<style scoped lang="scss">
.tox-sidebar-wrap {
&::-webkit-scrollbar {
width: 6px;
}
// 滚动条轨道
&::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
// 小滑块
&::-webkit-scrollbar-thumb {
background: rgba(80, 81, 82, 0.29);
border-radius: 10px;
}
}
.tinymce-boxz > textarea {
display: none;
}
</style>
<style lang="scss">
/* 隐藏apikey没有绑定当前域名的提示 */
.tox-notifications-container .tox-notification--warning {
display: none !important;
}
.tox.tox-tinymce {
max-width: 100%;
}
</style>
<template>
<div class="tinymce-boxz" style="width: 100%">
<Editor v-model="content" :init="init"/>
</div>
</template>
<script setup>
import tinymce from 'tinymce'
import Editor from "@tinymce/tinymce-vue";
import {defineProps} from "vue";
import {ElLoading, ElMessage, ElNotification} from "element-plus";
import {getToken} from '@/utils/auth'
import axios from "axios";
import 'tinymce/themes/silver'
import 'tinymce/icons/default/icons'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/directionality'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/visualchars'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/media'
import 'tinymce/plugins/template'
import 'tinymce/plugins/code'
import 'tinymce/plugins/codesample'
import 'tinymce/plugins/table'
import 'tinymce/plugins/pagebreak'
import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/autosave'
import '@/assets/axupimgs/plugin.js'//多图上传插件
const emit = defineEmits(['update:value','getFiles'])
const props = defineProps({
//默认值
value: {
type: String,
default: "",
},
imageUrl: {
type: String,
default: "",
},
fileUrl: {
type: String,
default: "",
},
plugins: {
type: [String, Array],
default:
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image axupimgs link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave",
},
toolbar: {
type: [String, Array],
default: [
"fullscreen undo redo | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ",
"styleselect formatselect fontselect fontsizeselect | table image axupimgs media pagebreak insertdatetime selectall visualblocks searchreplace | code preview | indent2em lineheight formatpainter",
],
},
fontFormats: {
type: [String, Array],
default: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;"
},
width: {
type: String,
default: 'auto'
},
height: {
type: Number,
default: 500
}
})
const fileLists=ref([])
const content = ref(props.value);
const imgUrl = ref();
// const apiKey = reactive("v4zo4n22oanvco29ws5drh0pecuf3gh53clx53cccj3grjwg");
const init = reactive({
language_url: '/langs/zh_CN.js', //汉化路径是自定义的
skin_url: '/skins/ui/oxide', //皮肤
content_css: '/skins/content/default/content.css',
language: 'zh_CN',
placeholder: "在这里输入文字", //textarea中的提示信息
min_width: 300,
min_height: 200,
width: props.width,
height: props.height, //注引入autoresize插件时此属性失效
resize: "both", //编辑器宽高是否可变false-否,true-高可变,'both'-宽高均可,注意引号
promotion: false,
branding: false, //tiny技术支持信息是否显示
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
elementpath: false, //元素路径是否显示
font_formats: props.fontFormats, //字体样式
plugins: props.plugins, //插件配置 axupimgs indent2em
toolbar: props.toolbar, //工具栏配置设为false则隐藏
menubar: "file edit view format table tools", //菜单栏配置设为false则隐藏不配置则默认显示全部菜单也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
images_upload_url: '/workflow/process/file/upload', //后端处理程序的url建议直接自定义上传函数image_upload_handler这个就可以不用了
// images_upload_base_path: '/demo', //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
paste_data_images: true, //图片是否可粘贴
file_picker_types: "file image", //file image media分别对应三个类型文件的上传link插件image和axupimgs插件media插件。想屏蔽某个插件的上传就去掉对应的参数
// 文件上传处理函数
setup: function (editor) {
editor.on('change', function (e) {
tinymce.activeEditor.save();//执行自动保存
});
},
//此处为图片上传处理函数
images_upload_handler: (blobInfo, success) => {
// new Promise((resolve, reject) => {
let formData = new FormData()
formData.append('file', blobInfo.blob())
//上传图片接口 上传成功后返回图片地址,用于显示在富文本中
uploadFile(formData, props.imageUrl, success, true)
// }),
},
images_upload_handler_not_loading: (blobInfo, success) => {
let formData = new FormData()
formData.append('file', blobInfo.blob())
//上传图片接口
uploadFile(formData, props.imageUrl, success, false)
},
file_picker_callback: (callback, value, meta) => {
// 使用案例http://tinymce.ax-z.cn/general/upload-images.php
// meta.filetype //根据这个判断点击的是什么file image media
let filetype; //限制文件的上传类型,需要什么就添加什么的后缀
if (meta.filetype == "image") {
filetype = ".jpg, .jpeg, .png, .gif, .ico, .svg";
} else if (meta.filetype == "media") {
filetype = ".mp3, .mp4, .avi, .mov";
} else {
filetype =
".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4, .jpg, .jpeg, .png, .gif, .ico, .svg";
}
let inputElem = document.createElement("input"); //创建文件选择
inputElem.setAttribute("type", "file");
inputElem.setAttribute("accept", filetype);
inputElem.click();
inputElem.onchange = () => {
let file = inputElem.files[0]; //获取文件信息
let xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', import.meta.env.VITE_BASE_URL + props.imageUrl);
xhr.setRequestHeader(
'Authorization', getToken()
)
let loading = ElLoading.service({
lock: true,
text: '文件上传中...',
background: 'rgba(0, 0, 0, 0.7)',
})
xhr.onload = function () {
let res;
// if (xhr.status != 200) {
// failure('HTTP Error: ' + xhr.status);
// return;
// }
res = JSON.parse(xhr.responseText);
ElNotification({
title: '提示',
message: res.code === 1000 ? '上传成功' : '上传失败',
type: res.code === 1000 ? 'success' : 'error'
})
loading.close()
console.log("🚀 ~ file:res.data ", res.data)
res.data.originalFileName=res.data.originalFilename
console.log("🚀 ~ file:'meta.filetype ",meta.filetype )
if (res && res.data && res.data.fileType &&
!["png", "jpg", "jpeg","gif", "svg","ico"].includes(res.data.fileType.toLowerCase())){
fileLists.value.push(res.data)
emit('getFiles',fileLists.value)
}
const fileUrl = res.data.url;
// '?fileId='+res.data.id+
callback(fileUrl + '?fileName=' + res.data.originalFilename, {text: file.name, title: file.name});
};
formData = new FormData();
formData.append('file', file, file.name);
xhr.send(formData);
//
// let reader = new FileReader();
// reader.readAsDataURL(file);
// reader.onload = function () {
// let formData;
// let id = "blobid" + new Date().getTime();
// let blobCache = tinymce.activeEditor.editorUpload.blobCache;
// let base64 = reader.result.split(",")[1];
// let blobInfo = blobCache.create(id, file, base64);
// blobCache.add(blobInfo);
// // callback(blobInfo.blobUri(), {alt: file.name});
// formData = new FormData();
// formData.append('file', file, file.name );
// uploadFile(formData, props.imageUrl,callback)
// };
};
},
});
//内容有变化,就更新内容,将值返回给父组件
watch(() => {
emit("update:value", content.value);
});
const uploadFile = (formData, url, success, isLoading) => {
let loading = null
if (isLoading) {
loading = ElLoading.service({
lock: true,
text: '图片上传中...',
background: 'rgba(0, 0, 0, 0.7)',
})
}
axios.post(
import.meta.env.VITE_BASE_URL + url,
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
Authorization: getToken()
}
}
).then(res => {
// if (res.status !== 200) {
// ElMessage.error("上传失败!")
// }
let data = res.data
if (data.code !== 1000) {
ElMessage.error(data.msg)
if (loading) {
loading.close()
}
} else {
if (isLoading) {
success(data.data.url)
} else {
success(data.data.url, data.data.originalFilename)
}
if (loading) {
loading.close()
}
}
})
}
</script>
<style scoped lang="scss">
.tox-sidebar-wrap {
&::-webkit-scrollbar {
width: 6px;
}
// 滚动条轨道
&::-webkit-scrollbar-track {
background: rgb(239, 239, 239);
border-radius: 2px;
}
// 小滑块
&::-webkit-scrollbar-thumb {
background: rgba(80, 81, 82, 0.29);
border-radius: 10px;
}
}
.tinymce-boxz > textarea {
display: none;
}
</style>
<style lang="scss">
/* 隐藏apikey没有绑定当前域名的提示 */
.tox-notifications-container .tox-notification--warning {
display: none !important;
}
.tox.tox-tinymce {
max-width: 100%;
}
</style>

View File

@@ -1,63 +1,63 @@
<template>
<el-tooltip
effect="dark"
:content="props.content"
placement="bottom-start"
:disabled="isShow"
>
<div :class="lines?'content-lines':textAlign=='left'?'left-content':'content'" :style="{width: props.width+'px'}" @mouseover="isShowTooltip">
<span ref="contentRef">
<slot name="content">{{ props.content }}</slot>
</span>
</div>
</el-tooltip>
</template>
<script setup>
const props = defineProps({
content: {
type: String,
default: ''
},
width: {
type: String,
default: '100%'
},
lines: {
type: Boolean,
default: false
},
textAlign: {
type: String,
default: ''
},
})
const contentRef = ref()
const isShow = ref(false)
const isShowTooltip = () => {
isShow.value = parseInt(props.width) > contentRef.value.offsetWidth;
}
</script>
<style scoped>
.left-content{
width: 45px;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.content {
width: 45px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.content-lines{
word-break:break-all;
overflow:hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
</style>
<template>
<el-tooltip
effect="dark"
:content="props.content"
placement="bottom-start"
:disabled="isShow"
>
<div :class="lines?'content-lines':textAlign=='left'?'left-content':'content'" :style="{width: props.width+'px'}" @mouseover="isShowTooltip">
<span ref="contentRef">
<slot name="content">{{ props.content }}</slot>
</span>
</div>
</el-tooltip>
</template>
<script setup>
const props = defineProps({
content: {
type: String,
default: ''
},
width: {
type: String,
default: '100%'
},
lines: {
type: Boolean,
default: false
},
textAlign: {
type: String,
default: ''
},
})
const contentRef = ref()
const isShow = ref(false)
const isShowTooltip = () => {
isShow.value = parseInt(props.width) > contentRef.value.offsetWidth;
}
</script>
<style scoped>
.left-content{
width: 45px;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.content {
width: 45px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.content-lines{
word-break:break-all;
overflow:hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
</style>

View File

@@ -1,85 +1,85 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>

View File

@@ -1,33 +1,33 @@
<template>
<div class="base-title">
<span></span>
<span>{{ title }}</span>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
default: ''
}
})
</script>
<style lang="scss" scoped>
.base-title {
display: flex;
justify-content: flex-start;
align-items: center;
margin: 15px 0;
font-weight: bold;
>span:first-child {
display: inline-block;
width: 10px;
height: 20px;
background: #BEA266;
margin-right: 5px;
}
}
<template>
<div class="base-title">
<span></span>
<span>{{ title }}</span>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
default: ''
}
})
</script>
<style lang="scss" scoped>
.base-title {
display: flex;
justify-content: flex-start;
align-items: center;
margin: 15px 0;
font-weight: bold;
>span:first-child {
display: inline-block;
width: 10px;
height: 20px;
background: #BEA266;
margin-right: 5px;
}
}
</style>

View File

@@ -1,69 +1,69 @@
<template>
<codemirror
v-model="javaCode"
:placeholder="editorPlaceholder"
:style="{ height: editorHeight+'px' }"
:autofocus="true"
:indent-with-tab="true"
:tabSize="tabSize"
:extensions="extensions"
:scrollbarStyle="null"
/>
</template>
<script setup>
import {Codemirror} from "vue-codemirror";
import {java, javaLanguage} from "@codemirror/lang-java";
const emit = defineEmits()
const props = defineProps({
value: {
type: String,
default: "",
},
editorPlaceholder: {
type: String,
default: "请输入代码",
},
editorHeight: {
type: String,
default: "300",
},
tabSize: {
type: Number,
default: 2,
}
})
const _value = computed({
get() {
return props.value || ""
},
set(value) {
emit('update:value', value)
}
})
const javaCode = ref();
const customJavaCodeTips = (context) => {
let word = context.matchBefore(/\w*/)
if (word.from == word.to && !context.explicit) return null;
return {
from: word.from?word.from:context.pos,
options: [
{label: "function", type: "keyword",apply:"function name(params) {\n\t\n}",detail: "definition"},
// {label: "hello", type: "variable", info: "(World)"},
{label: "fori", type: "keyword",apply:"for (let i = 0; i < list.length; i++) {\n\n}", detail: "loop"},
{label: "for", type: "keyword",apply:"for (let name of list) {\n\n}", detail: "of loop"},
{label: "psf", type: "keyword",apply:"public static final ", detail: "public static final"},
{label: "psv", type: "keyword",apply:"public static void name(){\n\n}", detail: "public static void"},
{label: "psfi", type: "keyword",apply:"public static final int ", detail: "public static final int"},
{label: "psfs", type: "keyword",apply:"public static final String ", detail: "public static final String"},
{label: "psvm", type: "keyword", apply: "public static void main(String[] args){\n\t\n}", detail: "main() 方法声明"}
]
}
}
const javaSnippets = javaLanguage.data.of({
autocomplete: customJavaCodeTips,
})
const extensions = ref([java(), javaSnippets]);
</script>
<template>
<codemirror
v-model="javaCode"
:placeholder="editorPlaceholder"
:style="{ height: editorHeight+'px' }"
:autofocus="true"
:indent-with-tab="true"
:tabSize="tabSize"
:extensions="extensions"
:scrollbarStyle="null"
/>
</template>
<script setup>
import {Codemirror} from "vue-codemirror";
import {java, javaLanguage} from "@codemirror/lang-java";
const emit = defineEmits()
const props = defineProps({
value: {
type: String,
default: "",
},
editorPlaceholder: {
type: String,
default: "请输入代码",
},
editorHeight: {
type: String,
default: "300",
},
tabSize: {
type: Number,
default: 2,
}
})
const _value = computed({
get() {
return props.value || ""
},
set(value) {
emit('update:value', value)
}
})
const javaCode = ref();
const customJavaCodeTips = (context) => {
let word = context.matchBefore(/\w*/)
if (word.from == word.to && !context.explicit) return null;
return {
from: word.from?word.from:context.pos,
options: [
{label: "function", type: "keyword",apply:"function name(params) {\n\t\n}",detail: "definition"},
// {label: "hello", type: "variable", info: "(World)"},
{label: "fori", type: "keyword",apply:"for (let i = 0; i < list.length; i++) {\n\n}", detail: "loop"},
{label: "for", type: "keyword",apply:"for (let name of list) {\n\n}", detail: "of loop"},
{label: "psf", type: "keyword",apply:"public static final ", detail: "public static final"},
{label: "psv", type: "keyword",apply:"public static void name(){\n\n}", detail: "public static void"},
{label: "psfi", type: "keyword",apply:"public static final int ", detail: "public static final int"},
{label: "psfs", type: "keyword",apply:"public static final String ", detail: "public static final String"},
{label: "psvm", type: "keyword", apply: "public static void main(String[] args){\n\t\n}", detail: "main() 方法声明"}
]
}
}
const javaSnippets = javaLanguage.data.of({
autocomplete: customJavaCodeTips,
})
const extensions = ref([java(), javaSnippets]);
</script>

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