Compare commits

..

42 Commits

Author SHA1 Message Date
jiangweidong
6ea86c7efe feat: VMware automatically syncs folders to node 2025-01-03 18:52:06 +08:00
zhaojisen
dc0a0ae868 Fixed: Change Tree Icon Position 2025-01-02 14:58:43 +08:00
Bai
5b3b8f72cd fix: system org 2024-12-26 14:44:05 +08:00
feng
df26679166 perf: Firefox unable to download file 2024-12-26 13:59:08 +08:00
zhaojisen
9efccb8ada fixed: Fixed tissue switching issues 2024-12-25 16:22:56 +08:00
zhaojisen
d784530539 Fixed: Fixed an issue with the number of cross-pages in Select All reverse 2024-12-25 15:24:51 +08:00
zhaojisen
afcc60f29c fixed: Optimize select all and deselect all functionality 2024-12-24 17:00:01 +08:00
zhaojisen
f8d581e455 Fixed: Optimize select all and deselect all functionality 2024-12-24 17:00:01 +08:00
zhaojisen
dba1540953 fixed: Fixed remarks text wrapping issue 2024-12-24 16:07:21 +08:00
Bai
456227abcf fix: ticket approve 2024-12-18 16:35:58 +08:00
feng
66532f4d4b fix: ticket duplicate submission 2024-11-26 16:27:27 +08:00
wangruidong
42f27eb30f perf: users use Select2 2024-10-17 10:34:54 +08:00
wangruidong
57920bf771 fix: user lack permission to view the type tree 2024-10-10 17:11:40 +08:00
ZhaoJiSen
290772f44e Merge pull request #4384 from jumpserver/pr@v3@fix_special_chara
fixed: Fixed + and - not being special characters
2024-10-09 18:37:03 +08:00
zhaojisen
f140f2f59e fixed: Fixed + and - not being special characters 2024-10-09 18:35:40 +08:00
zhaojisen
7b1883e012 fixed: Fixed + and - not being special characters 2024-10-09 18:28:00 +08:00
wisonic
352ac7e828 fix: assets proportion tooltip cause page bounced at first time 2024-09-27 15:16:26 +08:00
ZhaoJiSen
1cbd58664c Merge pull request #4375 from jumpserver/pr@v3@perf_import_style
perf: Import UI style optimizations
2024-09-26 17:35:26 +08:00
zhaojisen
e48da6be9b perf: Import UI style optimizations 2024-09-26 17:30:14 +08:00
wangruidong
fa31b36550 fix: xterm output truncate 2024-09-26 17:16:22 +08:00
ibuler
6b93a6563d perf: revert pre org if logout 2024-08-30 17:02:49 +08:00
feng
d561701049 perf: Ticket flow rule user display name(username) 2024-08-19 16:06:55 +08:00
Ewall555
edbf477c1e perf: Translate ticket cancel button 2024-08-15 15:49:49 +08:00
ZhaoJiSen
6a2578b339 Merge pull request #4292 from jumpserver/pr@v3@fix_loading
perf: add button loading status
2024-08-08 15:01:35 +08:00
zhaojisen
2cb7569cb0 perf: add button loading status 2024-08-08 15:00:11 +08:00
fit2bot
9e0c623b9a perf: add button loading status (#4287)
* perf: add button loading status

* perf: add button loading status

---------

Co-authored-by: zhaojisen <1301338853@qq.com>
2024-08-08 11:38:04 +08:00
feng
40bf040501 perf: Asset authorization: The number of accounts displayed is incorrect ignore @SPEC 2024-08-07 17:51:21 +08:00
halo
efee7c7bbf perf: Email service authentication username is optional 2024-07-26 14:20:20 +08:00
ZhaoJiSen
5daecb84ae Merge pull request #4251 from jumpserver/pr@v3@fix_data_refresh
fixed: Fixed an issue where the validation date does not refresh
2024-07-23 10:09:16 +08:00
feng
3be325214d perf: You can modify sudo permissions multiple times 2024-07-22 18:18:11 +08:00
zhaojisen
581509f42f fixed: Fixed an issue where the validation date does not refresh 2024-07-22 14:52:45 +08:00
zhaojisen
654b36b064 fixed: Fixed the issue that parameter push parameters could not be saved 2024-07-17 10:49:02 +08:00
feng626
dcec73ae67 Merge pull request #4224 from jumpserver/pr@v3@download
perf: Downloading files does not trigger the beforeunload event
2024-07-16 12:42:48 +08:00
feng
00bafa8164 perf: Downloading files does not trigger the beforeunload event 2024-07-16 12:40:31 +08:00
zhaojisen
da09af79a7 fixed:Fixed an issue where the user was unable to enter non-MD content 2024-07-15 19:08:46 +08:00
zhaojisen
b596815ea5 fixed:Fixed an issue where the user was unable to enter non-MD content 2024-07-15 19:08:46 +08:00
ibuler
cb37273e80 perf: table search two times, one init one search 2024-07-12 10:20:55 +08:00
zhaojisen
c5bf7d0ad2 fixed: Fixed an issue where push parameters could not be saved when adding an asset account 2024-07-11 15:18:11 +08:00
wangruidong
c31195a67a perf: profile improvement mfa disabled 2024-07-10 14:21:27 +08:00
wangruidong
1eb59b379a perf: profile improvement mfa cancel hide 2024-07-09 16:14:43 +08:00
ZhaoJiSen
b7cee17156 Merge pull request #4188 from jumpserver/pr@v3@fix_unuse_item
fixed: Remove unused fields
2024-07-08 19:01:07 +08:00
zhaojisen
f1c8874010 fixed: Remove unused fields 2024-07-08 18:57:37 +08:00
892 changed files with 23006 additions and 20266 deletions

View File

@@ -22,6 +22,5 @@ VUE_APP_LOGOUT_PATH = '/core/auth/logout/'
# Dev server for core proxy
VUE_APP_CORE_HOST = 'http://localhost:8080'
VUE_APP_CORE_WS = 'ws://localhost:8080'
VUE_APP_KOKO_HOST = 'http://localhost:5000'
VUE_APP_KOKO_WS = 'ws://localhost:5000'
VUE_APP_KAEL_HOST = 'http://localhost:8083'
VUE_APP_ENV = 'development'

View File

@@ -1,72 +0,0 @@
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 }}"

32
.github/workflows/jms-build-test.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: "Run Build Test"
on:
push:
branches:
- pr@*
- repr@*
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v3
with:
context: .
push: false
tags: jumpserver/lina:test
file: Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
- uses: LouisBrunner/checks-action@v1.5.0
if: always()
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: Check Build
conclusion: ${{ job.status }}

View File

@@ -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

View File

@@ -31,7 +31,7 @@ jobs:
tag: ${{ steps.get_version.outputs.TAG }}
- uses: actions/setup-node@v2
with:
node-version: '20.15'
node-version: '16.20'
- name: Install dependencies
run: yarn install
- name: Build web

View File

@@ -1,11 +1,36 @@
FROM jumpserver/lina-base:20240723_084702 AS stage-build
FROM node:16.20-bullseye-slim 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,id=lina \
sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& apt-get update \
&& apt-get install -y --no-install-recommends ${DEPENDENCIES} \
&& echo "no" | dpkg-reconfigure dash \
&& rm -rf /var/lib/apt/lists/*
ARG NPM_REGISTRY="https://registry.npmmirror.com"
RUN set -ex \
&& npm config set registry ${NPM_REGISTRY} \
&& yarn config set registry ${NPM_REGISTRY}
WORKDIR /data
ADD package.json yarn.lock /data
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn,sharing=locked,id=lina \
yarn install
ARG VERSION
ENV VERSION=$VERSION
ADD . /data
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn,sharing=locked \
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn,sharing=locked,id=lina \
sed -i "s@version-dev@${VERSION}@g" src/layout/components/NavHeader/About.vue \
&& yarn build

View File

@@ -1,22 +0,0 @@
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

View File

@@ -1,13 +1,13 @@
{
"name": "lina",
"version": "v4.0.0",
"description": "JumpServer Web UI",
"author": "JumpServer Team <support@fit2cloud.com>",
"license": "GPL-3.0-or-later",
"name": "vue-admin-template",
"version": "4.2.1",
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"scripts": {
"dev": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
"serve": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
"build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build",
"dev": "vue-cli-service serve",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
@@ -25,12 +25,10 @@
},
"dependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
"@fontsource/open-sans": "^5.0.24",
"@traptitech/markdown-it-katex": "^3.6.0",
"@ztree/ztree_v3": "3.5.44",
"axios": "0.28.0",
"axios-retry": "^3.1.9",
"caniuse-lite": "^1.0.30001642",
"cron-parser": "^4.0.0",
"crypto-js": "^4.1.1",
"css-color-function": "^1.3.3",
@@ -38,7 +36,7 @@
"deepmerge": "^4.2.2",
"dompurify": "^3.1.6",
"echarts": "4.7.0",
"element-ui": "2.15.14",
"element-ui": "2.13.2",
"eslint-plugin-html": "^6.0.0",
"highlight.js": "^11.9.0",
"install": "^0.13.0",
@@ -66,8 +64,7 @@
"normalize.css": "7.0.0",
"npm": "^7.8.0",
"nprogress": "0.2.0",
"path-to-regexp": "3.3.0",
"v-sanitize": "^0.0.13",
"path-to-regexp": "2.4.0",
"vue": "2.6.10",
"vue-codemirror": "4.0.6",
"vue-cookie": "^1.1.4",
@@ -117,7 +114,7 @@
"sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.16.0",
"serve-static": "^1.13.2",
"strip-ansi": "^7.1.0",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",

View File

@@ -21,39 +21,32 @@
}
.el-alert--info.is-light {
background-color: rgba(255, 255, 255, 0.5);
color: info;
background-color: light-9;
color: light-2;
border: 1px solid;
}
.el-alert--info .el-alert__description {
color: info;
}
.el-pagination.is-background {
.el-pagination__total,
.el-pagination__sizes,
.el-pager {
color: var(--color-icon-primary);
}
color: light-2;
}
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: #fff;
color: white;
background-color: primary;
}
.el-pagination.is-background .btn-next,
.el-pagination.is-background .btn-prev,
.el-pagination.is-background .el-pager li {
margin: 0 5px;
background-color: #fff;
color: var(--color-icon-primary);
min-width: 28px;
border-radius: 2px;
border: 1px solid #DCDFE6;
font-size: 12px;
font-weight: 400;
margin: 0 5px;
background-color: white;
color: #606266;
min-width: 28px;
border-radius: 2px;
border: 1px solid #DCDFE6;
font-size: 12px;
line-height: 26px;
font-weight: 400;
}
.el-breadcrumb__inner,
@@ -92,12 +85,8 @@
td .el-button.el-button--mini {
padding: 1px 6px;
padding: 1px 5px;
line-height: 1.5;
.el-icon--right {
margin-bottom: 2px;
}
}
.el-tabs__item.is-active, .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
@@ -202,7 +191,7 @@ td .el-button.el-button--mini {
}
.el-input--small .el-input__icon {
line-height: 30px;
line-height: 34px;
}
.option-group .el-select-dropdown__item.hover, .option-group .el-select-dropdown__item.selected {
@@ -235,10 +224,8 @@ td .el-button.el-button--mini {
}
.el-tag.el-tag--info .el-tag__close {
display: inline-block;
margin-top: 3px;
color: var(--color-text-primary);
background-color: inherit;
color: #333333!important;
background-color: inherit;
}
.el-tag.el-tag--info.is-hit {
@@ -293,7 +280,7 @@ td .el-button.el-button--mini {
}
.el-textarea__inner {
color: var(--color-text-primary);
border-radius: 0;
}
.el-pagination.is-background .number {
@@ -326,11 +313,11 @@ td .el-button.el-button--mini {
.el-tooltip__popper.is-light {
background: #FFF;
max-width: 500px;
border: 1px solid #e7eaec;
box-shadow: 0 1.6px 3.6px 0 rgba(0, 0, 0, .132), 0 .3px .9px 0 rgba(0, 0, 0, .108);
line-height: 1.5;
padding: 10px;
}
.el-tooltip__popper.is-light .popper__arrow {
border-bottom-color: #e7eaec !important;
}
.el-dialog__headerbtn .el-dialog__close {
@@ -339,7 +326,7 @@ td .el-button.el-button--mini {
}
.el-table__header thead tr th {
/*border-bottom: 1px solid #e7e7e7 !important;*/
border-bottom: 1px solid #e7e7e7 !important;
}
.el-table .cell,
@@ -436,34 +423,14 @@ td .el-button.el-button--mini {
flex-direction: column;
}
.el-dialog .el-dialog__header .el-dialog__title {
color: var(--color-text-primary);
}
.el-dialog .el-dialog__body {
max-height: 80vh;
overflow: auto;
padding: 30px;
}
.el-dialog .el-dialog__body .el-transfer-panel .el-transfer-panel__body .el-input__inner,
.el-dialog .el-dialog__body .el-transfer-panel .el-transfer-panel__header .el-checkbox__label,
.el-dialog .el-dialog__body .el-transfer-panel .el-transfer-panel__body .el-checkbox-group .el-checkbox.el-transfer-panel__item {
color: var(--color-text-primary);
}
.el-dialog .el-dialog__body .opera .el-button.is-disabled,
.el-dialog .el-dialog__body .el-transfer-panel .vip-footer .el-button.is-disabled {
color: var(--color-input-border);
}
.el-dialog .el-dialog__body .opera .el-button.is-disabled.el-button--primary {
color: #fff;
}
.el-dialog .el-dialog__body form {
padding-right: 20px;
margin-right: 20px;
}
.el-dialog .el-dialog__footer {

View File

@@ -16,3 +16,6 @@ export default {
}
}
</script>
<style>
</style>

View File

@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getLokiLog(data) {
return request({
url: `/api/v1/terminal/loki/logs/`,
method: 'get',
params: data
})
}

View File

