kuaifan 5370bee369 Merge branch 'dev' into pro
# Conflicts:
#	CHANGELOG.md
#	cmd
#	package.json
#	public/js/build/404.5645cb91.js
#	public/js/build/404.9598cd97.js
#	public/js/build/404.a5736629.js
#	public/js/build/AceEditor.8747edb1.js
#	public/js/build/AceEditor.af35593f.js
#	public/js/build/AceEditor.e7f5b602.js
#	public/js/build/DialogWrapper.0c7cd033.js
#	public/js/build/DialogWrapper.64072671.js
#	public/js/build/DialogWrapper.7fcb5b27.js
#	public/js/build/Drawio.2ca59c31.js
#	public/js/build/Drawio.6691a6ef.js
#	public/js/build/Drawio.e3576e4e.js
#	public/js/build/FileContent.3a899bcc.js
#	public/js/build/FileContent.c311c89c.js
#	public/js/build/FileContent.d8e600e1.js
#	public/js/build/FilePreview.87ca99d9.js
#	public/js/build/FilePreview.f8134ee5.js
#	public/js/build/FilePreview.f9f90ff4.js
#	public/js/build/IFrame.02598edc.js
#	public/js/build/IFrame.2a7489ee.js
#	public/js/build/IFrame.be9780e1.js
#	public/js/build/ImgUpload.29e2d88d.js
#	public/js/build/ImgUpload.a4eff264.js
#	public/js/build/ImgUpload.e96999cf.js
#	public/js/build/Minder.2bce6c16.js
#	public/js/build/Minder.b1d1145f.js
#	public/js/build/Minder.f5bc5aca.js
#	public/js/build/OnlyOffice.31e7af4f.js
#	public/js/build/OnlyOffice.574ad560.js
#	public/js/build/OnlyOffice.9ce921ed.js
#	public/js/build/ReportEdit.5eb3a319.js
#	public/js/build/ReportEdit.9141bb93.js
#	public/js/build/ReportEdit.e3369e09.js
#	public/js/build/SearchButton.906cea81.js
#	public/js/build/SearchButton.cf201525.js
#	public/js/build/SearchButton.d41addb6.js
#	public/js/build/TEditor.7b9a9d91.js
#	public/js/build/TEditor.971af80f.js
#	public/js/build/TEditor.cc94d929.js
#	public/js/build/TaskDetail.38815236.js
#	public/js/build/TaskDetail.d1a9952e.js
#	public/js/build/TaskDetail.dfd78b4a.js
#	public/js/build/add.0cfbdd9e.js
#	public/js/build/add.3673f91c.js
#	public/js/build/add.423bc480.js
#	public/js/build/application.005cc174.js
#	public/js/build/application.5587ac3b.js
#	public/js/build/application.5b8f123b.js
#	public/js/build/apps.4e0bf65b.js
#	public/js/build/apps.b0a3d4f5.js
#	public/js/build/apps.f77a8c4e.js
#	public/js/build/calendar.31470aa0.js
#	public/js/build/calendar.ad5d85d5.js
#	public/js/build/calendar.e08e7575.js
#	public/js/build/checkin.5d4c364e.js
#	public/js/build/checkin.ab08f01e.js
#	public/js/build/checkin.c05284a9.js
#	public/js/build/dashboard.7cced7be.js
#	public/js/build/dashboard.c82415db.js
#	public/js/build/dashboard.f6ed8299.js
#	public/js/build/dayjs.495f600d.js
#	public/js/build/dayjs.71653272.js
#	public/js/build/dayjs.cf033d87.js
#	public/js/build/delete.4072c68f.js
#	public/js/build/delete.5f06c51d.js
#	public/js/build/delete.b26aa3fd.js
#	public/js/build/device.4cff22ad.js
#	public/js/build/device.66a7e05a.js
#	public/js/build/device.a13f3ef0.js
#	public/js/build/dialog.97b951ce.js
#	public/js/build/dialog.e9f6d55f.js
#	public/js/build/dialog.eb7b795a.js
#	public/js/build/editor.18a511b5.js
#	public/js/build/editor.2cca497c.js
#	public/js/build/editor.e034df4e.js
#	public/js/build/email.0643f86b.js
#	public/js/build/email.1d00cb0c.js
#	public/js/build/email.d95a35c0.js
#	public/js/build/file.4fe82c29.js
#	public/js/build/file.684a63df.js
#	public/js/build/file.9dceb82f.js
#	public/js/build/fileMsg.0a0029c2.js
#	public/js/build/fileMsg.1f4ecb0f.js
#	public/js/build/fileMsg.f99b6f61.js
#	public/js/build/fileTask.72914205.js
#	public/js/build/fileTask.bf35fb6b.js
#	public/js/build/fileTask.f4356f14.js
#	public/js/build/index.236af26f.js
#	public/js/build/index.299c9f99.js
#	public/js/build/index.2ffa8f9e.js
#	public/js/build/index.7d6e1bbe.js
#	public/js/build/index.94a5d2da.css
#	public/js/build/index.af34aeb9.js
#	public/js/build/index.b0ae9460.js
#	public/js/build/index.b69b5f25.js
#	public/js/build/index.b71c2859.js
#	public/js/build/index.c3968cad.js
#	public/js/build/index.d1ae44be.js
#	public/js/build/index.e07db7f9.css
#	public/js/build/index.edee4b6e.css
#	public/js/build/index.ef9e1e57.js
#	public/js/build/index.fe32159a.js
#	public/js/build/jquery.0909250e.js
#	public/js/build/jquery.16b446fd.js
#	public/js/build/jquery.27f590f5.js
#	public/js/build/keyboard.3f5b3ac6.js
#	public/js/build/keyboard.5de3dd2c.js
#	public/js/build/keyboard.c3ef7d49.js
#	public/js/build/language.1fadd54c.js
#	public/js/build/language.8bb72294.js
#	public/js/build/language.f3d03ece.js
#	public/js/build/license.21482fde.js
#	public/js/build/license.60871496.js
#	public/js/build/license.add318a7.js
#	public/js/build/localforage.65ac7a2a.js
#	public/js/build/localforage.be4775a0.js
#	public/js/build/localforage.dd58f5ac.js
#	public/js/build/login.7560afa5.js
#	public/js/build/login.75b3978c.js
#	public/js/build/login.aa163163.js
#	public/js/build/meeting.a60d7e8d.js
#	public/js/build/meeting.aa5510c7.js
#	public/js/build/meeting.fdb9793b.js
#	public/js/build/password.267357fd.js
#	public/js/build/password.749ce44d.js
#	public/js/build/password.e6d81eb1.js
#	public/js/build/personal.69279937.js
#	public/js/build/personal.a27cef8e.js
#	public/js/build/personal.c613af3c.js
#	public/js/build/preload.5827bd38.js
#	public/js/build/preload.8ec61a5b.js
#	public/js/build/preload.c6189d87.js
#	public/js/build/preview.29e49902.js
#	public/js/build/preview.7329f0f4.js
#	public/js/build/preview.b452b0ee.js
#	public/js/build/preview.c64402ed.js
#	public/js/build/preview.ec796a92.js
#	public/js/build/preview.ec85a43c.js
#	public/js/build/pro.2128a514.js
#	public/js/build/pro.213d8da6.js
#	public/js/build/pro.9fb60d27.js
#	public/js/build/projectInvite.0b3bf524.js
#	public/js/build/projectInvite.393920f8.js
#	public/js/build/projectInvite.e9cee390.js
#	public/js/build/reportDetail.2db50632.js
#	public/js/build/reportDetail.90aaf973.js
#	public/js/build/reportDetail.d93cc650.js
#	public/js/build/reportEdit.84a81076.js
#	public/js/build/reportEdit.8baf23d4.js
#	public/js/build/reportEdit.d008dd34.js
#	public/js/build/swipe.0c72cce1.js
#	public/js/build/swipe.4567bb5d.js
#	public/js/build/swipe.92aebd0c.js
#	public/js/build/system.67c1b700.js
#	public/js/build/system.c45c70de.js
#	public/js/build/system.f3384133.js
#	public/js/build/task.1b9e0e77.js
#	public/js/build/task.a445c89e.js
#	public/js/build/task.d43091db.js
#	public/js/build/taskContent.20b80714.js
#	public/js/build/taskContent.3ebbd2f9.js
#	public/js/build/taskContent.9dc7a121.js
#	public/js/build/theme.72d103d1.js
#	public/js/build/theme.7f1b2ffd.js
#	public/js/build/theme.df79fe8f.js
#	public/js/build/token.0ecffef5.js
#	public/js/build/token.a7f5ccf5.js
#	public/js/build/token.ece75257.js
#	public/js/build/validEmail.1462dd30.js
#	public/js/build/validEmail.17a3e0d2.js
#	public/js/build/validEmail.ee19c1f3.js
#	public/js/build/version.137935c7.js
#	public/js/build/version.1441c1fd.js
#	public/js/build/version.b0154505.js
#	public/js/build/video.03b62c93.js
#	public/js/build/video.2dc7f3c6.js
#	public/js/build/video.531c68e2.js
#	public/js/build/view.18713f1b.js
#	public/js/build/view.7770155e.js
#	public/js/build/view.8c6a0cc1.js
#	public/manifest.json
2025-11-05 16:55:17 +08:00

