Compare commits
209 Commits
v4.0
...
pr@dev@per
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
150795ebac | ||
|
|
a636bb2037 | ||
|
|
9b6f54c1ed | ||
|
|
611341307b | ||
|
|
f8479c53ff | ||
|
|
e25bf46659 | ||
|
|
6d07307e56 | ||
|
|
6fb7fe8fa1 | ||
|
|
19cd497095 | ||
|
|
d858489367 | ||
|
|
341a30ba06 | ||
|
|
8390fb7429 | ||
|
|
5389f1d011 | ||
|
|
bde642570f | ||
|
|
3e7b970fe7 | ||
|
|
2421e822b4 | ||
|
|
b2e474e3f6 | ||
|
|
541836390a | ||
|
|
bb92e3f22b | ||
|
|
c9ad797b40 | ||
|
|
2a08310efc | ||
|
|
3b2803b9a1 | ||
|
|
1b8ac9112e | ||
|
|
9cc3dd4de9 | ||
|
|
120ef70eb1 | ||
|
|
541f4ebc62 | ||
|
|
a47636abc7 | ||
|
|
78f6f4b36a | ||
|
|
5abc0b77cf | ||
|
|
464638e782 | ||
|
|
37cfeb2077 | ||
|
|
44e297f01a | ||
|
|
febc283e36 | ||
|
|
dae33f55e8 | ||
|
|
c62cd27690 | ||
|
|
83443f8187 | ||
|
|
cb46f393e0 | ||
|
|
ddf5ac2151 | ||
|
|
88173f852a | ||
|
|
d5f16e90e2 | ||
|
|
d1c0aca4ff | ||
|
|
a42edf17ec | ||
|
|
dac5dfcd1c | ||
|
|
8e6ca146e1 | ||
|
|
9c06d36eab | ||
|
|
ab7bd574f8 | ||
|
|
6007dc8621 | ||
|
|
a0e7c48dc9 | ||
|
|
71dea791bf | ||
|
|
e1b9184f41 | ||
|
|
730d47f02a | ||
|
|
e82ec68935 | ||
|
|
e8e5975d7f | ||
|
|
3cb9dec978 | ||
|
|
c025441075 | ||
|
|
050b50fa74 | ||
|
|
e26befabc3 | ||
|
|
8545fc6136 | ||
|
|
e343e0df9d | ||
|
|
74519e6f3c | ||
|
|
1305f90372 | ||
|
|
bbc3f53c0a | ||
|
|
aa605adbc7 | ||
|
|
49ea7d0969 | ||
|
|
4221bdb2ab | ||
|
|
af4010e299 | ||
|
|
9b7c4ed353 | ||
|
|
879df90503 | ||
|
|
41f841532f | ||
|
|
0b9f47dd84 | ||
|
|
d32a376e8c | ||
|
|
0f8a8845df | ||
|
|
8bb2c66b99 | ||
|
|
b3d0be2f60 | ||
|
|
5a94ddd976 | ||
|
|
7b9627a80b | ||
|
|
5fcfecc060 | ||
|
|
f4d7a2283c | ||
|
|
40bb8410d3 | ||
|
|
45344ac620 | ||
|
|
5b894c9667 | ||
|
|
d89bd15b6d | ||
|
|
5e640dd45c | ||
|
|
09aa750794 | ||
|
|
744b215800 | ||
|
|
f4e11da053 | ||
|
|
2e6b5706d5 | ||
|
|
440a5b27ef | ||
|
|
932e16844e | ||
|
|
aff2e439dd | ||
|
|
a618794c14 | ||
|
|
8dd66c400a | ||
|
|
ac3ce464b7 | ||
|
|
4d01c6dabe | ||
|
|
47eeac23eb | ||
|
|
592f783245 | ||
|
|
c34ac6a56f | ||
|
|
9a7162cc9e | ||
|
|
5edf2f34dd | ||
|
|
859d824195 | ||
|
|
c382cc633e | ||
|
|
653e24773f | ||
|
|
ae489610ee | ||
|
|
b5e85c66e4 | ||
|
|
4060fa4c4a | ||
|
|
9630b79daa | ||
|
|
ad93917387 | ||
|
|
691590da7b | ||
|
|
71828fd78b | ||
|
|
5a45f31ac4 | ||
|
|
44901eee23 | ||
|
|
2d91fa107d | ||
|
|
7a6ade4bd9 | ||
|
|
951778668f | ||
|
|
0aca23bf38 | ||
|
|
9b97dc9a74 | ||
|
|
32cd030479 | ||
|
|
607bb476db | ||
|
|
1d676ec9b7 | ||
|
|
614ebb4121 | ||
|
|
8c2719a95d | ||
|
|
c6b0a958a6 | ||
|
|
3edebf3f4f | ||
|
|
f63405978e | ||
|
|
c582c8de98 | ||
|
|
c44e79ed3b | ||
|
|
fc7d5b9c29 | ||
|
|
335febd4a5 | ||
|
|
5ea2918fe7 | ||
|
|
7668d10ba5 | ||
|
|
df15d141da | ||
|
|
e2f4bbde79 | ||
|
|
3ca7de42af | ||
|
|
e6a577ba9b | ||
|
|
6290179460 | ||
|
|
4f3c9e9353 | ||
|
|
aa28a8f765 | ||
|
|
98d0a52fa2 | ||
|
|
8d9e1ffadb | ||
|
|
b3be312a4d | ||
|
|
7c41d148aa | ||
|
|
6dee911642 | ||
|
|
6dd35e5173 | ||
|
|
fdaa33f68d | ||
|
|
0b813bb719 | ||
|
|
7ba6b8d4e4 | ||
|
|
ef99e25fde | ||
|
|
d1e7b907e3 | ||
|
|
83f7dda5e7 | ||
|
|
80f929fdea | ||
|
|
1ec3d02933 | ||
|
|
fdf148cc2b | ||
|
|
c9e6ef89dc | ||
|
|
59f9f88f8b | ||
|
|
16417ae843 | ||
|
|
58bd0a17c8 | ||
|
|
c4a1eb6938 | ||
|
|
b7d9031889 | ||
|
|
96b29a9dc2 | ||
|
|
336e176639 | ||
|
|
2df4a9d66d | ||
|
|
45a102cff1 | ||
|
|
57ebfa0812 | ||
|
|
4e9dd57efe | ||
|
|
3fcc4ca160 | ||
|
|
958760811c | ||
|
|
b60e0251c2 | ||
|
|
3db0ed756e | ||
|
|
453c4b1e4e | ||
|
|
bf4d8ce7a6 | ||
|
|
34effdbe15 | ||
|
|
274db466f2 | ||
|
|
cbe697f9dc | ||
|
|
fb7acb100e | ||
|
|
ebb36847df | ||
|
|
beba4f1994 | ||
|
|
452796e3f5 | ||
|
|
02a7969d90 | ||
|
|
798dbec151 | ||
|
|
0e11a56e37 | ||
|
|
be5344344c | ||
|
|
e75d711e0a | ||
|
|
46ee116f3e | ||
|
|
f4b304338f | ||
|
|
e93e78307c | ||
|
|
d22079446f | ||
|
|
d57b99b00c | ||
|
|
e7321356af | ||
|
|
a0edc2c527 | ||
|
|
10ebcfd64d | ||
|
|
a3fedb9697 | ||
|
|
1eb8a18c66 | ||
|
|
f491c57c34 | ||
|
|
50b7f54652 | ||
|
|
5bf298a5bf | ||
|
|
124ff9a8c2 | ||
|
|
387ab4f1b3 | ||
|
|
d6fbdfa7ea | ||
|
|
cd4260fd8d | ||
|
|
baeece62d3 | ||
|
|
576c8f5891 | ||
|
|
5e97600807 | ||
|
|
4e2eb3a37d | ||
|
|
e92173f8e8 | ||
|
|
412d9c804e | ||
|
|
b84a725d4a | ||
|
|
58b39743e0 | ||
|
|
7651443c25 | ||
|
|
8d64e331d1 |
72
.github/workflows/build-base-image.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: Build and Push Base Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'pr*'
|
||||||
|
paths:
|
||||||
|
- 'package.json'
|
||||||
|
- 'package-lock.json'
|
||||||
|
- 'yarn.lock'
|
||||||
|
- 'Dockerfile-base'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Lock Pull Request
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
-d '{"state":"pending", "description":"Action running, merge disabled", "context":"Lock PR"}' \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.sha }}"
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract date
|
||||||
|
id: vars
|
||||||
|
run: echo "IMAGE_TAG=$(date +'%Y%m%d_%H%M%S')" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Extract repository name
|
||||||
|
id: repo
|
||||||
|
run: echo "REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build and push multi-arch image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
file: Dockerfile-base
|
||||||
|
tags: jumpserver/${{ env.REPO }}-base:${{ env.IMAGE_TAG }}
|
||||||
|
|
||||||
|
- name: Update Dockerfile
|
||||||
|
run: |
|
||||||
|
sed -i 's|-base:.* AS stage-build|-base:${{ env.IMAGE_TAG }} AS stage-build|' Dockerfile
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
run: |
|
||||||
|
git config --global user.name 'github-actions[bot]'
|
||||||
|
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||||
|
git add Dockerfile
|
||||||
|
git commit -m "perf: Update Dockerfile with new base image tag"
|
||||||
|
git push
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Unlock Pull Request
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||||
|
-d '{"state":"success", "description":"Action running, merge disabled", "context":"Lock PR"}' \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.sha }}"
|
||||||
46
.github/workflows/jms-build-test.yml
vendored
@@ -1,46 +0,0 @@
|
|||||||
name: "Run Build Test"
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'Dockerfile'
|
|
||||||
- 'Dockerfile*'
|
|
||||||
- 'package.json'
|
|
||||||
- 'yarn.lock'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
component: [lina]
|
|
||||||
version: [v4]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Prepare Build
|
|
||||||
run: |
|
|
||||||
sed -i 's@registry.npmmirror.com@registry.yarnpkg.com@g' yarn.lock
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build Image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
file: Dockerfile
|
|
||||||
tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }}
|
|
||||||
platforms: linux/amd64
|
|
||||||
build-args: |
|
|
||||||
VERSION=${{ matrix.version }}
|
|
||||||
APT_MIRROR=http://deb.debian.org
|
|
||||||
NPM_REGISTRY=https://registry.yarnpkg.com
|
|
||||||
outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
46
.github/workflows/jms-build-test.yml.disabled
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: "Run Build Test"
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'Dockerfile'
|
||||||
|
- 'Dockerfile*'
|
||||||
|
- 'package.json'
|
||||||
|
- 'yarn.lock'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
component: [ lina ]
|
||||||
|
version: [ v4 ]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Prepare Build
|
||||||
|
run: |
|
||||||
|
sed -i 's@registry.npmmirror.com@registry.yarnpkg.com@g' yarn.lock
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build Image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
file: Dockerfile
|
||||||
|
tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }}
|
||||||
|
platforms: linux/amd64
|
||||||
|
build-args: |
|
||||||
|
VERSION=${{ matrix.version }}
|
||||||
|
APT_MIRROR=http://deb.debian.org
|
||||||
|
NPM_REGISTRY=https://registry.yarnpkg.com
|
||||||
|
outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
2
.github/workflows/release-drafter.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
tag: ${{ steps.get_version.outputs.TAG }}
|
tag: ${{ steps.get_version.outputs.TAG }}
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '16.20'
|
node-version: '20.15'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install
|
run: yarn install
|
||||||
- name: Build web
|
- name: Build web
|
||||||
|
|||||||
32
Dockerfile
@@ -1,34 +1,4 @@
|
|||||||
FROM node:16.20-bullseye-slim AS stage-build
|
FROM jumpserver/lina-base:20240723_084702 AS stage-build
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
ARG DEPENDENCIES=" \
|
|
||||||
g++ \
|
|
||||||
make \
|
|
||||||
python3"
|
|
||||||
|
|
||||||
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
|
|
||||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
|
||||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
|
||||||
set -ex \
|
|
||||||
&& rm -f /etc/apt/apt.conf.d/docker-clean \
|
|
||||||
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
|
|
||||||
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
|
|
||||||
&& echo "no" | dpkg-reconfigure dash
|
|
||||||
|
|
||||||
ARG NPM_REGISTRY="https://registry.npmmirror.com"
|
|
||||||
|
|
||||||
RUN set -ex \
|
|
||||||
&& npm config set registry ${NPM_REGISTRY} \
|
|
||||||
&& yarn config set registry ${NPM_REGISTRY}
|
|
||||||
|
|
||||||
WORKDIR /data
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn,sharing=locked \
|
|
||||||
--mount=type=bind,source=package.json,target=package.json \
|
|
||||||
--mount=type=bind,source=yarn.lock,target=yarn.lock \
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ENV VERSION=$VERSION
|
ENV VERSION=$VERSION
|
||||||
|
|||||||
22
Dockerfile-base
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
FROM node:20.15-bullseye-slim
|
||||||
|
|
||||||
|
ARG DEPENDENCIES=" \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
python3"
|
||||||
|
|
||||||
|
RUN set -ex \
|
||||||
|
&& rm -f /etc/apt/apt.conf.d/docker-clean \
|
||||||
|
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
|
||||||
|
&& echo "no" | dpkg-reconfigure dash
|
||||||
|
|
||||||
|
WORKDIR /data
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
|
||||||
|
ARG NPM_MIRROR="https://registry.npmjs.org"
|
||||||
|
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn,sharing=locked,id=yarn-cache \
|
||||||
|
sed -i "s|https://registry.npmmirror.com|${NPM_MIRROR}|g" yarn.lock \
|
||||||
|
&& yarn install
|
||||||
13
package.json
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "Lina",
|
"name": "lina",
|
||||||
"version": "v4.0.0",
|
"version": "v4.0.0",
|
||||||
"description": "JumpServer Web UI",
|
"description": "JumpServer Web UI",
|
||||||
"author": "JumpServer Team <support@fit2cloud.com>",
|
"author": "JumpServer Team <support@fit2cloud.com>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vue-cli-service serve",
|
"dev": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build",
|
||||||
"build:prod": "vue-cli-service build",
|
"build:prod": "vue-cli-service build",
|
||||||
"build:stage": "vue-cli-service build --mode staging",
|
"build:stage": "vue-cli-service build --mode staging",
|
||||||
"preview": "node build/index.js --preview",
|
"preview": "node build/index.js --preview",
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
"@ztree/ztree_v3": "3.5.44",
|
"@ztree/ztree_v3": "3.5.44",
|
||||||
"axios": "0.28.0",
|
"axios": "0.28.0",
|
||||||
"axios-retry": "^3.1.9",
|
"axios-retry": "^3.1.9",
|
||||||
|
"caniuse-lite": "^1.0.30001642",
|
||||||
"cron-parser": "^4.0.0",
|
"cron-parser": "^4.0.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"css-color-function": "^1.3.3",
|
"css-color-function": "^1.3.3",
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
"normalize.css": "7.0.0",
|
"normalize.css": "7.0.0",
|
||||||
"npm": "^7.8.0",
|
"npm": "^7.8.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"path-to-regexp": "2.4.0",
|
"path-to-regexp": "3.3.0",
|
||||||
"v-sanitize": "^0.0.13",
|
"v-sanitize": "^0.0.13",
|
||||||
"vue": "2.6.10",
|
"vue": "2.6.10",
|
||||||
"vue-codemirror": "4.0.6",
|
"vue-codemirror": "4.0.6",
|
||||||
@@ -116,7 +117,7 @@
|
|||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"script-ext-html-webpack-plugin": "2.1.3",
|
"script-ext-html-webpack-plugin": "2.1.3",
|
||||||
"script-loader": "0.7.2",
|
"script-loader": "0.7.2",
|
||||||
"serve-static": "^1.13.2",
|
"serve-static": "^1.16.0",
|
||||||
"strip-ansi": "^7.1.0",
|
"strip-ansi": "^7.1.0",
|
||||||
"svg-sprite-loader": "4.1.3",
|
"svg-sprite-loader": "4.1.3",
|
||||||
"svgo": "1.2.2",
|
"svgo": "1.2.2",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export function testEmailSetting(data) {
|
|||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function importLicense(formData) {
|
export function importLicense(formData) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/xpack/license/import',
|
url: '/api/v1/xpack/license/import',
|
||||||
@@ -25,6 +26,7 @@ export function importLicense(formData) {
|
|||||||
data: formData
|
data: formData
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function testLdapSetting(data, refresh = true) {
|
export function testLdapSetting(data, refresh = true) {
|
||||||
let url = '/api/v1/settings/ldap/testing/config/'
|
let url = '/api/v1/settings/ldap/testing/config/'
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
@@ -96,9 +98,17 @@ export function getPublicSettings(isOpen) {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLogo() {
|
export function getLogo() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/xpack/interface/setting/',
|
url: '/api/v1/xpack/interface/setting/',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPreference() {
|
||||||
|
return request({
|
||||||
|
url: '/api/v1/users/preference/?category=luna',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,10 +65,6 @@ export function logout() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function refreshSessionIdAge() {
|
|
||||||
return getProfile()
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getProfile,
|
getProfile,
|
||||||
getUserList
|
getUserList
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 961 B After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/img/icons/h3c.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 940 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -2,6 +2,7 @@
|
|||||||
<Dialog
|
<Dialog
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:title="$tc('Assets')"
|
:title="$tc('Assets')"
|
||||||
|
:disabled-status="!isLoaded"
|
||||||
custom-class="asset-select-dialog"
|
custom-class="asset-select-dialog"
|
||||||
top="2vh"
|
top="2vh"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@@ -22,6 +23,8 @@
|
|||||||
:url="baseUrl"
|
:url="baseUrl"
|
||||||
class="tree-table"
|
class="tree-table"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
|
v-on="$listeners"
|
||||||
|
@loaded="handleTableLoaded"
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
@@ -64,6 +67,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
const vm = this
|
const vm = this
|
||||||
return {
|
return {
|
||||||
|
isLoaded: false,
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
rowSelected: _.cloneDeep(this.value) || [],
|
rowSelected: _.cloneDeep(this.value) || [],
|
||||||
rowsAdd: [],
|
rowsAdd: [],
|
||||||
@@ -124,6 +128,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleTableLoaded() {
|
||||||
|
this.isLoaded = true
|
||||||
|
},
|
||||||
handleClose() {
|
handleClose() {
|
||||||
this.$refs.ListPage.$refs.TreeList.componentKey += 1
|
this.$refs.ListPage.$refs.TreeList.componentKey += 1
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
import Select2 from '@/components/Form/FormFields/Select2.vue'
|
||||||
import AssetSelectDialog from './dialog.vue'
|
import AssetSelectDialog from './dialog.vue'
|
||||||
import { b } from 'css-color-function/lib/adjusters'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
componentName: 'AssetSelect',
|
componentName: 'AssetSelect',
|
||||||
@@ -38,6 +37,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/assets/'
|
default: '/api/v1/assets/assets/'
|
||||||
},
|
},
|
||||||
|
defaultPageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
baseNodeUrl: {
|
baseNodeUrl: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/nodes/'
|
default: '/api/v1/assets/nodes/'
|
||||||
@@ -71,6 +74,7 @@ export default {
|
|||||||
value: iValue,
|
value: iValue,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
clearable: true,
|
clearable: true,
|
||||||
|
defaultPageSize: this.defaultPageSize,
|
||||||
ajax: {
|
ajax: {
|
||||||
url: this.baseUrl,
|
url: this.baseUrl,
|
||||||
transformOption: (item) => {
|
transformOption: (item) => {
|
||||||
@@ -81,7 +85,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
b,
|
|
||||||
handleFocus() {
|
handleFocus() {
|
||||||
this.$refs.select2.selectRef.blur()
|
this.$refs.select2.selectRef.blur()
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/assets/'
|
default: '/api/v1/assets/assets/'
|
||||||
},
|
},
|
||||||
|
typeUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '/api/v1/assets/nodes/category/tree/'
|
||||||
|
},
|
||||||
nodeUrl: {
|
nodeUrl: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '/api/v1/assets/nodes/'
|
default: '/api/v1/assets/nodes/'
|
||||||
@@ -105,9 +109,9 @@ export default {
|
|||||||
showAssets: false,
|
showAssets: false,
|
||||||
showSearch: false,
|
showSearch: false,
|
||||||
customTreeHeaderName: this.$t('TypeTree'),
|
customTreeHeaderName: this.$t('TypeTree'),
|
||||||
url: '/api/v1/assets/nodes/category/tree/',
|
url: this.typeUrl,
|
||||||
nodeUrl: this.treeSetting?.nodeUrl || this.nodeUrl,
|
nodeUrl: this.treeSetting?.nodeUrl || this.nodeUrl,
|
||||||
treeUrl: `/api/v1/assets/nodes/category/tree/?assets=${showAssets ? '1' : '0'}&count_resource=${this.treeSetting.countResource || 'asset'}`,
|
treeUrl: `${this.typeUrl}?assets=${showAssets ? '1' : '0'}&count_resource=${this.treeSetting.countResource || 'asset'}`,
|
||||||
callback: {
|
callback: {
|
||||||
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
|
||||||
}
|
}
|
||||||
@@ -176,12 +180,12 @@ export default {
|
|||||||
setParam('node_id', '')
|
setParam('node_id', '')
|
||||||
setParam('asset_id', assetId)
|
setParam('asset_id', assetId)
|
||||||
} else if (treeNode.meta.type === 'category') {
|
} else if (treeNode.meta.type === 'category') {
|
||||||
url = setUrlParam(url, 'category', treeNode.meta.category)
|
setParam('category', treeNode.meta.category)
|
||||||
} else if (treeNode.meta.type === 'type') {
|
} else if (treeNode.meta.type === 'type') {
|
||||||
setParam('category', treeNode.meta.category)
|
setParam('category', treeNode.meta.category)
|
||||||
setParam('type', treeNode.meta._type)
|
setParam('type', treeNode.meta._type)
|
||||||
} else if (treeNode.meta.type === 'platform') {
|
} else if (treeNode.meta.type === 'platform') {
|
||||||
url = setUrlParam(url, 'platform', treeNode.id)
|
setParam('platform', treeNode.id)
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const query = this.setTreeUrlQuery()
|
const query = this.setTreeUrlQuery()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<AssetTreeTable
|
<AssetTreeTable
|
||||||
|
ref="AssetTreeTable"
|
||||||
:header-actions="headerActions"
|
:header-actions="headerActions"
|
||||||
:table-config="tableConfig"
|
:table-config="tableConfig"
|
||||||
:tree-setting="treeSetting"
|
:tree-setting="treeSetting"
|
||||||
@@ -47,9 +48,19 @@ export default {
|
|||||||
return this.tableUrl.replace('/assets/', `/assets/${row.id}/accounts/`)
|
return this.tableUrl.replace('/assets/', `/assets/${row.id}/accounts/`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nameDisabled: {
|
name: {
|
||||||
type: Boolean,
|
type: Object,
|
||||||
default: true
|
default: () => ({
|
||||||
|
formatter: DetailFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetDetail',
|
||||||
|
can: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
comment: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -80,11 +91,7 @@ export default {
|
|||||||
},
|
},
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
name: {
|
name: {
|
||||||
formatter: DetailFormatter,
|
...this.name
|
||||||
formatterArgs: {
|
|
||||||
route: 'AssetDetail',
|
|
||||||
can: !this.nameDisabled
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
labels: {
|
labels: {
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
@@ -99,7 +106,8 @@ export default {
|
|||||||
formatter: AccountInfoFormatter,
|
formatter: AccountInfoFormatter,
|
||||||
width: '100px'
|
width: '100px'
|
||||||
},
|
},
|
||||||
connectivity: connectivityMeta
|
connectivity: connectivityMeta,
|
||||||
|
comment: { ...this.comment }
|
||||||
},
|
},
|
||||||
tableAttrs: {
|
tableAttrs: {
|
||||||
rowClassName({ row }) {
|
rowClassName({ row }) {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export default {
|
|||||||
formatterData = data
|
formatterData = data
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span>{formatterData}</span>
|
<span style={{ whiteSpace: 'pre-wrap', lineHeight: '1.2' }}>{formatterData}</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (this.value instanceof Array) {
|
if (this.value instanceof Array) {
|
||||||
|
|||||||
@@ -10,13 +10,16 @@
|
|||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<slot />
|
<div v-loading="disabledStatus">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="showButtons" slot="footer" class="dialog-footer">
|
<div v-if="showButtons" slot="footer" class="dialog-footer">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<el-button v-if="showCancel && showButtons" size="small" @click="onCancel">{{ cancelTitle }}</el-button>
|
<el-button v-if="showCancel && showButtons" size="small" @click="onCancel">{{ cancelTitle }}</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="showConfirm && showButtons"
|
v-if="showConfirm && showButtons"
|
||||||
:loading="loadingStatus"
|
:disabled="disabledStatus"
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="onConfirm"
|
@click="onConfirm"
|
||||||
@@ -69,7 +72,7 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
loadingStatus: {
|
disabledStatus: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
@@ -79,7 +82,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
iWidth() {
|
iWidth() {
|
||||||
@@ -119,6 +123,7 @@ export default {
|
|||||||
|
|
||||||
&__body {
|
&__body {
|
||||||
padding: 20px 30px;
|
padding: 20px 30px;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
&:has(.el-table) {
|
&:has(.el-table) {
|
||||||
background: #f3f3f4;
|
background: #f3f3f4;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ export default {
|
|||||||
// 如果不想等,证明是 value 自己变化导致的, 需要重新渲染
|
// 如果不想等,证明是 value 自己变化导致的, 需要重新渲染
|
||||||
if (valJson !== this.formJson) {
|
if (valJson !== this.formJson) {
|
||||||
this.iValue = val
|
this.iValue = val
|
||||||
|
this.$log.debug('Sub form value changed, rerender form: ', this.formJson, valJson)
|
||||||
this.loading = true
|
this.loading = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -95,11 +96,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
outputValue: _.debounce(function(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}),
|
||||||
updateValue(val) {
|
updateValue(val) {
|
||||||
this.iValue = val
|
this.iValue = val
|
||||||
setTimeout(() => {
|
this.outputValue(val)
|
||||||
this.$emit('input', val)
|
|
||||||
}, 100)
|
|
||||||
},
|
},
|
||||||
objectToString(obj) {
|
objectToString(obj) {
|
||||||
let data = ''
|
let data = ''
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<span
|
<div
|
||||||
v-for="(group, i) in groups"
|
v-for="(group, i) in groups"
|
||||||
:key="'group-'+group.name"
|
:key="'group-'+group.name"
|
||||||
:slot="'id:'+group.name"
|
:slot="'id:'+group.name"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
:index="i"
|
:index="i"
|
||||||
:line="i !== 0 && !groupHidden(groups[i - 1], i - 1)"
|
:line="i !== 0 && !groupHidden(groups[i - 1], i - 1)"
|
||||||
/>
|
/>
|
||||||
</span>
|
</div>
|
||||||
</DataForm>
|
</DataForm>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import BasicTree from '@/components/Form/FormFields/BasicTree.vue'
|
|||||||
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
|
||||||
import { assignIfNot, toSentenceCase } from '@/utils/common'
|
import { assignIfNot, toSentenceCase } from '@/utils/common'
|
||||||
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
import TagInput from '@/components/Form/FormFields/TagInput.vue'
|
||||||
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
|
|
||||||
import i18n from '@/i18n/i18n'
|
import i18n from '@/i18n/i18n'
|
||||||
|
|
||||||
export class FormFieldGenerator {
|
export class FormFieldGenerator {
|
||||||
@@ -135,9 +134,6 @@ export class FormFieldGenerator {
|
|||||||
case 'comment':
|
case 'comment':
|
||||||
field.el.type = 'textarea'
|
field.el.type = 'textarea'
|
||||||
break
|
break
|
||||||
case 'users':
|
|
||||||
field.component = TransferSelect
|
|
||||||
field.el.label = field.label
|
|
||||||
}
|
}
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
@@ -197,6 +193,24 @@ export class FormFieldGenerator {
|
|||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setChoicesTips(field, fieldMeta, fieldRemoteMeta) {
|
||||||
|
// 设置 checkbox 的 tips
|
||||||
|
if (['checkbox-group', 'radio-group'].indexOf(field.type) !== -1) {
|
||||||
|
field.options.map(option => {
|
||||||
|
if (!option.tip && field.tips) {
|
||||||
|
option.tip = field.tips[option.value]
|
||||||
|
}
|
||||||
|
if (!option.tip) {
|
||||||
|
const match = option.label.match(/^(.+?)\s*\((.*?)\)$/)
|
||||||
|
if (match) {
|
||||||
|
option.label = match[1]
|
||||||
|
option.tip = match[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
afterGenerateField(field) {
|
afterGenerateField(field) {
|
||||||
field.label = toSentenceCase(field.label)
|
field.label = toSentenceCase(field.label)
|
||||||
|
|
||||||
@@ -204,15 +218,7 @@ export class FormFieldGenerator {
|
|||||||
field.el.placeholder = field.placeholder
|
field.el.placeholder = field.placeholder
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 checkbox 的 tips
|
this.setChoicesTips(field)
|
||||||
if (field.tips && ['checkbox-group', 'radio-group'].indexOf(field.type) !== -1) {
|
|
||||||
field.options.map(option => {
|
|
||||||
if (!option.tip && field.tips[option.value]) {
|
|
||||||
option.tip = field.tips[option.value]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
placement="right"
|
placement="right"
|
||||||
popper-class="help-tips"
|
popper-class="help-tips"
|
||||||
>
|
>
|
||||||
<div slot="content" v-sanitize="data.helpTip" /> <!-- Noncompliant -->
|
<div slot="content" v-sanitize="data.helpTip" class="help-tip-content" /> <!-- Noncompliant -->
|
||||||
<i class="fa fa-question-circle-o help-tip-icon" />
|
<i class="fa fa-question-circle-o help-tip-icon" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
@@ -322,4 +322,9 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.help-tip-content {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
>
|
>
|
||||||
{{ iSubmitBtnText }}
|
{{ iSubmitBtnText }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-if="defaultButton && hasSaveContinue"
|
v-if="defaultButton && hasSaveContinue"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
>
|
>
|
||||||
{{ $t("SaveAndAddAnother") }}
|
{{ $t("SaveAndAddAnother") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-if="defaultButton && hasReset"
|
v-if="defaultButton && hasReset"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -47,6 +49,7 @@
|
|||||||
>
|
>
|
||||||
{{ $t("Reset") }}
|
{{ $t("Reset") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-for="button in moreButtons"
|
v-for="button in moreButtons"
|
||||||
v-show="!button.hidden"
|
v-show="!button.hidden"
|
||||||
@@ -217,7 +220,7 @@ export default {
|
|||||||
|
|
||||||
.el-form-item__label {
|
.el-form-item__label {
|
||||||
padding: 0 30px 0 0;
|
padding: 0 30px 0 0;
|
||||||
line-height: 32px;
|
line-height: 30px;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
|||||||
@@ -8,99 +8,118 @@
|
|||||||
:label="item.name"
|
:label="item.name"
|
||||||
:prop="item.name"
|
:prop="item.name"
|
||||||
>
|
>
|
||||||
|
|
||||||
<template v-if="item.type === 'button' && !item.isVisible">
|
<template v-if="item.type === 'button' && !item.isVisible">
|
||||||
<el-button
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
:type="item.el && item.el.type"
|
<el-button
|
||||||
class="start-stop-btn"
|
:type="item.el && item.el.type"
|
||||||
size="mini"
|
class="start-stop-btn"
|
||||||
@click="item.callback()"
|
size="mini"
|
||||||
>
|
@click="item.callback()"
|
||||||
<i :class="item.icon" />{{ item.name }}
|
>
|
||||||
</el-button>
|
<i :class="item.icon" />
|
||||||
|
|
||||||
|
{{ item.name }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="item.type === 'input' && item.el && item.el.autoComplete">
|
<template v-if="item.type === 'input' && item.el && item.el.autoComplete">
|
||||||
<el-autocomplete
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
v-model="formModel[item.name]"
|
<el-autocomplete
|
||||||
:fetch-suggestions="item.el.query"
|
v-model="formModel[item.name]"
|
||||||
:placeholder="item.placeholder"
|
:fetch-suggestions="item.el.query"
|
||||||
class="inline-input"
|
:placeholder="item.placeholder"
|
||||||
size="mini"
|
class="inline-input"
|
||||||
@change="handleInputChange(item)"
|
size="mini"
|
||||||
@select="handleInputChange(item)"
|
clearable
|
||||||
/>
|
@change="handleInputChange(item)"
|
||||||
|
@select="handleInputChange(item)"
|
||||||
|
/>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="item.type === 'input'">
|
<template v-else-if="item.type === 'input'">
|
||||||
<el-input
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
v-model="formModel[item.name]"
|
<el-input
|
||||||
:class="!isFold ? 'special-style' : ''"
|
v-model="formModel[item.name]"
|
||||||
:placeholder="item.placeholder"
|
:class="!isFold ? 'special-style' : ''"
|
||||||
class="inline-input"
|
:placeholder="item.placeholder"
|
||||||
size="mini"
|
class="inline-input"
|
||||||
@change="item.callback(formModel[item.name])"
|
size="mini"
|
||||||
/>
|
@change="item.callback(formModel[item.name])"
|
||||||
|
/>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="item.type === 'select' && item.el && item.el.create">
|
<template v-if="item.type === 'select' && item.el && item.el.create">
|
||||||
<span class="filter-label">{{ item.name }}:</span>
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
<el-select
|
<span class="filter-label">{{ item.name }}:</span>
|
||||||
v-if="item.type === 'select' && item.el && item.el.create"
|
<el-select
|
||||||
:key="index"
|
v-if="item.type === 'select' && item.el && item.el.create"
|
||||||
v-model="formModel[item.name]"
|
:key="index"
|
||||||
:allow-create="item.el.create || false"
|
v-model="formModel[item.name]"
|
||||||
:filterable="item.el.create || false"
|
:allow-create="item.el.create || false"
|
||||||
:multiple="item.el.multiple"
|
:filterable="item.el.create || false"
|
||||||
:placeholder="item.name"
|
:multiple="item.el.multiple"
|
||||||
class="autoWidth-select"
|
:placeholder="item.name"
|
||||||
default-first-option
|
class="autoWidth-select"
|
||||||
size="mini"
|
default-first-option
|
||||||
@change="item.callback(item.value)"
|
size="mini"
|
||||||
>
|
@change="item.callback(item.value)"
|
||||||
<template slot="prefix">{{ item.label + ':' + item.value }}</template>
|
>
|
||||||
<el-option
|
<template slot="prefix">{{ item.label + ':' + item.value }}</template>
|
||||||
v-for="(option, id) in item.options"
|
<el-option
|
||||||
:key="id"
|
v-for="(option, id) in item.options"
|
||||||
:label="option.label"
|
:key="id"
|
||||||
:title="option.value"
|
:label="option.label"
|
||||||
:value="option.value"
|
:title="option.value"
|
||||||
/>
|
:value="option.value"
|
||||||
</el-select>
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="item.type === 'select' && (!item.el || !item.el.create)">
|
<template v-if="item.type === 'select' && (!item.el || !item.el.create)">
|
||||||
<el-dropdown
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
class="select-dropdown"
|
<el-dropdown
|
||||||
trigger="click"
|
class="select-dropdown"
|
||||||
@command="(command) => {
|
trigger="click"
|
||||||
item.value = command
|
@command="(command) => {
|
||||||
item.callback(command)
|
item.value = command
|
||||||
}"
|
item.callback(command)
|
||||||
>
|
}"
|
||||||
<el-button size="mini" type="primary">
|
>
|
||||||
<div class="text-content">
|
<el-button size="mini" type="primary">
|
||||||
<span class="content">
|
<div class="text-content">
|
||||||
{{ getLabel(item.value, item.options) }}
|
<span class="content">
|
||||||
<i class="el-icon-arrow-down el-icon--right" />
|
{{ getLabel(item.value, item.options) }}
|
||||||
</span>
|
<i class="el-icon-arrow-down el-icon--right" />
|
||||||
</div>
|
</span>
|
||||||
</el-button>
|
</div>
|
||||||
<el-dropdown-menu v-slot="dropdown">
|
</el-button>
|
||||||
<el-dropdown-item
|
<el-dropdown-menu v-slot="dropdown">
|
||||||
v-for="(option, i) in item.options"
|
<el-dropdown-item
|
||||||
:key="i"
|
v-for="(option, i) in item.options"
|
||||||
:command="option.value"
|
:key="i"
|
||||||
>
|
:command="option.value"
|
||||||
{{ option.label }}
|
>
|
||||||
</el-dropdown-item>
|
{{ option.label }}
|
||||||
</el-dropdown-menu>
|
</el-dropdown-item>
|
||||||
</el-dropdown>
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="item.type === 'switch'">
|
<template v-if="item.type === 'switch'">
|
||||||
<el-switch
|
<el-tooltip :disabled="!item.tip" :content="item.tip">
|
||||||
v-model="formModel[item.name]"
|
<el-switch
|
||||||
:active-text="item.name"
|
v-model="formModel[item.name]"
|
||||||
:disabled="item.disabled"
|
:active-text="item.name"
|
||||||
@change="item.callback(formModel[item.name])"
|
:disabled="item.disabled"
|
||||||
/>
|
@change="item.callback(formModel[item.name])"
|
||||||
|
/>
|
||||||
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div
|
<div
|
||||||
@@ -379,7 +398,6 @@ $input-border-color: #C0C4CC;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.editor {
|
.editor {
|
||||||
//margin-left: 30px;
|
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
defaultValue: 24,
|
||||||
displayMapper: {
|
displayMapper: {
|
||||||
'second': this.$t('Second'), // 'sec' is the default value of 'unit
|
'second': this.$t('Second'), // 'sec' is the default value of 'unit
|
||||||
'min': this.$t('Minute'), // 'min' is the default value of 'unit
|
'min': this.$t('Minute'), // 'min' is the default value of 'unit
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ export default {
|
|||||||
type: 'input-number',
|
type: 'input-number',
|
||||||
el: {
|
el: {
|
||||||
min: 8,
|
min: 8,
|
||||||
max: 30
|
max: 36,
|
||||||
|
size: 'mini'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-input v-model="rawValue.phone" required :placeholder="$tc('InputPhone')" @input="OnInputChange">
|
<el-input v-model="rawValue.phone" :placeholder="$tc('InputPhone')" required @input="onInputChange">
|
||||||
<el-select
|
<el-select
|
||||||
slot="prepend"
|
slot="prepend"
|
||||||
:placeholder="$tc('Select')"
|
:placeholder="$tc('Select')"
|
||||||
:value="rawValue.code"
|
:value="rawValue.code"
|
||||||
style="width: 75px;"
|
style="width: 105px;"
|
||||||
@change="OnChange"
|
@change="onChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="country in countries"
|
v-for="country in countries"
|
||||||
:key="country.value"
|
:key="country.name"
|
||||||
:label="country.value"
|
:label="country.value"
|
||||||
:value="country.value"
|
:value="country.value"
|
||||||
style="width: 200px;"
|
|
||||||
>
|
>
|
||||||
<span style="float: left">{{ country.name }}</span>
|
<span class="country-name">{{ country.name }}</span>
|
||||||
<span style="float: right; font-size: 13px">{{ country.value }}</span>
|
<span style="float: right; font-size: 13px">{{ country.value }}</span>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -24,19 +23,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PhoneInput',
|
name: 'PhoneInput',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: [Object, String],
|
type: [Object, String],
|
||||||
default: () => ({ 'code': '+86', 'phone': '' })
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
rawValue: {}
|
rawValue: {},
|
||||||
|
countries: [{ 'name': 'China', 'value': '+86' }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -45,26 +44,38 @@ export default {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return `${this.rawValue.code}${this.rawValue.phone}`
|
return `${this.rawValue.code}${this.rawValue.phone}`
|
||||||
},
|
}
|
||||||
countries: {
|
|
||||||
get() {
|
|
||||||
return this.publicSettings.COUNTRY_CALLING_CODES
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...mapGetters(['publicSettings'])
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.rawValue = this.value || { code: '+86', phone: '' }
|
const defaults = { code: localStorage.getItem('prePhoneCode') || '+86', phone: '' }
|
||||||
|
this.rawValue = this.value || defaults
|
||||||
|
this.$axios.get('/api/v1/common/countries/').then(res => {
|
||||||
|
this.countries = res.map(item => {
|
||||||
|
return { name: `${item.flag} ${item.name}`, value: item.phone_code }
|
||||||
|
})
|
||||||
|
})
|
||||||
this.$emit('input', this.fullPhone)
|
this.$emit('input', this.fullPhone)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
OnChange(countryCode) {
|
onChange(countryCode) {
|
||||||
this.rawValue.code = countryCode
|
this.rawValue.code = countryCode
|
||||||
this.OnInputChange()
|
this.onInputChange()
|
||||||
|
localStorage.setItem('prePhoneCode', countryCode)
|
||||||
},
|
},
|
||||||
OnInputChange() {
|
onInputChange() {
|
||||||
this.$emit('input', this.fullPhone)
|
this.$emit('input', this.fullPhone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.country-name {
|
||||||
|
display: inline-block;
|
||||||
|
width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -144,9 +144,6 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
choices: {
|
choices: {
|
||||||
handler(value, oldValue) {
|
handler(value, oldValue) {
|
||||||
if (value?.length === oldValue?.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setDefaultItems(value)
|
this.setDefaultItems(value)
|
||||||
@@ -345,6 +342,10 @@ export default {
|
|||||||
.protocol-item {
|
.protocol-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-button {
|
.input-button {
|
||||||
|
|||||||
@@ -125,16 +125,19 @@ export default {
|
|||||||
allowCreate: {
|
allowCreate: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
defaultPageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const vm = this
|
const vm = this
|
||||||
const defaultPageSize = 10
|
|
||||||
const defaultParams = {
|
const defaultParams = {
|
||||||
search: '',
|
search: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
hasMore: true,
|
hasMore: true,
|
||||||
pageSize: defaultPageSize
|
pageSize: vm.defaultPageSize
|
||||||
}
|
}
|
||||||
// 设置axios全局报错提示不显示
|
// 设置axios全局报错提示不显示
|
||||||
const validateStatus = (status) => {
|
const validateStatus = (status) => {
|
||||||
@@ -194,7 +197,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
iAjax() {
|
iAjax() {
|
||||||
const defaultPageSize = 10
|
|
||||||
const defaultMakeParams = (params) => {
|
const defaultMakeParams = (params) => {
|
||||||
const page = params.page || 1
|
const page = params.page || 1
|
||||||
const offset = (page - 1) * params.pageSize
|
const offset = (page - 1) * params.pageSize
|
||||||
@@ -237,7 +239,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const defaultAjax = {
|
const defaultAjax = {
|
||||||
url: '',
|
url: '',
|
||||||
pageSize: defaultPageSize,
|
pageSize: this.defaultPageSize,
|
||||||
makeParams: defaultMakeParams,
|
makeParams: defaultMakeParams,
|
||||||
transformOption: defaultTransformOption,
|
transformOption: defaultTransformOption,
|
||||||
processResults: defaultProcessResults,
|
processResults: defaultProcessResults,
|
||||||
|
|||||||
@@ -14,10 +14,12 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:title="label"
|
:title="label"
|
||||||
:visible.sync="showTransfer"
|
:visible.sync="showTransfer"
|
||||||
|
:disabled-status="!isLoaded"
|
||||||
class="the-dialog"
|
class="the-dialog"
|
||||||
width="730px"
|
width="730px"
|
||||||
@cancel="handleTransCancel"
|
@cancel="handleTransCancel"
|
||||||
@confirm="handleTransConfirm"
|
@confirm="handleTransConfirm"
|
||||||
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<krryPaging v-if="selectInitialized" ref="pageTransfer" class="transfer" v-bind="pagingTransfer" />
|
<krryPaging v-if="selectInitialized" ref="pageTransfer" class="transfer" v-bind="pagingTransfer" />
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@@ -77,13 +79,16 @@ export default {
|
|||||||
if (keyword) {
|
if (keyword) {
|
||||||
params['search'] = keyword
|
params['search'] = keyword
|
||||||
}
|
}
|
||||||
|
this.isLoaded = false
|
||||||
const data = await this.$axios.get(url, { params })
|
const data = await this.$axios.get(url, { params })
|
||||||
|
this.isLoaded = true
|
||||||
return data['results'].map(item => {
|
return data['results'].map(item => {
|
||||||
const n = transformOption(item)
|
const n = transformOption(item)
|
||||||
return { id: n.value, label: n.label }
|
return { id: n.value, label: n.label }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
isLoaded: false,
|
||||||
showTransfer: false,
|
showTransfer: false,
|
||||||
selectInitialized: false,
|
selectInitialized: false,
|
||||||
select2: {
|
select2: {
|
||||||
@@ -167,7 +172,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default {
|
|||||||
patterns.push([/\d/, i18n.t('NUMBER_REQUIRED')])
|
patterns.push([/\d/, i18n.t('NUMBER_REQUIRED')])
|
||||||
}
|
}
|
||||||
if (passwordRule['SECURITY_PASSWORD_SPECIAL_CHAR']) {
|
if (passwordRule['SECURITY_PASSWORD_SPECIAL_CHAR']) {
|
||||||
const pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]")
|
const pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?_+-]")
|
||||||
patterns.push([pattern, i18n.t('SPECIAL_CHAR_REQUIRED')])
|
patterns.push([pattern, i18n.t('SPECIAL_CHAR_REQUIRED')])
|
||||||
}
|
}
|
||||||
for (const [pattern, msg] of patterns) {
|
for (const [pattern, msg] of patterns) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
v-if="showColumnSettingPopover"
|
v-if="showColumnSettingPopover"
|
||||||
:cancel-title="$tc('RestoreDefault')"
|
:cancel-title="$tc('RestoreDefault')"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:title="$tc('TableSetting')"
|
:title="$tc('ListPreference')"
|
||||||
:visible.sync="showColumnSettingPopover"
|
:visible.sync="showColumnSettingPopover"
|
||||||
top="10%"
|
top="10%"
|
||||||
width="50%"
|
width="50%"
|
||||||
@@ -90,8 +90,14 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventBus.$off('showColumnSettingPopover', this.showColumnSettingPopoverHandler)
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$eventBus.$on('showColumnSettingPopover', ({ url }) => {
|
this.$eventBus.$on('showColumnSettingPopover', this.showColumnSettingPopoverHandler)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showColumnSettingPopoverHandler({ url }) {
|
||||||
if (url === this.url) {
|
if (url === this.url) {
|
||||||
this.checkAll = false
|
this.checkAll = false
|
||||||
this.showColumnSettingPopover = true
|
this.showColumnSettingPopover = true
|
||||||
@@ -105,9 +111,7 @@ export default {
|
|||||||
this.checkAll = false
|
this.checkAll = false
|
||||||
this.isIndeterminate = true
|
this.isIndeterminate = true
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleColumnConfirm() {
|
handleColumnConfirm() {
|
||||||
this.showColumnSettingPopover = false
|
this.showColumnSettingPopover = false
|
||||||
this.$emit('columnsUpdate', { columns: this.iCurrentColumns, url: this.url })
|
this.$emit('columnsUpdate', { columns: this.iCurrentColumns, url: this.url })
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ export default {
|
|||||||
this.toggleRowSelection(row, true)
|
this.toggleRowSelection(row, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$emit('loaded')
|
||||||
},
|
},
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
localStorage.setItem('paginationSize', val)
|
localStorage.setItem('paginationSize', val)
|
||||||
|
|||||||
@@ -171,14 +171,18 @@ export default {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventBus.$off('showExportDialog', this.showExportDialogHandler)
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$eventBus.$on('showExportDialog', ({ selectedRows, url, name }) => {
|
this.$eventBus.$on('showExportDialog', this.showExportDialogHandler)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showExportDialogHandler({ selectedRows, url, name }) {
|
||||||
if (url === this.url || url.indexOf(this.url) > -1) {
|
if (url === this.url || url.indexOf(this.url) > -1) {
|
||||||
this.showExportDialog()
|
this.showExportDialog()
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showExportDialog() {
|
showExportDialog() {
|
||||||
if (!this.mfaVerifyRequired) {
|
if (!this.mfaVerifyRequired) {
|
||||||
this.exportDialogShow = true
|
this.exportDialogShow = true
|
||||||
|
|||||||
@@ -142,14 +142,18 @@ export default {
|
|||||||
this.showTable = false
|
this.showTable = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventBus.$off('showImportDialog', this.showImportEventHandler)
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$eventBus.$on('showImportDialog', ({ url }) => {
|
this.$eventBus.$on('showImportDialog', this.showImportEventHandler)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showImportEventHandler({ url }) {
|
||||||
if (url === this.url) {
|
if (url === this.url) {
|
||||||
this.showImportDialog = true
|
this.showImportDialog = true
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.showImportDialog = false
|
this.showImportDialog = false
|
||||||
this.$emit('importDialogClose')
|
this.$emit('importDialogClose')
|
||||||
|
|||||||
@@ -44,8 +44,9 @@
|
|||||||
import DataTable from '@/components/Table/DataTable/index.vue'
|
import DataTable from '@/components/Table/DataTable/index.vue'
|
||||||
import { getUpdateObjURL } from '@/utils/common'
|
import { getUpdateObjURL } from '@/utils/common'
|
||||||
import { sleep } from '@/utils/time'
|
import { sleep } from '@/utils/time'
|
||||||
import { EditableInputFormatter, StatusFormatter } from '@/components/Table/TableFormatters'
|
import { EditableInputFormatter } from '@/components/Table/TableFormatters'
|
||||||
import { encryptPassword } from '@/utils/crypto'
|
import { encryptPassword } from '@/utils/crypto'
|
||||||
|
import getStatusColumnMeta from '@/components/Table/ListTable/TableAction/const'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ImportTable',
|
name: 'ImportTable',
|
||||||
@@ -223,38 +224,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
generateTableColumns(tableTitles, tableData) {
|
generateTableColumns(tableTitles, tableData) {
|
||||||
const vm = this
|
const columns = [{ ...getStatusColumnMeta.bind(this)().status }]
|
||||||
const columns = [{
|
|
||||||
prop: '@status',
|
|
||||||
label: vm.$t('Status'),
|
|
||||||
width: '80px',
|
|
||||||
align: 'center',
|
|
||||||
formatter: StatusFormatter,
|
|
||||||
formatterArgs: {
|
|
||||||
faChoices: {
|
|
||||||
ok: 'fa-check text-primary',
|
|
||||||
error: 'fa-times text-danger',
|
|
||||||
pending: 'fa-clock-o'
|
|
||||||
},
|
|
||||||
getChoicesKey(val) {
|
|
||||||
if (val === 'ok' || val === 'pending') {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
return 'error'
|
|
||||||
},
|
|
||||||
getTip(val) {
|
|
||||||
if (val === 'ok') {
|
|
||||||
return vm.$t('Success')
|
|
||||||
} else if (val === 'pending') {
|
|
||||||
return vm.$t('Pending')
|
|
||||||
} else if (val && val.name === 'error') {
|
|
||||||
return val.error
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
|
||||||
hasTips: true
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
for (const item of tableTitles) {
|
for (const item of tableTitles) {
|
||||||
const dataItemLens = tableData.map(d => {
|
const dataItemLens = tableData.map(d => {
|
||||||
if (!d) {
|
if (!d) {
|
||||||
|
|||||||
@@ -71,7 +71,16 @@ export default {
|
|||||||
this.listenViewPort()
|
this.listenViewPort()
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$eventBus.$on('labelSearch', label => {
|
this.$eventBus.$on('labelSearch', this.labelSearchHandler)
|
||||||
|
},
|
||||||
|
beforeDestroy(label) {
|
||||||
|
this.$eventBus.$off('labelSearch', this.labelSearchHandler)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleCascaderFocus() {
|
||||||
|
this.setSearchFocus()
|
||||||
|
},
|
||||||
|
labelSearchHandler(label) {
|
||||||
if (!label) {
|
if (!label) {
|
||||||
this.labelValue = []
|
this.labelValue = []
|
||||||
this.showLabelSearch = true
|
this.showLabelSearch = true
|
||||||
@@ -82,14 +91,6 @@ export default {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.showLabelSearch = true
|
this.showLabelSearch = true
|
||||||
}, 500)
|
}, 500)
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.$eventBus.$off('labelSearch')
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleCascaderFocus() {
|
|
||||||
this.setSearchFocus()
|
|
||||||
},
|
},
|
||||||
handleCascaderVisibleChange(visible) {
|
handleCascaderVisibleChange(visible) {
|
||||||
const input = this.$refs.labelCascader.$el
|
const input = this.$refs.labelCascader.$el
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'actionSetting',
|
name: 'actionSetting',
|
||||||
icon: 'system-setting',
|
icon: 'system-setting',
|
||||||
tip: this.$t('TableSetting'),
|
tip: this.$t('ListPreference'),
|
||||||
has: this.hasColumnSetting,
|
has: this.hasColumnSetting,
|
||||||
callback: this.handleTableSettingClick.bind(this)
|
callback: this.handleTableSettingClick.bind(this)
|
||||||
},
|
},
|
||||||
|
|||||||
40
src/components/Table/ListTable/TableAction/const.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { StatusFormatter } from '@/components/Table/TableFormatters'
|
||||||
|
import i18n from '@/i18n/i18n'
|
||||||
|
|
||||||
|
export const getStatusColumnMeta = (prop = '@status') => {
|
||||||
|
return {
|
||||||
|
status: {
|
||||||
|
prop: prop,
|
||||||
|
label: i18n.t('Status'),
|
||||||
|
width: '80px',
|
||||||
|
align: 'center',
|
||||||
|
formatter: StatusFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
faChoices: {
|
||||||
|
ok: 'fa-check text-primary',
|
||||||
|
error: 'fa-times text-danger',
|
||||||
|
pending: 'fa-clock-o'
|
||||||
|
},
|
||||||
|
getChoicesKey: (val) => {
|
||||||
|
if (val === 'ok' || val === 'pending') {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
return 'error'
|
||||||
|
},
|
||||||
|
getTip: (val) => {
|
||||||
|
if (val === 'ok') {
|
||||||
|
return i18n.t('Success')
|
||||||
|
} else if (val === 'pending') {
|
||||||
|
return i18n.t('Pending')
|
||||||
|
} else if ((val && val.name === 'error') || val.error !== undefined) {
|
||||||
|
return val.error
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
hasTips: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getStatusColumnMeta
|
||||||
@@ -189,22 +189,23 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.urlUpdated[this.tableUrl] = location.href
|
this.$set(this.urlUpdated, this.tableUrl, location.href)
|
||||||
},
|
},
|
||||||
deactivated() {
|
deactivated() {
|
||||||
this.isDeactivated = true
|
this.isDeactivated = true
|
||||||
},
|
},
|
||||||
activated() {
|
activated() {
|
||||||
this.isDeactivated = false
|
this.$nextTick(() => {
|
||||||
const preURL = this.urlUpdated[this.tableUrl]
|
this.isDeactivated = false
|
||||||
if (!preURL || preURL === location.href) {
|
const cleanUrl = this.tableUrl.split('?')[0]
|
||||||
return
|
const preURL = this.urlUpdated[cleanUrl]
|
||||||
}
|
|
||||||
this.urlUpdated[this.tableUrl] = location.href
|
if (!preURL || preURL === location.href) return
|
||||||
this.$log.debug('Reload the table get latest data: pre ', preURL, ' current: ', location.href)
|
|
||||||
setTimeout(() => {
|
this.$set(this.urlUpdated, this.tableUrl, location.href)
|
||||||
|
this.$log.debug('Reload the table get latest data: pre ', preURL, ' current: ', location.href)
|
||||||
this.reloadTable()
|
this.reloadTable()
|
||||||
}, 500)
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleActionInitialDone() {
|
handleActionInitialDone() {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default {
|
|||||||
const formatterArgs = Object.assign(this.formatterArgsDefault, this.col.formatterArgs || {})
|
const formatterArgs = Object.assign(this.formatterArgsDefault, this.col.formatterArgs || {})
|
||||||
return {
|
return {
|
||||||
formatterArgs: formatterArgs,
|
formatterArgs: formatterArgs,
|
||||||
data: formatterArgs.async ? [] : (this.cellValue || []),
|
listData: formatterArgs.async ? [] : (this.cellValue || []),
|
||||||
amount: '',
|
amount: '',
|
||||||
asyncGetDone: false
|
asyncGetDone: false
|
||||||
}
|
}
|
||||||
@@ -68,17 +68,18 @@ export default {
|
|||||||
return [this.$t('Loading') + '...']
|
return [this.$t('Loading') + '...']
|
||||||
}
|
}
|
||||||
const getItem = this.formatterArgs.getItem || (item => item.name)
|
const getItem = this.formatterArgs.getItem || (item => item.name)
|
||||||
|
|
||||||
let data = []
|
let data = []
|
||||||
if (Array.isArray(this.data)) {
|
|
||||||
data = this.data.map(item => getItem(item)) || []
|
if (Array.isArray(this.listData)) {
|
||||||
} else {
|
data = this.listData.map(item => getItem(item)).filter(Boolean)
|
||||||
// object {key: [value]}
|
} else if (this.listData && typeof this.listData === 'object') {
|
||||||
data = Object.entries(this.data).map(([key, value]) => {
|
data = Object.entries(this.listData).map(([key, value]) => {
|
||||||
const item = { key: key, value: value }
|
const item = { key: key, value: value }
|
||||||
return getItem(item)
|
return getItem(item)
|
||||||
}) || []
|
}).filter(Boolean)
|
||||||
}
|
}
|
||||||
data = data.filter(Boolean)
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
showItems() {
|
showItems() {
|
||||||
@@ -86,8 +87,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
cellValue() {
|
cellValue: {
|
||||||
this.computeAmount()
|
handler(newValue) {
|
||||||
|
// listData 需要重新赋值一遍 items 重新计算
|
||||||
|
this.listData = newValue
|
||||||
|
this.computeAmount()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -105,6 +110,7 @@ export default {
|
|||||||
// object {key: [value]}
|
// object {key: [value]}
|
||||||
cellValue = Object.keys(this.cellValue)
|
cellValue = Object.keys(this.cellValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.amount = (cellValue?.filter(value => !this.cellValueToRemove.includes(value)) || []).length
|
this.amount = (cellValue?.filter(value => !this.cellValueToRemove.includes(value)) || []).length
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -127,7 +133,7 @@ export default {
|
|||||||
const params = this.formatterArgs.ajax.params || {}
|
const params = this.formatterArgs.ajax.params || {}
|
||||||
const transform = this.formatterArgs.ajax.transform || (resp => resp[this.col.prop.replace('_amount', '')])
|
const transform = this.formatterArgs.ajax.transform || (resp => resp[this.col.prop.replace('_amount', '')])
|
||||||
const response = await this.$axios.get(url, { params: params })
|
const response = await this.$axios.get(url, { params: params })
|
||||||
this.data = transform(response)
|
this.listData = transform(response)
|
||||||
this.asyncGetDone = true
|
this.asyncGetDone = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>{{ value }}</span>
|
<span class="date">{{ dateValue }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,24 +10,31 @@ export default {
|
|||||||
name: 'DateFormatter',
|
name: 'DateFormatter',
|
||||||
extends: BaseFormatter,
|
extends: BaseFormatter,
|
||||||
data() {
|
data() {
|
||||||
let value
|
// let value
|
||||||
if (this.cellValue) {
|
// if (this.cellValue) {
|
||||||
value = toSafeLocalDateStr(this.cellValue)
|
// value = toSafeLocalDateStr(this.cellValue)
|
||||||
} else {
|
// } else {
|
||||||
value = '-'
|
// value = '-'
|
||||||
}
|
// }
|
||||||
// const locale = this.$i18n.locale
|
// const locale = this.$i18n.locale
|
||||||
// const value = dt.toLocaleString(locale, { hourCycle: 'h23' })
|
// const value = dt.toLocaleString(locale, { hourCycle: 'h23' })
|
||||||
// debug(this.$i18n.locale)
|
// debug(this.$i18n.locale)
|
||||||
return {
|
// return {
|
||||||
value: value
|
// value: value
|
||||||
}
|
// }
|
||||||
// return {
|
// return {
|
||||||
// value: `${year}-${month}-${date} ${hour}:${minutes}:${seconds}`
|
// value: `${year}-${month}-${date} ${hour}:${minutes}:${seconds}`
|
||||||
// }
|
// }
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dateValue() {
|
||||||
|
if (this.cellValue) {
|
||||||
|
return toSafeLocalDateStr(this.cellValue)
|
||||||
|
} else {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="width: 100%;min-height: 20px" @click.stop="editCell">
|
<div class="edit-container" style="min-height: 20px" @click.stop="editCell">
|
||||||
<el-input
|
<el-input
|
||||||
v-if="inEditMode"
|
v-if="inEditMode"
|
||||||
|
ref="inputRef"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
class="editInput"
|
class="editInput"
|
||||||
size="mini"
|
size="mini"
|
||||||
@@ -9,8 +10,17 @@
|
|||||||
@keyup.enter.native="onInputEnter"
|
@keyup.enter.native="onInputEnter"
|
||||||
/>
|
/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span>{{ iCellValue }}</span>
|
<span class="cellValue">{{ iCellValue }}</span>
|
||||||
|
<a
|
||||||
|
v-if="formatterArgs.showEditBtn"
|
||||||
|
:class="[{ 'disabled-link': this.$store.getters.currentOrgIsRoot },'edit-btn']"
|
||||||
|
style="padding-left: 5px"
|
||||||
|
@click="editCell"
|
||||||
|
>
|
||||||
|
<i class="fa fa-edit" />
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -61,6 +71,9 @@ export default {
|
|||||||
editCell() {
|
editCell() {
|
||||||
if (this.formatterArgs.canEdit) {
|
if (this.formatterArgs.canEdit) {
|
||||||
this.inEditMode = true
|
this.inEditMode = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.inputRef.focus()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getCellValue(val) {
|
getCellValue(val) {
|
||||||
@@ -88,7 +101,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.editInput ::v-deep .el-input__inner {
|
.editInput ::v-deep .el-input__inner {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
@@ -97,4 +110,35 @@ export default {
|
|||||||
.editInput {
|
.editInput {
|
||||||
padding: -6px;
|
padding: -6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-btn {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
transition: all 1s;
|
||||||
|
|
||||||
|
& > i {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.edit-btn {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellValue {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<span v-if="!iLabels || iLabels.length === 0" style="vertical-align: top;">
|
<span v-if="!iLabels || iLabels.length === 0" style="vertical-align: top;">
|
||||||
-
|
-
|
||||||
</span>
|
</span>
|
||||||
<div v-else>
|
<span v-else class="label-wrapper">
|
||||||
<div
|
<span
|
||||||
v-for="label of iLabels"
|
v-for="label of iLabels"
|
||||||
:key="label.id"
|
:key="label.id"
|
||||||
>
|
>
|
||||||
@@ -15,8 +15,9 @@
|
|||||||
class="tag-formatter"
|
class="tag-formatter"
|
||||||
@click="handleLabelSearch(label)"
|
@click="handleLabelSearch(label)"
|
||||||
/>
|
/>
|
||||||
</div>
|
<span />
|
||||||
</div>
|
</span>
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-if="formatterArgs.showEditBtn"
|
v-if="formatterArgs.showEditBtn"
|
||||||
@@ -30,15 +31,16 @@
|
|||||||
v-if="showDialog"
|
v-if="showDialog"
|
||||||
:title="$tc('BindLabel')"
|
:title="$tc('BindLabel')"
|
||||||
:visible.sync="showDialog"
|
:visible.sync="showDialog"
|
||||||
|
class="tag-dialog"
|
||||||
width="600px"
|
width="600px"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
@confirm="handleConfirm"
|
@confirm="handleConfirm"
|
||||||
>
|
>
|
||||||
<el-row :gutter="1" class="tag-select">
|
<el-row class="tag-select">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<Select2 v-model="keySelect2.value" v-bind="keySelect2" @change="handleKeyChanged" />
|
<Select2 v-model="keySelect2.value" v-bind="keySelect2" @change="handleKeyChanged" />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12" style="padding-left: 5px">
|
||||||
<Select2
|
<Select2
|
||||||
v-model="valueSelect2.value"
|
v-model="valueSelect2.value"
|
||||||
:disabled="!keySelect2.value"
|
:disabled="!keySelect2.value"
|
||||||
@@ -129,6 +131,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
|
watch: {
|
||||||
|
cellValue: {
|
||||||
|
handler(newValue) {
|
||||||
|
if (newValue) {
|
||||||
|
this.initial = this.formatterArgs.getLabels(this.cellValue)
|
||||||
|
this.iLabels = [...this.initial]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initial = this.formatterArgs.getLabels(this.cellValue)
|
this.initial = this.formatterArgs.getLabels(this.cellValue)
|
||||||
this.iLabels = [...this.initial]
|
this.iLabels = [...this.initial]
|
||||||
@@ -207,18 +219,11 @@ export default {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-select {
|
|
||||||
::v-deep .el-input__inner::placeholder {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-btn {
|
.edit-btn {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -233,9 +238,14 @@ export default {
|
|||||||
|
|
||||||
.label-container {
|
.label-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
.label-formatter-col {
|
.label-formatter-col {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -249,15 +259,23 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-zone {
|
.tag-dialog {
|
||||||
margin: 20px 0 0 0;
|
.tag-zone {
|
||||||
border: solid 1px #ebeef5;
|
margin: 20px 0 0 0;
|
||||||
padding: 10px;
|
border: solid 1px #ebeef5;
|
||||||
background: #f2f2f5;
|
padding: 10px;
|
||||||
|
background: #f2f2f5;
|
||||||
|
|
||||||
.tag-formatter {
|
.tag-formatter {
|
||||||
margin: 1px 3px;
|
margin: 1px 3px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-select {
|
||||||
|
::v-deep .el-input__inner::placeholder {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +288,6 @@ export default {
|
|||||||
|
|
||||||
.tag-formatter {
|
.tag-formatter {
|
||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-tip {
|
.tag-tip {
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tag {
|
.tag {
|
||||||
display: flex;
|
display: inline-block;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -234,12 +234,10 @@ export default {
|
|||||||
delete routeFilter.search
|
delete routeFilter.search
|
||||||
}
|
}
|
||||||
const asFilterTags = _.cloneDeep(this.filterTags)
|
const asFilterTags = _.cloneDeep(this.filterTags)
|
||||||
setTimeout(() => {
|
this.filterTags = {
|
||||||
this.filterTags = {
|
...asFilterTags,
|
||||||
...asFilterTags,
|
...routeFilter
|
||||||
...routeFilter
|
}
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
},
|
},
|
||||||
getValueLabel(key, value) {
|
getValueLabel(key, value) {
|
||||||
for (const field of this.options) {
|
for (const field of this.options) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default {
|
|||||||
showRenameBtn: false,
|
showRenameBtn: false,
|
||||||
drag: {
|
drag: {
|
||||||
isCopy: false,
|
isCopy: false,
|
||||||
isMove: true
|
isMove: !this.$store.getters.currentOrgIsRoot
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback: {
|
callback: {
|
||||||
|
|||||||
@@ -35,13 +35,29 @@ export default {
|
|||||||
]),
|
]),
|
||||||
announcement() {
|
announcement() {
|
||||||
const ann = this.publicSettings.ANNOUNCEMENT
|
const ann = this.publicSettings.ANNOUNCEMENT
|
||||||
return { id: ann['ID'], subject: ann['SUBJECT'], content: ann['CONTENT'], link: ann['LINK'] }
|
return {
|
||||||
|
id: ann['ID'],
|
||||||
|
subject: ann['SUBJECT'],
|
||||||
|
content: ann['CONTENT'],
|
||||||
|
link: ann['LINK'],
|
||||||
|
date_start: ann['DATE_START'],
|
||||||
|
date_end: ann['DATE_END']
|
||||||
|
}
|
||||||
},
|
},
|
||||||
enabled() {
|
enabled() {
|
||||||
return this.publicSettings.ANNOUNCEMENT_ENABLED && (this.announcement.content || this.announcement.subject)
|
return this.publicSettings.ANNOUNCEMENT_ENABLED && (this.announcement.content || this.announcement.subject) && this.isDateValid
|
||||||
},
|
},
|
||||||
title() {
|
title() {
|
||||||
return this.$t('Announcement') + ': ' + this.announcement.subject
|
return this.$t('Announcement') + ': ' + this.announcement.subject
|
||||||
|
},
|
||||||
|
isDateValid() {
|
||||||
|
if (this.announcement.date_start === undefined || this.announcement.date_end === undefined) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const now = new Date()
|
||||||
|
const start = new Date(this.announcement.date_start)
|
||||||
|
const end = new Date(this.announcement.date_end)
|
||||||
|
return now >= start && now <= end
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ export default {
|
|||||||
query[k] = v
|
query[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let key
|
||||||
if (this.$route.name.toLowerCase().includes('list')) {
|
if (this.$route.name.toLowerCase().includes('list')) {
|
||||||
return _.trimEnd(this.$route.path, '/') + '?' + new URLSearchParams(query).toString()
|
key = _.trimEnd(this.$route.path, '/') + '?' + new URLSearchParams(query).toString()
|
||||||
} else {
|
} else {
|
||||||
return new Date().getTime()
|
key = new Date().getTime()
|
||||||
}
|
}
|
||||||
|
return key
|
||||||
},
|
},
|
||||||
chatAiEnabled() {
|
chatAiEnabled() {
|
||||||
return this.publicSettings?.CHAT_AI_ENABLED
|
return this.publicSettings?.CHAT_AI_ENABLED
|
||||||
|
|||||||
@@ -59,18 +59,22 @@ export default {
|
|||||||
this.$router.push({ name: 'Profile' })
|
this.$router.push({ name: 'Profile' })
|
||||||
break
|
break
|
||||||
case 'PasswordAndSSHKey':
|
case 'PasswordAndSSHKey':
|
||||||
this.$router.push({ name: 'PasswordAndSSHKey' })
|
this.$router.push({ name: 'SSHKeyList' })
|
||||||
break
|
break
|
||||||
case 'Preferences':
|
case 'Preferences':
|
||||||
this.$router.push({ name: 'Preferences' })
|
this.$router.push({ name: 'Preferences' })
|
||||||
break
|
break
|
||||||
case 'logout':
|
case 'logout':
|
||||||
this.logout()
|
this.logout()
|
||||||
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logout() {
|
async logout() {
|
||||||
|
const currentOrg = this.$store.getters.currentOrg
|
||||||
|
if (currentOrg.autoEnter) {
|
||||||
|
await this.$store.dispatch('users/setCurrentOrg', this.$store.getters.preOrg)
|
||||||
|
}
|
||||||
|
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
<span class="msg-detail-time">{{ formatDate(currentMsg.date_created) }}</span>
|
<span class="msg-detail-time">{{ formatDate(currentMsg.date_created) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="msg-detail-txt">
|
<div class="msg-detail-txt">
|
||||||
<span v-sanitize="currentMsg.content.message" />
|
<MarkDown :value="currentMsg.content.message" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@@ -80,10 +80,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import { toSafeLocalDateStr } from '@/utils/time'
|
import { toSafeLocalDateStr } from '@/utils/time'
|
||||||
import Dialog from '@/components/Dialog'
|
import Dialog from '@/components/Dialog'
|
||||||
|
import MarkDown from '@/components/Widgets/MarkDown'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SiteMessages',
|
name: 'SiteMessages',
|
||||||
components: { Dialog },
|
components: {
|
||||||
|
Dialog,
|
||||||
|
MarkDown
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: false,
|
show: false,
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async handleSelectView(key, keyPath) {
|
async handleSelectView(key, keyPath) {
|
||||||
const routeName = this.viewsMapper[key] || '/'
|
const routeName = this.viewsMapper[key] || '/'
|
||||||
localStorage.setItem('PreView', key)
|
localStorage.setItem('preView', key)
|
||||||
// Next 之前要重置 init 状态,否则这些路由守卫就不走了
|
// Next 之前要重置 init 状态,否则这些路由守卫就不走了
|
||||||
await store.dispatch('app/reset')
|
await store.dispatch('app/reset')
|
||||||
if (!this.tipHasRead) {
|
if (!this.tipHasRead) {
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ export default {
|
|||||||
|
|
||||||
// 未找到与之对应的
|
// 未找到与之对应的
|
||||||
& ::v-deep .el-submenu__title {
|
& ::v-deep .el-submenu__title {
|
||||||
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
line-height: $headerHeight;
|
line-height: $headerHeight;
|
||||||
height: $headerHeight;
|
height: $headerHeight;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<el-alert v-if="helpMessage" type="success">
|
<el-alert v-if="helpMessage" type="success">
|
||||||
<span v-sanitize="helpMessage" class="announcement-main" />
|
<span v-sanitize="helpMessage" class="announcement-main" />
|
||||||
</el-alert>
|
</el-alert>
|
||||||
<transition v-if="!loading" appear mode="out-in" name="fade-transform">
|
<transition appear mode="out-in" name="fade-transform">
|
||||||
<slot>
|
<slot>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="computeActiveComponent" />
|
<component :is="computeActiveComponent" />
|
||||||
@@ -83,16 +83,18 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: true,
|
loading: false,
|
||||||
toSentenceCase: toSentenceCase
|
toSentenceCase: toSentenceCase,
|
||||||
|
activeTab: this.activeMenu
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
iActiveMenu: {
|
iActiveMenu: {
|
||||||
get() {
|
get() {
|
||||||
return this.activeMenu
|
return this.activeTab
|
||||||
},
|
},
|
||||||
set(item) {
|
set(item) {
|
||||||
|
this.activeTab = item
|
||||||
this.$emit('update:activeMenu', item)
|
this.$emit('update:activeMenu', item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -119,16 +121,13 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
$route(to, from) {
|
$route(to, from) {
|
||||||
const activeTab = to.query?.tab
|
// 好像没必要
|
||||||
if (activeTab && this.iActiveMenu !== activeTab) {
|
// const activeTab = to.query?.tab
|
||||||
this.iActiveMenu = activeTab
|
// if (activeTab && this.iActiveMenu !== activeTab) {
|
||||||
}
|
// this.iActiveMenu = activeTab
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
activated() {
|
|
||||||
this.iActiveMenu = this.getPropActiveTab()
|
|
||||||
this.loading = false
|
|
||||||
},
|
|
||||||
created() {
|
created() {
|
||||||
this.iActiveMenu = this.getPropActiveTab()
|
this.iActiveMenu = this.getPropActiveTab()
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -136,15 +135,8 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
handleTabClick(tab) {
|
handleTabClick(tab) {
|
||||||
this.$emit('tab-click', tab)
|
this.$emit('tab-click', tab)
|
||||||
this.$emit('update:activeMenu', tab.name)
|
this.iActiveMenu = tab.name
|
||||||
|
|
||||||
this.$cookie.set(this.$route.path, tab.name, 1)
|
this.$cookie.set(this.$route.path, tab.name, 1)
|
||||||
|
|
||||||
if (this.$router.currentRoute.query[this.$route.path]) {
|
|
||||||
this.$router.push({
|
|
||||||
query: { ...this.$route.query, [this.$route.path]: '' }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getPropActiveTab() {
|
getPropActiveTab() {
|
||||||
let activeTab = ''
|
let activeTab = ''
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export default [
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
meta: {
|
meta: {
|
||||||
title: i18n.t('CommandGroupDetail'),
|
title: i18n.t('CommandGroupDetail'),
|
||||||
activeMenu: ''
|
activeMenu: '/console/perms/acls/cmd-acls'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,13 +28,39 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/profile/password-and-ssh-key',
|
path: '/profile/password-and-ssh-key',
|
||||||
name: 'PasswordAndSSHKey',
|
component: empty,
|
||||||
component: () => import('@/views/profile/PasswordAndSSHKey/index'),
|
|
||||||
meta: {
|
meta: {
|
||||||
title: i18n.t('PasswordAndSSHKey'),
|
icon: 'personal'
|
||||||
icon: 'personal',
|
},
|
||||||
permissions: []
|
children: [
|
||||||
}
|
{
|
||||||
|
path: '',
|
||||||
|
component: () => import('@/views/profile/PasswordAndSSHKey/index'),
|
||||||
|
name: 'SSHKeyList',
|
||||||
|
icon: 'key',
|
||||||
|
meta: { title: i18n.t('PasswordAndSSHKey'), permissions: ['authentication.view_sshkey'] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: () => import('@/views/profile/PasswordAndSSHKey/SSHKey/SSHKeyCreateUpdate.vue'),
|
||||||
|
name: 'SSHKeyCreate',
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('SSHKey'),
|
||||||
|
permissions: ['authentication.add_sshkey']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':id/update',
|
||||||
|
component: () => import('@/views/profile/PasswordAndSSHKey/SSHKey/SSHKeyCreateUpdate.vue'),
|
||||||
|
name: 'SSHKeyUpdate',
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
title: i18n.t('SSHKey'),
|
||||||
|
permissions: ['authentication.change_sshkey']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/profile/passkeys',
|
path: '/profile/passkeys',
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ body {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: auto;
|
-webkit-font-smoothing: auto;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-primary);
|
||||||
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.428;
|
line-height: 1.428;
|
||||||
}
|
}
|
||||||
@@ -586,3 +586,16 @@ li.rmenu i.fa {
|
|||||||
color: var(--color-link);
|
color: var(--color-link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-table__row {
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px; /* 设置垂直滚动条的宽度 */
|
||||||
|
height: 6px; /* 设置水平滚动条的高度 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.black-theme-popover {
|
||||||
|
width: 300px;
|
||||||
|
max-height: 700px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ $single-menu-height: 38px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-menu--vertical {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.el-menu {
|
.el-menu {
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
background-color: inherit !important;
|
background-color: inherit !important;
|
||||||
@@ -139,6 +143,10 @@ $single-menu-height: 38px;
|
|||||||
.nest-menu .level2-menu {
|
.nest-menu .level2-menu {
|
||||||
line-height: $single-menu-height;
|
line-height: $single-menu-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-tooltip {
|
||||||
|
width: 55px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,15 +112,15 @@
|
|||||||
background: url('./icons/gpt.png') no-repeat center left transparent;
|
background: url('./icons/gpt.png') no-repeat center left transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.WebCloud_ico_docu {
|
|
||||||
background: url('icons/cloud.png') no-repeat center left transparent;
|
|
||||||
background-size: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.clickhouse_ico_docu {
|
&.clickhouse_ico_docu {
|
||||||
background: url('./icons/clickhouse.png') no-repeat center left transparent;
|
background: url('./icons/clickhouse.png') no-repeat center left transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.WebCloud_ico_docu {
|
||||||
|
background: url('./icons/cloud.png') no-repeat center left transparent;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
|
||||||
&.ico_loading {
|
&.ico_loading {
|
||||||
background: url(./icons/loading.gif) no-repeat scroll 0 0 transparent;
|
background: url(./icons/loading.gif) no-repeat scroll 0 0 transparent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import VueCookie from 'vue-cookie'
|
import VueCookie from 'vue-cookie'
|
||||||
|
|
||||||
const CURRENT_ORG_KEY = 'jms_current_org'
|
const CURRENT_ORG_KEY = 'currentOrg'
|
||||||
const CURRENT_ROLE_KEY = 'jms_current_role'
|
const CURRENT_ROLE_KEY = 'currentRole'
|
||||||
let cookieNamePrefix = VueCookie.get('SESSION_COOKIE_NAME_PREFIX')
|
let cookieNamePrefix = VueCookie.get('SESSION_COOKIE_NAME_PREFIX')
|
||||||
if (!cookieNamePrefix || ['""', "''"].indexOf(cookieNamePrefix) > -1) {
|
if (!cookieNamePrefix || ['""', "''"].indexOf(cookieNamePrefix) > -1) {
|
||||||
cookieNamePrefix = ''
|
cookieNamePrefix = ''
|
||||||
@@ -17,7 +17,7 @@ export function setTokenToCookie(value, expires) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentRoleLocal(username) {
|
export function getCurrentRoleLocal(username) {
|
||||||
const key = CURRENT_ROLE_KEY + '_' + username
|
const key = CURRENT_ROLE_KEY + ':' + username
|
||||||
const role = localStorage.getItem(key)
|
const role = localStorage.getItem(key)
|
||||||
if (role) {
|
if (role) {
|
||||||
return parseInt(role) || null
|
return parseInt(role) || null
|
||||||
@@ -26,12 +26,12 @@ export function getCurrentRoleLocal(username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function saveCurrentRoleLocal(username, role) {
|
export function saveCurrentRoleLocal(username, role) {
|
||||||
const key = CURRENT_ROLE_KEY + '_' + username
|
const key = CURRENT_ROLE_KEY + ':' + username
|
||||||
return localStorage.setItem(key, role)
|
return localStorage.setItem(key, role)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentOrgLocal(username) {
|
export function getCurrentOrgLocal(username) {
|
||||||
const key = CURRENT_ORG_KEY + '_' + username
|
const key = CURRENT_ORG_KEY + ':' + username
|
||||||
const value = localStorage.getItem(key)
|
const value = localStorage.getItem(key)
|
||||||
try {
|
try {
|
||||||
return JSON.parse(value)
|
return JSON.parse(value)
|
||||||
@@ -41,18 +41,18 @@ export function getCurrentOrgLocal(username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function saveCurrentOrgLocal(username, org) {
|
export function saveCurrentOrgLocal(username, org) {
|
||||||
const key = CURRENT_ORG_KEY + '_' + username
|
const key = CURRENT_ORG_KEY + ':' + username
|
||||||
localStorage.setItem(key, JSON.stringify(org))
|
localStorage.setItem(key, JSON.stringify(org))
|
||||||
VueCookie.set('X-JMS-ORG', org.id)
|
VueCookie.set('X-JMS-ORG', org.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPreOrgLocal(username, org) {
|
export function setPreOrgLocal(username, org) {
|
||||||
const key = 'PRE_ORG_' + username
|
const key = 'preOrg' + ':' + username
|
||||||
localStorage.setItem(key, JSON.stringify(org))
|
localStorage.setItem(key, JSON.stringify(org))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPreOrgLocal(username) {
|
export function getPreOrgLocal(username) {
|
||||||
const key = 'PRE_ORG_' + username
|
const key = 'preOrg' + ':' + username
|
||||||
const value = localStorage.getItem(key)
|
const value = localStorage.getItem(key)
|
||||||
try {
|
try {
|
||||||
return JSON.parse(value)
|
return JSON.parse(value)
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ export function getErrorResponseMsg(error) {
|
|||||||
}).filter(i => i).join('; ')
|
}).filter(i => i).join('; ')
|
||||||
} else if (typeof data === 'string') {
|
} else if (typeof data === 'string') {
|
||||||
return data
|
return data
|
||||||
|
} else {
|
||||||
|
msg = error.toString()
|
||||||
}
|
}
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
@@ -310,4 +312,26 @@ export function toSentenceCase(string) {
|
|||||||
}).join(' ')
|
}).join(' ')
|
||||||
return s[0].toUpperCase() + s.slice(1)
|
return s[0].toUpperCase() + s.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { BASE_URL }
|
export { BASE_URL }
|
||||||
|
|
||||||
|
export function openNewWindow(url) {
|
||||||
|
let count
|
||||||
|
let top = 50
|
||||||
|
count = parseInt(window.sessionStorage.getItem('newWindowCount'), 10)
|
||||||
|
if (isNaN(count)) {
|
||||||
|
count = 0
|
||||||
|
}
|
||||||
|
let left = 100 + count * 100
|
||||||
|
top = 50 + count * 50
|
||||||
|
if (left + screen.width / 3 > screen.width) {
|
||||||
|
// 支持两排足以
|
||||||
|
top = screen.height / 3
|
||||||
|
count = 1
|
||||||
|
left = 100
|
||||||
|
}
|
||||||
|
let params = 'toolbar=yes,scrollbars=yes,resizable=yes'
|
||||||
|
params = params + `,top=${top},left=${left},width=${screen.width / 3},height=${screen.height / 3}`
|
||||||
|
window.sessionStorage.setItem('newWindowCount', `${count + 1}`)
|
||||||
|
window.open(url, '_blank', params)
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ Object.assign(Table.components.TableBody.methods, {
|
|||||||
const range = document.createRange()
|
const range = document.createRange()
|
||||||
range.setStart(cellChild, 0)
|
range.setStart(cellChild, 0)
|
||||||
range.setEnd(cellChild, cellChild.childNodes.length)
|
range.setEnd(cellChild, cellChild.childNodes.length)
|
||||||
const rangeWidth = range.getBoundingClientRect().width
|
// rangeWidth 有可能是小数,因此就会导致原本 rangeWidth + padding = cellChild.offsetWidth 的大于了 cellChild.offsetWidth
|
||||||
|
const rangeWidth = Math.floor(range.getBoundingClientRect().width)
|
||||||
const padding = (parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
|
const padding = (parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
|
||||||
(parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0)
|
(parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0)
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export function isSameView(to, from) {
|
|||||||
|
|
||||||
export function getPropView() {
|
export function getPropView() {
|
||||||
const hasPermedViews = getPermedViews()
|
const hasPermedViews = getPermedViews()
|
||||||
const preView = localStorage.getItem('PreView')
|
const preView = localStorage.getItem('preView')
|
||||||
const hasPerm = hasPermedViews.indexOf(preView) > -1
|
const hasPerm = hasPermedViews.indexOf(preView) > -1
|
||||||
if (hasPerm) {
|
if (hasPerm) {
|
||||||
return preView
|
return preView
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import i18n from '@/i18n/i18n'
|
|||||||
import { eventBus } from '@/utils/const'
|
import { eventBus } from '@/utils/const'
|
||||||
import { getTokenFromCookie } from '@/utils/auth'
|
import { getTokenFromCookie } from '@/utils/auth'
|
||||||
import { getErrorResponseMsg } from '@/utils/common'
|
import { getErrorResponseMsg } from '@/utils/common'
|
||||||
import { refreshSessionIdAge } from '@/api/users'
|
|
||||||
import { MessageBox } from 'element-ui'
|
import { MessageBox } from 'element-ui'
|
||||||
import { message } from '@/utils/message'
|
import { message } from '@/utils/message'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
@@ -102,20 +101,6 @@ export function flashErrorMsg({ response, error }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let timer = null
|
|
||||||
|
|
||||||
function refreshSessionAgeDelay(response) {
|
|
||||||
if (response.request.responseURL.indexOf('/users/profile/') !== -1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer)
|
|
||||||
}
|
|
||||||
timer = setTimeout(function() {
|
|
||||||
refreshSessionIdAge()
|
|
||||||
}, 30 * 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ifConfirmRequired({ response, error }) {
|
function ifConfirmRequired({ response, error }) {
|
||||||
if (response.status !== 412) {
|
if (response.status !== 412) {
|
||||||
return null
|
return null
|
||||||
@@ -142,7 +127,6 @@ service.interceptors.response.use(
|
|||||||
*/
|
*/
|
||||||
response => {
|
response => {
|
||||||
// NProgress.done()
|
// NProgress.done()
|
||||||
refreshSessionAgeDelay(response)
|
|
||||||
const res = response.data
|
const res = response.data
|
||||||
store.dispatch('common/digestSQLQuery', response).then()
|
store.dispatch('common/digestSQLQuery', response).then()
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ async function checkLogin({ to, from, next }) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
Vue.$log.error(e)
|
Vue.$log.error(e)
|
||||||
const status = e.response.status
|
const status = e.response.status
|
||||||
|
if (store.getters.currentOrg.autoEnter) {
|
||||||
|
await store.dispatch('users/setCurrentOrg', store.getters.preOrg)
|
||||||
|
}
|
||||||
if (status === 401 || status === 403) {
|
if (status === 401 || status === 403) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location = process.env.VUE_APP_LOGIN_PATH
|
window.location = process.env.VUE_APP_LOGIN_PATH
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default {
|
|||||||
initial: {
|
initial: {
|
||||||
is_periodic: false,
|
is_periodic: false,
|
||||||
password_rules: {
|
password_rules: {
|
||||||
length: 16
|
length: 36
|
||||||
},
|
},
|
||||||
interval: 24,
|
interval: 24,
|
||||||
accounts: [],
|
accounts: [],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
initial: {
|
initial: {
|
||||||
is_periodic: false,
|
is_periodic: false,
|
||||||
password_rules: {
|
password_rules: {
|
||||||
length: 30
|
length: 36
|
||||||
},
|
},
|
||||||
interval: 24,
|
interval: 24,
|
||||||
secret_type: 'password',
|
secret_type: 'password',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import InputWithUnit from '@/components/Form/FormFields/InputWithUnit.vue'
|
|||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
const validatorInterval = (rule, value, callback) => {
|
const validatorInterval = (rule, value, callback) => {
|
||||||
if (parseInt(value) < 1) {
|
if (isNaN(parseInt(value, 10)) || parseInt(value) < 1) {
|
||||||
return callback(new Error(i18n.t('EnsureThisValueIsGreaterThanOrEqualTo1')))
|
return callback(new Error(i18n.t('EnsureThisValueIsGreaterThanOrEqualTo1')))
|
||||||
}
|
}
|
||||||
callback()
|
callback()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
reviewers: {
|
reviewers: {
|
||||||
hidden: (item) => !['review', 'warning'].includes(item.action),
|
hidden: (item) => !['review', 'warning', 'notify_and_warn'].includes(item.action),
|
||||||
rules: [rules.RequiredChange],
|
rules: [rules.RequiredChange],
|
||||||
el: {
|
el: {
|
||||||
value: [],
|
value: [],
|
||||||
|
|||||||
@@ -68,11 +68,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
activated() {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.$refs.listTable.reloadTable()
|
|
||||||
}, 300)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -32,15 +32,9 @@ export default {
|
|||||||
title: this.$t('Basic'),
|
title: this.$t('Basic'),
|
||||||
name: 'Detail'
|
name: 'Detail'
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
actions: {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -53,11 +53,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
computed: {}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<TabPage
|
<TabPage
|
||||||
:active-menu.sync="config.activeMenu"
|
:active-menu.sync="config.activeMenu"
|
||||||
:submenu="config.submenu"
|
:submenu="config.submenu"
|
||||||
@tab-click="handleTabClick"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -35,20 +34,6 @@ export default {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleTabClick(tab) {
|
|
||||||
const query = _.cloneDeep(this.$route.query)
|
|
||||||
const newQuery = {
|
|
||||||
...query,
|
|
||||||
tab: tab.name
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$router.replace({ query: newQuery })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: true,
|
loading: true,
|
||||||
platform: {},
|
platform: {},
|
||||||
|
changePlatformID: '',
|
||||||
defaultConfig: {
|
defaultConfig: {
|
||||||
initial: {},
|
initial: {},
|
||||||
platform: {},
|
platform: {},
|
||||||
@@ -131,7 +132,7 @@ export default {
|
|||||||
const { defaultConfig } = this
|
const { defaultConfig } = this
|
||||||
const { node, platform } = this.$route?.query || {}
|
const { node, platform } = this.$route?.query || {}
|
||||||
const nodesInitial = node ? [node] : []
|
const nodesInitial = node ? [node] : []
|
||||||
const platformId = platform || 'Linux'
|
const platformId = this.changePlatformID ? this.changePlatformID : (platform || 'Linux')
|
||||||
const url = `/api/v1/assets/platforms/${platformId}/`
|
const url = `/api/v1/assets/platforms/${platformId}/`
|
||||||
this.platform = await this.$axios.get(url)
|
this.platform = await this.$axios.get(url)
|
||||||
const initial = {
|
const initial = {
|
||||||
|
|||||||
@@ -25,17 +25,17 @@ export default {
|
|||||||
const platform = this.$route.query.type
|
const platform = this.$route.query.type
|
||||||
const baseFields = [[this.$t('Basic'), ['db_name']]]
|
const baseFields = [[this.$t('Basic'), ['db_name']]]
|
||||||
let tlsFields = ['use_ssl', 'ca_cert']
|
let tlsFields = ['use_ssl', 'ca_cert']
|
||||||
switch (platform) {
|
const platformFieldsMap = {
|
||||||
case 'redis':
|
redis: ['client_cert', 'client_key'],
|
||||||
tlsFields = tlsFields.concat(['client_cert', 'client_key'])
|
postgresql: ['client_cert', 'client_key', 'pg_ssl_mode'],
|
||||||
break
|
mysql: ['client_cert', 'client_key', 'allow_invalid_cert'],
|
||||||
case 'mysql':
|
mongodb: ['client_key', 'allow_invalid_cert']
|
||||||
tlsFields = tlsFields.concat(['client_cert', 'client_key', 'allow_invalid_cert'])
|
|
||||||
break
|
|
||||||
case 'mongodb':
|
|
||||||
tlsFields = tlsFields.concat(['client_key', 'allow_invalid_cert'])
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (platformFieldsMap[platform]) {
|
||||||
|
tlsFields = tlsFields.concat(platformFieldsMap[platform])
|
||||||
|
}
|
||||||
|
|
||||||
if (tlsFields.length > 2) {
|
if (tlsFields.length > 2) {
|
||||||
const secureField = [
|
const secureField = [
|
||||||
this.$t('Secure'), tlsFields, 2
|
this.$t('Secure'), tlsFields, 2
|
||||||
@@ -52,7 +52,14 @@ export default {
|
|||||||
},
|
},
|
||||||
use_ssl: {
|
use_ssl: {
|
||||||
label: this.$t('UseSSL'),
|
label: this.$t('UseSSL'),
|
||||||
component: 'el-switch'
|
component: 'el-switch',
|
||||||
|
on: {
|
||||||
|
change: ([event], updateForm) => {
|
||||||
|
updateForm({
|
||||||
|
pg_ssl_mode: event ? 'require' : 'prefer'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
allow_invalid_cert: {
|
allow_invalid_cert: {
|
||||||
label: this.$t('AllowInvalidCert'),
|
label: this.$t('AllowInvalidCert'),
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: this.$t('QuickTest'),
|
title: this.$t('Test'),
|
||||||
templateDialogVisible: false,
|
templateDialogVisible: false,
|
||||||
columnsDefault: ['name', 'username', 'asset'],
|
columnsDefault: ['name', 'username', 'asset'],
|
||||||
headerExtraActions: [
|
headerExtraActions: [
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ export default {
|
|||||||
},
|
},
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: tableUrl,
|
url: tableUrl,
|
||||||
category: 'all'
|
category: 'all',
|
||||||
|
extraQuery: { 'order': '-date_updated' }
|
||||||
},
|
},
|
||||||
headerActions: {
|
headerActions: {
|
||||||
handleImportClick: ({ selectedRows }) => {
|
handleImportClick: ({ selectedRows }) => {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default {
|
|||||||
row['auto_config'].ansible_enabled &&
|
row['auto_config'].ansible_enabled &&
|
||||||
row['auto_config'].ping_enabled,
|
row['auto_config'].ping_enabled,
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
if (row.platform.name === 'Gateway') {
|
if (row.platform.name.startsWith('Gateway')) {
|
||||||
this.GatewayVisible = true
|
this.GatewayVisible = true
|
||||||
const port = row.protocols.find(item => item.name === 'ssh').port
|
const port = row.protocols.find(item => item.name === 'ssh').port
|
||||||
if (!port) {
|
if (!port) {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ export default {
|
|||||||
row?.auto_config?.ansible_enabled &&
|
row?.auto_config?.ansible_enabled &&
|
||||||
row?.auto_config?.ping_enabled,
|
row?.auto_config?.ping_enabled,
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
if (row.platform.name === 'Gateway') {
|
if (row.platform.name.startsWith('Gateway')) {
|
||||||
this.GatewayVisible = true
|
this.GatewayVisible = true
|
||||||
const port = row.protocols.find(item => item.name === 'ssh').port
|
const port = row.protocols.find(item => item.name === 'ssh').port
|
||||||
if (!port) {
|
if (!port) {
|
||||||
|
|||||||
@@ -22,15 +22,17 @@
|
|||||||
:key="platform.id"
|
:key="platform.id"
|
||||||
:span="6"
|
:span="6"
|
||||||
>
|
>
|
||||||
<el-card
|
<el-tooltip :content="platform.name" :open-delay="1000">
|
||||||
:style="{ borderLeftColor: randomBorderColor(index) }"
|
<el-card
|
||||||
class="platform-item"
|
:style="{ borderLeftColor: randomBorderColor(index) }"
|
||||||
shadow="hover"
|
class="platform-item"
|
||||||
@click.native="createAsset(platform)"
|
shadow="hover"
|
||||||
>
|
@click.native="createAsset(platform)"
|
||||||
<img :src="loadImage(platform)" alt="icon" class="asset-icon">
|
>
|
||||||
<span class="platform-name">{{ platform.name }}</span>
|
<img :src="loadImage(platform)" alt="icon" class="asset-icon">
|
||||||
</el-card>
|
<span class="platform-name">{{ platform.name }}</span>
|
||||||
|
</el-card>
|
||||||
|
</el-tooltip>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
@@ -195,7 +197,11 @@ export default {
|
|||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
|
||||||
& ::v-deep .el-card__body {
|
& ::v-deep .el-card__body {
|
||||||
padding: 10px
|
padding: 10px;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
border-left: solid 4px;
|
border-left: solid 4px;
|
||||||
@@ -230,14 +236,16 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.asset-icon {
|
.asset-icon {
|
||||||
width: 1.5em;
|
width: 2em;
|
||||||
height: 1.5em;
|
height: 2em;
|
||||||
vertical-align: -0.2em;
|
vertical-align: -0.2em;
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.platform-name {
|
.platform-name {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -89,14 +89,15 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleTabClick(tab) {
|
handleTabClick(tab) {
|
||||||
const query = _.cloneDeep(this.$route.query)
|
// 这样不行,会闪
|
||||||
const newQuery = {
|
// const query = _.cloneDeep(this.$route.query)
|
||||||
...query,
|
// const newQuery = {
|
||||||
tab: tab.name
|
// ...query,
|
||||||
}
|
// tab: tab.name
|
||||||
this.$nextTick(() => {
|
// }
|
||||||
this.$router.replace({ query: newQuery })
|
// this.$nextTick(() => {
|
||||||
})
|
// this.$router.replace({ query: newQuery })
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('Timer'),
|
title: this.$t('TimerExecution'),
|
||||||
attrs: {
|
attrs: {
|
||||||
model: this.object.task,
|
model: this.object.task,
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
@@ -173,7 +173,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: this.$t('Region'),
|
key: this.$t('Region'),
|
||||||
value: this.object.task?.regions,
|
value: this.object.task?.regions_display,
|
||||||
formatter(row, value) {
|
formatter(row, value) {
|
||||||
return (<div>{
|
return (<div>{
|
||||||
value?.map((content) => {
|
value?.map((content) => {
|
||||||
|
|||||||
@@ -64,8 +64,11 @@ export default {
|
|||||||
formatter: DateFormatter
|
formatter: DateFormatter
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'summary.triggerMode',
|
prop: 'trigger',
|
||||||
label: this.$t('TriggerMode')
|
label: this.$t('TriggerMode'),
|
||||||
|
formatter: row => {
|
||||||
|
return row.trigger.label
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'actions',
|
prop: 'actions',
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
console.log('ProviderPanel', this.providers)
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export default {
|
|||||||
btn.loading = true
|
btn.loading = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
form.value.interval = parseInt(form.value.interval, 10)
|
||||||
this.$refs.form.$refs.form.dataForm.submitForm('form', false)
|
this.$refs.form.$refs.form.dataForm.submitForm('form', false)
|
||||||
},
|
},
|
||||||
handleSubmitSuccess(res) {
|
handleSubmitSuccess(res) {
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ export default {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
actions: {
|
actions: {
|
||||||
|
canUpdate: () => {
|
||||||
|
return this.Account.name !== 'default'
|
||||||
|
},
|
||||||
|
canDelete: () => {
|
||||||
|
return this.Account.name !== 'default'
|
||||||
|
},
|
||||||
deleteSuccessRoute: 'CloudAccountList',
|
deleteSuccessRoute: 'CloudAccountList',
|
||||||
updateCallback: () => {
|
updateCallback: () => {
|
||||||
const id = this.$route.params.id
|
const id = this.$route.params.id
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ export default {
|
|||||||
submitBtnSize: 'mini',
|
submitBtnSize: 'mini',
|
||||||
submitBtnText: this.$t('Add'),
|
submitBtnText: this.$t('Add'),
|
||||||
hasReset: false,
|
hasReset: false,
|
||||||
onSubmit: () => {},
|
onSubmit: () => {
|
||||||
|
},
|
||||||
submitMethod: () => 'post',
|
submitMethod: () => 'post',
|
||||||
getUrl: () => '',
|
getUrl: () => '',
|
||||||
cleanFormValue(data) {
|
cleanFormValue(data) {
|
||||||
@@ -86,7 +87,11 @@ export default {
|
|||||||
this.formConfig.fieldsMeta.protocols.el.hidden = true
|
this.formConfig.fieldsMeta.protocols.el.hidden = true
|
||||||
}
|
}
|
||||||
this.resourceType = val
|
this.resourceType = val
|
||||||
this.formConfig.fieldsMeta.value.el.ajax.url = url
|
if (url) {
|
||||||
|
this.formConfig.fieldsMeta.value.el.ajax.url = url
|
||||||
|
} else {
|
||||||
|
this.formConfig.fieldsMeta.attr.el.remote = false
|
||||||
|
}
|
||||||
this.formConfig.fieldsMeta.value.el.options = options
|
this.formConfig.fieldsMeta.value.el.options = options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,21 +156,31 @@ export default {
|
|||||||
tableConfig: {
|
tableConfig: {
|
||||||
columns: [
|
columns: [
|
||||||
{ prop: 'attr', label: this.$t('ResourceType'), formatter: tableFormatter('resource_type') },
|
{ prop: 'attr', label: this.$t('ResourceType'), formatter: tableFormatter('resource_type') },
|
||||||
{ prop: 'value', label: this.$t('Resource'), formatter: tableFormatter('resource', () => { return this.globalResource }) },
|
{
|
||||||
|
prop: 'value', label: this.$t('Resource'), formatter: tableFormatter('resource', () => {
|
||||||
|
return this.globalResource
|
||||||
|
})
|
||||||
|
},
|
||||||
{ prop: 'protocols', label: this.$t('Other'), formatter: tableFormatter('protocols') },
|
{ prop: 'protocols', label: this.$t('Other'), formatter: tableFormatter('protocols') },
|
||||||
{ prop: 'action', label: this.$t('Action'), align: 'center', width: '100px', formatter: (row, col, cellValue, index) => {
|
{
|
||||||
return (
|
prop: 'action',
|
||||||
<div className='input-button'>
|
label: this.$t('Action'),
|
||||||
<el-button
|
align: 'center',
|
||||||
icon='el-icon-minus'
|
width: '100px',
|
||||||
size='mini'
|
formatter: (row, col, cellValue, index) => {
|
||||||
style={{ 'flexShrink': 0 }}
|
return (
|
||||||
type='danger'
|
<div className='input-button'>
|
||||||
onClick={ this.handleDelete(index) }
|
<el-button
|
||||||
/>
|
icon='el-icon-minus'
|
||||||
</div>
|
size='mini'
|
||||||
)
|
style={{ 'flexShrink': 0 }}
|
||||||
} }
|
type='danger'
|
||||||
|
onClick={this.handleDelete(index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
],
|
],
|
||||||
totalData: this.value || [],
|
totalData: this.value || [],
|
||||||
hasPagination: false
|
hasPagination: false
|
||||||
@@ -177,7 +192,9 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
this.nameOptions.map((o) => { this.globalResource[o.value] = o.label })
|
this.nameOptions.map((o) => {
|
||||||
|
this.globalResource[o.value] = o.label
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$emit('input', this.tableConfig.totalData)
|
this.$emit('input', this.tableConfig.totalData)
|
||||||
@@ -218,9 +235,11 @@ export default {
|
|||||||
::v-deep .el-form-item:nth-child(-n+3) {
|
::v-deep .el-form-item:nth-child(-n+3) {
|
||||||
width: 43.5%;
|
width: 43.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-form-item:last-child {
|
::v-deep .el-form-item:last-child {
|
||||||
width: 6%;
|
width: 6%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-input {
|
.action-input {
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default {
|
|||||||
domain_enabled: true
|
domain_enabled: true
|
||||||
},
|
},
|
||||||
canSelect: (row) => {
|
canSelect: (row) => {
|
||||||
return row.platform?.name !== 'Gateway'
|
return !row.platform?.name.startsWith('Gateway')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||