<template>
  <div class="fullheight app_center_container">
    <el-container class="aside-tree fullheight">
      <el-aside
        class="fullheight"
        :width="asideWidth"
        style="border-right: 1px solid #eee"
        v-show="asideShow"
      >
        <ht-menu-tree
          highlight-current
          ref="htMenuTree"
          node-key="alias"
          :show-checkbox="false"
          :support-filter="true"
          :default-expand-all="false"
          @load="loadTreeData"
          :data="treeData"
          :defaultExpandedKeys="['app_menu']"
          @node-click="treeNodeClick"
        >
          <span class="custom-tree-node" slot-scope="{node, data}">
            <span class="show-ellipsis" :title="node.label">{{
              node.label
            }}</span>
            <el-dropdown
              @command="handleCommand"
              v-if="!hideMenu && data.parentId"
            >
              <span v-if="data.parentId">
                <i class="icon-more" title="更多操作" />
              </span>
              <el-dropdown-menu
                slot="dropdown"
                v-show="!hideMenu && data.parentId"
              >
                <el-dropdown-item
                  icon="el-icon-plus"
                  :command="{node: node, data, action: 'add'}"
                  >添加下级菜单</el-dropdown-item
                >
                <el-dropdown-item
                  icon="el-icon-upload2"
                  v-if="data.parentId !== '0'"
                  :command="{node: node, data, action: 'import'}"
                  >导入</el-dropdown-item
                >
                <el-dropdown-item
                  icon="el-icon-download"
                  v-if="data.parentId !== '0'"
                  :command="{node: node, data, action: 'export'}"
                  >导出</el-dropdown-item
                >
                <el-dropdown-item
                  icon="el-icon-edit"
                  v-if="data.parentId !== '-1'"
                  :command="{node: node, data, action: 'edit'}"
                  >编辑</el-dropdown-item
                >
                <el-dropdown-item
                  icon="el-icon-delete"
                  v-if="
                    data.parentId !== '-1' &&
                    (($store.state.login.currentUser.userAttrs &&
                      $store.state.login.currentUser.userAttrs.tenantId ===
                        data.tenantId) ||
                      data.tenantId == null)
                  "
                  :command="{node: node, data, action: 'delete'}"
                  >删除</el-dropdown-item
                >
              </el-dropdown-menu>
            </el-dropdown>
          </span>
        </ht-menu-tree>
      </el-aside>

      <div
        class="navbar-collapse"
        :class="{'navbar-collapse-right': !asideShow}"
        :style="navbarCollapseStyle"
        @click="asideShow = !asideShow"
      >
        <div class="navbar-collapse-bg">
          <i
            class="navbar-collapse-arrow"
            :class="{
              'el-icon-arrow-left': asideShow,
              'el-icon-arrow-right': !asideShow,
            }"
          ></i>
        </div>
      </div>

      <el-main class="app-center-main">
        <ht-table
          @load="loadData"
          :data="apps"
          :pageResult="pageResult"
          :selection="true"
          :quick-search-props="quickSearchProps"
          :show-export="false"
          :show-custom-column="false"
          :default-querys="defaultQuerys"
          ref="htTable"
          :header-cell-class-name="headerCellClassName"
          @selection-change="handleSelectionChange"
          :pageSizes="pageSizes"
          :customTableHeight="770"
          :card-view="isCardView"
          :card-item-mode="false"
          :default-sorter="[
            {direction: 'DESC', property: 'UPDATE_TIME_'},

            {direction: 'DESC', property: 'ID_'},
          ]"
        >
          <template slot="toolbar">
            <el-button @click="add" icon="el-icon-plus" type="primary"
              >添加</el-button
            >
            <div class="check-all">
              <el-checkbox
                v-model="checkAll"
                label="全选"
                @change="selectAll"
                :indeterminate="indeterminate"
              ></el-checkbox>
            </div>
            <el-button @click="toTagManager()">标签管理</el-button>
            <el-button
              size="small"
              @click="$refs.appUploadDialog.open()"
              icon="el-icon-back"
              >导入</el-button
            >
            <el-button
              size="small"
              @click="handleExport()"
              icon="el-icon-right"
              :disabled="isDisabled"
              >导出</el-button
            >
            <el-button @click="auth()" :disabled="isDisabled"
              >设置权限</el-button
            >

            <el-button
              @click="tenantPublish()"
              v-if="currentTenantId === '-1'"
              :disabled="isDisabled"
              >租户下发</el-button
            >
            <ht-delete-button
              url="${portal}/portal/sysApp/v1/remove"
              :disabled="isDisabled"
              :delete-list="selectedList"
              @after-delete="afterDelete"
              :ht-table="$refs.htTable"
              >删除</ht-delete-button
            >
          </template>
          <template v-slot:search>
            <ht-table-search-panel :divide="3" :label-width="80">
              <ht-table-search-field
                type="select"
                label="状态"
                prop="isPublish"
                :options="[
                  {key: '1', value: '已发布'},
                  {key: '0', value: '未发布'},
                ]"
              />
            </ht-table-search-panel>
          </template>
          <template #default v-if="!isCardView">
            <el-table-column
              type="index"
              width="50"
              align="center"
              label="序号"
            />
            <el-table-column
              prop="name"
              label="应用名称"
              :sortable="true"
              :show-overflow-tooltip="true"
              align="center"
            >
              <template v-slot="{row}">
                <el-link
                  type="primary"
                  @click="manage(row.id, row)"
                  title="查看详情"
                  >{{ row.name }}</el-link
                >
              </template>
            </el-table-column>
            <el-table-column
              prop="icon"
              label="图标"
              :show-overflow-tooltip="true"
              align="center"
            >
              <template v-slot="{row}">
                <img
                  v-if="row.icon && row.icon.indexOf('data:image') != -1"
                  :src="row.icon"
                  alt=""
                  srcset=""
                  style="width: 35px; height: 35px"
                />
                <i
                  v-else
                  :class="row.icon"
                  :style="{color: row.iconColor}"
                  class="app-icon"
                ></i>
              </template>
            </el-table-column>
            <el-table-column
              prop="menuName"
              label="菜单名称"
              :show-overflow-tooltip="true"
              align="center"
            ></el-table-column>
            <el-table-column
              prop="type"
              label="跳转模式"
              :sortable="true"
              :show-overflow-tooltip="true"
              align="center"
            >
              <template v-slot="{row}">
                <el-tag v-if="row.type === 1"> 常规应用</el-tag>
                <el-tag v-if="row.type === 2" type="primary">表单列表</el-tag>
                <el-tag v-if="row.type === 3" type="warning">数据列表</el-tag>
                <el-tag v-if="row.type === 4" type="success">图表</el-tag>
                <el-tag v-if="row.type === 5" type="danger">网页跳转</el-tag>
                <el-tag v-if="row.type === 6" type="primary">表单</el-tag>
                <el-tag v-if="row.type === 7" type="warning">流程模块</el-tag>
                <el-tag v-if="row.type === 8" type="success">流程</el-tag>
                <el-tag v-if="row.type === 9" type="danger">datav大屏</el-tag>
              </template>
            </el-table-column>
            <el-table-column
              prop="sn"
              label="排序"
              :sortable="true"
              :show-overflow-tooltip="true"
              align="center"
            ></el-table-column>
            <ht-table-column
              prop="isPublish"
              label="是否发布"
              :show-overflow-tooltip="true"
              :render-header="renderHeaderMethod"
              :filters="[
                {text: '未发布', value: 0},
                {text: '已发布', value: 1},
              ]"
              align="center"
            >
              <template v-slot="{row}">
                <el-tag v-if="row.isPublish === 0">未发布</el-tag>
                <el-tag type="success" v-if="row.isPublish === 1"
                  >已发布</el-tag
                >
              </template>
            </ht-table-column>
            <el-table-column width="240" label="操作" align="left">
              <template v-slot="{row}">
                <el-button
                  type="text"
                  @click="handleTableCommand({row: row, action: 'auth'})"
                  >权限</el-button
                >
                <el-button
                  type="text"
                  v-if="row.isPublish === 0"
                  @click="handleTableCommand({row: row, action: 'publish'})"
                  >发布</el-button
                >
                <el-button
                  type="text"
                  v-if="row.isPublish !== 0"
                  @click="handleTableCommand({row: row, action: 'view'})"
                  >查看发布</el-button
                >
                <el-button
                  type="text"
                  @click="handleTableCommand({row: row, action: 'tagSet'})"
                  >标签</el-button
                >
              </template>
            </el-table-column>
          </template>
          <template #card="{data}" v-else>
            <app-card-view
              :data="data"
              @card-click="handleCardClick"
              @command="handleCardCommand"
              @selection-change="handleSelectionChange"
              ref="cardView"
            ></app-card-view>
          </template>
        </ht-table>
      </el-main>
    </el-container>

    <!-- 菜单 -->
    <menu-dialog
      ref="menuDialog"
      :tree-data="treeData"
      @confirm="loadTreeData()"
    ></menu-dialog>
    <!-- 导入 -->
    <file-upload-dialog ref="fileUploadDialog"></file-upload-dialog>
    <!-- 对话框 -->
    <app-dialog ref="appDialog" @refresh="$refs.htTable.load()"></app-dialog>
    <!-- 发布应用 -->
    <app-publish-dialog
      ref="appPublishDialog"
      @refresh="$refs.htTable.load()"
    ></app-publish-dialog>

    <el-dialog
      :visible="tagDialogVisible"
      :close-on-click-modal="false"
      width="30%"
      title="设置标签"
      :before-close="beforeClose"
    >
      <el-form>
        <ht-form-item label="应用标签">
          <tree-select
            :normalizer="normalizer"
            v-model="appTags"
            :multiple="true"
            :options="appTagList"
            noOptionsText="暂无数据"
            :disableBranchNodes="true"
            placeholder="请选择应用标签"
            class=""
          ></tree-select>
        </ht-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <!--        <el-button type="text" @click="tagConfig">配置标签信息</el-button>-->
        <el-button type="default" @click="beforeClose">{{
          $t('eip.common.cancel')
        }}</el-button>
        <el-button type="primary" @click="appTagSave">{{
          $t('eip.common.save')
        }}</el-button>
      </div>
    </el-dialog>
    <eip-auth-dialog @onConfirm="authConfirm" ref="appAuth" :is-tip="false" />

    <!-- 导入菜单 -->
    <app-upload-dialog ref="appUploadDialog" @refresh="$refs.htTable.load()" />

    <app-info-dialog
      ref="appInfoDialog"
      @refresh="$refs.htTable.load()"
      @after-add="afterAdd"
    ></app-info-dialog>
    <app-setting-dialog
      ref="appSettingDialog"
      @refresh="$refs.htTable.load()"
    ></app-setting-dialog>
    <app-copy-dialog ref="appCopyDialog" @refresh="$refs.htTable.load()" />
    <app-tenant-publish-dialog ref="appTenantPublishDialog" />
  </div>