841 lines
36 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="page-apply">
<PageTitle :title="$L('应用')"/>
<div class="apply-wrapper">
<div class="apply-head">
<div class="apply-nav">
<h1>{{ $L('应用') }}</h1>
</div>
</div>
<div class="apply-content">
<template v-for="t in applyTypes">
<div v-if="isExistAdminList" class="apply-row-title">
{{ t == 'base' ? $L('常用') : $L('管理员') }}
</div>
<Row :gutter="16">
<Col
v-for="(item, key) in (t == 'base' ? filterMicroAppsMenus : filterMicroAppsMenusAdmin)"
:key="`micro_` + key"
:xs="{ span: 6 }"
:sm="{ span: 6 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 3 }">
<div class="apply-col">
<div class="apply-item" @click="applyClick({value: 'microApp'}, item)">
<div class="logo">
<div class="apply-icon no-dark-content" :style="{backgroundImage: `url(${item.icon})`}"></div>
</div>
<p>{{ item.label }}</p>
</div>
</div>
</Col>
<Col
v-for="(item, key) in applyList"
:key="key"
v-if="((t=='base' && !item.type) || item.type == t) && item.show !== false"
:xs="{ span: 6 }"
:sm="{ span: 6 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 3 }">
<div class="apply-col">
<template v-if="item.value === 'exportManage'">
<EPopover
v-model="exportPopoverShow"
trigger="click"
placement="bottom"
popperClass="apply-export-popover"
:transfer="true">
<div slot="reference" class="apply-item">
<div class="logo">
<div class="apply-icon no-dark-content" :class="getLogoClass(item.value)"></div>
</div>
<p>{{ $L(item.label) }}</p>
</div>
<ul class="apply-export-menu">
<li @click="handleExport('task')">{{ $L('导出任务统计') }}</li>
<li @click="handleExport('overdue')">{{ $L('导出超期任务') }}</li>
<li @click="handleExport('approve')">{{ $L('导出审批数据') }}</li>
<li @click="handleExport('checkin')">{{ $L('导出签到数据') }}</li>
</ul>
</EPopover>
</template>
<div v-else class="apply-item" @click="applyClick(item)">
<div class="logo">
<div class="apply-icon no-dark-content" :class="getLogoClass(item.value)"></div>
<div @click.stop="applyClick(item, 'badge')" class="apply-box-top-report">
<Badge v-if="showBadge(item,'approve')" :overflow-count="999" :count="approveUnreadNumber"/>
<Badge v-if="showBadge(item,'report')" :overflow-count="999" :count="reportUnreadNumber"/>
</div>
</div>
<p>{{ $L(item.label) }}</p>
</div>
</div>
</Col>
</Row>
</template>
</div>
</div>
<!--MY BOT-->
<DrawerOverlay v-model="mybotShow" placement="right" :size="720">
<template v-if="mybotShow" #title>
{{ $L('我的机器人') }}
</template>
<template v-if="mybotShow" #more>
<a href="javascript:void(0)" @click="applyClick({value: 'mybot-add'}, {id: 0})">{{ $L('添加机器人') }}</a>
</template>
<div v-if="mybotShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body full-body">
<div v-if="mybotList.length === 0" class="empty-data">
<Loading v-if="mybotLoad"/>
<span v-else>{{ $L('您没有创建机器人') }}</span>
</div>
<ul v-else class="ivu-modal-wrap-ul">
<li v-for="(item, key) in mybotList" :key="key">
<div class="modal-item-img">
<img :src="item.avatar">
</div>
<div class="modal-item-info">
<div class="modal-item-name">
<h4 class="user-select-auto">{{ item.name }}</h4>
</div>
<div class="modal-item-mybot user-select-auto">
<p><span>ID:</span>{{ item.id }}</p>
<p><span>{{ $L('清理时间') }}:</span>{{ item.clear_day }}</p>
<p><span>Webhook:</span>{{ item.webhook_url || '-' }}</p>
<p><span>{{ $L('Webhook事件') }}:</span>{{ formatWebhookEvents(item.webhook_events) }}</p>
</div>
<div class="modal-item-btns">
<Button icon="md-chatbubbles" @click="applyClick({value: 'mybot-chat'}, item)">{{ $L('开始聊天') }}</Button>
<Button icon="md-create" @click="applyClick({value: 'mybot-add'}, item)">{{ $L('修改') }}</Button>
<Button icon="md-trash" @click="applyClick({value: 'mybot-del'}, item)">{{ $L('删除') }}</Button>
</div>
</div>
</li>
</ul>
</div>
</div>
</DrawerOverlay>
<!--MY BOT 设置-->
<Modal
v-model="mybotModifyShow"
:title="$L(mybotModifyData.id > 0 ? '修改机器人' : '添加机器人')"
:mask-closable="false">
<Form :model="mybotModifyData" v-bind="formOptions" @submit.native.prevent>
<Alert v-if="mybotModifyData.system_name" type="error" style="margin-bottom:18px">{{ $L(`正在修改系统机器人:${mybotModifyData.system_name}`) }}</Alert>
<FormItem prop="avatar" :label="$L('头像')">
<ImgUpload v-model="mybotModifyData.avatar" :num="1" :width="512" :height="512" whcut="cover"/>
</FormItem>
<FormItem prop="name" :label="$L('名称')">
<Input v-model="mybotModifyData.name" :maxlength="20" :placeholder="$L('机器人名称')"/>
</FormItem>
<FormItem prop="clear_day" :label="$L('消息保留')">
<Input v-model="mybotModifyData.clear_day" :maxlength="3" type="number" :placeholder="$L('默认90天')">
<div slot="append">{{ $L('天') }}</div>
</Input>
</FormItem>
<FormItem prop="webhook_url" label="Webhook">
<Input v-model="mybotModifyData.webhook_url" :maxlength="255" :show-word-limit="0.9" type="textarea" placeholder="Webhook"/>
</FormItem>
<FormItem prop="webhook_events" :label="$L('Webhook事件')">
<CheckboxGroup v-model="mybotModifyData.webhook_events">
<Checkbox v-for="option in webhookEventOptions" :key="option.value" :label="option.value">
{{ $L(option.label) }}
</Checkbox>
</CheckboxGroup>
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="mybotModifyShow=false">{{ $L('取消') }}</Button>
<Button type="primary" :loading="mybotModifyLoad > 0" @click="onMybotModify">{{ $L('保存') }}</Button>
</div>
</Modal>
<!--AI BOT-->
<DrawerOverlay v-model="aibotShow" placement="right" :size="720">
<template v-if="aibotShow" #title>
{{ $L('AI 列表') }}
</template>
<template v-if="aibotShow" #more>
<a href="javascript:void(0)" @click="applyClick({value: 'robot-setting'}, 'openai')" v-if="userIsAdmin">{{ $L('机器人设置') }}</a>
</template>
<div v-if="aibotShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body full-body">
<ul class="ivu-modal-wrap-ul">
<li v-for="(item, key) in aibotList" :key="key">
<div class="modal-item-img">
<img :src="item.src">
</div>
<div class="modal-item-info">
<div class="modal-item-name">
<h4>{{ item.label }}</h4>
<div v-if="item.tag" class="modal-item-tag" @click="applyClick({value: 'robot-setting'}, item.value)">
{{ item.tag }}
<em v-if="item.tags.length > 1">+{{ item.tags.length - 1 }}</em>
</div>
</div>
<p class="modal-item-desc" @click="openDetail(item.desc)">{{ item.desc }}</p>
<div class="modal-item-btns">
<Button icon="md-chatbubbles" :loading="aibotDialogSearchLoad == item.value" @click="onGoToChat(item.value)">{{ $L('开始聊天') }}</Button>
<Button v-if="userIsAdmin" icon="md-settings" @click="applyClick({value: 'robot-setting'}, item.value)">{{ $L('设置') }}</Button>
</div>
</div>
</li>
</ul>
</div>
</div>
</DrawerOverlay>
<!--AI BOT 设置-->
<DrawerOverlay v-model="aibotSettingShow" placement="right" :size="950">
<template v-if="aibotSettingShow" #title>
{{ $L('AI 设置') }}
</template>
<div v-if="aibotSettingShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<Tabs v-model="aibotTabAction" :animated="false" class="ai-tabs">
<TabPane v-for="(item, key) in aibotList" :key="key" :label="item.label" :name="item.value">
<div class="aibot-setting">
<SystemAibot
v-if="aibotTabAction == item.value"
:type="item.value"
@on-update-setting="handleAITags"/>
</div>
</TabPane>
</Tabs>
</div>
</div>
</DrawerOverlay>
<!--签到-->
<DrawerOverlay v-model="signInShow" placement="right" :size="500">
<template v-if="signInShow" #title>
{{ $L('签到管理') }}
</template>
<template v-if="signInShow" #more>
<a href="javascript:void(0)" @click="signInSettingShow=true" v-if="userIsAdmin">{{ $L('签到设置') }}</a>
</template>
<div v-if="signInShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<Checkin/>
</div>
</div>
</DrawerOverlay>
<!--签到设置-->
<DrawerOverlay v-model="signInSettingShow" placement="right" :size="720">
<template v-if="signInSettingShow" #title>
{{ $L('签到设置') }}
</template>
<div v-if="signInSettingShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<SystemCheckin/>
</div>
</div>
</DrawerOverlay>
<!--会议-->
<DrawerOverlay v-model="meetingShow" placement="right" :size="720">
<template v-if="meetingShow" #title>
{{ $L('会议') }}
</template>
<template v-if="meetingShow" #more>
<a href="javascript:void(0)" @click="meetingSettingShow = true" v-if="userIsAdmin">{{ $L('会议设置') }}</a>
</template>
<div v-if="meetingShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body full-body">
<SystemMeetingNav @openDetail="openDetail" @onMeeting="onMeeting"/>
</div>
</div>
</DrawerOverlay>
<!--会议设置-->
<DrawerOverlay v-model="meetingSettingShow" placement="right" :size="600">
<template v-if="meetingSettingShow" #title>
{{ $L('会议设置') }}
</template>
<div v-if="meetingSettingShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body full-body">
<SystemMeeting/>
</div>
</div>
</DrawerOverlay>
<!--LDAP-->
<DrawerOverlay v-model="ldapShow" placement="right" :size="700">
<template v-if="ldapShow" #title>
{{ $L('LDAP 设置') }}
</template>
<div v-if="ldapShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<SystemThirdAccess/>
</div>
</div>
</DrawerOverlay>
<!--邮件-->
<DrawerOverlay v-model="mailShow" placement="right" :size="700">
<template v-if="mailShow" #title>
{{ $L('邮件通知') }}
</template>
<div v-if="mailShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<SystemEmailSetting/>
</div>
</div>
</DrawerOverlay>
<!--App 推送-->
<DrawerOverlay v-model="appPushShow" placement="right" :size="700">
<template v-if="appPushShow" #title>
{{ $L('APP 推送') }}
</template>
<div v-if="appPushShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<SystemAppPush/>
</div>
</div>
</DrawerOverlay>
<!--AI 助手-->
<DrawerOverlay v-model="aiAssistantShow" placement="right" :size="800">
<template v-if="aiAssistantShow" #title>
{{ $L('AI 助手') }}
</template>
<div v-if="aiAssistantShow" class="ivu-modal-wrap-apply">
<div class="ivu-modal-wrap-apply-body">
<SystemAiAssistant/>
</div>
</div>
</DrawerOverlay>
<!--扫码登录-->
<Modal
v-model="scanLoginShow"
:title="$L('扫码登录')"
:mask-closable="false">
<div class="mobile-scan-login-box">
<div class="mobile-scan-login-title">{{ $L(`你好,扫码确认登录`) }}</div>
<div class="mobile-scan-login-subtitle">{{ $L('为确保帐号安全,请确认是本人操作') }}</div>
</div>
<div slot="footer" class="adaption">
<Button type="default" @click="scanLoginShow=false">{{ $L('取消登录') }}</Button>
<Button type="primary" :loading="scanLoginLoad" @click="scanLoginSubmit">{{ $L('确认登录') }}</Button>
</div>
</Modal>
<!--发起群投票接龙-->
<UserSelect
ref="wordChainAndVoteRef"
v-model="sendData"
:multiple-max="1"
:title="sendType == 'vote' ? $L('选择群组发起投票') : $L('选择群组发起接龙')"
:before-submit="goWordChainAndVote"
:show-select-all="false"
:only-group="true"
show-dialog
module/>
</div>
</template>
<script>
import {mapGetters, mapState} from "vuex";
import DrawerOverlay from "../../components/DrawerOverlay";
import UserSelect from "../../components/UserSelect";
import SystemAibot from "./setting/components/SystemAibot";
import SystemCheckin from "./setting/components/SystemCheckin";
import Checkin from "./setting/checkin";
import SystemMeeting from "./setting/components/SystemMeeting";
import SystemMeetingNav from "./setting/components/SystemMeetingNav.vue";
import SystemThirdAccess from "./setting/components/SystemThirdAccess";
import SystemEmailSetting from "./setting/components/SystemEmailSetting";
import SystemAppPush from "./setting/components/SystemAppPush";
import SystemAiAssistant from "./setting/components/SystemAiAssistant";
import emitter from "../../store/events";
import {AIBotList, AIModelNames} from "../../utils/ai";
import ImgUpload from "../../components/ImgUpload.vue";
export default {
components: {
ImgUpload,
UserSelect,
DrawerOverlay,
SystemAibot,
SystemCheckin,
Checkin,
SystemMeeting,
SystemMeetingNav,
SystemThirdAccess,
SystemEmailSetting,
SystemAppPush,
SystemAiAssistant
},
data() {
return {
applyTypes: ['base', 'admin'],
//
mybotShow: false,
mybotList: [],
mybotLoad: 0,
mybotModifyShow: false,
mybotModifyData: {},
mybotModifyLoad: 0,
webhookEventOptions: [
{value: 'message', label: '接收消息'},
{value: 'dialog_open', label: '打开会话'},
{value: 'member_join', label: '成员加入'},
{value: 'member_leave', label: '成员退出'},
],
//
aibotShow: false,
aibotList: AIBotList,
aibotSettingShow: false,
aibotTabAction: "openai",
aibotDialogSearchLoad: "",
//
signInShow: false,
signInSettingShow: false,
//
meetingShow: false,
meetingSettingShow: false,
//
ldapShow: false,
//
mailShow: false,
//
appPushShow: false,
//
aiAssistantShow: false,
//
exportPopoverShow: false,
//
scanLoginShow: false,
scanLoginLoad: false,
scanLoginCode: '',
//
sendData: [],
sendType: '',
}
},
activated() {
this.$store.dispatch("updateMicroAppsStatus")
},
computed: {
...mapState([
'systemConfig',
'userInfo',
'userIsAdmin',
'reportUnreadNumber',
'approveUnreadNumber',
'cacheDialogs',
'windowOrientation',
'formOptions',
'routeLoading',
'microAppsIds'
]),
...mapGetters([
'filterMicroAppsMenus',
'filterMicroAppsMenusAdmin',
]),
applyList() {
const list = [
{value: "approve", label: "审批中心", sort: 30, show: this.microAppsIds.includes('approve')},
{value: "favorite", label: "我的收藏", sort: 45},
{value: "recent", label: "最近打开", sort: 47},
{value: "report", label: "工作报告", sort: 50},
{value: "mybot", label: "我的机器人", sort: 55},
{value: "robot", label: "AI 机器人", sort: 60, show: this.microAppsIds.includes('ai')},
{value: "signin", label: "签到打卡", sort: 70},
{value: "meeting", label: "在线会议", sort: 80},
{value: "createGroup", label: "创建群组", sort: 85},
{value: "word-chain", label: "群接龙", sort: 90},
{value: "vote", label: "群投票", sort: 100},
{value: "addProject", label: "创建项目", sort: 110},
{value: "addTask", label: "添加任务", sort: 120},
{value: "scan", label: "扫一扫", sort: 130, show: $A.isEEUIApp},
]
// 竖屏模式
if (this.windowPortrait) {
list.push(...[
{value: "calendar", label: "日历", sort: 10},
{value: "file", label: "文件", sort: 20},
{value: "setting", label: "设置", sort: 140},
])
}
// 管理员
if (this.userIsAdmin) {
list.push(...[
{type: 'admin', value: "ldap", label: "LDAP", sort: 160},
{type: 'admin', value: "mail", label: "邮件通知", sort: 170},
{type: 'admin', value: "appPush", label: "APP 推送", sort: 180},
{type: 'admin', value: "aiAssistant", label: "AI 助手", sort: 185},
{type: 'admin', value: "complaint", label: "举报管理", sort: 190},
{type: 'admin', value: "exportManage", label: "数据导出", sort: 195},
{type: 'admin', value: "allUser", label: "团队管理", sort: 200},
])
}
//
return list.sort((a, b) => a.sort - b.sort);
},
isExistAdminList() {
return this.filterMicroAppsMenusAdmin.length > 0 || this.applyList.map(h => h.type).indexOf('admin') !== -1;
}
},
methods: {
normalizeWebhookEvents(events = [], useFallback = false) {
if (!Array.isArray(events)) {
events = events ? [events] : [];
}
const allowed = this.webhookEventOptions.map(item => item.value);
const result = events.filter(item => allowed.includes(item));
if (result.length) {
return Array.from(new Set(result));
}
return useFallback ? ['message'] : [];
},
enhanceMybotItem(item = {}) {
const data = $A.cloneJSON(item || {});
let events = data.webhook_events;
if (typeof events === 'undefined' || events === null) {
events = ['message'];
}
events = this.normalizeWebhookEvents(events, false);
if (!events.length) {
events = [];
}
data.webhook_events = events;
return data;
},
formatWebhookEvents(events) {
const values = this.normalizeWebhookEvents(events, false);
const labels = this.webhookEventOptions
.filter(option => values.includes(option.value))
.map(option => this.$L(option.label));
return labels.length ? labels.join('、') : '-';
},
getLogoClass(name) {
name = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
return name
},
showBadge(item, type) {
let num = 0;
switch (type) {
case 'approve':
num = this.approveUnreadNumber;
break;
case 'report':
num = this.reportUnreadNumber;
break;
}
return item.value == type && num > 0
},
// 点击应用
applyClick(item, params = '') {
switch (item.value) {
case 'calendar':
case 'file':
case 'setting':
this.goForward({name: 'manage-' + item.value});
break;
case 'report':
emitter.emit('openReport', params == 'badge' ? 'receive' : 'my');
break;
case 'favorite':
emitter.emit('openFavorite');
break;
case 'recent':
emitter.emit('openRecent');
break;
case 'mybot':
this.getMybot();
this.mybotShow = true;
break;
case 'mybot-chat':
this.chatMybot(params.id);
break;
case 'mybot-add':
this.addMybot(params);
break;
case 'mybot-del':
this.delMybot(params);
break;
case 'robot':
this.getAITags();
this.aibotShow = true;
break;
case 'robot-setting':
this.aibotTabAction = params;
this.aibotSettingShow = true;
break;
case 'signin':
this.signInShow = true;
break;
case 'meeting':
this.meetingShow = true;
break;
case 'ldap':
this.ldapShow = true;
break;
case 'mail':
this.mailShow = true;
break;
case 'appPush':
this.appPushShow = true;
break;
case 'aiAssistant':
this.aiAssistantShow = true;
break;
case 'scan':
$A.eeuiAppScan(this.scanResult);
break;
case 'word-chain':
case 'vote':
this.sendData = [];
this.sendType = item.value;
this.$refs.wordChainAndVoteRef.onSelection()
break;
}
this.$emit("on-click", item.value, params);
},
handleExport(type) {
this.exportPopoverShow = false;
emitter.emit('openManageExport', type);
},
// 获取我的机器人
getMybot() {
this.mybotLoad++
this.$store.dispatch("call", {
url: 'users/bot/list',
}).then(({data}) => {
this.mybotList = (data.list || []).map(item => this.enhanceMybotItem(item));
}).finally(_ => {
this.mybotLoad--
});
},
// 与我的机器人聊天
chatMybot(userid) {
this.$store.dispatch("openDialogUserid", userid).catch(({msg}) => {
$A.modalError(msg || this.$L('打开会话失败'))
});
},
// 添加修改我的机器人
addMybot(info) {
this.mybotModifyData = this.enhanceMybotItem(info)
this.mybotModifyShow = true;
},
// 删除我的机器人
delMybot(info) {
$A.modalInput({
title: `删除机器人:${info.name}`,
placeholder: `请输入备注原因`,
okText: "删除",
okType: "error",
onOk: remark => {
if (!remark) {
return `请输入备注原因`
}
return new Promise((resolve, reject) => {
this.$store.dispatch("call", {
url: 'users/bot/delete',
data: {
id: info.id,
remark
}
}).then(({msg}) => {
const index = this.mybotList.findIndex(item => item.id === info.id);
if (index > -1) {
this.mybotList.splice(index, 1);
}
$A.messageSuccess(msg);
resolve();
}).catch(({msg}) => {
reject(msg);
});
})
}
});
},
// 添加/修改我的机器人
onMybotModify() {
this.mybotModifyLoad++
this.$store.dispatch("editUserBot", this.mybotModifyData).then(({data, msg}) => {
const botData = this.enhanceMybotItem(data);
const index = this.mybotList.findIndex(item => item.id === botData.id);
if (index > -1) {
this.mybotList.splice(index, 1, botData);
} else {
this.mybotList.unshift(botData);
}
this.mybotModifyShow = false;
this.mybotModifyData = {};
$A.messageSuccess(msg);
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.mybotModifyLoad--;
});
},
// 获取AI标签
getAITags() {
this.$store.dispatch("call", {
url: 'system/setting/aibot_models',
}).then(({data}) => {
this.handleAITags(data);
});
},
// 处理AI标签
handleAITags(data) {
for (let key in data) {
const match = key.match(/^(.*?)_models$/);
if (match) {
const value = match[1];
this.aibotList.map(h => {
if (h.value == value) {
const items = AIModelNames(data[key])
h.tags = items.map(item => item.label);
h.tag = data[key.slice(0, -1)];
items.some(item => {
if (item.value == h.tag) {
h.tag = item.label;
return true;
}
})
}
});
}
}
},
// 开始聊天
onGoToChat(type) {
let dialogId = 0;
this.cacheDialogs.some(h => {
if (h.email == `ai-${type}@bot.system`) {
dialogId = h.id;
return true;
}
})
if (dialogId) {
this.$store.dispatch("openDialog", dialogId)
return
}
//
this.aibotDialogSearchLoad = type;
this.$store.dispatch("call", {
url: 'users/search/ai',
data: {type},
}).then(({data}) => {
this.$store.dispatch("openDialogUserid", data.userid).catch(({msg}) => {
$A.modalError(msg)
}).finally(_ => {
this.aibotDialogSearchLoad = '';
});
}).catch(({msg}) => {
this.aibotDialogSearchLoad = '';
$A.messageError(msg || '机器人暂未开启');
});
},
// 会议
onMeeting(name) {
switch (name) {
case 'createMeeting':
emitter.emit('addMeeting', {
type: 'create',
userids: [this.userId],
});
break;
case 'joinMeeting':
emitter.emit('addMeeting', {
type: 'join',
});
break;
}
},
// 扫一扫
scanResult(text) {
const arr = (text + "").match(/^https?:\/\/(.*?)\/login\?qrcode=(.*?)$/)
if (arr) {
// 扫码登录
if ($A.getDomain(text) != $A.getDomain($A.mainUrl())) {
let content = this.$L('请确认扫码的服务器与当前服务器一致')
content += `<br/>${this.$L('二维码服务器')}: ${$A.getDomain(text)}`
content += `<br/>${this.$L('当前服务器')}: ${$A.getDomain($A.mainUrl())}`
$A.modalWarning({
language: false,
title: this.$L('扫码登录'),
content
})
return
}
this.scanLoginCode = arr[2];
this.scanLoginShow = true;
return
}
if (/^https?:\/\//i.test(text)) {
// 打开链接
this.$store.dispatch('openAppChildPage', {
pageType: 'app',
pageTitle: ' ',
url: 'web.js',
params: {
url: text
},
});
}
},
// 扫描登录提交
scanLoginSubmit() {
if (this.scanLoginLoad === true) {
return
}
this.scanLoginLoad = true
//
this.$store.dispatch("call", {
url: "users/login/qrcode",
data: {
type: "login",
code: this.scanLoginCode,
}
}).then(({msg}) => {
this.scanLoginShow = false
$A.messageSuccess(msg)
}).catch(({msg}) => {
$A.messageError(msg)
}).finally(_ => {
this.scanLoginLoad = false
});
},
// 打开明细
openDetail(desc) {
$A.modalInfo({
content: desc,
});
},
// 前往接龙与投票
goWordChainAndVote() {
return new Promise((resolve, reject) => {
if (this.sendData.length === 0) {
$A.messageError("请选择对话或成员");
reject()
return
}
const dialog_id = Number(this.sendData[0].replace('d:', ''))
this.$store.dispatch("openDialog", dialog_id).then(async () => {
await new Promise(resolve => setTimeout(resolve, 300));
requestAnimationFrame(_ => {
const type = this.sendType == 'word-chain' ? 'dialogDroupWordChain' : 'dialogGroupVote'
this.$store.state[type] = {type: 'create', dialog_id: dialog_id}
})
})
resolve()
})
}
}
}
</script>