@@ -15,7 +15,6 @@ export function testEmailSetting(data) {
data: data
})
}
export function importLicense(formData) {
return request({
url: '/api/v1/xpack/license/import',
@@ -26,7 +25,6 @@ export function importLicense(formData) {
data: formData
})
}
export function testLdapSetting(data, refresh = true) {
let url = '/api/v1/settings/ldap/testing/config/'
if (refresh) {
@@ -98,17 +96,9 @@ export function getPublicSettings(isOpen) {
method: 'get'
})
}
export function getLogo() {
return request({
url: '/api/v1/xpack/interface/setting/',
method: 'get'
})
}
export function getPreference() {
return request({
url: '/api/v1/users/preference/?category=luna',
method: 'get'
})
}

View File

@@ -65,6 +65,10 @@ export function logout() {
})
}
export function refreshSessionIdAge() {
return getProfile()
}
export default {
getProfile,
getUserList

View File

@@ -1 +0,0 @@
<svg t="1717741737122" class="icon" viewBox="0 0 1653 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5514" width="200" height="200"><path d="M344.8620198 721.82988526a57.857089 57.857089 0 0 1-46.13274501-56.07295017v-308.4012244a59.89610558 59.89610558 0 0 1 46.13274501-56.07295017l286.35436058-62.06256065 30.07549089-122.72329718H328.80476645A210.78331632 210.78331632 0 0 0 116.61962599 327.28021902v364.47417458a213.71440233 213.71440233 0 0 0 212.18514046 212.31257895h332.48710482l-30.07549089-122.21354321zM1178.05508073 116.49690269H843.01920461l30.58524561 122.72329718 286.35436059 62.06256065a57.98452749 57.98452749 0 0 1 46.132745 56.07295017v308.4012244a60.15098257 60.15098257 0 0 1-46.13274502 56.07295017l-286.35436057 62.06256066-30.58524561 122.72329716H1178.05508073a212.44001744 212.44001744 0 0 0 212.94977139-212.82233291V327.28021902A213.33208686 213.33208686 0 0 0 1178.05508073 116.49690269z" fill="#F76E05" p-id="5515"></path><path d="M631.21638038 495.49906876h244.29964793v30.07549166H631.21638038z" fill="#F76E05" p-id="5516"></path></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.7 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743450082" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="39383" width="200" height="200"><path d="M18.753 17.145h468.424l-0.02 468.426H18.774V17.145h-0.02z m0 0" fill="#F25022" p-id="39384"></path><path d="M534.999 17.145h468.422c0 156.141 0.022 312.283-0.02 468.426H535.038c-0.06-156.162-0.039-312.285-0.039-468.426z m0 0" fill="#80BA01" p-id="39385"></path><path d="M18.753 533.352c156.141 0.058 312.282-0.019 468.424 0.058v468.386H18.753V533.352z m0 0" fill="#02A4EF" p-id="39386"></path><path d="M535.018 533.41c156.124-0.058 312.243-0.019 468.383-0.019v468.422H534.999c0.019-156.163-0.02-312.28 0.019-468.403z m0 0" fill="#FFB902" p-id="39387"></path></svg>

Before

Width:  |  Height:  |  Size: 721 B

View File

@@ -1 +0,0 @@
<svg t="1717743450082" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="39383" width="200" height="200"><path d="M18.753 17.145h468.424l-0.02 468.426H18.774V17.145h-0.02z m0 0" fill="#F25022" p-id="39384"></path><path d="M534.999 17.145h468.422c0 156.141 0.022 312.283-0.02 468.426H535.038c-0.06-156.162-0.039-312.285-0.039-468.426z m0 0" fill="#80BA01" p-id="39385"></path><path d="M18.753 533.352c156.141 0.058 312.282-0.019 468.424 0.058v468.386H18.753V533.352z m0 0" fill="#02A4EF" p-id="39386"></path><path d="M535.018 533.41c156.124-0.058 312.243-0.019 468.383-0.019v468.422H534.999c0.019-156.163-0.02-312.28 0.019-468.403z m0 0" fill="#FFB902" p-id="39387"></path></svg>

Before

Width:  |  Height:  |  Size: 721 B

View File

@@ -1 +0,0 @@
<svg t="1717743183519" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="34140" width="200" height="200"><path d="M521.30666655 248.79999969c4.93333313 0 9.14666625 0.73333312 12.66666657 2.17333406l181.97333343 106.71999938a34.00000031 34.00000031 0 0 0 26.83999969-0.61333313l168.72-94.69333312L520.06666624 36.26666656 128.02666624 262.38666687l171.20000063 95.93333344c3.69333375 1.63999969 7.8 2.46666656 12.33333281 2.46666656 4.93333313 0 9.04000031-0.82666687 12.33333375-2.46666656l184.45333312-107.04c4.32-1.63999969 8.64-2.46666656 12.96-2.46666656" fill="#5BCA87" p-id="34141"></path><path d="M763.02666687 421.28a34.39999969 34.39999969 0 0 0-9.52000032 23.28l3 200.17333312a28.74666656 28.74666656 0 0 1-9.86666625 22.04000063l-4.54666687 4.38666656-167.49333375 103.39999969a34.89333375 34.89333375 0 0 0-10.39999969 7.56c-5.86666687 5.83999969-8.93333344 13.39999969-9.19999969 22.65333375l2.79999938 186.6 384-230.04-6.61333313-441.36-161.47999968 93.43999969a40.89333375 40.89333375 0 0 0-10.68 7.86666656" fill="#EC5D3E" p-id="34142"></path><path d="M292.4400003 667.69333344a30.40000031 30.40000031 0 0 1-9.86666718-21.58666688V444.68c0-8.44000031-3.29333344-16.13333344-9.87999938-23.13333375a55.63999969 55.63999969 0 0 0-10.8-7.71999938l-162.85333406-90.66666656V765.46666625l387.42666656 222.40000031V801.25333344c-0.21333375-9.25333312-3.40000031-16.75999969-9.57333281-22.51999969a31.81333312 31.81333312 0 0 0-10.8-7.40000063l-168.72-99.31999968-4.93333313-4.32z" fill="#2464F5" p-id="34143"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743357432" class="icon" viewBox="0 0 1228 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="37305" width="200" height="200"><path d="M779.7248 289.8944h37.4784l106.8032-106.8032 5.2736-45.3632A480.1024 480.1024 0 0 0 148.224 371.968c11.8784-4.864 25.088-5.632 37.4784-2.2528l213.6064-35.2256s10.9056-17.9712 16.4864-16.896a266.496 266.496 0 0 1 364.6976-27.6992h-0.768z" fill="#EA4335" p-id="37306"></path><path d="M1076.224 371.9168a481.28 481.28 0 0 0-145.1008-233.8304l-149.9136 149.9136a266.496 266.496 0 0 1 97.792 211.3536v26.624a133.4272 133.4272 0 1 1 0 266.8544h-266.752l-26.624 26.9824v160l26.624 26.624h266.752A347.0336 347.0336 0 0 0 1076.224 371.9168" fill="#4285F4" p-id="37307"></path><path d="M344.9856 1004.9536h266.8544v-213.6064H344.9856a132.608 132.608 0 0 1-55.0912-12.032l-37.4784 11.6224-107.5712 106.8032-9.3696 37.4784a345.1904 345.1904 0 0 0 209.5104 69.7344" fill="#34A853" p-id="37308"></path><path d="M344.9856 311.9616a347.0336 347.0336 0 0 0-209.5104 622.1312l154.7776-154.7776a133.4272 133.4272 0 1 1 176.5376-176.4864L621.568 448a346.6752 346.6752 0 0 0-276.5824-136.0384" fill="#FBBC05" p-id="37309"></path></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743147068" class="icon" viewBox="0 0 1027 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32927" width="200" height="200"><path d="M402.3125 208.25c16.875-5.62500027 33.75-8.4375 50.625-11.24999973 19.68749973 25.3125 25.3125 59.0625 33.75 89.99999946 5.62500027 33.75 11.24999973 67.5 11.24999973 101.25 5.62500027 22.50000027 2.81249973 47.81250027 2.81250054 70.31250054s-2.81249973 42.1875 0 64.68749946c0 30.93750027-2.81249973 59.0625-2.81250054 90.00000027-5.62500027 19.68749973 0 39.37500027-5.62499946 59.0625-8.4375-2.81249973-11.24999973-11.24999973-14.06250027-16.875-33.75-50.625-64.68750027-101.25-92.8125-154.68749973-28.12499973-56.25000027-56.25000027-112.49999973-59.0625-177.1875-5.62500027-50.625 28.12499973-98.43750027 75.9375-115.31250027z m174.37500027-8.4375c5.62500027-2.81249973 8.4375 0 14.06249946 0 22.50000027 5.62500027 47.81250027 8.4375 67.5 22.50000027s36.56249973 33.75 42.1875 56.24999946c8.4375 28.12499973 5.62500027 59.0625 0 87.18750054-8.4375 36.56249973-25.3125 70.31249973-42.1875 104.06249973-5.62500027 11.24999973-11.24999973 19.68749973-16.875 30.93750027-8.4375 19.68749973-22.50000027 39.37500027-33.75 59.0625-19.68749973 33.75-39.37500027 61.87499973-59.0625 95.62499973-2.81249973 2.81249973-5.62500027 11.24999973-11.24999973 5.62500027-2.81249973-33.75-5.62500027-67.5-8.4375-104.06250054-5.62500027-44.99999973-2.81249973-87.18749973-2.81249973-132.18749946 2.81249973-28.12499973 2.81249973-59.0625 5.62499946-87.18750054 5.62500027-33.75 11.24999973-70.31249973 22.50000027-104.06249973 11.24999973-8.4375 11.24999973-25.3125 22.50000027-33.75zM222.31250027 309.5c2.81249973 0 5.62500027 5.62500027 8.4375 8.4375 81.56250027 106.87500027 154.68749973 219.375 213.74999973 340.31249973 5.62500027 8.4375 11.24999973 19.68749973 11.24999973 30.93750027-11.24999973-2.81249973-19.68749973-8.4375-28.12499973-14.06250027-53.43749973-28.12499973-106.87500027-59.0625-160.3125-89.99999946-19.68749973-14.06250027-39.37500027-28.12499973-56.25000027-42.1875-33.75-22.50000027-56.25000027-64.68750027-53.43749973-106.87500027 2.81249973-50.625 30.93750027-92.8125 64.68750027-126.5625z m582.1875 0h5.62499946c14.06250027 19.68749973 33.75 39.37500027 45.00000054 61.87499973 11.24999973 19.68749973 16.875 44.99999973 19.68749973 67.5 0 25.3125-8.4375 53.43749973-28.12499973 73.12500027-11.24999973 11.24999973-19.68749973 22.50000027-33.75 30.93750027-64.68750027 50.625-135 90.00000027-208.12500027 126.5625-11.24999973 5.62500027-19.68749973 14.06250027-33.75 14.06249946 2.81249973-14.06250027 11.24999973-28.12499973 16.875-39.37499946 47.81250027-98.43750027 106.87500027-191.25000027 171.56249973-281.25000054 14.06250027-14.06250027 30.93750027-33.75 45.00000054-53.43749973z m-705.93750027 225.00000027c2.81249973-2.81249973 0-8.4375 5.62500027-11.25000054 8.4375 2.81249973 16.875 8.4375 22.49999946 11.25000054 101.25 56.25000027 202.5 112.49999973 300.93750027 174.37499946 2.81249973 2.81249973 5.62500027 5.62500027 5.62500027 8.4375H239.18750027c-39.37500027 0-75.9375-16.875-104.06250054-44.99999973-22.50000027-25.3125-42.1875-59.0625-44.99999973-92.8125 5.62500027-14.06250027 2.81249973-28.12499973 8.4375-44.99999973z m810-2.81250054c5.62500027-2.81249973 14.06250027-8.4375 19.68749973-5.62499946 0 14.06250027 5.62500027 30.93750027 5.62500027 44.99999973-2.81249973 19.68749973-2.81249973 36.56249973-11.24999973 53.43749973-5.62500027 14.06250027-14.06250027 30.93750027-25.3125 42.1875-14.06250027 11.24999973-22.50000027 25.3125-39.37500027 33.75-16.875 14.06250027-42.1875 16.875-61.87499973 19.68750054h-202.5c2.81249973-2.81249973 2.81249973-5.62500027 5.62499946-8.4375 101.25-64.68750027 205.31249973-123.75000027 309.37500027-180.00000054zM242 748.25c36.56249973-2.81249973 73.12500027 0 109.6875-5.62500027 25.3125 0 53.43749973-2.81249973 78.74999973 0-5.62500027 11.24999973-19.68749973 16.875-28.12499973 22.50000027-28.12499973 19.68749973-56.25000027 36.56249973-87.18749973 50.625s-67.5 8.4375-92.8125-11.24999973c-19.68749973-14.06250027-36.56249973-36.56249973-47.81250027-56.25000027h67.5z m357.18749973-5.62500027c25.3125-2.81249973 50.625 0 78.75000054 0 33.75 2.81249973 70.31249973 0 106.87499946 5.62500027 25.3125 2.81249973 50.625 0 73.12500027 2.81249973-8.4375 16.875-22.50000027 33.75-36.56249973 47.81250027-22.50000027 22.50000027-56.25000027 33.75-87.18750054 28.12499973-28.12499973-8.4375-50.625-25.3125-75.9375-39.37499946-14.06250027-8.4375-25.3125-16.875-39.37499946-25.3125-8.4375-8.4375-14.06250027-11.24999973-19.68750054-19.68750054z" fill="#C71F1E" p-id="32928"></path></svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743099498" class="icon" viewBox="0 0 2030 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="30911" width="200" height="200"><path d="M1669.09384945 432.48813594c15.51186469 21.69491531 27.11864437 51.1457625 25.81694906 112.86779625-17.46440719 193.78983094-181.96610156 316.14915281-345.76271156 316.14915281-177.24745781 0-302.04745781-127.56610125-377.111865-270.10169531C954.30062883 557.72203344 941.44639195 520.13559312 929.35147664 487.59322063c-23.701695 32.21694937-73.6542375 84.77288156-99.09152531 109.23389812A629.15254219 629.15254219 0 0 0 890.24639133 720.81355906c20.01355969 31.18644094 70.508475 101.74915219 142.69830562 157.61355938 65.62711875 50.60338969 128.59661062 81.68135625 199.81016906 99.41694937a487.81016906 487.81016906 0 0 0 354.65762719-50.00677968c128.81355937-73.81694906 219.60678-209.78983031 236.04067781-350.96949188-31.72881375-52.61016937-100.501695-114.76610156-154.35932156-144.37966031zM585.37859508 381.12542375a238.96949156 238.96949156 0 0 1 126.96949125 36.39322031c30.53559281-32.5423725 57.54576281-66.16949156 85.58644125-100.06779656A370.54915219 370.54915219 0 0 0 214.66673039 621.01694937a373.09830469 373.09830469 0 0 0 4.39322062 57.00339c10.3593225 12.79999969 114.71186438 4.12203375 130.98305063-10.52203406a242.49491531 242.49491531 0 0 1-4.55593219-46.48135594 239.89152563 239.89152563 0 0 1 239.89152563-239.89152562zM585.37859508 992a370.6576275 370.6576275 0 0 1-320.97627094-185.38305094c4.98983062-6.61694906 121.60000031-19.57966125 149.42372812-18.00678a239.07796594 239.07796594 0 0 0 171.55254282 72.29830594s147.52542375 11.33559281 285.39661031-97.62711937c0 0 51.85084781 73.87118625 91.66101656 101.64067781 0 0-130.00677938 127.07796656-377.05762687 127.07796656z" fill="#E1251B" p-id="30912"></path><path d="M1545.05317101 74.305085C1369.9209682 0.70508469 1199.0735107 22.18305125 1030.23283195 146.27796594 881.35147664 255.67457656 822.1243582 365.88474594 726.88367976 460.47457625c-113.89830469 113.13898313-199.32203344 151.21355906-267.06440718 176.81355938-69.96610125 26.46779625-167.59322062 44.52881344-240.75932157 40.51525406a371.41694906 371.41694906 0 0 0 45.34237313 128.59661062c186.79322063-3.19999969 318.48135562-74.68474594 403.41694875-126.48135656 74.2508475-45.28813594 185.97966094-159.34915219 244.61016937-233.22033844 94.21016906-118.56271219 216.94915219-231.97288125 329.16610219-267.55254281 156.7457625-49.62711844 309.1525425 19.79661 383.02372875 117.85762688 6.61694906 8.62372875 145.13898281 58.3593225 188.691525 95.78305125C1797.31079883 324.88135625 1721.8124932 148.61016969 1545.05317101 74.305085z" fill="#E1251B" p-id="30913" class="custom-cursor-on-hover"></path><path d="M1809.24300164 377.81694875A497.35593188 497.35593188 0 0 0 1526.39554383 286.91525469c-122.63050875 0-245.42372906 47.78305125-331.82372813 132.88135594-62.86101656 61.83050812-93.4508475 112.00000031-163.14576281 195.57966093a570.35932219 570.35932219 0 0 0 92.63728781 108.47457563c9.00339-13.12542375 59.66101688-84.82711875 97.62711844-135.21355875 48.81355969-64.10847469 98.38644094-115.36271156 173.5593225-145.03050844a350.04745781 350.04745781 0 0 1 427.498305 139.3355925A486.02033906 486.02033906 0 0 0 1809.24300164 377.81694875z" fill="#E1251B" p-id="30914" class="custom-cursor-on-hover"></path></svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743116713" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="31939" width="200" height="200"><path d="M718.5408 453.8368c-4.1984 0-8.3968-0.7168-12.5952-0.7168a103.8336 103.8336 0 0 0-67.8912 25.088 139.6736 139.6736 0 0 0 13.6192-60.3136 133.12 133.12 0 0 0-2.4576-25.7024 139.5712 139.5712 0 0 0-274.432 0 133.12 133.12 0 0 0-2.4576 25.7024 139.6736 139.6736 0 0 0 13.6192 60.3136 103.8336 103.8336 0 0 0-67.8912-25.088c-4.1984 0-8.3968 0-12.5952 0.7168a104.5504 104.5504 0 1 0 101.0688 159.4368 116.736 116.736 0 0 0 6.144-11.0592 105.1648 105.1648 0 0 0 4.9152-76.6976 62.6688 62.6688 0 0 1 27.3408 20.48l2.6624 3.8912a83.2512 83.2512 0 0 1 133.9392-3.3792l4.7104 6.8608 51.2 73.9328a84.0704 84.0704 0 0 0 62.464 34.6112h5.5296a104.5504 104.5504 0 0 0 12.5952-208.384z" fill="#E6002D" p-id="31940"></path><path d="M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m200.8064 732.3648h-6.8608a152.4736 152.4736 0 0 1-120.5248-58.9824S509.2352 564.6336 508.0064 563.2a42.1888 42.1888 0 0 0-32.4608-15.2576 40.96 40.96 0 0 0-24.064 7.5776l122.88 175.4112a62.5664 62.5664 0 0 0 77.0048 20.48A97.5872 97.5872 0 0 1 593.92 783.5648a97.0752 97.0752 0 0 1-95.5392-39.1168l-49.4592-70.656a174.8992 174.8992 0 1 1-143.36-290.5088 209.7152 209.7152 0 0 1 413.9008 0 174.7968 174.7968 0 0 1-6.144 349.0816z" fill="#E6002D" p-id="31941"></path></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1 +0,0 @@
<svg t="1717746661932" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="60936" width="200" height="200"><path d="M29.696 541.696A30.72 30.72 0 0 0 59.52 512 452.16 452.16 0 0 1 512 59.456a439.68 439.68 0 0 1 225.664 61.44l16.704 10.432 7.04 4.608-3.84 7.488c-1.216 2.496-1.536 6.592-1.536 16.64 0 44.352 37.504 81.856 81.856 81.856s81.856-37.504 81.856-81.856a83.008 83.008 0 0 0-108.544-77.824l-8.96 3.136-4.48 1.792-4.096-2.624A520.768 520.768 0 0 0 512 0C230.4 0 0 230.4 0 512c0 15.68 14.08 29.696 29.696 29.696z m588.16-186.24c-13.056-93.568-37.12-164.224-62.336-203.584a383.808 383.808 0 0 0-43.776-2.752c-14.784 0-29.568 1.088-43.776 2.752-25.216 39.36-49.28 109.44-62.4 203.584z m221.696 0a365.504 365.504 0 0 0-203.52-184.96c21.312 51.392 36.608 115.456 45.888 184.96z m-497.472 0c9.28-69.504 24.576-133.568 45.952-184.96a365.504 365.504 0 0 0-203.584 184.96z m520.512 250.688a358.4 358.4 0 0 0 0-188.288H688c2.688 31.232 3.84 62.4 3.84 94.144 0 31.744-1.664 62.912-3.84 94.144z m-237.568 0c2.176-29.568 3.84-61.312 3.84-94.144 0-33.408-1.664-64.64-3.84-94.144H398.976c-2.752 29.568-3.84 61.312-3.84 94.144 0 33.408 1.664 64.64 3.84 94.144z m-289.024 0A1073.92 1073.92 0 0 1 332.16 512c0-31.744 1.152-62.912 3.84-94.144H161.408a358.4 358.4 0 0 0 0 188.288zM512 1024c281.6 0 512-230.4 512-512a30.72 30.72 0 0 0-29.696-29.696 30.72 30.72 0 0 0-29.76 29.696A452.16 452.16 0 0 1 512 964.544a439.68 439.68 0 0 1-225.664-61.44l-16.704-10.432-7.04-4.608 3.84-7.488c1.216-2.496 1.536-6.592 1.536-16.64 0-44.352-37.504-81.856-81.856-81.856s-81.856 37.504-81.856 81.856a83.008 83.008 0 0 0 108.544 77.824l8.96-3.136 4.48-1.792 4.096 2.624A520.768 520.768 0 0 0 512 1024z m-0.256-149.12c14.72 0 29.568-1.088 43.776-2.752 25.152-39.36 49.28-109.44 62.4-203.584H405.568c13.12 93.568 37.184 164.224 62.4 203.584 14.208 1.664 28.992 2.752 43.776 2.752z m124.224-21.312a365.504 365.504 0 0 0 203.584-185.024h-157.632c-9.28 69.504-24.576 133.568-45.952 184.96z m-247.936 0c-21.376-51.456-36.672-115.52-45.952-185.024H184.448a365.504 365.504 0 0 0 203.52 184.96z" fill="#448CF7" p-id="60937"></path></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1 +0,0 @@
<svg t="1717747391666" class="icon" viewBox="0 0 1333 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4694" width="200" height="200"><path d="M1018.488284 0.541672L1314.82427 0a18.458499 18.458499 0 0 1 13.083451 31.500282L894.070504 465.337499a18.458499 18.458499 0 0 1-26.104401 0L720.079363 317.450758a18.458499 18.458499 0 0 1 0-26.093983L1005.477751 5.937553a18.458499 18.458499 0 0 1 13.02095-5.406298zM1018.488284 1023.446662l296.335986 0.552088a18.458499 18.458499 0 0 0 13.083451-31.500282L894.070504 558.650834a18.458499 18.458499 0 0 0-26.104401 0L720.079363 706.547992a18.458499 18.458499 0 0 0 0 26.1044l285.398388 285.398388a18.458499 18.458499 0 0 0 13.02095 5.406298z" fill="#054496" p-id="4695"></path><path d="M821.319852 500.275312L327.34668 5.416715A18.437665 18.437665 0 0 0 314.29448 0H18.510582A18.479332 18.479332 0 0 0 5.437549 31.531532l466.566676 467.400018a18.500166 18.500166 0 0 1 0 26.146067L5.458382 992.425551a18.489749 18.489749 0 0 0 13.083451 31.562782h295.74223a18.437665 18.437665 0 0 0 13.052201-5.416715l493.973172-494.858596a16.593899 16.593899 0 0 0 0-23.448127z" fill="#87BB4C" p-id="4696"></path></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1 +0,0 @@
<svg t="1717746166860" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="51952" width="200" height="200"><path d="M928.856 10.912H95.142C42.814 10.912 0 53.726 0 106.054v224.202h231.25v-36.64c0-28.418 23.046-51.454 51.464-51.454h458.58c28.42 0 51.456 23.036 51.456 51.456v36.64H1024V106.052c0-52.328-42.816-95.142-95.144-95.142zM792.75 730.38c0 28.42-23.036 51.466-51.456 51.466h-458.58c-28.418 0-51.464-23.046-51.464-51.466v-36.63H0v224.194c0 52.336 42.816 95.142 95.144 95.142h833.714c52.328 0 95.142-42.806 95.142-95.142V693.752H792.75v36.63zM0.006 627.628h231.25V396.38H0.006v231.25z m792.74 0h231.25V396.38H792.748v231.25z" fill="#E72F52" p-id="51953"></path></svg>

Before

Width:  |  Height:  |  Size: 713 B

View File

@@ -1 +0,0 @@
<svg t="1717743207396" class="icon" viewBox="0 0 1402 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="35171" width="200" height="200"><path d="M1216.84017881 832.26669714c-22.01770438 22.42169837-66.05311315 55.95324845-143.01407896 55.95324845H600.84945441c143.01407897-139.88312044 264.01045355-257.44554135 275.01930505-268.65639054a860.50843905 860.50843905 0 0 1 65.9521143-61.60917245c55.04426026-50.29732444 98.9786702-55.8522496 137.45915242-55.85224962 55.04426026 0 98.9786702 22.32069952 137.56015263 55.95324846 76.96096581 72.71902281 76.96096581 201.4922929 0 274.2113157z m93.42374503-363.79711171a304.81390494 304.81390494 0 0 0-225.42897111-100.79664655c-77.06196465 0-143.01407897 27.97662354-203.51226695 72.71902278-22.01770438 22.52269721-54.94326142 44.84339811-82.51589098 78.47594568-21.91670555 22.32069952-494.89335097 492.5703818-494.89335097 492.57038317 27.47163072 5.55492517 60.59918544 5.55492517 87.96981869 5.55492517h599.42694635c44.03540877 0 76.96096581 0 110.08852053-5.55492517a335.11349765 335.11349765 0 0 0 203.41126672-89.58579738c126.45030092-123.21834493 126.45030092-330.265563 5.45392772-453.3829077z" fill="#00A3FF" p-id="35172"></path><path d="M528.73642327 435.44302817c-60.80118311-45.14639325-121.70336508-67.66909045-193.51339969-67.66909045a306.02588827 306.02588827 0 0 0-226.74195328 101.60463453 333.80051551 333.80051551 0 0 0 5.55492517 462.97777956c55.24625795 50.80231726 110.59351474 78.98093847 176.94962165 84.63686387l127.1572928-124.22833194h-71.91103484c-71.91103347-5.65592402-116.14843991-28.27962006-143.72106809-56.45824128a206.03723244 206.03723244 0 0 1-5.55492656-282.29120635c38.68247989-39.49046924 82.91988635-56.45824127 138.26714315-56.45824267 33.12755473 0 82.91988635 5.65592402 132.71221657 56.55924012 22.11870323 22.52269721 82.91988635 67.66909045 105.03858956 90.29278788h5.55492518l82.91988496-84.73786132v-5.65592401c-38.68247989-39.49046924-99.58466186-90.29278651-132.71221658-118.57240794" fill="#00C8DC" p-id="35173"></path><path d="M1114.32655611 290.00498256A436.81913102 436.81913102 0 0 0 705.58504746 7.00678432c-218.3590661 0-391.87473546 160.8908378-425.507283 360.66615456 16.76577435 0 33.63254755-5.45392634 55.95324845-5.45392634 22.42169837 0 50.49932212 5.45392634 72.82002164 5.45392634 27.97662354-138.67113711 151.19496845-238.55879549 296.73401291-238.55879412a310.06583359 310.06583359 0 0 1 279.96823856 177.55561331s5.55492517 5.55492517 5.55492517 0c39.18747409-5.55492517 84.03087084-16.66477551 123.21834492-16.66477551 0 5.55492517 0 5.55492517 0 0" fill="#006EFF" p-id="35174"></path></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743207396" class="icon" viewBox="0 0 1402 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="35171" width="200" height="200"><path d="M1216.84017881 832.26669714c-22.01770438 22.42169837-66.05311315 55.95324845-143.01407896 55.95324845H600.84945441c143.01407897-139.88312044 264.01045355-257.44554135 275.01930505-268.65639054a860.50843905 860.50843905 0 0 1 65.9521143-61.60917245c55.04426026-50.29732444 98.9786702-55.8522496 137.45915242-55.85224962 55.04426026 0 98.9786702 22.32069952 137.56015263 55.95324846 76.96096581 72.71902281 76.96096581 201.4922929 0 274.2113157z m93.42374503-363.79711171a304.81390494 304.81390494 0 0 0-225.42897111-100.79664655c-77.06196465 0-143.01407897 27.97662354-203.51226695 72.71902278-22.01770438 22.52269721-54.94326142 44.84339811-82.51589098 78.47594568-21.91670555 22.32069952-494.89335097 492.5703818-494.89335097 492.57038317 27.47163072 5.55492517 60.59918544 5.55492517 87.96981869 5.55492517h599.42694635c44.03540877 0 76.96096581 0 110.08852053-5.55492517a335.11349765 335.11349765 0 0 0 203.41126672-89.58579738c126.45030092-123.21834493 126.45030092-330.265563 5.45392772-453.3829077z" fill="#00A3FF" p-id="35172"></path><path d="M528.73642327 435.44302817c-60.80118311-45.14639325-121.70336508-67.66909045-193.51339969-67.66909045a306.02588827 306.02588827 0 0 0-226.74195328 101.60463453 333.80051551 333.80051551 0 0 0 5.55492517 462.97777956c55.24625795 50.80231726 110.59351474 78.98093847 176.94962165 84.63686387l127.1572928-124.22833194h-71.91103484c-71.91103347-5.65592402-116.14843991-28.27962006-143.72106809-56.45824128a206.03723244 206.03723244 0 0 1-5.55492656-282.29120635c38.68247989-39.49046924 82.91988635-56.45824127 138.26714315-56.45824267 33.12755473 0 82.91988635 5.65592402 132.71221657 56.55924012 22.11870323 22.52269721 82.91988635 67.66909045 105.03858956 90.29278788h5.55492518l82.91988496-84.73786132v-5.65592401c-38.68247989-39.49046924-99.58466186-90.29278651-132.71221658-118.57240794" fill="#00C8DC" p-id="35173"></path><path d="M1114.32655611 290.00498256A436.81913102 436.81913102 0 0 0 705.58504746 7.00678432c-218.3590661 0-391.87473546 160.8908378-425.507283 360.66615456 16.76577435 0 33.63254755-5.45392634 55.95324845-5.45392634 22.42169837 0 50.49932212 5.45392634 72.82002164 5.45392634 27.97662354-138.67113711 151.19496845-238.55879549 296.73401291-238.55879412a310.06583359 310.06583359 0 0 1 279.96823856 177.55561331s5.55492517 5.55492517 5.55492517 0c39.18747409-5.55492517 84.03087084-16.66477551 123.21834492-16.66477551 0 5.55492517 0 5.55492517 0 0" fill="#006EFF" p-id="35174"></path></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1 +0,0 @@
<svg t="1717745876738" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="50950" width="200" height="200"><path d="M494.272 0L347.968 89.088l146.304 86.4V0z m43.904 175.552l146.304-87.488L538.176 0v175.552z m0 731.392l146.304-87.872-146.304-87.68v175.552z m-43.904 0V731.52l-146.304 88.128 146.304 87.36m409.6-205.696L757.568 614.4v175.552l146.304-88.704M289.472 614.4l-146.304 87.68 146.304 87.872V614.4z m468.096-73.152l146.304-88.128-146.304-87.424v175.552z m-468.096 0V365.696L143.168 453.632l146.304 87.68m614.4-336.768L757.568 117.12V292.48l146.304-88m-614.4-87.488l-146.304 88.32 146.304 87.168V117.12z m629.056 307.2V248.704l-146.304 88.256 146.304 87.296m-789.952 0l146.304-88.064-146.304-87.488v175.552z m146.304 146.432L128.576 482.752v175.552l146.304-87.616m497.344 0.192l146.304 87.424V482.752L772.224 570.88m-438.848 43.52v175.552l146.304-88L333.376 614.4m380.352 175.552V614.4l-146.304 87.68 146.304 87.872M333.376 307.2l146.304-88.128-146.304-87.424V307.2z m380.352 541.248l-146.304 88.768L713.728 1024v-175.552z m0-555.904V131.648L567.424 212.672l146.304 79.872" fill="#57B382" p-id="50951"></path><path d="M494.272 0v175.552L347.968 89.088 494.272 0m43.904 175.552V0l146.304 88.064-146.304 87.488m0 731.392V731.52l146.304 87.68-146.304 87.808m-43.904 0l-146.304-87.36 146.304-88.128v175.488z m409.6-205.696l-146.304 88.704V614.4l146.304 86.848M289.472 614.4v175.552L143.168 702.08 289.472 614.4m468.096-73.152V365.696l146.304 87.424-146.304 88.128m-468.096 0L143.168 453.632l146.304-87.936v175.552z m614.4-336.64L757.568 292.48V117.12l146.304 87.488m-614.4-87.488V292.48L143.168 205.44l146.304-88.384m629.056 307.2l-146.304-87.296 146.304-88.32V424.32z m-789.952 0V248.704l146.304 87.488-146.304 88.064m146.304 146.432l-146.304 87.616V482.752l146.304 87.936m497.344 0.192l146.304-88.128v175.552L772.224 570.88m-438.848 43.52l146.304 87.552-146.304 88V614.4z m380.352 175.552l-146.304-87.936L713.728 614.4v175.552zM333.376 307.2V131.648l146.304 87.424L333.376 307.2m380.352 541.248V1024l-146.304-86.784 146.304-88.768m0-555.904L567.424 212.672l146.304-81.024v160.896z" fill="#57B382" p-id="50952" class="custom-cursor-on-hover"></path></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1 +0,0 @@
<svg t="1717746510567" class="icon" viewBox="0 0 1351 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="55261" width="200" height="200"><path d="M416.92885 824.173591c-56.901379 30.927289-130.232881 35.397249-203.685192-3.745101a159.190971 159.190971 0 0 1-65.35806-64.754011c-79.130368-147.025432 15.826074-294.775723 150.770533-309.635319 7.369393-0.845668 14.738786-1.328907 22.228989-1.328907 59.317574 0 112.353042 25.732471 149.320817 66.324538a249.50832 249.50832 0 0 1-26.457329-111.628184c0-16.188503 1.691336-31.893767 4.590769-47.236601a320.508194 320.508194 0 0 0-127.575067-26.45733c-6.161296 0-12.201782 0.604049-18.242268 0.966478C83.252396 339.122556-77.424535 571.198033 39.036038 806.897801c25.370042 51.344132 66.686967 93.748345 117.668669 119.601625 115.614904 58.713525 230.50495 50.377654 319.420907 0.966478 31.531338-17.51741 38.659111-59.921622 15.946883-88.070288-0.241619-0.362429-0.483239-0.604049-0.724858-0.966477-18.000649-22.349799-49.290367-27.907046-74.418789-14.255548z" fill="#62B0DB" p-id="55262"></path><path d="M443.869418 399.527417c0-16.188503 1.691336-31.893767 4.590769-47.236602 23.557896-123.709156 137.602274-215.403735 270.855398-203.081143 24.041135 2.174575 46.994982 8.094251 68.740732 16.792551 50.377654-17.879839 104.3796-28.148665 160.91855-28.148665 16.550932 0 32.981054 0.845668 49.169557 2.537004C928.558024 59.448048 827.561096 5.929341 715.328864 0.492904c-204.65167-10.027207-377.167953 134.098792-412.565202 326.18625-4.34915 23.678706-6.886154 47.96146-6.886154 72.848263 0 15.826074 1.208097 31.289718 2.899433 46.511743 7.369393-0.845668 14.738786-1.328907 22.228989-1.328907 59.317574 0 112.473852 25.732471 149.320817 66.324538-16.792551-33.464293-26.457329-71.277736-26.457329-111.507374z" fill="#8FC361" p-id="55263"></path><path d="M1114.725806 778.386706S880.717374 806.172943 749.034777 723.176663c-66.928586-42.162593-43.73312-127.937496 50.015225-152.461869 63.666724-16.671742 302.024306-14.376357 457.989657 13.04745 156.086161 27.423807 124.675634 166.717417-142.313853 194.624462zM1316.961282 782.615047s-67.170206 87.22462-241.981874 113.561139c-72.727453 10.993685-135.06527 13.289069-224.102035 0 0 0-70.311258-18.967126-82.392231 35.638868-14.376357 65.23725 157.656688 128.420735 327.998396 62.458627 172.274664-66.566157 220.477743-211.658634 220.477744-211.658634z" fill="#ADD079" p-id="55264"></path><path d="M1341.244036 531.089205s-44.457978-76.955793-241.136206-131.924217c-195.228511-54.605995-295.86301 15.463644-346.240665-30.202431-24.886803-22.470608-5.194818-77.318222 23.557896-101.480167 46.994982-39.504779 176.744624-83.600328 323.407627-20.416843 214.558067 92.540247 240.411348 284.023657 240.411348 284.023658z" fill="#A2CB70" p-id="55265"></path><path d="M783.948786 456.791225s234.008432-27.786236 365.69103 55.210044c66.928586 42.162593 43.73312 127.937496-50.015225 152.461869-63.666724 16.671742-302.024306 14.376357-457.989658-13.04745-156.086161-27.302997-124.675634-166.717417 142.313853-194.624463z m11.839353 535.42869c146.663003 63.183485 276.412645 19.208746 323.407627-20.416843 28.631904-24.161944 48.444699-78.888749 23.557896-101.480167-50.377654-45.666075-151.012153 24.403564-346.240665-30.20243-196.678228-54.968424-241.136206-131.924217-241.136206-131.924217s25.97409 191.60422 240.411348 284.023657zM579.780355 456.791225s67.170206-87.22462 241.981874-113.561139c72.727453-10.993685 135.06527-13.289069 224.102036 0 0 0 70.311258 18.967126 82.39223-35.638868 14.376357-65.23725-157.656688-128.420735-327.998396-62.458626-172.274664 66.566157-220.477743 211.658634-220.477744 211.658633z" fill="#4885BE" p-id="55266"></path></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1 +0,0 @@
<svg t="1717747284124" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2464" width="200" height="200"><path d="M838.4 416c-6.4-70.4-64-115.2-134.4-115.2-19.2 0-38.4 6.4-51.2 6.4-44.8-51.2-115.2-83.2-185.6-83.2-89.6 0-172.8 51.2-211.2 128h-12.8C115.2 352 19.2 448 12.8 576s96 224 224 230.4h294.4c25.6 0 44.8-19.2 44.8-44.8s-19.2-44.8-44.8-44.8H249.6c-70.4 0-134.4-57.6-134.4-128s51.2-128 121.6-134.4c12.8 0 25.6 0 38.4 6.4h6.4l25.6 6.4C320 390.4 390.4 320 473.6 320c57.6 0 108.8 32 140.8 83.2 6.4 6.4 6.4 12.8 6.4 19.2l6.4-6.4c19.2-19.2 51.2-19.2 70.4-19.2 44.8 0 70.4 38.4 70.4 76.8 0 12.8-6.4 25.6-6.4 38.4 12.8 6.4 19.2 19.2 38.4 19.2 6.4-6.4 19.2-12.8 19.2-19.2 64 6.4 115.2 57.6 108.8 128-6.4 57.6-57.6 108.8-121.6 108.8-51.2 0-96-32-115.2-83.2h51.2c6.4 0 12.8-6.4 12.8-12.8s0-6.4-6.4-6.4l-96-128c-6.4-6.4-12.8-12.8-19.2-6.4h-6.4l-96 128c-6.4 6.4-6.4 19.2 6.4 19.2 6.4 0 6.4 6.4 6.4 6.4h57.6c19.2 115.2 128 192 243.2 172.8 115.2-19.2 192-128 172.8-243.2-25.6-96-89.6-160-179.2-179.2z" fill="#F3A22F" p-id="2465"></path></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +0,0 @@
<svg t="1717743387740" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="38378" width="200" height="200"><path d="M912.192 0C973.952 0 1024 50.048 1024 111.808v800.384c0 61.76-50.048 111.808-111.808 111.808H111.808A111.808 111.808 0 0 1 0 912.192V111.808C0 50.048 50.048 0 111.808 0h800.384zM672 185.152c-23.936-1.088-30.912 6.144-30.656 30.4 1.28 116.864 0.832 233.728 0.384 350.592-0.128 37.76 2.368 75.52-3.392 113.216-6.912 45.184-33.92 71.68-76.16 82.88-52.672 13.952-107.136-1.728-131.2-36.736-17.6-25.728-19.84-55.552-19.904-85.632-0.192-120.32-0.448-240.64 0.192-360.96 0.128-18.432-4.032-26.24-24.448-26.24-20.416 0.128-27.136 8-24.128 26.432 4.608 28.16-8.256 37.12-34.24 33.152-23.168-3.456-35.2 5.248-30.912 29.952 5.312 30.4-6.912 42.304-37.248 37.248-20.416-3.392-30.72 2.304-30.144 26.88 1.6 79.04-0.512 158.08 1.024 237.184 2.24 113.088 79.104 204.8 189.632 230.912a462.08 462.08 0 0 0 187.136 5.632c133.12-23.04 214.08-117.824 214.4-252.416V435.2c0-74.496-0.896-148.992 0.448-223.424 0.448-21.76-6.4-27.264-27.2-26.56-41.152 1.536-82.432 1.92-123.52 0z m-422.784 133.76c-16.832-3.84-18.752 7.04-19.2 21.568-0.384 15.296 3.968 22.208 20.736 22.464 18.496 0.32 22.528-7.36 22.528-24.128 0-16.96-7.296-22.144-24.064-19.84z m73.6-65.92l-4.992 0.448c-17.792-2.816-20.928 7.04-20.8 22.272 0 15.104 6.592 19.456 20.864 19.648 15.68 0.256 22.72-4.224 22.656-21.248 0-17.024-6.72-23.04-22.72-20.672z m-134.464 3.904c-10.88 0.384-12.288 7.36-12.608 16-0.448 11.008 2.88 17.664 15.168 16 12.672 1.216 15.168-6.144 14.912-16.768-0.32-11.84-6.656-15.552-17.472-15.232z m68.032-3.648c-11.776 0.32-19.904 1.664-19.52 16.512 0.32 11.776 1.472 19.968 16.448 19.328 11.52-0.448 21.12-0.896 18.944-16.192 1.28-11.904-0.96-20.096-15.872-19.648z m126.592-68.032c-17.088-0.32-20.8 6.848-20.928 22.336-0.128 16.96 6.848 22.656 22.592 20.352 17.664 2.88 20.288-7.04 20.736-21.952 0.512-17.28-7.232-20.48-22.4-20.736z m-58.816 7.104l-4.736 0.32c-12.48-0.96-22.272-0.064-22.336 16.96 0 15.872 7.552 19.072 21.056 18.752 12.352-0.256 22.08-0.64 22.208-17.6 0.128-16.128-7.616-19.648-20.928-18.112z m-137.6 6.016c-9.088-0.128-10.816 5.632-10.432 13.056 0.384 9.088 6.464 10.304 13.632 9.792 7.872-0.64 11.776-4.928 11.008-12.992-0.832-8.832-7.232-9.792-14.208-9.856z m65.728-5.632h-3.584c-11.328 0.32-11.392 7.936-11.456 16.128 0 10.88 6.976 12.544 15.616 12.096 10.368 0.512 12.928-5.248 13.184-14.528 0.32-13.056-7.552-13.952-17.28-13.696z m66.816-55.68c-7.808 0.256-16.832-0.96-17.472 10.56-0.704 11.712 6.592 15.616 17.024 15.744 9.152 0.128 15.424-2.944 15.36-13.312 0.832-11.008-5.952-13.312-14.912-12.992z m-63.68 0.448c-7.936-0.128-12.352 3.072-12.288 11.456 0.128 7.424 2.752 12.8 11.008 13.376 8.32 0.512 11.712-4.288 12.032-12.032 0.64-7.808-2.176-12.608-10.752-12.8z" fill="#3860F4" p-id="38379" class="custom-cursor-on-hover"></path></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1 +0,0 @@
<svg t="1717747341803" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3484" width="200" height="200"><path d="M813.6 65H451.9c-81.8 0-144.7 62.7-144.7 144.1v100.4h-97.5C127.9 309.5 65 372.3 65 453.7v360.5c0 81.4 62.8 144.2 144.7 144.2h358.6c81.8 0 144.7-62.7 144.7-144.2V710.7h100.6c81.8 0 144.7-62.7 144.7-144.2V206c3.2-75.3-62.9-141-144.7-141z m37.8 504.6c-0.4 20.6-17.1 37.3-37.7 37.5H609.2V814c-0.3 20.7-17 37.3-37.7 37.6H209.8c-20.7-0.2-37.4-16.9-37.8-37.6V453.6c0.3-20.7 17.1-37.4 37.8-37.6h204.4V209.1c0-21.9 18.9-37.5 37.8-37.5h361.7c20.6 0.3 37.3 16.9 37.7 37.5v360.5z m0 0" fill="#8FBE48" p-id="3485"></path><path d="M514.8 268.7v235H272.7V745h242.2V510H757V268.7H514.8z m0 0" fill="#F2B624" p-id="3486"></path></svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -1 +0,0 @@
<svg t="1717743222537" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="36225" width="200" height="200"><path d="M830.537143 476.525714L706.413714 961.828571a8.484571 8.484571 0 0 0 0 4.022858 9.069714 9.069714 0 0 0 8.996572 6.948571h248.100571a9.069714 9.069714 0 0 0 9.069714-10.971429l-124.708571-485.302857a9.142857 9.142857 0 0 0-17.334857 0M147.602286 586.386286L51.492571 961.828571a8.996571 8.996571 0 0 0 9.069715 10.971429h191.488a9.142857 9.142857 0 0 0 7.241143-3.291429 8.777143 8.777143 0 0 0 1.755428-3.657142 8.484571 8.484571 0 0 0 0-4.022858L164.864 586.459429a8.777143 8.777143 0 0 0-3.291429-4.534858 9.216 9.216 0 0 0-10.752 0 8.777143 8.777143 0 0 0-3.218285 4.534858" fill="#00E5E5" p-id="36226"></path><path d="M317.074286 275.748571l-175.104 686.08a8.777143 8.777143 0 0 0 1.682285 7.460572c1.682286 2.194286 4.242286 3.437714 6.948572 3.437714h350.354286a9.069714 9.069714 0 0 0 9.069714-10.898286L334.409143 275.748571a8.777143 8.777143 0 0 0-3.291429-4.608 9.216 9.216 0 0 0-10.752 0 8.777143 8.777143 0 0 0-3.291428 4.608" fill="#006EFF" p-id="36227"></path><path d="M619.227429 57.490286A8.777143 8.777143 0 0 0 615.862857 52.955429a9.216 9.216 0 0 0-10.752 0 8.777143 8.777143 0 0 0-3.291428 4.534857L362.569143 961.828571a8.996571 8.996571 0 0 0 8.996571 10.898286h478.354286a9.216 9.216 0 0 0 9.142857-6.875428 8.996571 8.996571 0 0 0 0-4.022858L619.154286 57.490286z" fill="#006EFF" p-id="36228"></path><path d="M443.318857 375.442286L291.474286 961.828571a9.069714 9.069714 0 0 0 9.069714 10.971429l302.957714 0.073143a9.216 9.216 0 0 0 7.314286-3.364572 9.142857 9.142857 0 0 0 1.828571-7.68L460.653714 375.442286a9.216 9.216 0 0 0-8.704-6.290286 9.216 9.216 0 0 0-8.630857 6.290286" fill="#00E5E5" p-id="36229"></path></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1 +0,0 @@
<svg t="1717746226986" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="52962" width="200" height="200"><path d="M527.36 102.4H450.048L350.0032 266.8544h68.9152L25.6 921.6h263.68l96.256-164.7616H317.1328l299.7248-489.984L527.36 102.4z m124.4672 211.7632l-233.1136 387.584h257.6896l32.512 55.0912H455.168L364.4928 921.6H998.4l-183.7056-327.168H681.472l27.3408-58.0608h69.12l-126.1568-222.208z" fill="#2558E6" p-id="52963"></path></svg>

Before

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -4,7 +4,6 @@
<script>
import DataActions from '@/components/DataActions'
export default {
name: 'ActionsGroup',
components: {
@@ -25,7 +24,9 @@ export default {
},
moreActionsTitle: {
type: String,
default: ''
default() {
return this.$t('common.MoreActions')
}
},
moreActionsPlacement: {
type: String,
@@ -44,9 +45,8 @@ export default {
iMoreAction() {
const defaultBtn = {
name: 'moreActions',
title: '',
title: this.$t('common.MoreActions'),
type: 'primary',
icon: 'el-icon-more',
plain: true
}
const btn = {
@@ -62,3 +62,7 @@ export default {
}
}
</script>
<style scoped>
</style>

View File

@@ -1,5 +1,6 @@
import { UpdateToken, UploadSecret } from '@/components/Form/FormFields'
import Select2 from '@/components/Form/FormFields/Select2.vue'
import AssetSelect from '@/components/Apps/AssetSelect/index.vue'
import { Required, RequiredChange } from '@/components/Form/DataForm/rules'
import AutomationParamsForm from '@/views/assets/Platform/AutomationParamsSetting.vue'
@@ -7,17 +8,11 @@ export const accountFieldsMeta = (vm) => {
const defaultPrivilegedAccounts = ['root', 'administrator']
return {
assets: {
component: Select2,
label: vm.$t('Assets'),
rules: [Required],
component: AssetSelect,
label: vm.$t('assets.Asset'),
el: {
multiple: true,
ajax: {
url: '/api/v1/assets/assets/',
transformOption: (item) => {
return { label: item.name + '(' + item.address + ')', value: item.id }
}
}
multiple: false
},
hidden: () => {
return vm.platform || vm.asset
@@ -41,14 +36,14 @@ export const accountFieldsMeta = (vm) => {
},
on_invalid: {
rules: [Required],
label: vm.$t('AccountPolicy'),
helpTip: vm.$t('AccountPolicyHelpText'),
label: vm.$t('accounts.AccountPolicy'),
helpText: vm.$t('accounts.BulkCreateStrategy'),
hidden: () => {
return vm.platform || vm.asset
}
},
name: {
label: vm.$t('Name'),
label: vm.$t('common.Name'),
rules: [RequiredChange],
on: {
input: ([value], updateForm) => {
@@ -87,7 +82,7 @@ export const accountFieldsMeta = (vm) => {
}
},
privileged: {
label: vm.$t('Privileged'),
label: vm.$t('assets.Privileged'),
hidden: () => {
return vm.addTemplate
}
@@ -109,42 +104,42 @@ export const accountFieldsMeta = (vm) => {
}
},
su_from_username: {
label: vm.$t('UserSwitchFrom'),
label: vm.$t('assets.UserSwitchFrom'),
hidden: (formValue) => {
return vm.platform || vm.asset || vm.addTemplate
}
},
password: {
label: vm.$t('Password'),
label: vm.$t('assets.Password'),
component: UpdateToken,
hidden: (formValue) => {
return formValue.secret_type !== 'password' || vm.addTemplate
}
},
ssh_key: {
label: vm.$t('PrivateKey'),
label: vm.$t('assets.PrivateKey'),
component: UploadSecret,
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
},
passphrase: {
label: vm.$t('Passphrase'),
label: vm.$t('assets.Passphrase'),
component: UpdateToken,
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
},
token: {
label: vm.$t('Token'),
label: vm.$t('assets.Token'),
component: UploadSecret,
hidden: (formValue) => formValue.secret_type !== 'token' || vm.addTemplate
},
access_key: {
id: 'access_key',
label: vm.$t('AccessKey'),
label: vm.$t('assets.AccessKey'),
component: UploadSecret,
hidden: (formValue) => formValue.secret_type !== 'access_key' || vm.addTemplate
},
api_key: {
id: 'api_key',
label: vm.$t('ApiKey'),
label: vm.$t('assets.ApiKey'),
component: UploadSecret,
hidden: (formValue) => formValue.secret_type !== 'api_key' || vm.addTemplate
},
@@ -156,7 +151,7 @@ export const accountFieldsMeta = (vm) => {
}
},
push_now: {
helpTip: vm.$t('WindowsPushHelpText'),
helpText: vm.$t('accounts.AccountPush.WindowsPushHelpText'),
hidden: (formValue) => {
const automation = vm.iPlatform.automation || {}
return !automation.push_account_enabled ||
@@ -167,7 +162,7 @@ export const accountFieldsMeta = (vm) => {
}
},
params: {
label: vm.$t('PushParams'),
label: vm.$t('assets.PushParams'),
component: AutomationParamsForm,
el: {},
hidden: (formValue) => {
@@ -184,10 +179,10 @@ export const accountFieldsMeta = (vm) => {
}
},
is_active: {
label: vm.$t('IsActive')
label: vm.$t('common.IsActive')
},
comment: {
label: vm.$t('Comment'),
label: vm.$t('common.Comment'),
hidden: () => {
return vm.addTemplate
}

View File

@@ -2,8 +2,6 @@
<AutoDataForm
v-if="!loading"
ref="AutoDataForm"
:class="addTemplate? '': 'account-add'"
:submit-btn-text="submitBtnText"
v-bind="$data"
@submit="confirm"
/>
@@ -46,7 +44,6 @@ export default {
return {
loading: true,
usernameChanged: false,
submitBtnText: this.$t('Confirm'),
iPlatform: {
automation: {},
su_enabled: false,
@@ -61,13 +58,14 @@ export default {
form: Object.assign({ 'on_invalid': 'error' }, this.account || {}),
encryptedFields: ['secret'],
fields: [
[this.$t('AccountTemplate'), ['template']],
[this.$t('Basic'), ['assets', 'name', 'username', 'privileged', 'su_from', 'su_from_username']],
[this.$t('Secret'), [
[this.$t('assets.Asset'), ['assets']],
[this.$t('accounts.AccountTemplate'), ['template']],
[this.$t('common.Basic'), ['name', 'username', 'privileged', 'su_from', 'su_from_username']],
[this.$t('assets.Secret'), [
'secret_type', 'password', 'ssh_key', 'token',
'access_key', 'passphrase', 'api_key'
]],
[this.$t('Other'), ['push_now', 'params', 'on_invalid', 'is_active', 'comment']]
[this.$t('common.Other'), ['push_now', 'params', 'on_invalid', 'is_active', 'comment']]
],
fieldsMeta: accountFieldsMeta(this),
hasSaveContinue: false
@@ -102,23 +100,23 @@ export default {
setSecretTypeOptions() {
const choices = [
{
label: this.$t('Password'),
label: this.$t('assets.Password'),
value: 'password'
},
{
label: this.$t('SSHKey'),
label: this.$t('assets.SSHKey'),
value: 'ssh_key'
},
{
label: this.$t('Token'),
label: this.$t('assets.Token'),
value: 'token'
},
{
label: this.$t('AccessKey'),
label: this.$t('assets.AccessKey'),
value: 'access_key'
},
{
label: this.$t('ApiKey'),
label: this.$t('assets.ApiKey'),
value: 'api_key'
}
]
@@ -153,25 +151,3 @@ export default {
}
}
</script>
<style lang='scss' scoped>
.account-add {
::v-deep .el-form-item {
margin-bottom: 5px;
.help-block {
margin-bottom: 5px;
}
}
::v-deep .form-group-header {
.hr-line-dashed {
margin: 5px 0;
}
h3 {
margin-bottom: 10px;
}
}
}
</style>

View File

@@ -8,7 +8,6 @@
:title="title"
:visible.sync="iVisible"
v-bind="$attrs"
width="900px"
v-on="$listeners"
>
<AccountCreateUpdateForm
@@ -53,7 +52,7 @@ export default {
title: {
type: String,
default: function() {
return this.$t('AddAccount')
return this.$t('assets.AddAccount')
}
}
},
@@ -92,7 +91,7 @@ export default {
data = formValue
url = `/api/v1/accounts/accounts/bulk/`
if (data.assets.length === 0) {
this.$message.error(this.$tc('PleaseSelectAsset'))
this.$message.error(this.$tc('assets.PleaseSelectAsset'))
return
}
}
@@ -114,7 +113,7 @@ export default {
this.$axios.patch(`/api/v1/accounts/accounts/${this.account.id}/`, data).then(() => {
this.iVisible = false
this.$emit('add', true)
this.$message.success(this.$tc('UpdateSuccessMsg'))
this.$message.success(this.$tc('common.updateSuccessMsg'))
}).catch(error => this.setFieldError(error))
},
handleResult(resp, error) {
@@ -127,7 +126,7 @@ export default {
}
if (!bulkCreate) {
if (!error) {
this.$message.success(this.$tc('CreateSuccessMsg'))
this.$message.success(this.$tc('common.createSuccessMsg'))
} else {
this.setFieldError(error)
}
@@ -172,3 +171,7 @@ export default {
}
}
</script>
<style scoped>
</style>

View File

@@ -27,7 +27,7 @@
:account="account"
:add-template="true"
:asset="iAsset"
:title="accountCreateByTemplateTitle"
:title="accountCreateUpdateTitle"
:visible.sync="showAddTemplateDialog"
@add="addAccountSuccess"
@bulk-create-done="showBulkCreateResult($event)"
@@ -36,7 +36,6 @@
v-if="showResultDialog"
:result="createAccountResults"
:visible.sync="showResultDialog"
@close-all="closeAll"
/>
<AccountBulkUpdateDialog
v-if="updateSelectedDialogSetting.visible"
@@ -119,7 +118,8 @@ export default {
columnsDefault: {
type: Array,
default: () => ([
'name', 'username', 'asset', 'date_updated'
'name', 'username', 'asset', 'privileged',
'secret_type', 'is_active', 'date_updated'
])
},
headerExtraActions: {
@@ -140,8 +140,7 @@ export default {
showAddDialog: false,
showAddTemplateDialog: false,
createAccountResults: [],
accountCreateUpdateTitle: this.$t('AddAccount'),
accountCreateByTemplateTitle: this.$t('AddAccountByTemplate'),
accountCreateUpdateTitle: this.$t('assets.AddAccount'),
iAsset: this.asset,
account: {},
secretUrl: '',
@@ -159,7 +158,6 @@ export default {
},
columnsMeta: {
name: {
width: '120px',
formatter: function(row) {
const to = {
name: 'AssetAccountDetail',
@@ -173,6 +171,7 @@ export default {
}
},
asset: {
label: this.$t('assets.Asset'),
formatter: function(row) {
const to = {
name: 'AssetDetail',
@@ -185,10 +184,8 @@ export default {
}
}
},
username: {
width: '120px'
},
secret_type: {
width: '100px',
formatter: function(row) {
return row.secret_type.label
}
@@ -199,16 +196,17 @@ export default {
}
},
has_secret: {
width: '120px',
width: '100px',
formatterArgs: {
showFalse: false
}
},
privileged: {
label: this.$t('assets.Privileged'),
width: '120px',
formatterArgs: {
showText: false,
showFalse: true
showFalse: false
}
},
connectivity: connectivityMeta,
@@ -218,11 +216,11 @@ export default {
hasUpdate: false, // can set function(row, value)
hasDelete: false, // can set function(row, value)
hasClone: this.hasClone,
moreActionsTitle: this.$t('More'),
moreActionsTitle: this.$t('common.More'),
extraActions: [
{
name: 'View',
title: this.$t('View'),
title: this.$t('common.View'),
can: this.$hasPerm('accounts.view_accountsecret'),
type: 'primary',
callback: ({ row }) => {
@@ -236,29 +234,25 @@ export default {
}
},
{
name: 'Update',
title: this.$t('Edit'),
can: this.$hasPerm('accounts.change_account') && !this.$store.getters.currentOrgIsRoot,
name: 'ClearSecret',
title: this.$t('common.ClearSecret'),
can: this.$hasPerm('accounts.change_account'),
type: 'primary',
callback: ({ row }) => {
const data = {
...this.asset,
...row.asset
}
vm.account = row
vm.iAsset = data
vm.showAddDialog = false
vm.accountCreateUpdateTitle = this.$t('UpdateAccount')
setTimeout(() => {
vm.showAddDialog = true
this.$axios.patch(
`/api/v1/accounts/accounts/clear-secret/`,
{ account_ids: [row.id] }
).then(() => {
this.$message.success(this.$tc('common.ClearSuccessMsg'))
})
}
},
{
name: 'Test',
title: this.$t('Test'),
title: this.$t('accounts.Test'),
can: ({ row }) =>
!this.$store.getters.currentOrgIsRoot &&
this.$hasPerm('accounts.verify_account') &&
this.$hasPerm('accounts.change_account') &&
row.asset['auto_config'].ansible_enabled &&
row.asset['auto_config'].ping_enabled,
callback: ({ row }) => {
@@ -271,16 +265,20 @@ export default {
}
},
{
name: 'ClearSecret',
title: this.$t('ClearSecret'),
can: this.$hasPerm('accounts.change_account'),
type: 'primary',
name: 'Update',
title: this.$t('common.Update'),
can: this.$hasPerm('accounts.change_account') && !this.$store.getters.currentOrgIsRoot,
callback: ({ row }) => {
this.$axios.patch(
`/api/v1/accounts/accounts/clear-secret/`,
{ account_ids: [row.id] }
).then(() => {
this.$message.success(this.$tc('ClearSuccessMsg'))
const data = {
...this.asset,
...row.asset
}
vm.account = row
vm.iAsset = data
vm.showAddDialog = false
vm.accountCreateUpdateTitle = this.$t('assets.UpdateAccount')
setTimeout(() => {
vm.showAddDialog = true
})
}
}
@@ -297,10 +295,17 @@ export default {
hasCreate: false,
hasImport: this.hasImport,
hasExport: this.hasExport && this.$hasPerm('accounts.view_accountsecret'),
handleImportClick: ({ selectedRows }) => {
this.$eventBus.$emit('showImportDialog', {
selectedRows,
url: '/api/v1/accounts/accounts/',
name: this?.name
})
},
exportOptions: {
url: this.exportUrl,
mfaVerifyRequired: true,
tips: this.$t('AccountExportTips')
tips: this.$t('accounts.AccountExportTips')
},
importOptions: {
canImportCreate: this.$hasPerm('accounts.add_account'),
@@ -309,9 +314,8 @@ export default {
extraActions: [
{
name: 'add',
title: this.$t('Create'),
title: this.$t('common.Add'),
type: 'primary',
icon: 'plus',
can: () => {
return vm.$hasPerm('accounts.add_account') && !this.$store.getters.currentOrgIsRoot
},
@@ -320,13 +324,14 @@ export default {
setTimeout(() => {
vm.iAsset = this.asset
vm.account = {}
vm.accountCreateUpdateTitle = this.$t('assets.AddAccount')
vm.showAddDialog = true
})
}
},
{
name: 'add-template',
title: this.$t('TemplateAdd'),
title: this.$t('common.TemplateAdd'),
has: !(this.platform || this.asset),
can: () => {
return vm.$hasPerm('accounts.add_account') && !this.$store.getters.currentOrgIsRoot
@@ -336,6 +341,7 @@ export default {
setTimeout(() => {
vm.iAsset = this.asset
vm.account = {}
vm.accountCreateUpdateTitle = this.$t('assets.AddAccount')
vm.showAddTemplateDialog = true
})
}
@@ -344,10 +350,10 @@ export default {
],
extraMoreActions: [
{
name: 'TestSelected',
title: this.$t('TestSelected'),
name: 'BulkVerify',
title: this.$t('accounts.BulkVerify'),
type: 'primary',
icon: 'fa-link',
fa: 'fa-link',
can: ({ selectedRows }) => {
return selectedRows.length > 0 &&
['clickhouse', 'redis', 'website', 'chatgpt'].indexOf(selectedRows[0].asset.type.value) === -1 &&
@@ -362,15 +368,15 @@ export default {
{ action: 'verify', accounts: ids }).then(res => {
openTaskPage(res['task'])
}).catch(err => {
this.$message.error(this.$tc('BulkVerifyErrorMsg' + ' ' + err))
this.$message.error(this.$tc('common.bulkVerifyErrorMsg' + ' ' + err))
})
}.bind(this)
},
{
name: 'BatchClearSecret',
title: this.$t('ClearSecret'),
name: 'ClearSecrets',
title: this.$t('common.ClearSecret'),
type: 'primary',
icon: 'clean',
fa: 'clean',
can: ({ selectedRows }) => {
return selectedRows.length > 0 && vm.$hasPerm('accounts.change_account')
},
@@ -381,16 +387,16 @@ export default {
this.$axios.patch(
'/api/v1/accounts/accounts/clear-secret/',
{ account_ids: ids }).then(() => {
this.$message.success(this.$tc('ClearSuccessMsg'))
this.$message.success(this.$tc('common.ClearSuccessMsg'))
}).catch(err => {
this.$message.error(this.$tc('ClearErrorMsg' + ' ' + err))
this.$message.error(this.$tc('common.bulkClearErrorMsg' + ' ' + err))
})
}.bind(this)
},
{
name: 'UpdateSelected',
title: this.$t('UpdateSelected'),
icon: 'batch-update',
name: 'actionUpdateSelected',
title: this.$t('accounts.AccountBatchUpdate'),
fa: 'batch-update',
can: ({ selectedRows }) => {
return selectedRows.length > 0 &&
!this.$store.getters.currentOrgIsRoot &&
@@ -436,12 +442,12 @@ export default {
this.tableConfig.columnsMeta.actions.formatterArgs.extraActions.push(
{
name: 'Delete',
title: this.$t('Delete'),
title: this.$t('common.Delete'),
can: this.$hasPerm('accounts.delete_account'),
type: 'primary',
callback: ({ row }) => {
const msg = this.$t('AccountDeleteConfirmMsg')
this.$confirm(msg, this.$tc('Info'), {
const msg = this.$t('accounts.AccountDeleteConfirmMsg')
this.$confirm(msg, this.$tc('common.Info'), {
type: 'warning',
confirmButtonClass: 'el-button--danger',
beforeClose: async(action, instance, done) => {
@@ -449,7 +455,7 @@ export default {
this.$axios.delete(`/api/v1/accounts/accounts/${row.id}/`).then(() => {
done()
this.$refs.ListTable.reloadTable()
this.$message.success(this.$tc('DeleteSuccessMsg'))
this.$message.success(this.$tc('common.deleteSuccessMsg'))
})
}
})
@@ -458,12 +464,6 @@ export default {
)
}
},
activated() {
// 由于组件嵌套较深,有可能导致 Error in activated hook: "TypeError: Cannot read properties of undefined (reading 'getList')" 的问题
setTimeout(() => {
this.refresh()
}, 300)
},
methods: {
onUpdateAuthDone(account) {
Object.assign(this.account, account)
@@ -481,27 +481,15 @@ export default {
this.$refs.ListTable.reloadTable()
},
showBulkCreateResult(results) {
this.showResultDialog = false
this.createAccountResults = results
setTimeout(() => {
this.showResultDialog = true
this.createAccountResults = results
}, 350)
}, 100)
},
handleAccountBulkUpdate() {
this.updateSelectedDialogSetting.visible = false
this.$refs.ListTable.reloadTable()
},
closeAll() {
setTimeout(() => {
this.showResultDialog = false
}, 350)
setTimeout(() => {
this.showAddDialog = false
}, 800)
setTimeout(() => {
this.refresh()
}, 1000)
}
}
}

View File

@@ -30,11 +30,11 @@ export default {
}
},
data() {
const errorProp = this.$t('Error')
const errorProp = this.$t('common.Error')
const stateMap = {
'created': this.$tc('Created'),
'updated': this.$tc('Updated'),
'skipped': this.$tc('Skipped')
'created': this.$tc('common.Created'),
'updated': this.$tc('common.Updated'),
'skipped': this.$tc('common.Skipped')
}
const stateClsMap = {
'created': 'color-primary',
@@ -42,16 +42,16 @@ export default {
'skipped': 'color-default'
}
return {
title: this.$t('AddAccountResult'),
title: this.$t('accounts.AddAccountResult'),
config: {
columns: [
{
prop: 'asset',
label: this.$t('Asset')
label: this.$t('assets.Asset')
},
{
prop: 'state',
label: this.$t('Status'),
label: this.$t('common.Status'),
width: '200px',
formatter: (row) => {
if (row.error) {
@@ -71,11 +71,11 @@ export default {
computed: {
summary() {
const labels = {
total: this.$tc('Total'),
created: this.$tc('Created'),
updated: this.$tc('Updated'),
skipped: this.$tc('Skipped'),
error: this.$tc('Error')
total: this.$tc('common.Total'),
created: this.$tc('common.Created'),
updated: this.$tc('common.Updated'),
skipped: this.$tc('common.Skipped'),
error: this.$tc('common.Error')
}
const grouped = _.groupBy(this.result, 'state')
const groupedLength = _.mapValues(grouped, 'length')
@@ -91,7 +91,7 @@ export default {
},
methods: {
closeDialog() {
this.$emit('close-all')
this.$emit('update:visible', false)
}
}
}

View File

@@ -23,7 +23,7 @@ export default {
data() {
return {
config: {
title: this.$t('HistoryPassword'),
title: this.$t('accounts.HistoryPassword'),
visible: false,
width: '60%',
tableConfig: {
@@ -32,7 +32,7 @@ export default {
columns: ['secret', 'version', 'history_date'],
columnsMeta: {
secret: {
label: this.$t('Password'),
label: this.$t('assets.Password'),
formatter: ShowKeyCopyFormatter,
formatterArgs: {
hasDownload: false,
@@ -40,7 +40,7 @@ export default {
}
},
history_date: {
label: this.$t('HistoryDate')
label: this.$t('accounts.HistoryDate')
},
secret_type: {
width: '200px'

View File

@@ -65,7 +65,7 @@ export default {
</script>
<style lang="scss" scoped>
.item-textarea ::v-deep .el-textarea__inner {
.item-textarea > > > .el-textarea__inner {
height: 110px;
}
@@ -78,12 +78,12 @@ export default {
border-bottom: none;
}
::v-deep .el-form-item__label {
> > > .el-form-item__label {
padding-right: 20px;
line-height: 30px;
}
::v-deep .el-form-item__content {
> > > .el-form-item__content {
line-height: 30px;
pre {

View File

@@ -1,7 +1,7 @@
<template>
<Dialog
:destroy-on-close="true"
:title="$tc('UpdateAssetUserToken')"
:title="$tc('assets.UpdateAssetUserToken')"
:visible.sync="visible"
width="50"
@cancel="handleCancel()"
@@ -9,19 +9,19 @@
v-on="$listeners"
>
<el-form label-position="right" label-width="90px">
<el-form-item :label="$tc('Name')">
<el-form-item :label="$tc('assets.Name')">
<el-input v-model="account['asset_name']" readonly />
</el-form-item>
<el-form-item :label="$tc('Username')">
<el-form-item :label="$tc('assets.Username')">
<el-input v-model="account['username']" readonly />
</el-form-item>
<el-form-item :label="$tc('Password')">
<el-form-item :label="$tc('assets.Password')">
<UpdateToken v-model="authInfo.password" />
</el-form-item>
<el-form-item :label="$tc('SSHSecretKey')">
<el-form-item :label="$tc('assets.SSHSecretKey')">
<UploadKey @input="getFile" />
</el-form-item>
<el-form-item :label="$tc('Passphrase')">
<el-form-item :label="$tc('assets.Passphrase')">
<UpdateToken v-model="authInfo.passphrase" />
</el-form-item>
</el-form>
@@ -75,12 +75,12 @@ export default {
{ disableFlashErrorMsg: true }
).then(res => {
this.authInfo = { password: '', private_key: '' }
this.$message.success(this.$tc('UpdateSuccessMsg'))
this.$message.success(this.$tc('common.updateSuccessMsg'))
this.$emit('updateAuthDone', res)
this.$emit('update:visible', false)
}).catch(err => {
const errMsg = Object.values(err.response.data).join(', ')
this.$message.error(this.$tc('UpdateErrorMsg') + ' ' + errMsg)
this.$message.error(this.$tc('common.updateErrorMsg') + ' ' + errMsg)
this.$emit('update:visible', true)
})
},

View File

@@ -10,11 +10,11 @@
@confirm="accountConfirmHandle"
v-on="$listeners"
>
<el-form :model="secretInfo" class="password-form" label-position="right" label-width="130px">
<el-form-item :label="$tc('Name')">
<el-form :model="secretInfo" class="password-form" label-position="right" label-width="100px">
<el-form-item :label="$tc('assets.Name')">
<span>{{ account['name'] }}</span>
</el-form-item>
<el-form-item :label="$tc('Username')">
<el-form-item :label="$tc('assets.Username')">
<span>{{ account['username'] }}</span>
</el-form-item>
<el-form-item :label="secretTypeLabel">
@@ -27,16 +27,16 @@
@input="onShowKeyCopyFormatterChange"
/>
</el-form-item>
<el-form-item v-if="secretType === 'ssh_key'" :label="$tc('SshKeyFingerprint')">
<el-form-item v-if="secretType === 'ssh_key'" :label="$tc('assets.sshKeyFingerprint')">
<span>{{ sshKeyFingerprint }}</span>
</el-form-item>
<el-form-item :label="$tc('DateCreated')">
<el-form-item :label="$tc('common.DateCreated')">
<span>{{ account['date_created'] | date }}</span>
</el-form-item>
<el-form-item :label="$tc('DateUpdated')">
<el-form-item :label="$tc('common.DateUpdated')">
<span>{{ account['date_updated'] | date }}</span>
</el-form-item>
<el-form-item v-if="showPasswordRecord" v-perms="'accounts.view_accountsecret'" :label="$tc('PasswordRecord')">
<el-form-item v-if="showPasswordRecord" v-perms="'accounts.view_accountsecret'" :label="$tc('accounts.PasswordRecord')">
<el-link
:underline="false"
type="success"
@@ -90,7 +90,7 @@ export default {
title: {
type: String,
default: function() {
return this.$tc('Detail')
return this.$tc('assets.AccountDetail')
}
},
showPasswordRecord: {
@@ -142,7 +142,7 @@ export default {
}
const url = this.type === 'account' ? `/api/v1/accounts/accounts` : `/api/v1/accounts/account-templates`
this.$axios.patch(`${url}/${this.account.id}/`, params).then(() => {
this.$message.success(this.$tc('UpdateSuccessMsg'))
this.$message.success(this.$tc('common.updateSuccessMsg'))
})
},
showSecretDialog() {
@@ -167,7 +167,7 @@ export default {
</script>
<style lang="scss" scoped>
.item-textarea ::v-deep .el-textarea__inner {
.item-textarea >>> .el-textarea__inner {
height: 110px;
}
@@ -180,18 +180,12 @@ export default {
border-bottom: none;
}
::v-deep .el-form-item__label {
display: flex;
align-items: center;
justify-content: flex-start;
>>> .el-form-item__label {
padding-right: 20px;
line-height: 30px;
word-break: keep-all;
overflow-wrap: break-word;
white-space: normal;
}
::v-deep .el-form-item__content {
>>> .el-form-item__content {
line-height: 30px;
pre {

View File

@@ -1,6 +1,8 @@
import i18n from '@/i18n/i18n'
import { ChoicesFormatter } from '@/components/Table/TableFormatters'
export const connectivityMeta = {
label: i18n.t('assets.Connectivity'),
formatter: ChoicesFormatter,
formatterArgs: {
faChoices: {
@@ -20,5 +22,5 @@ export const connectivityMeta = {
}
}
},
width: '130px'
width: '100px'
}

View File

@@ -8,7 +8,7 @@
</tr>
<tr>
<td colspan="2">
<el-button :disabled="disabled" :type="type" size="small" @click="addObjects">{{ $t('Add') }}</el-button>
<el-button :disabled="disabled" :type="type" size="small" @click="addObjects">{{ $t('common.Add') }}</el-button>
</td>
</tr>
</table>

View File

@@ -1,8 +1,8 @@
<template>
<Dialog
:close-on-click-modal="false"
:title="$tc('Assets')"
:disabled-status="!isLoaded"
:loading-status="!isLoaded"
:title="$tc('assets.Assets')"
custom-class="asset-select-dialog"
top="2vh"
v-bind="$attrs"
@@ -16,14 +16,12 @@
ref="ListPage"
:header-actions="headerActions"
:node-url="baseNodeUrl"
:sync-select-to-url="false"
:table-config="tableConfig"
:tree-setting="iTreeSetting"
:tree-url="`${baseNodeUrl}children/tree/`"
:url="baseUrl"
:tree-setting="treeSetting"
class="tree-table"
v-bind="$attrs"
v-on="$listeners"
@loaded="handleTableLoaded"
/>
</Dialog>
@@ -78,17 +76,17 @@ export default {
columns: [
{
prop: 'name',
label: this.$t('Name'),
label: this.$t('assets.Name'),
sortable: true
},
{
prop: 'address',
label: this.$t('IpDomain'),
label: this.$t('assets.ipDomain'),
sortable: 'custom'
},
{
prop: 'platform',
label: this.$t('Platform'),
label: this.$t('assets.Platform'),
sortable: true,
formatter: function(row) {
return row.platform.name
@@ -122,17 +120,9 @@ export default {
}
}
},
computed: {
iTreeSetting() {
return { ...this.treeSetting, selectSyncToRoute: false }
}
},
methods: {
handleTableLoaded() {
this.isLoaded = true
},
handleClose() {
this.$refs.ListPage.$refs.TreeList.componentKey += 1
this.$eventBus.$emit('treeComponentKey')
},
handleConfirm() {
this.$emit('confirm', this.rowSelected, this.rowsAdd)
@@ -156,6 +146,9 @@ export default {
if (selectValueIndex > -1) {
this.rowSelected.splice(selectValueIndex, 1)
}
},
handleTableLoaded() {
this.isLoaded = true
}
}
}

View File

@@ -37,10 +37,6 @@ export default {
type: String,
default: '/api/v1/assets/assets/'
},
defaultPageSize: {
type: Number,
default: 10
},
baseNodeUrl: {
type: String,
default: '/api/v1/assets/nodes/'
@@ -74,7 +70,6 @@ export default {
value: iValue,
multiple: true,
clearable: true,
defaultPageSize: this.defaultPageSize,
ajax: {
url: this.baseUrl,
transformOption: (item) => {
@@ -139,22 +134,16 @@ export default {
.tree-table {
.left {
padding: 5px 0;
padding: 5px;
.ztree {
height: 100%;
}
}
.right {
.transition-box {
padding-left: 0;
min-height: 500px;
height: inherit !important;
}
}
.mini {
padding-top: 8px;
width: 1px;
}
.transition-box {

View File

@@ -2,10 +2,9 @@
<TreeTable
ref="TreeList"
:active-menu.sync="treeTableConfig.activeMenu"
:component="treeComponent"
:table-config="tableConfig"
:tree-tab-config="treeTableConfig"
:tree-width="treeWidth"
component="TabTree"
v-bind="$attrs"
v-on="$listeners"
>
@@ -68,14 +67,12 @@ export default {
const vm = this
return {
treeComponent: 'TabTree',
treeTabConfig: {
activeMenu: 'CustomTree',
submenu: [
{
title: this.$t('AssetTree'),
title: this.$t('assets.AssetTree'),
name: 'CustomTree',
icon: 'fa-tree',
treeSetting: {
showAssets,
showMenu: false,
@@ -101,14 +98,13 @@ export default {
}
},
{
title: this.$t('TypeTree'),
icon: 'fa-list-ul',
title: this.$t('assets.BuiltinTree'),
name: 'BuiltinTree',
treeSetting: {
showRefresh: true,
showAssets: false,
showSearch: false,
customTreeHeaderName: this.$t('TypeTree'),
customTreeHeaderName: this.$t('assets.BuiltinTree'),
url: this.typeUrl,
nodeUrl: this.treeSetting?.nodeUrl || this.nodeUrl,
treeUrl: `${this.typeUrl}?assets=${showAssets ? '1' : '0'}&count_resource=${this.treeSetting.countResource || 'asset'}`,
@@ -122,9 +118,6 @@ export default {
}
},
computed: {
treeWidth() {
return '23.6%'
},
treeTableConfig() {
if (this.treeSetting.notShowBuiltinTree) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
@@ -161,42 +154,33 @@ export default {
$('#m_show_asset_only_current_node').css('color', '#606266')
}
},
getAssetsUrl(treeNode) {
let url = this.treeSetting?.url || this.url
const setParam = (param, value, delay) => {
setTimeout(() => {
url = setUrlParam(url, param, value)
})
}
if (treeNode.meta.type === 'node') {
const nodeId = treeNode.meta.data.id
setParam('node_id', nodeId)
setParam('asset_id', '')
url = setUrlParam(url, 'node_id', nodeId)
url = setUrlParam(url, 'asset_id', '')
} else if (treeNode.meta.type === 'asset') {
const assetId = treeNode.meta.data?.id || treeNode.id
setParam('node_id', '')
setParam('asset_id', assetId)
url = setUrlParam(url, 'node_id', '')
url = setUrlParam(url, 'asset_id', assetId)
} else if (treeNode.meta.type === 'category') {
setParam('category', treeNode.meta.category)
url = setUrlParam(url, 'category', treeNode.meta.category)
} else if (treeNode.meta.type === 'type') {
setParam('category', treeNode.meta.category)
setParam('type', treeNode.meta._type)
url = setUrlParam(url, 'category', treeNode.meta.category)
url = setUrlParam(url, 'type', treeNode.meta._type)
} else if (treeNode.meta.type === 'platform') {
setParam('platform', treeNode.id)
}
setTimeout(() => {
const query = this.setTreeUrlQuery()
url = query ? `${url}&${query}` : url
this.$set(this.tableConfig, 'url', url)
})
if (this.treeSetting.selectSyncToRoute !== false) {
setRouterQuery(this, url)
url = setUrlParam(url, 'platform', treeNode.id)
}
const query = this.setTreeUrlQuery()
url = query ? `${url}&${query}` : url
this.$set(this.tableConfig, 'url', url)
setRouterQuery(this, url)
}
}
}
</script>
<style lang='scss' scoped>
</style>

View File

@@ -7,7 +7,7 @@
type="primary"
@click="onOpenDialog"
>
{{ $tc('Setting') }}
{{ $tc('common.Setting') }}
</el-button>
</div>
<Dialog
@@ -50,7 +50,7 @@ export default {
title: {
type: String,
default: function() {
return this.$t('PushParams')
return this.$t('assets.PushParams')
}
},
assets: {

View File

@@ -1,5 +1,5 @@
<template>
<ListTable ref="ListTable" :header-actions="headerActions" :table-config="tableConfig" />
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
</template>
<script>
@@ -27,7 +27,7 @@ export default {
],
columnsMeta: {
ip: {
label: this.$t('IP')
label: this.$t('assets.ip')
},
actions: {
formatterArgs: {
@@ -37,7 +37,7 @@ export default {
extraActions: [
{
name: 'UnlockIP',
title: this.$t('Unblock'),
title: this.$t('setting.Unblock'),
can: this.$hasPerm('settings.change_security'),
type: 'primary',
callback: ({ row }) => {
@@ -45,7 +45,7 @@ export default {
'/api/v1/settings/security/unlock-ip/',
{ ips: [row.ip] }
).then(() => {
vm.$message.success(this.$tc('UnlockSuccessMsg'))
vm.$message.success(this.$tc('common.UnlockSuccessMsg'))
vm.$refs.ListTable.reloadTable()
})
}
@@ -68,7 +68,7 @@ export default {
extraMoreActions: [
{
name: 'UnlockSelected',
title: this.$t('UnblockSelected'),
title: this.$t('setting.BulkUnblock'),
type: 'primary',
can: ({ selectedRows }) => {
return selectedRows.length > 0
@@ -77,12 +77,10 @@ export default {
vm.$axios.post(
'/api/v1/settings/security/unlock-ip/',
{
ips: selectedRows.map(v => {
return v.ip
})
ips: selectedRows.map(v => { return v.ip })
}
).then(res => {
vm.$message.success(vm.$tc('UnlockSuccessMsg'))
vm.$message.success(vm.$tc('common.UnlockSuccessMsg'))
vm.$refs.ListTable.reloadTable()
})
}

View File

@@ -6,18 +6,18 @@
type="primary"
@click="onOpenDialog"
>
{{ $tc('View') }}
<span>({{ $tc('LockedIP', ipCounts ) }})</span>
{{ $tc('common.View') }}
<span>({{ $tc('setting.LockedIP', ipCounts ) }})</span>
</el-button>
</div>
<Dialog
:destroy-on-close="true"
:visible.sync="visible"
:title="title"
width="40%"
:show-cancel="false"
:show-confirm="false"
:title="title"
:visible.sync="visible"
:destroy-on-close="true"
v-bind="$attrs"
width="40%"
v-on="$listeners"
>
<BlockedIPList />
@@ -43,7 +43,7 @@ export default {
title: {
type: String,
default: function() {
return this.$t('BlockedIPS')
return this.$t('setting.BlockedIPS')
}
},
url: {

View File

@@ -11,7 +11,7 @@
v-on="$listeners"
>
<el-form :model="secretInfo" class="password-form" label-position="right" label-width="100px">
<el-form-item :label="$tc('OldSecret')">
<el-form-item :label="$tc('accounts.AccountChangeSecret.OldSecret')">
<ShowKeyCopyFormatter
:cell-value="secretInfo.old_secret"
:col="{ formatterArgs: {
@@ -19,7 +19,7 @@
}}"
/>
</el-form-item>
<el-form-item :label="$tc('NewSecret')">
<el-form-item :label="$tc('accounts.AccountChangeSecret.NewSecret')">
<ShowKeyCopyFormatter
:cell-value="secretInfo.new_secret"
:col="{ formatterArgs: {
@@ -54,7 +54,7 @@ export default {
title: {
type: String,
default: function() {
return this.$tc('ViewSecret')
return this.$tc('common.ViewSecret')
}
}
},
@@ -65,7 +65,8 @@ export default {
mfaDialogVisible: true
}
},
computed: {},
computed: {
},
mounted() {
this.showSecretDialog()
},
@@ -88,7 +89,7 @@ export default {
</script>
<style lang="scss" scoped>
.item-textarea ::v-deep .el-textarea__inner {
.item-textarea >>> .el-textarea__inner {
height: 110px;
}
@@ -101,12 +102,12 @@ export default {
border-bottom: none;
}
::v-deep .el-form-item__label {
>>> .el-form-item__label {
padding-right: 20px;
line-height: 30px;
}
::v-deep .el-form-item__content {
>>> .el-form-item__content {
line-height: 30px;
pre {

View File

@@ -12,31 +12,31 @@
<el-input
v-model="inputValue"
:disabled="isLoading"
:placeholder="$tc('InputMessage')"
:rows="expanded ? 3 :2"
:placeholder="$tc('common.InputMessage')"
type="textarea"
@compositionend="isIM = false"
@compositionstart="isIM = true"
@keypress.native="onKeyEnter"
/>
<div class="input-action">
<span class="right">
<i :class="{'active': inputValue }" class="fa fa-send" @click="onSendHandle" />
</span>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { useChat } from '../../useChat.js'
import Select2 from '../../../../Form/FormFields/Select2.vue'
import { useChat } from '../../useChat.js'
const { setLoading } = useChat()
export default {
components: { Select2 },
props: {
expanded: {
type: Boolean,
default: false
}
},
data() {
return {
@@ -46,7 +46,7 @@ export default {
url: '/api/v1/settings/chatai-prompts/',
value: '',
multiple: false,
placeholder: this.$t('Prompt'),
placeholder: this.$t('common.Prompt'),
ajax: {
transformOption: (item) => {
return { label: item.name, value: item.content }
@@ -91,14 +91,11 @@ export default {
display: flex;
height: 100%;
flex-direction: column;
.chat-action {
width: 100%;
margin: 6px 0;
&::v-deep .el-select {
&>>> .el-select {
width: 50%;
.el-input__inner {
height: 28px;
line-height: 28px;
@@ -107,47 +104,60 @@ export default {
background-color: #f7f7f8;
font-size: 13px;
color: rgba(0, 0, 0, 0.45);
&:hover {
background-color: #ededed;
}
}
.el-input__icon {
line-height: 0;
line-height: 0px;
}
}
}
.chat-input {
flex: 1;
display: flex;
flex-direction: column;
border: 1px solid #DCDFE6;
border-radius: 12px;
&::v-deep .el-textarea {
&:has(.el-textarea__inner:focus) {
border: 1px solid var(--color-primary);
}
&>>> .el-textarea {
height: 100%;
.el-textarea__inner {
height: 100%;
padding: 8px 10px;
border: none;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
resize: none;
border-radius: 5px;
&::-webkit-scrollbar {
width: 12px;
}
}
}
.el-textarea.is-disabled + .input-action {
background-color: #F5F7FA;
cursor: no-drop;
i {
cursor: no-drop;
}
}
.input-action {
overflow: hidden;
padding: 0 16px 15px;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
.right {
float: right;
.active {
color: var(--color-primary);
}
i {
cursor: pointer;
}
}
}
}
}
</style>

View File

@@ -21,8 +21,8 @@
<div class="action">
<el-tooltip
v-if="isSystemError && isLoading"
:content="$tc('Reconnect')"
:open-delay="500"
:content="$tc('common.Reconnect')"
effect="dark"
placement="top"
>
<svg-icon icon-class="refresh" @click="onRefresh" />
@@ -59,8 +59,7 @@ export default {
props: {
item: {
type: Object,
default: () => {
}
default: () => {}
}
},
data() {
@@ -70,7 +69,7 @@ export default {
dropdownOptions: [
{
action: 'copy',
label: this.$t('Copy')
label: this.$t('common.Copy')
}
]
}
@@ -105,69 +104,56 @@ export default {
.chat-item {
display: flex;
padding: 16px 14px 0;
&:last-child {
padding-bottom: 16px;
}
.avatar {
width: 22px;
height: 22px;
margin-top: 2px;
.header-avatar {
width: 100%;
height: 100%;
&::v-deep img {
&>>> img {
background-color: #e5e5e7;
}
}
}
.content {
margin-left: 6px;
overflow: hidden;
.operational {
display: flex;
justify-content: space-between;
overflow: hidden;
.copy {
float: right;
cursor: pointer;
}
}
.message {
display: -webkit-box;
.message-content {
flex: 1;
padding: 6px 10px;
border-radius: 2px 12px 12px;
background-color: #f0f1f5;
}
.action {
.svg-icon {
transform: translateY(50%);
margin-left: 3px;
cursor: pointer;
}
.el-dropdown {
height: 32px;
line-height: 37px;
font-size: 13px;
.el-dropdown-link {
i {
padding: 4px 5px;
font-size: 15px;
color: #8d9091;
&:hover {
color: #7b8085
}
@@ -175,27 +161,21 @@ export default {
}
}
}
.error {
color: red;
}
}
}
}
.user-role {
flex-direction: row-reverse;
.content {
margin-right: 10px;
.operational {
flex-direction: row-reverse;
}
.message {
flex-direction: row-reverse;
.message-content {
background-color: var(--menu-hover);
border-radius: 12px 2px 12px 12px;

View File

@@ -6,7 +6,7 @@
<span />
<span />
</span>
<div v-else v-sanitize="text" class="inline-block markdown-body" />
<div v-else class="inline-block markdown-body" v-html="text" />
</div>
</div>
</template>
@@ -19,12 +19,12 @@ import hljs from 'highlight.js'
import 'highlight.js/styles/atom-one-dark.css'
import { copy } from '@/utils/common'
/* eslint-disable vue/no-v-html */
export default {
props: {
message: {
type: Object,
default: () => {
}
default: () => {}
}
},
data() {
@@ -86,8 +86,7 @@ export default {
if (this.$refs.textRef) {
const copyBtn = this.$refs.textRef.querySelectorAll('.code-block-header__copy')
copyBtn.forEach((btn) => {
btn.removeEventListener('click', () => {
})
btn.removeEventListener('click', () => {})
})
}
}
@@ -98,31 +97,24 @@ export default {
<style lang="scss" scoped>
.markdown-body {
font-size: 13px;
&::v-deep p {
&>>> p {
margin-bottom: 0 !important;
}
background: inherit;
&::v-deep pre {
&>>> pre {
padding: 0 0 6px 0;
.hljs.code-block-body {
border-radius: 4px;
}
}
&::v-deep .code-block-wrapper {
&>>> .code-block-wrapper {
background: #1F2329;
padding: 2px 6px;
margin: 5px 0;
.code-block-body {
padding: 5px 10px 0;
}
;
};
.code-block-header {
margin-bottom: 4px;
overflow: hidden;
@@ -132,13 +124,11 @@ export default {
.code-block-header__copy {
float: right;
cursor: pointer;
&:hover {
color: #6e747b;
}
}
}
.hljs.code-block-body.javascript {
.hljs-comment {
display: block;
@@ -146,20 +136,16 @@ export default {
}
}
}
::v-deep .link-style {
>>> .link-style {
color: #487bf4;
&:hover {
color: #275ee3;
}
}
.loading-box {
.loading-box{
margin-left: 6px;
}
.loading-box span {
.loading-box span{
display: inline-block;
width: 5px;
height: 5px;
@@ -169,29 +155,24 @@ export default {
background: #676A6c;
animation: load 1.2s ease infinite;
}
.loading-box span:last-child {
.loading-box span:last-child{
margin-right: 0;
}
@keyframes load {
0% {
@keyframes load{
0%{
opacity: 1;
}
100% {
100%{
opacity: 0;
}
}
.loading-box span:nth-child(1) {
.loading-box span:nth-child(1){
animation-delay: 0.23s;
}
.loading-box span:nth-child(2) {
.loading-box span:nth-child(2){
animation-delay: 0.36s;
}
.loading-box span:nth-child(3) {
.loading-box span:nth-child(3){
animation-delay: 0.49s;
}
</style>

View File

@@ -2,12 +2,7 @@
<div class="chat-content">
<div id="scrollRef" class="chat-list">
<div v-if="showIntroduction" class="introduction">
<div
v-for="(item, index) in introduction"
:key="index"
class="introduction-item"
@click="sendIntroduction(item)"
>
<div v-for="(item, index) in introduction" :key="index" class="introduction-item" @click="sendIntroduction(item)">
<div class="head">
<i v-if="item.icon" :class="item.icon" />
<span class="title">{{ item.title }}</span>
@@ -27,8 +22,8 @@
round
size="small"
@click="onStopHandle"
>{{ $tc('Stop') }}</el-button>
<ChatInput ref="chatInput" :expanded="expanded" @send="onSendHandle" @select-prompt="onSelectPromptHandle" />
>{{ $tc('common.Stop') }}</el-button>
<ChatInput ref="chatInput" @send="onSendHandle" @select-prompt="onSelectPromptHandle" />
</div>
</div>
</template>
@@ -57,18 +52,23 @@ export default {
ChatMessage
},
props: {
expanded: {
type: Boolean,
default: false
}
},
data() {
return {
socket: {},
prompt: '',
conversationId: '',
currentConversationId: '',
showIntroduction: false,
introduction: []
introduction: [
{
title: this.$t('common.introduction.ConceptTitle'),
content: this.$t('common.introduction.ConceptContent')
},
{
title: this.$t('common.introduction.IdeaTitle'),
content: this.$t('common.introduction.IdeaContent')
}
]
}
},
computed: {
@@ -86,23 +86,23 @@ export default {
this.initChatMessage()
},
initWebSocket() {
const { NODE_ENV, VUE_APP_KOKO_HOST } = process.env || {}
const api = '/koko/ws/chat/system/'
const { NODE_ENV, VUE_APP_KAEL_HOST } = process.env || {}
const api = '/kael/chat/system/'
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'
const path = `${protocol}://${window.location.host}${api}`
const index = VUE_APP_KOKO_HOST?.indexOf('://')
const localPath = protocol + VUE_APP_KOKO_HOST?.substring(index, VUE_APP_KOKO_HOST?.length) + api
const index = VUE_APP_KAEL_HOST?.indexOf('://')
const localPath = protocol + VUE_APP_KAEL_HOST?.substring(index, VUE_APP_KAEL_HOST?.length) + api
const url = NODE_ENV === 'development' ? localPath : path
createWebSocket(url, this.onWebSocketMessage)
},
initChatMessage() {
this.prompt = ''
this.showIntroduction = true
this.conversationId = ''
this.currentConversationId = ''
this.$refs.chatInput.select.value = ''
const chat = {
message: {
content: this.$t('ChatHello'),
content: this.$t('common.ChatHello'),
role: 'assistant',
create_time: new Date()
}
@@ -119,10 +119,10 @@ export default {
}
},
onChatMessage(data) {
if (data.id) {
if (data.conversation_id) {
setLoading(true)
removeLoadingMessageInChat()
this.conversationId = data.id
this.currentConversationId = data.conversation_id
updateChaMessageContentById(data.message.id, data)
}
if (data.message?.type === 'finish') {
@@ -132,18 +132,20 @@ export default {
},
onSystemMessage(data) {
data.message = {
content: data.data,
content: data.system_message,
role: 'assistant',
create_time: new Date()
}
removeLoadingMessageInChat()
addMessageToActiveChat(data)
this.socketReadyStateSuccess = false
setLoading(true)
},
onSendHandle(value) {
this.showIntroduction = false
this.socket = ws || {}
if (ws?.readyState === 1) {
this.socketReadyStateSuccess = true
const chat = {
message: {
content: value,
@@ -152,9 +154,9 @@ export default {
}
}
const message = {
data: value,
content: value,
prompt: this.prompt,
id: this.conversationId || ''
conversation_id: this.currentConversationId || ''
}
addChatMessageById(chat)
onSend(message)
@@ -162,19 +164,20 @@ export default {
} else {
const chat = {
message: {
content: this.$t('ConnectionDropped'),
content: this.$t('common.ConnectionDropped'),
role: 'assistant',
create_time: new Date()
},
type: 'error'
}
addChatMessageById(chat)
this.socketReadyStateSuccess = false
setLoading(true)
}
},
onSelectPromptHandle(value) {
this.prompt = value
this.conversationId = ''
this.currentConversationId = ''
this.showIntroduction = false
this.onSendHandle(value)
},
@@ -183,13 +186,13 @@ export default {
this.initChatMessage()
},
onStopHandle() {
const message = {
id: this.conversationId || '',
interrupt: true
}
onSend(message)
removeLoadingMessageInChat()
setLoading(false)
this.$axios.post(
'/kael/interrupt_current_ask/',
{ id: this.currentConversationId || '' }
).finally(() => {
removeLoadingMessageInChat()
setLoading(false)
})
},
sendIntroduction(item) {
this.showIntroduction = false
@@ -223,16 +226,13 @@ export default {
&:first-child {
margin-top: 0;
}
.head {
margin-bottom: 2px;
.title {
font-weight: 500;
color: #373739;
}
}
.content {
display: inline-block;
color: #a7a7ab;
@@ -240,35 +240,30 @@ export default {
}
}
}
.chat-list {
flex: 1;
position: relative;
padding: 0 15px 25px;
overflow-y: auto;
user-select: text;
&::-webkit-scrollbar {
width: 12px;
}
}
.input-box {
position: relative;
//height: 60px;
height: 160px;
padding: 0 15px;
margin-bottom: 15px;
//border-top: 1px solid #ececec;
border-top: 1px solid #ececec;
}
.stop {
position: absolute;
top: -37px;
left: 50%;
z-index: 11;
transform: translateX(-50%);
::v-deep i {
>>> i {
margin-right: 4px;
}
}

View File

@@ -1,14 +1,17 @@
<template>
<div class="container">
<div class="close-sidebar">
<i v-if="hasClose" class="el-icon-download" @click="onClose" />
</div>
<div v-if="!expanded" class="close-sidebar">
<i class="fa fa-expand" style="font-weight: 200" @click="$emit('expand')" />
</div>
<div v-if="expanded" class="close-sidebar">
<i class="fa fa-compress" style="font-weight: 200" @click="$emit('compress')" />
<i v-if="hasClose" class="el-icon-close" @click="onClose" />
</div>
<el-tabs v-model="active" :tab-position="'right'" @tab-click="handleClick">
<el-tab-pane v-for="(item) in submenu" :key="item.name" :name="item.name">
<span slot="label">
<el-tooltip effect="dark" placement="left" :content="item.label">
<svg-icon :icon-class="item.icon" />
</el-tooltip>
</span>
</el-tab-pane>
</el-tabs>
</div>
</template>
@@ -26,21 +29,18 @@ export default {
submenu: {
type: Array,
default: () => []
},
expanded: {
type: Boolean,
default: false
}
},
data() {
return {}
return {
}
},
methods: {
onClose() {
this.$emit('close')
handleClick(tab, event) {
this.$emit('tab-click', tab)
},
handleExpand() {
this.$emit('expand-full')
onClose() {
this.$parent.onClose()
}
}
}
@@ -51,23 +51,17 @@ export default {
width: 100%;
height: 100%;
background-color: #f0f1f5;
.close-sidebar {
height: 48px;
padding: 12px 0;
text-align: center;
font-size: 16px;
font-size: 14px;
cursor: pointer;
i {
font-size: 16px;
font-weight: 600;
padding: 4px;
}
i, .svg {
border-radius: 2px;
&:hover {
color: var(--color-primary);
background: var(--menu-hover);
@@ -75,16 +69,10 @@ export default {
}
}
}
.el-icon-download {
transform: rotate(-90deg)
}
::v-deep .el-tabs {
>>> .el-tabs {
.el-tabs__item {
padding: 0 10px;
font-size: 14px;
padding: 0 13px;
font-size: 15px;
:hover {
color: #7b8085;
}

View File

@@ -1,44 +1,26 @@
<template>
<DrawerPanel
ref="drawer"
:default-show-panel="!!defaultShowPanel"
:expanded="expanded"
:height="height"
:icon="robotUrl"
:modal="false"
@toggle="onToggle"
>
<div class="chat">
<div class="container">
<div ref="header" class="header" @mousedown="handleMoveMouseDown" @mouseup="handleMouseMoveUp">
<div class="left">
<img :src="robotUrl" alt="">
<span class="title">{{ title }}</span>
</div>
<span class="new" @click="onNewChat">
<i class="el-icon-plus" />
<span>{{ $tc('NewChat') }}</span>
</span>
</div>
<div class="content">
<keep-alive>
<component :is="active" ref="component" :expanded="expanded" />
</keep-alive>
<div class="chat">
<div class="container">
<div class="header">
<div class="left">
<img :src="robotUrl" alt="">
<span class="title">{{ title }}</span>
</div>
<span class="new" @click="onNewChat">
<i class="el-icon-plus" />
<span>{{ $tc('common.NewChat') }}</span>
</span>
</div>
<div class="sidebar">
<Sidebar
:active.sync="active"
:expanded="expanded"
v-bind="$attrs"
@close="onClose"
@compress="compress"
@expand="expandFull"
v-on="$listeners"
/>
<div class="content">
<keep-alive>
<component :is="active" ref="component" />
</keep-alive>
</div>
</div>
</DrawerPanel>
<div class="sidebar">
<Sidebar v-bind="$attrs" :active.sync="active" :submenu="submenu" />
</div>
</div>
</template>
<script>
@@ -46,11 +28,9 @@ import Sidebar from './components/Sidebar/index.vue'
import Chat from './components/ChitChat/index.vue'
import { getInputFocus } from './useChat.js'
import { ws } from '@/utils/socket'
import DrawerPanel from '@/components/Apps/DrawerPanel/index.vue'
export default {
components: {
DrawerPanel,
Chat,
Sidebar
},
@@ -58,13 +38,9 @@ export default {
title: {
type: String,
default: function() {
return this.$t('ChatAI')
return this.$t('setting.ChatAI')
}
},
defaultShowPanel: {
type: Boolean,
default: false
},
drawerPanelVisible: {
type: Boolean,
default: () => false
@@ -73,46 +49,29 @@ export default {
data() {
return {
active: 'chat',
robotUrl: require('@/assets/img/robot-assistant.png'),
height: '400px',
expanded: false,
clientOffset: {}
robotUrl: require('../../../assets/img/robot-assistant.png'),
submenu: [
{
name: 'chat',
label: this.$t('common.Chat'),
icon: 'chat'
}
]
}
},
watch: {
},
mounted() {
this.handlePostMessage()
drawerPanelVisible(value) {
if (value && !ws) {
this.initWebSocket()
}
}
},
methods: {
handlePostMessage() {
window.addEventListener('message', (event) => {
if (event.data === 'show-chat-panel') {
this.$refs.drawer.show = true
}
})
},
handleMoveMouseDown(event) {
this.$refs.drawer.handleHeaderMoveDown(event)
},
handleMouseMoveUp(event) {
this.$refs.drawer.handleHeaderMoveUp(event)
},
initWebSocket() {
if (!ws) {
this.$refs.component?.init()
}
this.$refs.component?.init()
},
onClose() {
this.$refs.drawer.show = false
},
expandFull() {
this.height = '100%'
this.expanded = true
},
compress() {
this.height = '400px'
this.expanded = false
this.$parent.show = false
},
onNewChat() {
this.active = 'chat'
@@ -120,12 +79,6 @@ export default {
this.$refs.component?.onNewChat()
getInputFocus()
})
},
onToggle(status) {
this.initWebSocket()
if (status) {
getInputFocus()
}
}
}
}
@@ -136,16 +89,12 @@ export default {
display: flex;
width: 100%;
height: 100%;
pointer-events: auto;
.container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.header {
background: linear-gradient(90deg, #ebf1ff 24.34%, #e5fbf8 56.18%, #f2ebfe 90.18%);;
display: flex;
justify-content: space-between;
height: 48px;

View File

@@ -1,8 +1,8 @@
<template>
<div ref="drawer" :class="{show: show}" class="drawer">
<div v-if="modal" :style="{'background-color': modal ? 'rgba(0, 0, 0, .3)' : 'transparent'}" class="modal" />
<div ref="panel" :style="{width: width, height: height }" class="drawer-panel">
<div v-show="!show && !defaultShowPanel" ref="dragBox" class="handle-button">
<div :style="{'background-color': modal ? 'rgba(0, 0, 0, .3)' : 'transparent'}" class="modal" />
<div :style="{'width': width}" class="drawer-panel">
<div v-show="!show" ref="dragBox" class="handle-button">
<i v-if="icon.startsWith('fa') || icon.startsWith('el')" :class="show ? 'el-icon-close': icon" />
<img v-else :src="icon" alt="">
</div>
@@ -12,6 +12,7 @@
</div>
</div>
</template>
<script>
export default {
@@ -25,10 +26,6 @@ export default {
type: String,
default: '440px'
},
height: {
type: String,
default: '400px'
},
modal: {
type: Boolean,
default: true
@@ -36,20 +33,11 @@ export default {
clickNotClose: {
type: Boolean,
default: false
},
expanded: {
type: Boolean,
default: false
},
defaultShowPanel: {
type: Boolean,
default: false
}
},
data() {
return {
show: this.defaultShowPanel,
clientOffset: {}
show: false
}
},
watch: {
@@ -57,17 +45,7 @@ export default {
if (value && !this.clickNotClose) {
this.addEventClick()
}
const event = value ? 'show-chat-panel' : 'close-chat-panel'
window.parent.postMessage(event, '*')
this.$emit('toggle', this.show)
},
expanded(value) {
if (value) {
this.$refs.panel.style.top = '0px'
} else {
this.$refs.panel.style.top = 'auto'
this.$refs.panel.style.bottom = '2px'
}
}
},
mounted() {
@@ -77,65 +55,49 @@ export default {
beforeDestroy() {
const element = this.$refs.drawer
element.remove()
// window.removeEventListener('click', this.closeSidebar)
window.removeEventListener('click', this.closeSidebar)
},
methods: {
handleHeaderMoveUp(event) {
this.handleMouseMoveUp(event)
},
handleHeaderMoveDown(event) {
this.handleMoveMouseDown(event, true)
},
handleMoveMouseDown(event, isHeader = false) {
const dragBox = this.$refs.dragBox
const vm = this
const rect = dragBox.getBoundingClientRect()
const parentRect = dragBox.parentElement.getBoundingClientRect()
const clientOffset = this.clientOffset
clientOffset.clientX = event.clientX
clientOffset.clientY = event.clientY
const handleOnMouseMove = _.debounce(function(event) {
const diffY = rect.top - parentRect.top
const maxY = window.innerHeight - parentRect.height
let parentY = event.clientY - diffY
// 这个是拖动的 header, 不是 bar
if (isHeader) {
parentY = event.clientY - rect.height / 2
}
if (parentY < 0) {
parentY = 0
} else if (parentY > maxY) {
parentY = maxY
}
if (vm.$refs.panel) {
vm.$refs.panel.style.top = parentY + 'px'
}
})
document.onmousemove = handleOnMouseMove
document.onmouseup = function() {
document.removeEventListener('mousemove', handleOnMouseMove)
setTimeout(() => {
document.onmousemove = null
document.onmouseup = null
}, 0)
}
},
handleMouseMoveUp(event) {
const clientOffset = this.clientOffset
const clientX = event.clientX
const clientY = event.clientY
if (this.isDifferenceWithinThreshold(clientX, clientOffset.clientX) &&
this.isDifferenceWithinThreshold(clientY, clientOffset.clientY)) {
this.show = !this.show
}
},
init() {
this.$nextTick(() => {
const dragBox = this.$refs.dragBox
dragBox.addEventListener('mousedown', this.handleMoveMouseDown, false)
dragBox.addEventListener('mouseup', this.handleMouseMoveUp, false)
const clientOffset = {}
dragBox.addEventListener('mousedown', (event) => {
const offsetX = dragBox.getBoundingClientRect().left
const offsetY = dragBox.getBoundingClientRect().top
const innerX = event.clientX - offsetX
const innerY = event.clientY - offsetY
clientOffset.clientX = event.clientX
clientOffset.clientY = event.clientY
document.onmousemove = function(event) {
dragBox.style.left = event.clientX - innerX + 'px'
dragBox.style.top = event.clientY - innerY + 'px'
const dragDivTop = window.innerHeight - dragBox.getBoundingClientRect().height
const dragDivLeft = window.innerWidth - dragBox.getBoundingClientRect().width
dragBox.style.left = dragDivLeft + 'px'
dragBox.style.left = '-48px'
if (dragBox.getBoundingClientRect().top <= 0) {
dragBox.style.top = '0px'
}
if (dragBox.getBoundingClientRect().top >= dragDivTop) {
dragBox.style.top = dragDivTop + 'px'
}
event.preventDefault()
event.stopPropagation()
}
document.onmouseup = function() {
document.onmousemove = null
document.onmouseup = null
}
}, false)
dragBox.addEventListener('mouseup', (event) => {
const clientX = event.clientX
const clientY = event.clientY
if (this.isDifferenceWithinThreshold(clientX, clientOffset.clientX) && this.isDifferenceWithinThreshold(clientY, clientOffset.clientY)) {
this.show = !this.show
}
})
})
},
isDifferenceWithinThreshold(num1, num2, threshold = 5) {
@@ -143,6 +105,13 @@ export default {
return difference <= threshold
},
addEventClick() {
window.addEventListener('click', this.closeSidebar)
},
closeSidebar(evt) {
const parent = evt.target.closest('.drawer-panel')
if (!parent && evt.target.className === 'modal') {
this.show = false
}
},
insertToBody() {
const element = this.$refs.drawer
@@ -166,10 +135,11 @@ export default {
.drawer-panel {
position: fixed;
bottom: 1px;
right: -1px;
top: 0;
right: 0;
width: 100%;
min-width: 260px;
height: 100vh;
user-select: none;
transition: transform .25s cubic-bezier(.7, .3, .1, 1);
box-shadow: 0 0 8px 4px #00000014;
@@ -217,26 +187,23 @@ export default {
pointer-events: auto;
color: #fff;
background-color: #FFFFFF;
opacity: 0.9;
box-shadow: 0 0 8px 4px #00000014;
cursor: pointer;
&:hover {
left: -51px !important;
left: -50px !important;
width: 50px !important;
transform: scale(1.01);
transform: scale(1.06);
}
i {
font-size: 20px;
line-height: 45px;
pointer-events: none;
}
img {
width: 22px;
height: 22px;
transform: translateY(10%);
margin-left: 3px;
pointer-events: none;
}
}
</style>

View File

@@ -4,18 +4,18 @@
:destroy-on-close="true"
:show-cancel="false"
:show-confirm="false"
:title="$tc('TestGatewayTestConnection')"
:title="$tc('assets.TestGatewayTestConnection')"
:visible.sync="iVisible"
top="35vh"
width="40%"
>
<el-row :gutter="20">
<el-col :md="4" :sm="24">
<div style="line-height: 34px">{{ $t('SSHPort') }}</div>
<div style="line-height: 34px">{{ $t('assets.SSHPort') }}</div>
</el-col>
<el-col :md="14" :sm="24">
<el-input v-model="port" />
<span class="help-tips help-block">{{ $t('TestGatewayHelpMessage') }}</span>
<span class="help-tips help-block">{{ $t('assets.TestGatewayHelpMessage') }}</span>
</el-col>
<el-col :md="4" :sm="24">
<el-button
@@ -25,7 +25,7 @@
type="primary"
@click="dialogConfirm"
>
{{ this.$t('Confirm') }}
{{ this.$t('common.Confirm') }}
</el-button>
</el-col>
</el-row>
@@ -75,7 +75,7 @@ export default {
methods: {
dialogConfirm() {
if (isNaN(this.port)) {
return this.$message.error(this.$tc('TestPortErrorMsg'))
return this.$message.error(this.$tc('common.TestPortErrorMsg'))
}
this.$axios.post(
`/api/v1/assets/gateways/${this.cell}/test-connective/`,

View File

@@ -1,21 +1,17 @@
<template>
<AssetTreeTable
ref="AssetTreeTable"
:header-actions="headerActions"
:table-config="tableConfig"
:tree-setting="treeSetting"
/>
<TreeTable :header-actions="headerActions" :table-config="tableConfig" :tree-setting="treeSetting" />
</template>
<script type="text/jsx">
import AssetTreeTable from '@/components/Apps/AssetTreeTable'
import { AccountInfoFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
import TreeTable from '../../Table/TreeTable/index.vue'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import { AccountInfoFormatter } from '@/components/Table/TableFormatters'
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
export default {
name: 'GrantedAssets',
components: {
AssetTreeTable
TreeTable
},
props: {
treeUrl: {
@@ -38,29 +34,11 @@ export default {
vm.tableConfig.url = url
}
},
actions: {
type: Object,
default: null
},
getShowUrl: {
type: Function,
default({ row, col }) {
return this.tableUrl.replace('/assets/', `/assets/${row.id}/accounts/`)
}
},
name: {
type: Object,
default: () => ({
formatter: DetailFormatter,
formatterArgs: {
route: 'AssetDetail',
can: true
}
})
},
comment: {
type: Object,
default: () => ({})
}
},
data() {
@@ -70,11 +48,9 @@ export default {
showMenu: false,
showRefresh: true,
showAssets: false,
showSearch: false,
url: this.tableUrl,
// ?assets=0不显示资产. =1显示资产
treeUrl: this.treeUrl,
notShowBuiltinTree: true,
callback: {
onSelected: (event, node) => vm.onSelected(node, vm),
refresh: vm.refreshObjectAssetPermission
@@ -87,32 +63,24 @@ export default {
columnsExclude: ['spec_info'],
columnsShow: {
min: ['name', 'address', 'accounts'],
default: ['name', 'address', 'platform', 'connectivity', 'view_account', 'actions']
default: ['name', 'address', 'platform', 'view_account', 'connectivity']
},
columnsMeta: {
name: {
...this.name
},
labels: {
formatter: DetailFormatter,
formatterArgs: {
showEditBtn: false
route: 'AssetDetail'
}
},
actions: {
...this.actions
has: false
},
view_account: {
label: this.$t('Accounts'),
label: this.$t('assets.Account'),
formatter: AccountInfoFormatter,
width: '100px'
},
connectivity: connectivityMeta,
comment: { ...this.comment }
},
tableAttrs: {
rowClassName({ row }) {
return !row.is_active ? 'row_disabled' : ''
}
connectivity: connectivityMeta
}
},
headerActions: {
@@ -135,8 +103,4 @@ export default {
</script>
<style scoped>
.row_disabled, .row_disabled:hover, .row_disabled:hover > td {
cursor: not-allowed;
background-color: rgba(192, 196, 204, 0.28) !important;
}
</style>

View File

@@ -37,7 +37,7 @@ export default {
],
columnsMeta: {
name: {
label: this.$t('Asset'),
label: this.$t('assets.Asset'),
formatter: (row) => {
const to = {
name: 'AssetDetail',

View File

@@ -18,8 +18,7 @@ export default {
props: {
object: {
type: Object,
default: () => {
}
default: () => {}
}
},
data() {
@@ -39,8 +38,7 @@ export default {
],
columnsMeta: {
name: {
label: this.$t('Name'),
width: 85,
label: this.$t('common.Name'),
formatter: (row) => {
const to = {
name: 'UserDetail',
@@ -54,7 +52,7 @@ export default {
}
},
system_roles: {
label: this.$t('SystemRoles'),
label: this.$t('users.SystemRoles'),
formatter: (row) => {
return row['system_roles'].map(item => item['display_name']).join(', ') || '-'
},
@@ -62,7 +60,7 @@ export default {
columnKey: 'system_roles'
},
org_roles: {
label: this.$t('OrgRoles'),
label: this.$t('users.OrgRoles'),
formatter: (row) => {
return row['org_roles'].map(item => item['display_name']).join(', ') || '-'
},

View File

@@ -1,7 +1,7 @@
<template>
<div>
<el-row :gutter="20">
<el-col :md="16" :sm="24">
<el-col :md="12" :sm="24">
<IBox :title="title" class="block" v-bind="$attrs">
<el-timeline>
<el-timeline-item
@@ -18,14 +18,14 @@
type="primary"
@click.native="onClick(activity)"
>
{{ $tc('Detail') }}
{{ $tc('common.Detail') }}
</el-link>
</el-timeline-item>
</el-timeline>
</IBox>
</el-col>
</el-row>
<DiffDetail ref="DetailDialog" :title="$tc('OperateLog')" />
<DiffDetail ref="DetailDialog" :title="$tc('route.OperateLog')" />
</div>
</template>
@@ -33,7 +33,6 @@
import IBox from '@/components/IBox/index.vue'
import DiffDetail from '@/components/Dialog/DiffDetail.vue'
import { openTaskPage } from '@/utils/jms'
import { toSafeLocalDateStr } from '@/utils/time'
export default {
name: 'ResourceActivity',
@@ -50,11 +49,11 @@ export default {
data() {
return {
activityUrl: `/api/v1/audits/activities/?resource_id=${this.object.id}`,
title: `${this.$t('Last30')}`,
title: `${this.$t('common.Activity')} - ${this.$t('common.Last30')}`,
activities: [
{
content: this.$t('Now'),
timestamp: toSafeLocalDateStr(this.$moment()),
content: this.$t('common.Now'),
timestamp: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
type: 'primary'
}
]
@@ -66,11 +65,9 @@ export default {
methods: {
getActivities() {
this.$axios.get(this.activityUrl).then(res => {
const activities = res || []
activities.forEach(activity => {
activity.timestamp = toSafeLocalDateStr(activity.timestamp)
this.activities.push(activity)
})
for (const i in res) {
this.activities.push(res[i])
}
})
},
onClick(activity) {

View File

@@ -16,7 +16,7 @@
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24">
<el-alert
:title="$tc('ReLoginTitle')"
:title="$tc('auth.ReLoginTitle')"
center
style="margin-bottom: 20px;"
type="error"
@@ -26,7 +26,7 @@
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24">
<el-button class="confirm-btn" size="mini" type="primary" @click="logout">
{{ this.$t('ReLogin') }}
{{ this.$t('auth.ReLogin') }}
</el-button>
</el-col>
</el-row>
@@ -50,7 +50,7 @@
</el-col>
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24" style="display: flex; align-items: center; margin-bottom: 20px;">
<el-col :md="24" :sm="24" style="display: flex; margin-bottom: 20px;">
<el-input
v-model="secretValue"
:placeholder="inputPlaceholder"
@@ -61,7 +61,7 @@
<el-button
:disabled="smsBtnDisabled"
size="mini"
style="line-height: 14px; float: right;"
style="line-height:20px; float: right;"
type="primary"
@click="sendSMSCode"
>
@@ -73,7 +73,7 @@
<el-row :gutter="24" style="margin: 10px auto;">
<el-col :md="24" :sm="24">
<el-button class="confirm-btn" size="mini" type="primary" @click="handleConfirm">
{{ this.$t('Confirm') }}
{{ this.$t('common.Confirm') }}
</el-button>
</el-col>
</el-row>
@@ -101,11 +101,11 @@ export default {
},
data() {
return {
title: this.$t('CurrentUserVerify'),
title: this.$t('common.CurrentUserVerify'),
smsWidth: 0,
subTypeSelected: '',
inputPlaceholder: '',
smsBtnText: this.$t('SendVerificationCode'),
smsBtnText: this.$t('common.SendVerificationCode'),
smsBtnDisabled: false,
confirmTypeRequired: '',
subTypeChoices: [],
@@ -132,7 +132,7 @@ export default {
this.inputPlaceholder = this.subTypeChoices.filter(item => item.name === val)[0]?.placeholder
this.smsWidth = val === 'sms' ? 6 : 0
},
performConfirm: _.debounce(function({ response, callback, cancel }) {
performConfirm: _.throttle(function({ response, callback, cancel }) {
if (this.processing || this.visible) {
return
}
@@ -150,7 +150,7 @@ export default {
this.callback()
this.visible = false
}).catch(() => {
this.title = this.$t('NeedReLogin')
this.title = this.$t('auth.NeedReLogin')
this.visible = true
})
return
@@ -162,34 +162,32 @@ export default {
this.visible = true
}).catch((err) => {
const data = err.response?.data
const msg = data?.error || data?.detail || data?.msg || this.$t('GetConfirmTypeFailed')
const msg = data?.error || data?.detail || data?.msg || this.$t('common.GetConfirmTypeFailed')
this.$message.error(msg)
this.cancel(err)
}).finally(() => {
this.processing = false
})
}, 500),
}, 300),
logout() {
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
},
sendSMSCode() {
this.$axios.post(`/api/v1/authentication/mfa/select/`, { type: 'sms' }).then(res => {
this.$message.success(this.$tc('VerificationCodeSent'))
this.$message.success(this.$tc('common.VerificationCodeSent'))
let time = 60
this.smsBtnDisabled = true
const interval = setInterval(() => {
const originText = this.smsBtnText
this.smsBtnText = this.$t('common.Pending') + `: ${time}`
this.smsBtnDisabled = true
time -= 1
this.smsBtnText = `${this.$t('Pending')}: ${time}`
if (time <= 0) {
clearInterval(interval)
this.smsBtnText = this.$t('SendVerificationCode')
if (time === 0) {
this.smsBtnText = originText
this.smsBtnDisabled = false
clearInterval(interval)
}
}, 1000)
}).catch(() => {
this.$message.error(this.$tc('FailedToSendVerificationCode'))
})
},
handleConfirm() {
@@ -197,23 +195,17 @@ export default {
return this.logout()
}
if (this.subTypeSelected === 'otp' && this.secretValue.length !== 6) {
return this.$message.error(this.$tc('MFAErrorMsg'))
return this.$message.error(this.$tc('common.MFAErrorMsg'))
}
const data = {
confirm_type: this.confirmTypeRequired,
mfa_type: this.confirmTypeRequired === 'mfa' ? this.subTypeSelected : '',
secret_key: this.confirmTypeRequired === 'password' ? encryptPassword(this.secretValue) : this.secretValue
}
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(() => {
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(res => {
this.callback()
this.secretValue = ''
this.visible = false
this.$nextTick(() => {
this.callback()
})
}).catch((err) => {
this.$message.error(err.message || this.$tc('ConfirmFailed'))
})
}
}
@@ -221,11 +213,11 @@ export default {
</script>
<style lang="scss" scoped>
.dialog-content ::v-deep .el-dialog__footer {
.dialog-content >>> .el-dialog__footer {
padding: 0;
}
.dialog-content ::v-deep .el-dialog {
.dialog-content >>> .el-dialog {
padding: 8px;
.el-dialog__body {
@@ -238,4 +230,5 @@ export default {
width: 100%;
line-height: 20px;
}
</style>

View File

@@ -1,5 +1,5 @@
<script type="text/jsx">
import { toSafeLocalDateStr } from '@/utils/time'
import { toSafeLocalDateStr } from '@/utils/common'
export default {
name: 'ItemValue',
@@ -47,9 +47,9 @@ export default {
methods: {
toChoicesDisplay(value) {
if (!value) {
return this.$t('No')
return this.$t('common.No')
}
return this.$t('Yes')
return this.$t('common.Yes')
},
isDatetime(value) {
if (typeof value !== 'string') {
@@ -78,7 +78,7 @@ export default {
formatterData = data
}
return (
<span style={{ whiteSpace: 'pre-wrap', lineHeight: '1.2' }}>{formatterData}</span>
<span style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', lineHeight: '1.2' }}>{formatterData}</span>
)
}
if (this.value instanceof Array) {
@@ -92,7 +92,7 @@ export default {
)
}
return (
<span title={this.displayValue}>{this.displayValue}</span>
<span>{this.displayValue}</span>
)
}
}

View File

@@ -1,20 +1,14 @@
<template>
<IBox v-if="loading" style="width: 100%; height: 200px" />
<div v-else>
<DetailCard v-if="hasObject && items.length > 0" :items="validItems" :loading="loading" v-bind="$attrs" />
</div>
<DetailCard v-if="!loading && hasObject && items.length > 0" :items="items" v-bind="$attrs" />
</template>
<script>
import DetailCard from './index.vue'
import { copy } from '@/utils/common'
import { toSafeLocalDateStr } from '@/utils/time'
import IBox from '@/components/IBox/index.vue'
import LabelsDetailFormatter from '../Formatters/LabelsDetailFormatter.vue'
import { copy, toSafeLocalDateStr } from '@/utils/common'
export default {
name: 'AutoDetailCard',
components: { IBox, DetailCard },
components: { DetailCard },
props: {
object: {
type: Object,
@@ -61,9 +55,6 @@ export default {
},
hasObject() {
return Object.keys(this.iObject).length > 0
},
validItems() {
return this.items.filter(item => this.isHidden(item))
}
},
async mounted() {
@@ -78,92 +69,13 @@ export default {
if (val === '-') {
return <span>{'-'}</span>
}
return (
<span style={{ cursor: 'pointer' }} onClick={() => copy(val)} title={val}>
{val}
</span>
)
return (<span style={{ cursor: 'pointer' }} onClick={() => copy(val)}>
{val}
</span>)
}
}
return formatter
},
isHidden(item) {
let has = item.has
if (typeof has === 'function') {
has = has()
}
if (has === undefined) {
has = true
}
return has
},
parseValue(value, tp) {
if (value === null || value === '') {
value = '-'
} else if (value === 0) {
value = 0
} else if (tp === 'datetime') {
value = toSafeLocalDateStr(value)
} else if (tp === 'labeled_choice') {
value = value?.['label']
} else if (tp === 'related_field' || tp === 'nested object' || value?.name) {
value = value?.['name']
} else if (tp === 'm2m_related_field') {
value = value?.map(item => item['name']).join(', ')
} else if (tp === 'boolean') {
value = value ? this.$t('Yes') : this.$t('No')
}
return value
},
getComponentByName(name) {
if (name === 'labels') {
return LabelsDetailFormatter
}
return null
},
parseArrayValue(value, excludes, label) {
if (Array.isArray(value)) {
const tp = typeof value[0]
for (const [index, item] of value.entries()) {
let object = {}
if (tp === 'object') {
const firstValue = value[0]
if (firstValue.hasOwnProperty('name')) {
value.forEach(item => {
const fieldName = `${name}.${item.name}`
if (excludes.includes(fieldName)) {
return
}
object = {
key: item.label,
value: item.value
}
})
} else {
const fieldName = `${name}.${item.name}`
if (excludes.includes(fieldName)) {
continue
}
object = {
key: item.label,
value: item.value
}
}
} else if (tp === 'string') {
object = {
value: value[index]
}
if (index === 0) {
object['key'] = label
}
}
if (index !== value.length - 1) {
object['class'] = 'array-item'
}
this.items.push(object)
}
}
},
async optionAndGenFields() {
const data = await this.$store.dispatch('common/getUrlMeta', { url: this.url })
let remoteMeta = data.actions['GET'] || {}
@@ -176,7 +88,6 @@ export default {
const excludes = (this.excludes || []).concat(defaultExcludes)
fields = fields.filter(item => !excludes.includes(item))
const defaultFormatter = this.defaultFormatter(fields)
for (const name of fields) {
if (typeof name === 'object') {
this.items.push(name)
@@ -193,31 +104,61 @@ export default {
let value = this.iObject[name]
const label = fieldMeta.label
const component = this.getComponentByName(name)
if (component) {
this.items.push({
key: label,
value: value,
component: component
})
continue
}
const formatter = this.formatters[name]
if (formatter) {
this.items.push({
key: label,
value: value,
formatter: formatter
})
continue
}
if (Array.isArray(value)) {
this.parseArrayValue(value, excludes, label)
if (typeof value[0] === 'object') {
const firstValue = value[0]
if (firstValue.hasOwnProperty('name')) {
value.forEach(item => {
const fieldName = `${name}.${item.name}`
if (excludes.includes(fieldName)) {
return
}
this.items.push({
key: item.label,
value: item.value
})
})
} else {
value.forEach((item, index) => {
const v = Object.entries(item).map(([key, value]) => `${key}:${value}`).join(', ')
const data = { value: v }
if (index === 0) {
data['key'] = label
}
this.items.push(data)
})
}
} else if (typeof value[0] === 'string') {
value.forEach((item, index) => {
let data = {}
if (index === 0) {
data = {
key: label,
value: value[index]
}
} else {
data = {
value: value[index]
}
}
this.items.push(data)
})
}
continue
}
value = this.parseValue(value, fieldMeta.type)
if (value === null || value === '') {
value = '-'
} else if (fieldMeta.type === 'datetime') {
value = toSafeLocalDateStr(value)
} else if (fieldMeta.type === 'labeled_choice') {
value = value?.['label']
} else if (fieldMeta.type === 'related_field' || fieldMeta.type === 'nested object') {
value = value?.['name']
} else if (fieldMeta.type === 'm2m_related_field') {
value = value?.map(item => item['name']).join(', ')
} else if (fieldMeta.type === 'boolean') {
value = value ? this.$t('common.Yes') : this.$t('common.No')
}
if (value === undefined) {
if (this.showUndefine) {
@@ -230,7 +171,7 @@ export default {
const item = {
key: label,
value: value,
formatter: defaultFormatter[name]
formatter: this.formatters[name] || defaultFormatter[name]
}
this.items.push(item)
}

View File

@@ -1,17 +1,9 @@
<template>
<IBox :fa="fa" :title="title">
<el-form :label-width="labelWidth" class="content" label-position="left">
<span v-for="item in items" :key="item.key">
<el-form-item v-if="item.has !== false" :class="item.class" :label="item.key">
<span slot="label"> {{ formateLabel(item.key) }}</span>
<span
:is="item.component"
v-if="item.component"
v-bind="{...item}"
/>
<ItemValue v-else :value="item.value" class="item-value" v-bind="item" />
</el-form-item>
</span>
<el-form class="content" label-position="left" label-width="25%">
<el-form-item v-for="item in iItems" :key="item.key" :label="item.key">
<ItemValue :value="item.value" class="item-value" v-bind="item" />
</el-form-item>
</el-form>
<slot />
</IBox>
@@ -28,12 +20,12 @@ export default {
title: {
type: String,
default() {
return this.$t('BasicInfo')
return this.$t('common.BasicInfo')
}
},
fa: {
type: String,
default: 'fa-info-circle-o'
default: 'fa-info-circle'
},
items: {
type: Array,
@@ -42,10 +34,6 @@ export default {
align: {
type: String,
default: 'left'
},
labelWidth: {
type: String,
default: '25%'
}
},
data() {
@@ -54,72 +42,48 @@ export default {
return !item.hasOwnProperty('has') || item.has === true
})
}
},
methods: {
formateLabel(label) {
if (!label) {
return label
}
return label.replace(' amount', '').replace('数量', '')
}
}
}
</script>
<style lang="scss" scoped>
.el-card__body {
padding: 20px 40px;
}
.el-form-item {
border-bottom: 1px dashed #EBEEF5;
padding: 1px 0;
margin-bottom: 0;
&:last-child {
border-bottom: none;
.el-card__body {
padding: 20px 40px;
}
&.array-item {
border-bottom: none;
.el-form-item {
border-bottom: 1px dashed #EBEEF5;
padding: 1px 0;
margin-bottom: 0;
::v-deep .el-form-item__content {
border-bottom: 1px dashed #EBEEF5
&:last-child {
border-bottom: none;
}
::v-deep .el-form-item__label:last-child {
border: 1px dashed #EBEEF5;
&:hover {
}
>>> .el-form-item__label {
padding-right: 8%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
>>> .el-form-item__content {
font-size: 13px;
}
>>> .el-tag--mini {
margin-right: 3px;
}
}
::v-deep .el-form-item__label {
padding-right: 8%;
overflow: hidden;
color: var(--color-icon-primary);
span {
display: inline-block;
line-height: 1.5;
}
.item-value span {
word-break: break-word;
}
::v-deep .el-form-item__content {
color: var(--color-text-primary);
.content {
font-size: 13px;
line-height: 40px;
line-height: 2.5;
}
::v-deep .el-tag--mini {
margin-right: 3px;
}
}
.item-value span {
word-break: break-word;
}
.content {
font-size: 13px;
line-height: 2.5;
}
</style>

View File

@@ -1,32 +0,0 @@
<template>
<div>
<ILabel
v-for="item in value"
:key="item.key"
:label="item"
/>
</div>
</template>
<script>
import ILabel from '@/components/Widgets/ILabel/index.vue'
export default {
name: 'LabelsDetailFormatter',
components: { ILabel },
props: {
label: {
type: String,
default: ''
},
value: {
type: Array,
default: () => []
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,29 +1,23 @@
<template>
<IBox :title="title" :type="type" class="the-box" v-bind="$attrs">
<IBox :title="title" :type="type" v-bind="$attrs">
<table class="CardTable" style="width: 100%;table-layout:fixed;">
<tr>
<td colspan="2">
<Select2 ref="select2" v-model="select2.value" :disabled="iDisabled" show-select-all v-bind="select2" />
<Select2 ref="select2" v-model="select2.value" :disabled="iDisabled" v-bind="select2" />
</td>
</tr>
<slot />
<tr>
<td colspan="2">
<el-button :disabled="iDisabled" :loading="submitLoading" :type="type" size="small" @click="addObjects">
{{ $t('Add') }}
{{ $t('common.Add') }}
</el-button>
</td>
</tr>
<template v-if="showHasObjects">
<tr v-for="obj of iHasObjects" :key="obj.value" class="item">
<td style="width: 100%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
<el-tooltip
:content="obj.label.toString()"
:open-delay="500"
effect="dark"
placement="left"
style="margin: 4px;"
>
<el-tooltip :content="obj.label" effect="dark" placement="left" style="margin: 4px;">
<b>{{ obj.label }}</b>
</el-tooltip>
</td>
@@ -38,7 +32,7 @@
<td colspan="2">
<el-button :disabled="iDisabled" :type="type" size="small" style="width: 100%" @click="loadMore">
<i class="fa fa-arrow-down" />
{{ $t('More') }}
{{ $t('common.More') }}
</el-button>
</td>
</tr>
@@ -47,9 +41,9 @@
</template>
<script>
import Select2 from '@/components/Form/FormFields/Select2.vue'
import IBox from '../../IBox/index.vue'
import { createSourceIdCache } from '@/api/common'
import { Select2 } from '@/components/Form/FormFields'
import IBox from '@/components/IBox/index.vue'
import { mapGetters } from 'vuex'
export default {
@@ -107,33 +101,25 @@ export default {
},
performDelete: {
type: Function,
default: (obj, that) => {
}
default: (obj, that) => {}
},
allowCreate: {
type: Boolean,
default: false
},
select2Config: {
type: Object,
default: () => {
}
},
onDeleteSuccess: {
type: Function,
default(obj, that) {
// 从 hasObjects 中移除这个object
// 从hasObjects中移除这个object
const theRemoveIndex = that.iHasObjects.findIndex((v) => v.value === obj.value)
that.iHasObjects.splice(theRemoveIndex, 1)
// 从 disabled values 中移除这个 value
// 从disabled values中移除这个value
while (that.select2.disabledValues.indexOf(obj.value) !== -1) {
const i = that.select2.disabledValues.indexOf(obj.value)
that.$log.debug('disabled values remove index: ', i)
this.$log.debug('disabled values remove index: ', i)
that.select2.disabledValues.splice(i, 1)
}
that.$message.success(that.$t('RemoveSuccessMsg'))
that.$message.success(that.$t('common.RemoveSuccessMsg'))
}
},
onDeleteFail: {
@@ -154,23 +140,15 @@ export default {
},
performAdd: {
type: Function,
default: (objects, that) => {
}
},
showAddAll: {
type: Boolean,
default: false
default: (objects, that) => {}
},
onAddSuccess: {
type: Function,
default(objects, that) {
that.$log.debug('Select value', that.select2.value)
const oldValues = that.iHasObjects.map(item => item.value)
that.iHasObjects = [...that.iHasObjects, ...objects.filter(item => !oldValues.includes(item.value))]
that.iHasObjects = [...that.iHasObjects, ...objects]
that.$refs.select2.clearSelected()
that.$message.success(that.$t('AddSuccessMsg'))
this.$refs.select2.refresh()
this.$emit('addSuccess')
that.$message.success(that.$t('common.AddSuccessMsg'))
}
},
getHasObjects: {
@@ -183,7 +161,6 @@ export default {
iHasObjects: this.hasObjects || [],
totalHasObjectsLength: 0,
submitLoading: false,
selectAllDisabled: false,
params: {
page: 1,
hasMore: false,
@@ -195,8 +172,7 @@ export default {
value: this.value,
disabled: this.disabled,
disabledValues: [],
allowCreate: this.allowCreate,
...this.select2Config
allowCreate: this.allowCreate
}
}
},
@@ -277,13 +253,11 @@ export default {
}
})
data = this.iAjax.processResults.bind(this)(data)
if (data.results) {
data.results.forEach((v) => {
if (!this.iHasObjects.find((item) => item.value === v.value)) {
this.iHasObjects.push(v)
}
})
}
data.results && data.results.forEach((v) => {
if (!this.hasObjects.find((item) => item.value === v.value)) {
this.iHasObjects.push(v)
}
})
// 如果还有其它页,继续获取, 如果没有就停止
this.params.hasMore = !!data.pagination
this.totalHasObjectsLength = data.total
@@ -293,7 +267,6 @@ export default {
return
}
this.select2.disabledValues = this.hasObjectsId
if (this.getHasObjects) {
this.getHasObjects(this.hasObjectsId).then((data) => {
this.iHasObjects = data
@@ -305,9 +278,9 @@ export default {
}
},
removeObject(obj) {
this.performDelete(obj, this).then(() => {
this.onDeleteSuccess(obj, this)
}).catch(error => {
this.performDelete(obj, this).then(
() => this.onDeleteSuccess(obj, this)
).catch(error => {
this.onDeleteFail(error, this)
})
},
@@ -317,43 +290,29 @@ export default {
return
}
this.performAdd(objects, this).then(
() => {
this.onAddSuccess(objects, this)
}
() => this.onAddSuccess(objects, this)
)
},
async selectAll() {
this.selectAllDisabled = true
this.disabled = true
await this.$refs.select2.selectAll()
this.selectAllDisabled = false
this.disabled = false
}
}
}
</script>
<style lang='scss' scoped>
b, strong {
font-weight: 700;
font-size: 13px;
}
<style scoped>
b, strong {
font-weight: 700;
font-size: 13px;
}
tr td {
line-height: 1.42857;
padding: 8px;
vertical-align: top;
}
tr td {
line-height: 1.42857;
padding: 8px;
vertical-align: top;
}
tr.item td {
border-top: 1px solid #e7eaec;
}
.box-margin {
margin-bottom: 20px;
}
.the-box ::v-deep .el-card__body {
padding: 20px;
}
tr.item td {
border-top: 1px solid #e7eaec;
}
.box-margin {
margin-bottom: 20px;
}
</style>

View File

@@ -46,7 +46,7 @@ export default {
font-weight: 600;
}
.right-side ::v-deep .el-tag {
.right-side >>> .el-tag {
font-weight: 600;
padding: 3px 8px;
text-shadow: none;
@@ -67,7 +67,6 @@ export default {
border-style: solid solid none;
border-width: 1px 0;
}
.no-margins {
margin: 0 !important;
}

View File

@@ -6,18 +6,12 @@
v-show="action.dropdown.length > 0"
:key="action.name"
class="action-item"
placement="bottom-start"
trigger="click"
placement="bottom-start"
@command="handleDropdownCallback"
>
<el-button :size="size" class="more-action" v-bind="cleanButtonAction(action)">
<span v-if="action.icon && !action.icon.startsWith('el-')" class="pre-icon">
<i v-if="action.icon.startsWith('fa')" :class="'fa fa-fw ' + action.icon" />
<svg-icon v-else :icon-class="action.icon" />
</span>
<span v-if="action.title">
{{ action.title }}<i class="el-icon-arrow-down el-icon--right" />
</span>
<el-button class="more-action" :size="size" v-bind="cleanButtonAction(action)">
{{ action.title }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown" style="overflow: auto;max-height: 60vh">
<template v-for="option in action.dropdown">
@@ -29,21 +23,17 @@
>
{{ option.group }}
</div>
<el-tooltip :key="option.name" :content="option.tip" :disabled="!option.tip" :open-delay="500" placement="top">
<el-dropdown-item
:key="option.name"
:command="[option, action]"
:title="option.tip"
class="dropdown-item"
v-bind="{...option, icon: ''}"
>
<span v-if="option.icon" class="pre-icon">
<i v-if="option.icon.startsWith('fa')" :class="'fa fa-fw ' + option.icon" />
<svg-icon v-else :icon-class="option.icon" />
</span>
{{ option.title }}
</el-dropdown-item>
</el-tooltip>
<el-dropdown-item
:key="option.name"
:command="[option, action]"
v-bind="option"
>
<span v-if="option.fa">
<i v-if="option.fa.startsWith('fa-')" :class="'fa ' + option.fa" />
<svg-icon v-else :icon-class="option.fa" style="font-size: 14px; margin-right: 2px; margin-left: -2px;" />
</span>
{{ option.title }}
</el-dropdown-item>
</template>
</el-dropdown-menu>
</el-dropdown>
@@ -52,15 +42,15 @@
v-else
:key="action.name"
:size="size"
v-bind="cleanButtonAction(action)"
class="action-item"
v-bind="{...cleanButtonAction(action), icon: action.icon && action.icon.startsWith('el-') ? action.icon : ''}"
@click="handleClick(action)"
>
<el-tooltip :content="action.tip" :disabled="!action.tip" :open-delay="500" placement="top">
<el-tooltip :disabled="!action.tip" :content="action.tip" placement="top">
<span>
<span v-if="action.icon && !action.icon.startsWith('el-')" style="vertical-align: initial">
<i v-if="action.icon.startsWith('fa')" :class="'fa ' + action.icon" />
<svg-icon v-else :icon-class="action.icon" />
<span v-if="action.fa" style="vertical-align: initial;">
<i v-if="action.fa.startsWith('fa-')" :class="'fa ' + action.fa" />
<svg-icon v-else :icon-class="action.fa" style="font-size: 14px;" />
</span>
{{ action.title }}
</span>
@@ -71,7 +61,6 @@
</template>
<script>
import { toSentenceCase } from '@/utils/common'
export default {
name: 'DataActions',
@@ -99,21 +88,8 @@ export default {
}
},
methods: {
hasIcon(action, type = '') {
const icon = action.icon
if (!icon) {
return false
}
if (type) {
return icon.startsWith(type)
}
return true
},
handleDropdownCallback(command) {
const [option, dropdown] = command
if (option.disabled) {
return
}
const defaultCallback = () => this.$log.debug('No callback found: ', option, dropdown)
let callback = option.callback
if (!callback) {
@@ -124,13 +100,7 @@ export default {
}
return callback(option)
},
toSentenceCase(s) {
return toSentenceCase(s)
},
handleClick(action) {
if (action.disabled) {
return
}
if (action && action.callback) {
action.callback(action)
} else {
@@ -165,7 +135,7 @@ export default {
if (!v) {
continue
}
const action = { ...v }
const action = Object.assign({}, v)
// 是否拥有这个action
const has = this.checkItem(action, 'has')
delete action['has']
@@ -177,15 +147,10 @@ export default {
// 是否是disabled
const can = this.checkItem(action, 'can')
if (typeof can === 'string') {
action.disabled = true
action.tip = can
} else {
action.disabled = !can
}
delete action['can']
action.disabled = !can
if (action.dropdown) {
// const dropdown = this.cleanActions(action.dropdown)
action.dropdown = this.cleanActions(action.dropdown)
}
cleanedActions.push(action)
@@ -197,157 +162,49 @@ export default {
</script>
<style lang="scss" scoped>
$btn-text-color: #ffffff;
$color-btn-background: #E8F7F4;
$color-btn-focus-background: #83CBBA;
$color-divided: #E4E7ED;
$color-drop-menu-title: #909399;
$color-drop-menu-border: #e4e7ed;
// 通用
.layout {
.action-item {
margin-left: 5px;
&:first-child {
margin-left: 0;
}
}
.el-button.el-button--default {
color: var(--color-text-primary) !important;
}
}
// 主要是左侧 LeftSide
.layout.header-action {
.action-item.el-dropdown {
font-size: 11px;
.more-action.el-button--default {
::v-deep .el-icon-arrow-down.el-icon--right {
color: var(--color-icon-primary) !important;
}
}
.el-button--primary {
::v-deep .el-icon-arrow-down.el-icon--right {
color: #ffffff !important;
}
&.el-dropdown-selfdefine {
border: none;
}
}
}
}
// 主要是 Table 中的操作列
.layout.table-actions {
display: flex;
justify-content: center;
align-items: flex-end;
.el-button {
display: flex;
align-items: center;
padding: 2px 6px;
color: $btn-text-color;
* {
vertical-align: baseline !important;
}
}
::v-deep .action-item.el-dropdown .el-button {
display: block;
color: var(--color-primary);
background-color: $color-btn-background;
border-color: $color-btn-focus-background;
&:focus {
color: $btn-text-color;
background-color: $color-btn-focus-background !important;
}
&:hover {
color: $btn-text-color;
background-color: $color-btn-focus-background;
}
}
}
// 下拉 options
.el-dropdown-menu {
::v-deep .more-batch-processing {
text-align: center;
.dropdown-menu-title {
text-align: left;
font-size: 12px;
color: #909399;
line-height: 30px;
padding-left: 10px;
padding-top: 10px;
border-top: solid 1px #e4e7ed;
}
&:hover {
background-color: transparent !important;
}
.dropdown-menu-title:first-child {
padding-top: 0;
border-top: none;
}
&.el-dropdown-menu__item--divided {
margin-top: 0;
border-top: none;
color: var(--color-text-primary);
cursor: auto;
font-size: 12px;
line-height: 30px;
border-bottom: 1px solid $color-divided;
.el-button-ungroup .action-item {
margin-left: 4px;
}
&:before {
height: 0;
}
}
}
.dropdown-item {
color: var(--color-text-primary);
.pre-icon {
width: 17px;
display: inline-block;
}
::v-deep i.fa {
font-size: 13px;
height: 13px;
width: 13px;
margin-right: 0;
}
::v-deep .svg-icon {
font-size: 13px;
height: 13px;
width: 13px;
}
}
.el-dropdown-menu__item {
&.is-disabled {
color: var(--color-disabled);
cursor: not-allowed;
pointer-events: auto;
}
&:not(.is-disabled):hover {
background-color: var(--color-disabled-background);
}
}
.dropdown-menu-title {
text-align: left;
.el-button-ungroup .action-item:first-child {
margin-left: 0;
}
::v-deep .more-batch-processing {
&.el-dropdown-menu__item--divided {
margin-top: 0;
border-top: none;
color: #909399;
cursor: auto;
font-size: 12px;
color: $color-drop-menu-title;
line-height: 30px;
padding-left: 10px;
padding-top: 10px;
border-top: solid 1px $color-drop-menu-border;
&:first-child {
padding-top: 0;
border-top: none;
border-bottom: 1px solid #E4E7ED;
&:before {
height: 0;
}
}
&.el-dropdown-menu__item:not(.is-disabled):hover {
color: #909399;
background-color: #FFFFFF;
}
}
</style>

View File

@@ -8,7 +8,7 @@
>
<div>
<div v-if="isEmpty()" style="text-align: center">
{{ this.$tc('NoContent') }}
{{ this.$tc('common.NoContent') }}
</div>
<div v-else>
<el-table
@@ -16,18 +16,18 @@
class="diffTable"
>
<el-table-column
:label="$tc('ChangeField')"
:label="$tc('audits.ChangeField')"
:prop="fieldName"
show-overflow-tooltip
width="150"
width="100"
/>
<el-table-column
:label="$tc('BeforeChange')"
:label="$tc('audits.BeforeChange')"
:prop="leftKeyName"
show-overflow-tooltip
/>
<el-table-column
:label="$tc('AfterChange')"
:label="$tc('audits.AfterChange')"
:prop="rightKeyName"
show-overflow-tooltip
/>
@@ -98,7 +98,7 @@ export default {
width: 100%;
max-height: 80vh;
& ::v-deep td {
& >>> td {
padding: 5px 0 !important;
}
}

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