</template>

<script>
import portal from '@/api/portal'
import req from '@/request.js'
const treeSelect = () => import('@riophae/vue-treeselect')
const eipAuthDialog = () => import('@/components/dialog/EipAuthDialog.vue')
const htMenuTree = () => import('@/components/system/HtMenuTree.vue')
const menuDialog = () => import('@/components/portal/MenuDialog.vue')
const appPublishDialog = () =>
  import('@/components/portal/AppPublishDialog.vue')
const appDialog = () => import('@/components/portal/AppDialog.vue')
const AppCardView = () => import('@/views/portal/appcenter/AppCardView')
const AppInfoDialog = () => import('@/views/portal/appcenter/AppInfoDialog')
const AppSettingDialog = () =>
  import('@/views/portal/appcenter/AppSettingDialog')
const FileUploadDialog = () => import('@/components/dialog/FileUploadDialog')
const AppUploadDialog = () => import('@/views/portal/appcenter/AppUploadDialog')
const AppCopyDialog = () => import('@/views/portal/appcenter/AppCopyDialog.vue')
const AppTenantPublishDialog = () =>
  import('@/views/portal/appcenter/AppTenantPublishDialog.vue')
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import styles from '@/assets/css/element-variables.scss'
import {mapState, mapMutations} from 'vuex'
import tableHeaderFilter from '@/mixins/tableHeaderFilter.js'
import _ from 'lodash'
const EipSysTypeSelector = () =>
  import('@/components/selector/EipSysTypeSelector.vue')
const QUICK_SEARCH_PROPS = [{prop: 'name', label: '应用名称'}]

export default {
  name: 'app-center',
  components: {
    AppCopyDialog,
    treeSelect,
    eipAuthDialog,
    htMenuTree,
    menuDialog,
    appPublishDialog,
    appDialog,
    AppCardView,
    AppInfoDialog,
    AppSettingDialog,
    FileUploadDialog,
    AppUploadDialog,
    EipSysTypeSelector,
    AppTenantPublishDialog,
  },
  mixins: [tableHeaderFilter],
  data() {
    return {
      apps: [],
      pageResult: {
        page: 1,
        pageSize: 15,
        total: 0,
      },
      pageSizes: [15, 20, 50, 100, 200, 300],
      selectId: '',
      deleteUrl: window.context.portal + '/portal/sysApp/v1/remove',
      searchForm: {
        appName: '',
        isPublish: false,
        notPublish: false,
      },
      appTagList: [],
      tagDialogVisible: false,
      appTags: [],
      asideWidth: styles.aside_width,
      asideShow: true,
      treeData: [],
      hideMenu: false,
      defaultQuerys: [],
      rootMenuAlias: 'app_menu',
      isDisabled: true,
      selectedList: [],
      isCardView: true,
      quickSearchProps: QUICK_SEARCH_PROPS,
      inputVal: '',
      checkAll: false,
      indeterminate: false,
    }
  },
  computed: mapState({
    uploadHeaders: function (mapState) {
      return {Authorization: 'Bearer ' + mapState.login.currentUser.token}
    },
    tenantId(state) {
      return (
        state.login.currentUser.userAttrs && state.login.currentUser.userAttrs
      )
    },
    navbarCollapseStyle: function () {
      return {top: '50%'}
    },
    currentTenantId: function (state) {
      return state.user.currentUserDetail && state.user.currentUserDetail.user.tenantId
    },
  }),
  watch: {
    selectedList: {
      handler(val) {
        this.isDisabled = val.length < 1
      },
      deep: true,
    },
  },
  created() {
    this.$root.$on('refresh', () => {
      this.$refs.htTable.load()
    })
  },
  mounted() {
    this.setshowDialog(true)
  },
  beforeDestroy() {
    this.setshowDialog(false)
  },
  methods: {
    ...mapMutations({
      setshowDialog: 'user/setshowDialog',
    }),
    handleSelectionChange(selection) {
      this.selectedList = selection
      this.indeterminate = this.$refs.cardView.indeterminate()
      this.checkAll = this.$refs.cardView.selectedAll()
    },
    loadData(query, cb) {
      portal
        .getSysAppList(query)
        .then((data) => {
          this.apps = data.rows
          this.pageResult = {
            page: data.page,
            pageSize: data.pageSize,
            total: data.total,
          }
        })
        .finally(() => {
          cb && cb()
        })
    },
    add() {
      this.$refs.appInfoDialog.open()
    },
    afterAdd(data) {
      this.$refs.appSettingDialog.open(data, true)
    },
    publish(app) {
      this.$confirm('是否发布该应用？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.savePublish(app)
        })
        .catch(() => {})
    },
    savePublish(app) {
      let param = _.cloneDeep(app)
      param.isPublish = 1
      portal.publishApp(param).then((data) => {
        if (data.state) {
          this.$message({type: 'success', message: data.message})
          this.$refs.htTable.load()
        }
      })
    },
    view(app) {
      this.$refs.appPublishDialog.view(app)
    },
    beforeClose() {
      this.tagDialogVisible = false
      this.appTags = []
    },
    afterDelete() {
      this.$refs.htTable.load()
    },
    manage(id, row) {
      let menuName = row.menuName ? row.menuName : ''
      this.$refs.appDialog.open(id, menuName)
    },
    normalizer(node) {
      return {
        id: node.id,
        label: node.name,
        children: node.children,
        isDefaultExpanded: false,
      }
    },
    auth(app) {
      let _this = this
      let id = ''
      if (app) {
        this.selectId = app.id
        id = app.id
      } else {
        let ids = this.getSelectIdList()
        if (ids.length <= 0) {
          this.$message.warning('请选择需要设置的应用')
          return
        } else {
          id = ids[0]
          this.selectId = ''
        }
      }
      portal.getRights(id, 'app').then(function (resp) {
        if (resp.data) {
          let conf = {
            right: resp.data.right,
            permissionList: resp.data.type,
            autoClose: false,
          }
          _this.$refs.appAuth.showDialog(conf)
        }
      })
    },
    batchSaveRights(data) {
      let param = {
        ids: this.getSelectIdList(),
        objType: 'app',
        ownerNameJson: JSON.stringify(data),
      }
      let _this = this
      this.$http
        .post('${portal}/sys/authUser/v1/batchSaveRights', param)
        .then((resp) => {
          _this.showResponse(resp)
        })
    },
    saveRight(data) {
      let param = {
        id: this.selectId,
        objType: 'app',
        ownerNameJson: JSON.stringify(data),
      }
      let _this = this
      this.$http
        .post('${portal}/sys/authUser/v1/saveRights', param)
        .then((resp) => {
          _this.showResponse(resp)
        })
    },
    showResponse(resp) {
      if (resp.data) {
        if (resp.data.state) {
          this.$message.success('授权成功')
          this.$refs.appAuth.closeDialog()
        } else {
          this.$message.error(resp.data.message)
        }
      }
    },
    authConfirm(data) {
      if (this.selectId) {
        this.saveRight(data)
      } else {
        this.batchSaveRights(data)
      }
    },
    tagSet(app) {
      if (!app.isPublish) {
        this.$message.warning('发布应用才可设置标签')
        return
      }
      this.selectId = app.id
      this.loadAppTagsType(app.menuId)
      this.loadAppTags(app.id)
      this.tagDialogVisible = true
    },
    //加载旧数据
    loadAppTags(appId) {
      req
        .get(
          window.context.portal + '/portal/sysApp/v1/getAppTagsById/' + appId
        )
        .then((resp) => {
          if (
            resp.data.state &&
            resp.data.value &&
            resp.data.value.length != 0
          ) {
            this.appTags = []
            resp.data.value.forEach((item) => {
              if (item.tagId != '{}') {
                this.appTags.push(item.tagId)
              }
            })
          }
        })
    },
    //获取标签分类
    loadAppTagsType(menuId) {
      req
        .get(window.context.portal + '/portal/sysTag/v1/tags?typeId=' + menuId)
        .then((resp) => {
          this.appTagList = resp.data
        })
    },
    appTagSave() {
      req
        .post(
          window.context.portal +
            '/portal/sysApp/v1/saveAppTags/' +
            this.selectId,
          this.appTags.join(',')
        )
        .then((resp) => {
          if (resp.data.state) {
            this.$message({type: 'success', message: resp.data.message})
            this.tagDialogVisible = false
            this.appTags = []
          }
        })
    },
    //跳转到标签配置页面
    tagConfig() {
      this.$router.push('/sysTagManager')
    },
    getSelectIdList() {
      return this.selectedList.map((e) => e.id)
    },
    handleExport(selectedIds) {
      let ids = selectedIds || this.getSelectIdList()
      if (ids.length === 0) {
        this.$message.warning('请选择至少一项记录')
        return
      }
      let url = `${
        window.context.portal
      }/portal/sysApp/v1/export?ids=${ids.join(',')}&status=check`

      req.download(url).catch((error) => {
        const decoder = new TextDecoder('utf-8')
        const text = decoder.decode(error.response.data)
        if (text) {
          let data = JSON.parse(text)
          if (data.message.includes('是否继续导出')) {
            this.$confirm(data.message, '提示', {
              type: 'warning',
              closeOnClickModal: false,
            })
              .then(() => {
                let url = `${
                  window.context.portal
                }/portal/sysApp/v1/export?ids=${ids.join(',')}&status=none`
                req.download(url).catch(() => {
                  this.$message('导出失败，请联系管理员')
                })
              })
              .catch(() => {})
          }
        }
      })
    },
    loadTreeData(cb) {
      portal
        .getMenuTree()
        .then((data) => {
          this.treeData = data[0].children.filter(
            (item) => item.alias === this.rootMenuAlias
          )
          this.$store.dispatch('menu/getAppTypes')
        })
        .finally(() => {
          cb && cb()
        })
    },
    handleCommand(command) {
      switch (command.action) {
        case 'edit':
          this.$refs.menuDialog.open(command.data, 'edit')
          break
        case 'add':
          this.$refs.menuDialog.open(command.data, 'add')
          break
        case 'delete':
          this.$confirm(`是否删除菜单[${command.data.name}]?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'success',
          })
            .then(() => {
              this.$http
                .remove(
                  `${window.context.portal}/sys/sysMenu/v1/remove?id=${command.data.id}`
                )
                .then((resp) => {
                  if (resp.data.state) {
                    this.$message.success(resp.data.message)
                    this.loadTreeData()
                  }
                })
            })
            .catch(() => {})
          break
        case 'export':
          this.exportFile(command.data)
          break
        case 'import':
          this.importFile(command.data)
          break
      }
    },
    handleTableCommand(command) {
      switch (command.action) {
        case 'manage':
          this.manage(command.row.id)
          break
        case 'publish':
          this.publish(command.row)
          break
        case 'view':
          this.view(command.row)
          break
        case 'tagSet':
          this.tagSet(command.row)
          break
        case 'auth':
          this.auth(command.row)
          break
        case 'remove':
          this.remove(command.row)
          break
      }
    },
    exportFile(data) {
      let id = data.id
      let url =
        window.context.portal + '/sys/sysMenu/v1/export?parentMenuId=' + id
      req.download(url)
    },
    importFile(data) {
      this.$refs.fileUploadDialog.open(
        window.context.portal + '/sys/sysMenu/v1/import?parentMenuId=' + data.id
      )
    },
    treeNodeClick(node) {
      if (node.alias == this.rootMenuAlias) {
        this.defaultQuerys.splice(0)
      } else {
        this.$set(this.defaultQuerys, 0, {
          property: 'MENU_ID_',
          value: node.id,
          operation: 'IN',
        })
      }
      this.$refs.htTable.load()
    },
    toTagManager() {
      this.$router.push('/applicationModule/appTagManager')
    },
    handleCardClick(data) {
      this.$refs.appSettingDialog.open(data)
    },
    handleCardCommand(value) {
      let {command, data} = value
      switch (command) {
        case 'modify':
          this.$refs.appInfoDialog.open(data)
          break
        case 'auth':
          this.auth(data)
          break
        case 'publish':
          this.publish(data)
          break
        case 'view':
          this.view(data)
          break
        case 'tag':
          this.tagSet(data)
          break
        case 'remove':
          this.remove(data.id)
          break
        case 'update':
          this.update(data.id)
          break
        case 'export':
          this.handleExport([data.id])
          break
        case 'copy':
          this.copyApp(data)
          break
        default:
          break
      }
    },
    update(id) {
      req
        .post(`${window.context.portal}/portal/sysApp/v1/update?id=${id}`, {})
        .then((resp) => {
          if (resp.data.state) {
            this.$message.success('更新成功')
          }
        })
    },
    remove(id) {
      this.$confirm('是否删除该应用?', '提示', {
        type: 'warning',
        closeOnClickModal: false,
      })
        .then(() => {
          req
            .remove(
              `${window.context.portal}/portal/sysApp/v1/remove?ids=${id}`
            )
            .then((resp) => {
              if (resp.data.state) {
                this.$message.success(resp.data.message)
                this.$refs.htTable.load()
              }
            })
        })
        .catch(() => {})
    },
    copyApp(app) {
      this.$refs.appCopyDialog.open(app)
    },
    tenantPublish() {
      let ids = this.getSelectIdList()
      if (ids.length === 0) {
        this.$message.warning('请选择下发应用')
        return
      }
      this.$refs.appTenantPublishDialog.open(ids)
    },
    selectAll(checked) {
      this.$refs.cardView.selectAll(checked)
    },
  },
}
</script>

<style lang="scss" scoped>
.app_center_container {
  height: 100%;
  overflow: auto;
}
.card {
  margin: 5px;
  min-height: 200px;
  text-align: center;
}
.card i {
  font-size: 60px;
  display: block;
  margin: 10px 0;
}
.card-item-actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  background: #fafafa;
  justify-content: center;
  margin-top: 30px;
  .actions__btn {
    margin-bottom: 10px;
  }
  .confirm__btn {
    margin-left: 10px;
  }
}
.pagination {
  // position: absolute;
  // bottom: 0;
  margin-top: 20px;
}
.form-editor-dialog >>> .el-dialog__header {
  display: none;
}
.form-editor-dialog >>> .el-dialog__body {
  padding: 0;
  height: 100%;
}
.card-title {
  font-weight: bold;
  font-size: 20px;
}
.card-background {
  width: 80px;
  height: 80px;
  margin: 10px auto;
  border-radius: 15px;
}
.image {
  width: 30px;
  height: 30px;
}
.app-image {
  width: 60px;
  height: 60px;
  margin: 10px;
}
.input-search {
  width: 400px;
  margin: 0px 12px 0 6px;
}
.card-item {
  cursor: default;
  display: block;
  position: relative;
}
.sticky {
  width: 1px;
  height: 0;
  position: absolute;
  top: 0;
  right: 5px;
  border-left: 40px solid #fff;
  border-top: 40px solid #ededed;
}
.card-checkbox {
  position: absolute;
  top: -35px;
  right: 0;
}
.card-checkbox input[type='checkbox'] {
  opacity: 0;
}
.card-checkbox input[type='checkbox'] + span::after {
  opacity: 1;
  content: '';
  position: absolute;
  width: 6px;
  height: 11px;
  background: transparent;
  right: 7px;
  border: 2px solid #fff;
  border-top: none;
  border-left: none;
  -webkit-transform: rotate(35deg);
  -moz-transform: rotate(35deg);
  -o-transform: rotate(35deg);
  -ms-transform: rotate(35deg);
  transform: rotate(35deg);
}
.card-item.checked .el-card {
  outline: 1px solid #5492f5;
}
.card-item.checked .sticky {
  border-top-color: #5492f5;
}

.card-item-actions > ul {
  padding: 0;
  margin: 0;
  list-style: none;
  width: 100%;
}

.card-item-actions > ul > li {
  cursor: pointer;
  width: 20%;
  float: left;
  margin: 12px 0;
  font-size: 16px;
  color: #555;
  text-align: center;
}

.card-item-actions > ul > li > span {
  margin-left: 5px;
  font-size: 14px;
}

.card-item-actions > ul > li > span > span {
  margin-left: 5px;
  font-size: 14px;
  color: #f45159;
}

.card-item-actions > ul > li:hover {
  color: #5492f5;
}

.check-all {
  border: #dcdee0 solid 1px;
  display: inline;
  padding: 7px 10px 8px;
  border-radius: 1px;
  margin: 0 10px;
}

>>> .el-tree-node__content:hover .el-dropdown {
  display: inline-block;
}
>>> .custom-tree-node {
  width: calc(100% - 40px); // flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
.custom-tree-node i {
  visibility: hidden;
  font-weight: bold;
}
.custom-tree-node:hover i {
  visibility: visible;
}
.app-icon {
  font-size: 24px;
  margin-right: 10px;
}

::v-deep {
  .cell > .el-table__column-filter-trigger {
    display: none;
  }
  .app-center-main,
  .app-center-main .el-main {
    padding: 0 10px !important;
  }

  .navbar-collapse {
    position: relative;
    top: 50%;
    cursor: pointer;
    width: 0;
    height: 0;
  }

  .navbar-collapse.navbar-collapse-right {
    top: 40%;
  }

  .navbar-collapse:hover {
    transform: scale(1) translateY(2px);
  }

  .navbar-collapse:hover .navbar-collapse-arrow {
    color: #333333;
  }

  .navbar-collapse-arrow {
    position: relative;
    top: 38%;
    right: 15px;
    font-size: 18px;
    color: #a8a8a8;
  }

  .navbar-collapse-bg {
    -webkit-transition: all 0.12s ease;
    height: 50px;
    border-bottom: 8px solid transparent;
    border-right: none;
    border-left: 12px solid #ebebeb;
    border-top: 8px solid transparent;
    opacity: 0.9;
  }
  .tree-select-radio .vue-treeselect__control {
    border-radius: 2px;
    height: 32px;
  }

  .common-tools {
    margin-right: 32px;
  }

  .pagination-panel {
    margin-right: 32px;
  }
}
</style>
