Merge commit 'f57d3cf02c50d8555471ec65091caef1dbdd4cc1' into pro
@ -868,6 +868,7 @@ class DialogController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} api/dialog/msg/sendfiles 17. 群发文件上传
|
||||
* @api {post} api/dialog/msg/sendfiles 18. 群发文件上传
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
@ -1728,7 +1729,7 @@ class DialogController extends AbstractController
|
||||
$user = User::auth();
|
||||
//
|
||||
$dialog_id = intval(Request::input('dialog_id'));
|
||||
$userids = Request::input('userids');
|
||||
$userids = Base::json2array(Request::input('userids'));
|
||||
//
|
||||
if (!is_array($userids)) {
|
||||
return Base::retError('请选择群成员');
|
||||
@ -1766,7 +1767,7 @@ class DialogController extends AbstractController
|
||||
$user = User::auth();
|
||||
//
|
||||
$dialog_id = intval(Request::input('dialog_id'));
|
||||
$userids = Request::input('userids');
|
||||
$userids = Base::json2array(Request::input('userids'));
|
||||
//
|
||||
$type = 'remove';
|
||||
if (empty($userids)) {
|
||||
@ -1886,4 +1887,76 @@ class DialogController extends AbstractController
|
||||
'list' => $builder->take(20)->get()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} api/dialog/okr/add 39. 创建OKR评论会话
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName okr__add
|
||||
*
|
||||
* @apiParam {String} name 标题
|
||||
* @apiParam {Number} link_id 关联id
|
||||
* @apiParam {Array} userids 群成员,格式: [userid1, userid2, userid3]
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function okr__add()
|
||||
{
|
||||
$user = User::auth();
|
||||
//
|
||||
$name = trim(Request::input('name'));
|
||||
$link_id = intval(Request::input('link_id'));
|
||||
$userids = Request::input('userids');
|
||||
//
|
||||
if (empty($name)) {
|
||||
return Base::retError('群名称至少2个字');
|
||||
}
|
||||
//
|
||||
$dialog = WebSocketDialog::createGroup($name, $userids, 'okr', $user->userid);
|
||||
if (empty($dialog)) {
|
||||
return Base::retError('创建群组失败');
|
||||
}
|
||||
if ($link_id) {
|
||||
$dialog->link_id = $link_id;
|
||||
$dialog->save();
|
||||
}
|
||||
return Base::retSuccess('创建成功', $dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} api/dialog/okr/push 40. 推送OKR相关信息
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup dialog
|
||||
* @apiName okr__push
|
||||
*
|
||||
* @apiParam {String} text 发送内容
|
||||
* @apiParam {Number} userid 成员ID
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function okr__push()
|
||||
{
|
||||
User::auth();
|
||||
$text = trim(Request::input('text'));
|
||||
$userid = intval(Request::input('userid'));
|
||||
//
|
||||
$botUser = User::botGetOrCreate('okr-alert');
|
||||
if (empty($botUser)) {
|
||||
return Base::retError('机器人不存在');
|
||||
}
|
||||
//
|
||||
$dialog = WebSocketDialog::checkUserDialog($botUser, $userid);
|
||||
if ($dialog) {
|
||||
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid);
|
||||
}
|
||||
return Base::retSuccess('success', $dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,6 +328,8 @@ class UsersController extends AbstractController
|
||||
$data = $user->toArray();
|
||||
$data['nickname_original'] = $user->getRawOriginal('nickname');
|
||||
$data['department_name'] = $user->getDepartmentName();
|
||||
// 适用默认部门下第1级负责人才能添加部门OKR
|
||||
$data['department_owner'] = UserDepartment::where('parent_id',0)->where('owner_userid', $user->userid())->exists();
|
||||
return Base::retSuccess('success', $data);
|
||||
}
|
||||
|
||||
@ -538,6 +540,16 @@ class UsersController extends AbstractController
|
||||
$query->select('userid')->from('web_socket_dialog_users')->where('dialog_id', $keys['dialog_id']);
|
||||
});
|
||||
}
|
||||
if ($keys['departments']) {
|
||||
if (!is_array($keys['departments'])) {
|
||||
$keys['departments'] = explode(",", $keys['departments']);
|
||||
}
|
||||
$builder->where(function($query) use ($keys) {
|
||||
foreach ($keys['departments'] AS $department) {
|
||||
$query->orWhereRaw("FIND_IN_SET('{$department}', department)");
|
||||
}
|
||||
});
|
||||
}
|
||||
if (in_array($sorts['az'], ['asc', 'desc'])) {
|
||||
$builder->orderBy('az', $sorts['az']);
|
||||
} else {
|
||||
@ -601,7 +613,10 @@ class UsersController extends AbstractController
|
||||
*/
|
||||
public function basic()
|
||||
{
|
||||
User::auth();
|
||||
$sharekey = Request::header('Sharekey');
|
||||
if(empty($sharekey) || !Meeting::getShareInfo($sharekey)){
|
||||
User::auth();
|
||||
}
|
||||
//
|
||||
$userid = Request::input('userid');
|
||||
$array = Base::json2array($userid);
|
||||
@ -1108,6 +1123,8 @@ class UsersController extends AbstractController
|
||||
* - join: 加入会议,有效参数:meetingid (必填)
|
||||
* @apiParam {String} [meetingid] 频道ID(不是数字)
|
||||
* @apiParam {String} [name] 会话ID
|
||||
* @apiParam {String} [sharekey] 分享的key
|
||||
* @apiParam {String} [username] 用户名称
|
||||
* @apiParam {Array} [userids] 邀请成员
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
@ -1116,12 +1133,20 @@ class UsersController extends AbstractController
|
||||
*/
|
||||
public function meeting__open()
|
||||
{
|
||||
$user = User::auth();
|
||||
//
|
||||
$type = trim(Request::input('type'));
|
||||
$meetingid = trim(Request::input('meetingid'));
|
||||
$name = trim(Request::input('name'));
|
||||
$userids = Request::input('userids');
|
||||
$sharekey = trim(Request::input('sharekey'));
|
||||
$username = trim(Request::input('username'));
|
||||
$user = null;
|
||||
if(!empty($sharekey) && $type === 'join'){
|
||||
if(!Meeting::getShareInfo($sharekey)){
|
||||
return Base::retError('分享链接已过期');
|
||||
}
|
||||
}else{
|
||||
$user = User::auth();
|
||||
}
|
||||
$isCreate = false;
|
||||
// 创建、加入
|
||||
if ($type === 'join') {
|
||||
@ -1131,13 +1156,13 @@ class UsersController extends AbstractController
|
||||
}
|
||||
} elseif ($type === 'create') {
|
||||
$meetingid = strtoupper(Base::generatePassword(11, 1));
|
||||
$name = $name ?: "{$user->nickname} 发起的会议";
|
||||
$name = $name ?: "{$user?->nickname} 发起的会议";
|
||||
$channel = "DooTask:" . substr(md5($meetingid . env("APP_KEY")), 16);
|
||||
$meeting = Meeting::createInstance([
|
||||
'meetingid' => $meetingid,
|
||||
'name' => $name,
|
||||
'channel' => $channel,
|
||||
'userid' => $user->userid
|
||||
'userid' => $user?->userid
|
||||
]);
|
||||
$meeting->save();
|
||||
$isCreate = true;
|
||||
@ -1153,7 +1178,10 @@ class UsersController extends AbstractController
|
||||
if (empty($meetingSetting['appid']) || empty($meetingSetting['app_certificate'])) {
|
||||
return Base::retError('会议功能配置错误,请联系管理员');
|
||||
}
|
||||
$uid = intval(str_pad( Request::header('fd'), 6, 9, STR_PAD_LEFT) . $user->userid);
|
||||
$uid = intval(str_pad(Base::generatePassword(4,1), 9, 8, STR_PAD_LEFT));
|
||||
if($user){
|
||||
$uid = intval(str_pad(Request::header('fd'), 5, 9, STR_PAD_LEFT).$user->userid);
|
||||
}
|
||||
try {
|
||||
$service = new AgoraTokenGenerator($meetingSetting['appid'], $meetingSetting['app_certificate'], $meeting->channel, $uid);
|
||||
} catch (\Exception $e) {
|
||||
@ -1170,7 +1198,8 @@ class UsersController extends AbstractController
|
||||
if (!User::whereUserid($userid)->exists()) {
|
||||
continue;
|
||||
}
|
||||
$dialog = WebSocketDialog::checkUserDialog($user, $userid);
|
||||
$botUser = User::botGetOrCreate('meeting-alert');
|
||||
$dialog = WebSocketDialog::checkUserDialog($botUser, $userid);
|
||||
if ($dialog) {
|
||||
$res = WebSocketDialogMsg::sendMsg(null, $dialog->id, 'meeting', $data, $user->userid);
|
||||
if (Base::isSuccess($res)) {
|
||||
@ -1182,13 +1211,68 @@ class UsersController extends AbstractController
|
||||
//
|
||||
$data['appid'] = $meetingSetting['appid'];
|
||||
$data['uid'] = $uid;
|
||||
$data['userimg'] = $user->userimg;
|
||||
$data['nickname'] = $user->nickname;
|
||||
$data['userimg'] = $sharekey ? Base::fillUrl('avatar/'.$username.'.png') : $user?->userimg;
|
||||
$data['nickname'] = $sharekey ? $username : $user?->nickname;
|
||||
$data['token'] = $token;
|
||||
$data['msgs'] = $msgs;
|
||||
//
|
||||
Meeting::setTouristInfo($data);
|
||||
//
|
||||
return Base::retSuccess('success', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/meeting/link 16. 【会议】获取分享链接
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup users
|
||||
* @apiName meeting__link
|
||||
*
|
||||
* @apiParam {String} meetingid 频道ID(不是数字)
|
||||
* @apiParam {String} [sharekey] 分享的key
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function meeting__link()
|
||||
{
|
||||
$meetingid = trim(Request::input('meetingid'));
|
||||
$sharekey = trim(Request::input('sharekey'));
|
||||
if(empty($sharekey) || !Meeting::getShareInfo($sharekey)){
|
||||
User::auth();
|
||||
}
|
||||
$meeting = Meeting::whereMeetingid($meetingid)->first();
|
||||
if (empty($meeting)) {
|
||||
return Base::retError('频道ID不存在');
|
||||
}
|
||||
return Base::retSuccess('success', $meeting->getShareLink());
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/meeting/tourist 16. 【会议】游客信息
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup users
|
||||
* @apiName meeting__tourist
|
||||
*
|
||||
* @apiParam {String} tourist_id 游客ID
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function meeting__tourist()
|
||||
{
|
||||
$touristId = trim(Request::input('tourist_id'));
|
||||
if ($touristInfo = Meeting::getTouristInfo($touristId)) {
|
||||
return Base::retSuccess('success', $touristInfo);
|
||||
}
|
||||
return Base::retError('Id不存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/meeting/invitation 17. 【会议】发送邀请
|
||||
*
|
||||
@ -1222,7 +1306,8 @@ class UsersController extends AbstractController
|
||||
if (!User::whereUserid($userid)->exists()) {
|
||||
continue;
|
||||
}
|
||||
$dialog = WebSocketDialog::checkUserDialog($user, $userid);
|
||||
$botUser = User::botGetOrCreate('meeting-alert');
|
||||
$dialog = WebSocketDialog::checkUserDialog($botUser, $userid);
|
||||
if ($dialog) {
|
||||
$res = WebSocketDialogMsg::sendMsg(null, $dialog->id, 'meeting', $data, $user->userid);
|
||||
if (Base::isSuccess($res)) {
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Cache;
|
||||
use App\Module\Base;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* App\Models\Meeting
|
||||
*
|
||||
@ -30,5 +34,58 @@ namespace App\Models;
|
||||
*/
|
||||
class Meeting extends AbstractModel
|
||||
{
|
||||
const CACHE_KEY = 'meeting_share_link_code';
|
||||
const CACHE_EXPIRED_TIME = 6; // 小时
|
||||
|
||||
/**
|
||||
* 获取分享链接
|
||||
* @return mixed
|
||||
*/
|
||||
public function getShareLink()
|
||||
{
|
||||
$code = base64_encode("{$this->meetingid}" . Base::generatePassword());
|
||||
Cache::put(self::CACHE_KEY.'_'.$code, [
|
||||
'id' => $this->id,
|
||||
'meetingid' => $this->meetingid,
|
||||
'channel' => $this->channel,
|
||||
], Carbon::now()->addHours(self::CACHE_EXPIRED_TIME));
|
||||
return Base::fillUrl("meeting/{$this->meetingid}/".$code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分享信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getShareInfo($code)
|
||||
{
|
||||
if(Cache::has(self::CACHE_KEY.'_'.$code)){
|
||||
return Cache::get(self::CACHE_KEY.'_'.$code);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存访客信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function setTouristInfo($data)
|
||||
{
|
||||
Cache::put(Meeting::CACHE_KEY.'_'.$data['uid'], [
|
||||
'uid' => $data['uid'],
|
||||
'userimg' => $data['userimg'],
|
||||
'nickname' => $data['nickname'],
|
||||
], Carbon::now()->addHours(self::CACHE_EXPIRED_TIME));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取访客信息
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getTouristInfo($touristId)
|
||||
{
|
||||
if(Cache::has(Meeting::CACHE_KEY.'_'.$touristId)){
|
||||
return Cache::get(Meeting::CACHE_KEY.'_'.$touristId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,13 +533,17 @@ class User extends AbstractModel
|
||||
return url("images/avatar/default_anon.png");
|
||||
case 'approval-alert@bot.system':
|
||||
return url("images/avatar/default_approval.png");
|
||||
case 'okr-alert@bot.system':
|
||||
return url("images/avatar/default_task.png");
|
||||
case 'ai-openai@bot.system':
|
||||
return url("images/avatar/default_openai.png");
|
||||
case 'ai-claude@bot.system':
|
||||
return url("images/avatar/default_claude.png");
|
||||
case 'bot-manager@bot.system':
|
||||
return url("images/avatar/default_bot.png");
|
||||
}
|
||||
case 'meeting-alert@bot.system':
|
||||
return url("images/avatar/default_meeting.png");
|
||||
}
|
||||
// 生成文字头像
|
||||
if (self::$defaultAvatarMode === 'auto') {
|
||||
return url("avatar/" . urlencode($nickname) . ".png");
|
||||
@ -607,6 +611,32 @@ class User extends AbstractModel
|
||||
])->save();
|
||||
}
|
||||
//
|
||||
switch ($key) {
|
||||
case 'system-msg':
|
||||
$update['nickname'] = '系统消息';
|
||||
break;
|
||||
case 'task-alert':
|
||||
$update['nickname'] = '任务提醒';
|
||||
break;
|
||||
case 'check-in':
|
||||
$update['nickname'] = '签到打卡';
|
||||
break;
|
||||
case 'anon-msg':
|
||||
$update['nickname'] = '匿名消息';
|
||||
break;
|
||||
case 'approval-alert':
|
||||
$update['nickname'] = '审批';
|
||||
break;
|
||||
case 'okr-alert':
|
||||
$update['nickname'] = "OKR提醒";
|
||||
break;
|
||||
case 'bot-manager':
|
||||
$update['nickname'] = '机器人管理';
|
||||
break;
|
||||
case 'meeting-alert':
|
||||
$update['nickname'] = '会议通知';
|
||||
break;
|
||||
}
|
||||
$update['nickname'] = UserBot::systemBotName($email);
|
||||
}
|
||||
if ($update) {
|
||||
|
||||
@ -58,6 +58,7 @@ class UserBot extends AbstractModel
|
||||
'ai-wenxin' => '文心一言',
|
||||
'ai-qianwen' => '通义千问',
|
||||
'bot-manager' => '机器人管理',
|
||||
'meeting-alert' => '会议通知',
|
||||
default => '', // 不是系统机器人时返回空(也可以拿来判断是否是系统机器人)
|
||||
};
|
||||
}
|
||||
|
||||
@ -496,7 +496,7 @@ class WebSocketDialog extends AbstractModel
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->exists()) {
|
||||
if (!WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->exists() && $dialog->group_type != 'okr') {
|
||||
throw new ApiException('不在成员列表内', ['dialog_id' => $dialog_id], -4003);
|
||||
}
|
||||
return $dialog;
|
||||
|
||||
25
cmd
@ -162,20 +162,20 @@ run_exec() {
|
||||
|
||||
run_mysql() {
|
||||
if [ "$1" = "backup" ]; then
|
||||
# 备份数据库
|
||||
database=$(env_get DB_DATABASE)
|
||||
username=$(env_get DB_USERNAME)
|
||||
password=$(env_get DB_PASSWORD)
|
||||
# 备份数据库
|
||||
mkdir -p ${cur_path}/docker/mysql/backup
|
||||
filename="${cur_path}/docker/mysql/backup/${database}_$(date "+%Y%m%d%H%M%S").sql.gz"
|
||||
run_exec mariadb "exec mysqldump --databases $database -u$username -p$password" | gzip > $filename
|
||||
judge "备份数据库"
|
||||
[ -f "$filename" ] && echo -e "备份文件:$filename"
|
||||
elif [ "$1" = "recovery" ]; then
|
||||
# 还原数据库
|
||||
database=$(env_get DB_DATABASE)
|
||||
username=$(env_get DB_USERNAME)
|
||||
password=$(env_get DB_PASSWORD)
|
||||
# 还原数据库
|
||||
mkdir -p ${cur_path}/docker/mysql/backup
|
||||
list=`ls -1 "${cur_path}/docker/mysql/backup" | grep ".sql.gz"`
|
||||
if [ -z "$list" ]; then
|
||||
@ -198,6 +198,24 @@ run_mysql() {
|
||||
run_exec mariadb "gunzip < /$inputname | mysql -u$username -p$password $database"
|
||||
run_exec php "php artisan migrate"
|
||||
judge "还原数据库"
|
||||
elif [ "$1" = "empty" ]; then
|
||||
read -rp "确定要清空数据库吗?(Y/n): " empty
|
||||
[[ -z ${empty} ]] && empty="Y"
|
||||
case $empty in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo -e "${RedBG} 开始清空... ${Font}"
|
||||
;;
|
||||
*)
|
||||
echo -e "${GreenBG} 终止清空。 ${Font}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
./cmd mysql backup
|
||||
$COMPOSE stop mariadb
|
||||
$COMPOSE rm -f mariadb
|
||||
rm -rf "./docker/mysql/data"
|
||||
$COMPOSE up -d mariadb
|
||||
judge "清空数据库"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -331,6 +349,7 @@ if [ $# -gt 0 ]; then
|
||||
run_exec php "composer update"
|
||||
fi
|
||||
run_exec php "php artisan migrate"
|
||||
run_exec nginx "nginx -s reload"
|
||||
restart_php
|
||||
$COMPOSE up -d
|
||||
elif [[ "$1" == "uninstall" ]]; then
|
||||
@ -424,6 +443,8 @@ if [ $# -gt 0 ]; then
|
||||
run_mysql backup
|
||||
elif [ "$1" = "recovery" ]; then
|
||||
run_mysql recovery
|
||||
elif [ "$1" = "empty" ]; then
|
||||
run_mysql empty
|
||||
else
|
||||
e="mysql $@" && run_exec mariadb "$e"
|
||||
fi
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddWebSocketDialogsLinkId extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
Schema::table('web_socket_dialogs', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('web_socket_dialogs', 'link_id')) {
|
||||
$table->bigInteger('link_id')->nullable()->default(0)->after('owner_id')->comment('关联id');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
Schema::table('web_socket_dialogs', function (Blueprint $table) {
|
||||
$table->dropColumn("link_id");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -49,6 +49,7 @@ services:
|
||||
- drawio-webapp
|
||||
- drawio-export
|
||||
- minder
|
||||
- okr
|
||||
- ai
|
||||
restart: unless-stopped
|
||||
|
||||
@ -149,7 +150,7 @@ services:
|
||||
|
||||
approve:
|
||||
container_name: "dootask-approve-${APP_ID}"
|
||||
image: "hitosea2020/go-approve:0.1.4"
|
||||
image: "kuaifan/dooapprove:0.0.2"
|
||||
environment:
|
||||
TZ: "${TIMEZONE:-PRC}"
|
||||
MYSQL_HOST: "${DB_HOST}"
|
||||
@ -172,6 +173,24 @@ services:
|
||||
extnetwork:
|
||||
ipv4_address: "${APP_IPPR}.12"
|
||||
restart: unless-stopped
|
||||
|
||||
okr:
|
||||
container_name: "dootask-okr-${APP_ID}"
|
||||
image: "kuaifan/doookr:0.0.5"
|
||||
environment:
|
||||
TZ: "${TIMEZONE:-PRC}"
|
||||
DOO_TASK_URL: "http://${APP_IPPR}.3"
|
||||
MYSQL_HOST: "${DB_HOST}"
|
||||
MYSQL_PORT: "${DB_PORT}"
|
||||
MYSQL_DBNAME: "${DB_DATABASE}"
|
||||
MYSQL_USERNAME: "${DB_USERNAME}"
|
||||
MYSQL_PASSWORD: "${DB_PASSWORD}"
|
||||
networks:
|
||||
extnetwork:
|
||||
ipv4_address: "${APP_IPPR}.13"
|
||||
depends_on:
|
||||
- mariadb
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
extnetwork:
|
||||
|
||||
@ -184,6 +184,11 @@ server {
|
||||
proxy_pass http://service/api/approve/verifyToken;
|
||||
}
|
||||
|
||||
# OKR
|
||||
location /apps/okr/ {
|
||||
proxy_pass http://okr:5566/apps/okr/;
|
||||
}
|
||||
|
||||
# AI
|
||||
location /ai/ {
|
||||
proxy_http_version 1.1;
|
||||
|
||||
@ -1250,6 +1250,8 @@ Markdown 格式发送
|
||||
退出
|
||||
会议组件加载失败!
|
||||
|
||||
OKR管理
|
||||
OKR结果分析
|
||||
计划时间冲突提示
|
||||
忽略并继续
|
||||
你确定要清除缓存吗?
|
||||
@ -1349,3 +1351,26 @@ AI机器人
|
||||
|
||||
汇报人
|
||||
提交时间
|
||||
|
||||
应用
|
||||
机器人设置
|
||||
去聊天
|
||||
返回
|
||||
会议设置
|
||||
我是一个人工智能助手,为用户提供问题解答和指导。我没有具体的身份,只是一个程序。您有什么问题可以问我哦?
|
||||
我是Claude,一个由Anthropic公司创造出来的AI助手机器人。我的工作是帮助人类,与人对话并给出解答。
|
||||
我是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。
|
||||
我是达摩院自主研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码。
|
||||
机器人暂未开启
|
||||
创建一个全新的会议视频会议,与会者可以在实时中进行面对面的视听交流。通过视频会议平台,参与者可以分享屏幕、共享文档,并与其他与会人员进行讨论和协。
|
||||
加入视频会议,参与已经创建的会议,在会议过程中与其他参会人员进行远程实时视听交流和协作。
|
||||
新会议
|
||||
新建会议
|
||||
LDAP设置
|
||||
邮件管理
|
||||
APP推送
|
||||
流程设置
|
||||
邮件
|
||||
签到
|
||||
签到管理
|
||||
常用
|
||||
@ -16884,6 +16884,28 @@
|
||||
"fr": "Échec du chargement du composant conférence!",
|
||||
"id": "Perakitan perakitan gagal!"
|
||||
},
|
||||
{
|
||||
"key": "OkR管理",
|
||||
"zh": "",
|
||||
"zh-CHT": "OkR管理",
|
||||
"en": "OkR management",
|
||||
"ko": "Okr 매니지먼트",
|
||||
"ja": "OkRマネジメントです",
|
||||
"de": "Das ist OkR.",
|
||||
"fr": "Gestion des OkR",
|
||||
"id": "OkR manajemen"
|
||||
},
|
||||
{
|
||||
"key": "OkR结果分析",
|
||||
"zh": "",
|
||||
"zh-CHT": "OkR結果分析",
|
||||
"en": "Analysis of OkR results",
|
||||
"ko": "Okr 결과 분석",
|
||||
"ja": "OkR結果分析です",
|
||||
"de": "Wenn die ergebnisse umgekehrt sind",
|
||||
"fr": "Analyse des résultats OkR",
|
||||
"id": "Analisis hasil OkR"
|
||||
},
|
||||
{
|
||||
"key": "以下人员已存在任务",
|
||||
"zh": "",
|
||||
@ -17785,5 +17807,247 @@
|
||||
"de": "Zeit bis zur abgabe",
|
||||
"fr": "Heure de soumission",
|
||||
"id": "Waktu pengiriman"
|
||||
},
|
||||
{
|
||||
"key": "OKR管理",
|
||||
"zh": "",
|
||||
"zh-CHT": "OKR管理",
|
||||
"en": "OKR",
|
||||
"ko": "Okr 매니지먼트",
|
||||
"ja": "OKRマネジメントです",
|
||||
"de": "Das ist OKR.",
|
||||
"fr": "Gestion des OKR",
|
||||
"id": "OKR manajemen"
|
||||
},
|
||||
{
|
||||
"key": "OKR结果分析",
|
||||
"zh": "",
|
||||
"zh-CHT": "OKR結果分析",
|
||||
"en": "Analysis of OKR results",
|
||||
"ko": "Okr 결과 분석",
|
||||
"ja": "OKR結果分析です",
|
||||
"de": "Wenn die ergebnisse umgekehrt sind",
|
||||
"fr": "Analyse des résultats OKR",
|
||||
"id": "Analisis hasil OKR"
|
||||
},
|
||||
{
|
||||
"key": "应用",
|
||||
"zh": "",
|
||||
"zh-CHT": "應用",
|
||||
"en": "Application",
|
||||
"ko": "응용",
|
||||
"ja": "応用です",
|
||||
"de": "Anwendung",
|
||||
"fr": "Les applications",
|
||||
"id": "Aplikasi"
|
||||
},
|
||||
{
|
||||
"key": "机器人设置",
|
||||
"zh": "",
|
||||
"zh-CHT": "機器人設置",
|
||||
"en": "Robot setup",
|
||||
"ko": "로봇 설정",
|
||||
"ja": "ロボット設置です",
|
||||
"de": "Ich programmiere roboter.",
|
||||
"fr": "Paramétrage du robot",
|
||||
"id": "Pengaturan robot"
|
||||
},
|
||||
{
|
||||
"key": "去聊天",
|
||||
"zh": "",
|
||||
"zh-CHT": "去聊天",
|
||||
"en": "Go to chat",
|
||||
"ko": "이야기를 나누다",
|
||||
"ja": "おしゃべりに行きます",
|
||||
"de": "Nur zum plaudern.",
|
||||
"fr": "Aller au chat",
|
||||
"id": "Pergi ngobrol"
|
||||
},
|
||||
{
|
||||
"key": "返回",
|
||||
"zh": "",
|
||||
"zh-CHT": "返回",
|
||||
"en": "Back",
|
||||
"ko": "돌아가",
|
||||
"ja": "戻ります",
|
||||
"de": "Abreise.",
|
||||
"fr": "Le retour",
|
||||
"id": "Kembali"
|
||||
},
|
||||
{
|
||||
"key": "会议设置",
|
||||
"zh": "",
|
||||
"zh-CHT": "會議設置",
|
||||
"en": "Meeting setup",
|
||||
"ko": "회의 설정",
|
||||
"ja": "会議のセッティングです",
|
||||
"de": "Set.",
|
||||
"fr": "Configuration des réunions",
|
||||
"id": "Pengaturan pertemuan"
|
||||
},
|
||||
{
|
||||
"key": "我是一个人工智能助手,为用户提供问题解答和指导。我没有具体的身份,只是一个程序。您有什么问题可以问我哦?",
|
||||
"zh": "",
|
||||
"zh-CHT": "我是一個人工智能助手,爲用戶提供問題解答和指導。我沒有具體的身份,只是一個程序。您有什麼問題可以問我哦?",
|
||||
"en": "I'm an AI assistant that provides questions and guidance to users. I don't have a specific identity, just a program. Do you have any questions for me?",
|
||||
"ko": "나는 인공지능 어시스턴트로 사용자에게 질문에 대답하고 안내하는 일을 한다.나는 어떤 정체성도 가지고 있지 않고 단지 하나의 프로그램일 뿐이다.저한테 물어봐도 되겠습니까?",
|
||||
"ja": "私はaiアシスタントをしていて、ユーザーの質問に答えたり指導したりしています。私は特定の身分ではなく、ただのプログラムです。何か質問がありましたら私に聞いてくださいね?",
|
||||
"de": "Ich bin ein assistent der ki, der meinen nutzern rätsel und anleitung gibt. Keine identität, nur ein programm. Haben sie irgendwelche fragen an mich?",
|
||||
"fr": "Je suis un assistant d’ia qui fournit des réponses aux questions et des conseils aux utilisateurs. Je n’ai pas d’identité spécifique, juste un programme. Avez-vous une question à Me Poser?",
|
||||
"id": "Aku asisten ai dengan solusi dan bimbingan untuk pelanggan. Aku tak punya identitas khusus, hanya sebuah program. Anda punya pertanyaan untuk saya?"
|
||||
},
|
||||
{
|
||||
"key": "我是Claude,一个由Anthropic公司创造出来的AI助手机器人。我的工作是帮助人类,与人对话并给出解答。",
|
||||
"zh": "",
|
||||
"zh-CHT": "我是Claude,一個由Anthropic公司創造出來的AI助手機器人。我的工作是幫助人類,與人對話並給出解答。",
|
||||
"en": "I'm Claude, an AI assistant robot created by the Anthropic company. My job is to help people, to talk to people and give answers.",
|
||||
"ko": "저는 anthropic에서 만든 ai 도우미 로봇인 claude입니다.제 일은 사람들을 돕고, 사람들과 대화하고, 답을 주는 것입니다.",
|
||||
"ja": "私はClaudeですAnthropic社のAIアシスタントロボットです私の仕事は人間を助け、対話し、答えを出すことです。",
|
||||
"de": "Ich heiße Claude, ein ai-roboter, entwickelt Von einer firma kröne. Meine aufgabe ist es, den menschen zu helfen, mit ihnen zu sprechen und antworten zu geben.",
|
||||
"fr": "Je suis Claude, un robot assistant AI créé par la société Anthropic. Mon travail est d’aider l’humanité, de lui parler et de lui donner des réponses.",
|
||||
"id": "Aku Claude, robot asisten AI yang diciptakan oleh Anthropic company. Tugasku adalah membantu manusia, berbicara dengan manusia, dan memberi jawaban."
|
||||
},
|
||||
{
|
||||
"key": "我是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。",
|
||||
"zh": "",
|
||||
"zh-CHT": "我是文心一言,英文名是ERNIE Bot。我能夠與人對話互動,回答問題,協助創作,高效便捷地幫助人們獲取信息、知識和靈感。",
|
||||
"en": "My English name is ERNIE Bot. I can interact with people, answer questions, help create, and help people access information, knowledge, and inspiration efficiently and easily.",
|
||||
"ko": "저의 영어 이름은 어니봇 (ernie bot)입니다.저는 사람들과 대화하고 교류할 수 있으며, 질문에 대답할 수 있고, 창작을 도울 수 있으며, 사람들이 효율적이고 편리하게 정보, 지식과 영감을 얻을 수 있도록 도와줍니다.",
|
||||
"ja": "私は文心一言、英語名はERNIE Botです。私は人と対話したり、質問に答えたり、創作を手伝ったり、効率的で便利に人々が情報や知識、インスピレーションを得る手助けをすることができます。",
|
||||
"de": "Entschuldigung, aber ich bin ein guter sprecher. Der englische name ist ERNIE ott. Ich kann mit menschen kommunizieren, fragen beantworten, bei der entwicklung helfen und sie effizient und effizient dabei unterstützen, informationen, Wissen und inspiration zu beschaffen.",
|
||||
"fr": "Je suis wenxin yiyan. Mon nom anglais est ERNIE Bot. Je suis capable de dialoguer et d’interagir avec les gens, de répondre aux questions, d’aider à la création et d’aider les gens à accéder à l’information, à la connaissance et à l’inspiration de manière efficace et pratique.",
|
||||
"id": "Aku ERNIE Bot dalam bahasa inggris. Saya dapat berinteraksi dengan orang-orang, menjawab pertanyaan, membantu menciptakan, dan membantu secara efektif untuk membantu orang mendapatkan informasi, pengetahuan, dan ilham."
|
||||
},
|
||||
{
|
||||
"key": "我是达摩院自主研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码。",
|
||||
"zh": "",
|
||||
"zh-CHT": "我是達摩院自主研發的超大規模語言模型,能夠回答問題、創作文字,還能表達觀點、撰寫代碼。",
|
||||
"en": "I am a large scale language model independently developed by Dharma Institute, which can answer questions, create text, express opinions, and write code.",
|
||||
"ko": "저는 달마원에서 자주적으로 개발한 초대형 규모의 언어 모형입니다. 문제에 대답하고 문자를 창작할 수 있으며, 또한 관점을 표현하고 코드를 작성할 수 있습니다.",
|
||||
"ja": "私は達磨院が独自に開発した超大規模言語モデルで、質問に答えたり、文字を書いたり、意見を述べたり、コードを書いたりすることができます。",
|
||||
"de": "Als sprachmodell, das seit einiger zeit Von der dharma initiative entwickelt wurde, konnte ich fragen beantworten, schreiben, eine meinung äußern und codes schreiben.",
|
||||
"fr": "Je suis un modèle de langage à très grande échelle développé par la maison dharma. Je suis capable de répondre à des questions, de créer des mots, mais aussi d’exprimer des opinions et d’écrire du code.",
|
||||
"id": "Saya adalah model bahasa berukuran besar yang dikembangkan oleh dharma sendiri, menjawab pertanyaan, menulis, mengungkapkan gagasan, dan menulis kode."
|
||||
},
|
||||
{
|
||||
"key": "机器人暂未开启",
|
||||
"zh": "",
|
||||
"zh-CHT": "機器人暫未開啓",
|
||||
"en": "The robot has not been turned on",
|
||||
"ko": "로봇이 아직 켜지지 않았습니다",
|
||||
"ja": "ロボットはまだ起動していません",
|
||||
"de": "Der roboter wird aktiv bleiben",
|
||||
"fr": "Le robot n’est pas activé",
|
||||
"id": "Robot tak bisa dimatikan"
|
||||
},
|
||||
{
|
||||
"key": "创建一个全新的会议视频会议,与会者可以在实时中进行面对面的视听交流。通过视频会议平台,参与者可以分享屏幕、共享文档,并与其他与会人员进行讨论和协。",
|
||||
"zh": "",
|
||||
"zh-CHT": "創建一個全新的會議視頻會議,與會者可以在實時中進行面對面的視聽交流。通過視頻會議平臺,參與者可以分享屏幕、共享文檔,並與其他與會人員進行討論和協。",
|
||||
"en": "Create a new conference video conferencing where attendees can meet face-to-face in real time. Through the video conferencing platform, participants can share screens, share documents, and discuss and collaborate with other participants.",
|
||||
"ko": "실시간 시청각 대면 대화가 가능한 새로운 화상 회의를 만듭니다.화상 회의 플랫폼을 통해 참가자들은 화면을 공유하고 문서를 공유하며 다른 참가자들과 토론하고 협력할 수 있다.",
|
||||
"ja": "参加者同士がリアルタイムで対面でコミュニケーションできる、まったく新しいビデオ会議を作ります。ビデオ会議のプラットフォームを通じて、参加者はスクリーンを共有したり、文書を共有したり、他の参加者と議論を和協することができます。",
|
||||
"de": "Erstellen sie eine neue video-konferenz, bei der die teilnehmer direkten audio-kontakt in echtzeit haben. Auf der videokonferenz können die teilnehmer bildschirm-teile teilen, dokumente teilen und mit den anderen teilnehmern erörtern und diskutieren.",
|
||||
"fr": "Créez une nouvelle vidéoconférence de conférence où les participants peuvent communiquer en face à face en temps réel. La plateforme de visioconférence permet aux participants de partager des écrans, de partager des documents, de discuter et de s’associer avec les autres participants.",
|
||||
"id": "Buatlah konferensi video konferensi yang sama sekali baru di mana peserta dapat bertemu langsung dan saling bertatap muka secara langsung. Melalui platform konferensi video, peserta dapat berbagi layar, berbagi dokumen, dan berunding dengan peserta lain."
|
||||
},
|
||||
{
|
||||
"key": "加入视频会议,参与已经创建的会议,在会议过程中与其他参会人员进行远程实时视听交流和协作。",
|
||||
"zh": "",
|
||||
"zh-CHT": "加入視頻會議,參與已經創建的會議,在會議過程中與其他參會人員進行遠程實時視聽交流和協作。",
|
||||
"en": "Join a video conference, participate in a conference that has already been created, and communicate and collaborate remotely with other attendees in real-time.",
|
||||
"ko": "화상회의에 가입하고 이미 설립된 회의에 참여하며 회의과정에 기타 회의참가자들과 원거리 실시간 시청각 교류와 협력을 진행한다.",
|
||||
"ja": "ビデオ会議に参加して、すでに作成された会議に参加し、会議中に他の参加者と遠隔でリアルタイムでコミュニケーションを取り、協働します。",
|
||||
"de": "Bieten sie videokonferenzen an, nehmen an bereits erstellten Treffen teil, während deren aug - und echtzeit-kommunikation mit anderen teilnehmern durchgeführt wird.",
|
||||
"fr": "Rejoignez la vidéoconférence et participez à une Réunion déjà créée. Communiquez et collaborez à distance et en temps réel avec les autres participants au cours de la Réunion.",
|
||||
"id": "Bergabunglah dengan konferensi video untuk berperan serta dalam konferensi yang telah diciptakan dengan mengadakan komunikasi audiovisual dan kolaborasi jarak jauh dengan partisipan lain selama sesi."
|
||||
},
|
||||
{
|
||||
"key": "新建会议",
|
||||
"zh": "",
|
||||
"zh-CHT": "新建會議",
|
||||
"en": "New meeting",
|
||||
"ko": "새 회의",
|
||||
"ja": "会議を新設します",
|
||||
"de": "Neu installierte sitzung",
|
||||
"fr": "Nouvelle conférence créée",
|
||||
"id": "Konferensi bangunan baru"
|
||||
},
|
||||
{
|
||||
"key": "LDAP设置",
|
||||
"zh": "",
|
||||
"zh-CHT": "LDAP設置",
|
||||
"en": "LDAP Settings",
|
||||
"ko": "Ldap 설정",
|
||||
"ja": "LDAP設定です",
|
||||
"de": "Das ist eine ldap-einstellung",
|
||||
"fr": "Paramètres de LDAP",
|
||||
"id": "Pengaturan LDAP"
|
||||
},
|
||||
{
|
||||
"key": "邮件管理",
|
||||
"zh": "",
|
||||
"zh-CHT": "郵件管理",
|
||||
"en": "Mail",
|
||||
"ko": "우편물 관리",
|
||||
"ja": "メール管理です",
|
||||
"de": "Mails management und so weiter.",
|
||||
"fr": "Gestion du courrier",
|
||||
"id": "Manajemen surat"
|
||||
},
|
||||
{
|
||||
"key": "流程设置",
|
||||
"zh": "",
|
||||
"zh-CHT": "流程設置",
|
||||
"en": "Process setup",
|
||||
"ko": "프로세스 설정",
|
||||
"ja": "プロセス設定です",
|
||||
"de": "Prozedere",
|
||||
"fr": "Configuration du processus",
|
||||
"id": "Pengaturan arus"
|
||||
},
|
||||
{
|
||||
"key": "邮件",
|
||||
"zh": "",
|
||||
"zh-CHT": "郵件",
|
||||
"en": "Mail",
|
||||
"ko": "메일",
|
||||
"ja": "メールです",
|
||||
"de": "E-mail?",
|
||||
"fr": "Le courrier",
|
||||
"id": "Email"
|
||||
},
|
||||
{
|
||||
"key": "签到",
|
||||
"zh": "",
|
||||
"zh-CHT": "簽到",
|
||||
"en": "Sign-in",
|
||||
"ko": "서명 해 주시기 바 랍니다",
|
||||
"ja": "サインインします",
|
||||
"de": "Trag dich ein.",
|
||||
"fr": "Pointage",
|
||||
"id": "Tanda tangan"
|
||||
},
|
||||
{
|
||||
"key": "签到管理",
|
||||
"zh": "",
|
||||
"zh-CHT": "簽到管理",
|
||||
"en": "Check-in",
|
||||
"ko": "로그인 관리",
|
||||
"ja": "サインイン管理",
|
||||
"de": "Trag die unterschrift ins management",
|
||||
"fr": "Gestion des inscriptions",
|
||||
"id": "Manajemen tanda tangan masuk"
|
||||
},
|
||||
{
|
||||
"key": "常用",
|
||||
"zh": "",
|
||||
"zh-CHT": "常用",
|
||||
"en": "In common use",
|
||||
"ko": "흔히 사용하는",
|
||||
"ja": "よく使います",
|
||||
"de": "Verwende sie.",
|
||||
"fr": "Couramment utilisés",
|
||||
"id": "Umum"
|
||||
}
|
||||
]
|
||||
@ -87,5 +87,8 @@
|
||||
"url": "https://www.dootask.com/desktop/publish"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"dependencies": {
|
||||
"@micro-zoe/micro-app": "^0.8.11"
|
||||
}
|
||||
}
|
||||
|
||||
96
public/docs/assets/main.bundle.js
vendored
1
public/docs/assets/main.css
vendored
@ -49,7 +49,6 @@ input[type="date"] {
|
||||
src: url('./glyphicons-halflings-regular.eot');
|
||||
src: url('./glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
|
||||
url('./glyphicons-halflings-regular.woff') format('woff'),
|
||||
url('./glyphicons-halflings-regular.woff2') format('woff2'),
|
||||
url('./glyphicons-halflings-regular.ttf') format('truetype'),
|
||||
url('./glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
|
||||
}
|
||||
|
||||
@ -5,30 +5,20 @@
|
||||
<meta name="description" content="APP接口文档">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link href="assets/bootstrap.min.css?v=1691302932133" rel="stylesheet" media="screen">
|
||||
<link href="assets/prism.css?v=1691302932133" rel="stylesheet" />
|
||||
<link href="assets/prism-toolbar.css?v=1691302932133" rel="stylesheet" />
|
||||
<link href="assets/prism-diff-highlight.css?v=1691302932133" rel="stylesheet" />
|
||||
<link href="assets/main.css?v=1691302932133" rel="stylesheet" media="screen, print">
|
||||
<link href="assets/favicon.ico?v=1691302932133" rel="icon" type="image/x-icon">
|
||||
<link href="assets/apple-touch-icon.png?v=1691302932133" rel="apple-touch-icon" sizes="180x180">
|
||||
<link href="assets/favicon-32x32.png?v=1691302932133" rel="icon" type="image/png" sizes="32x32">
|
||||
<link href="assets/favicon-16x16.png?v=1691302932133" rel="icon" type="image/png" sizes="16x16">
|
||||
<link href="assets/bootstrap.min.css" rel="stylesheet" media="screen">
|
||||
<link href="assets/prism.css" rel="stylesheet" />
|
||||
<link href="assets/main.css" rel="stylesheet" media="screen, print">
|
||||
<link href="assets/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link href="assets/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180">
|
||||
<link href="assets/favicon-32x32.png" rel="icon" type="image/png" sizes="32x32">
|
||||
<link href="assets/favicon-16x16.png"rel="icon" type="image/png" sizes="16x16">
|
||||
</head>
|
||||
|
||||
<body class="container-fluid">
|
||||
|
||||
<!-- SIDENAV -->
|
||||
<script id="template-sidenav" type="text/x-handlebars-template">
|
||||
<nav id="scrollingNav" class="col-sm-3 col-lg-2 sidebar-offcanvas">
|
||||
<div class="nav-toggle visible-xs">
|
||||
<button type="button" class="btn btn-link" data-toggle="offcanvas">
|
||||
<span class="sr-only">{{__ "Toggle navigation"}}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
<nav id="scrollingNav">
|
||||
<div class="sidenav-search">
|
||||
<input class="form-control search" data-action='filter-search' type="text" placeholder="{{__ "Filter..."}}">
|
||||
<span class="search-reset">x</span>
|
||||
@ -155,12 +145,7 @@
|
||||
<p>{{{nl2br article.description}}}</p>
|
||||
{{/if}}
|
||||
<span class="method meth-{{toLowerCase article.type}}">{{article.type}}</span>
|
||||
<pre
|
||||
data-type="{{toLowerCase article.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-http">{{article.url}}</code></pre>
|
||||
<pre data-type="{{toLowerCase article.type}}"><code class="language-http">{{article.url}}</code></pre>
|
||||
|
||||
{{#if article.permission}}
|
||||
<p>
|
||||
@ -189,12 +174,7 @@
|
||||
<div class="tab-content">
|
||||
{{#each article.examples}}
|
||||
<div class="tab-pane{{#ifCond @index '==' 0}} active{{/ifCond}}" id="examples-{{../id}}-{{@index}}">
|
||||
<pre
|
||||
data-type="{{type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{type}}">{{content}}</code></pre>
|
||||
<pre data-type="{{type}}"><code class="language-{{type}}">{{content}}</code></pre>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@ -227,9 +207,8 @@
|
||||
<tbody>
|
||||
{{#each params}}
|
||||
<tr>
|
||||
<td class="code">
|
||||
{{{nestObject this}}}
|
||||
{{#if this.optional}}
|
||||
<td class="code">{{this.field}}
|
||||
{{#if optional}}
|
||||
<span class="label optional">{{__ "optional"}}</span>
|
||||
{{else}}
|
||||
{{#if ../template.showRequiredLabels}}
|
||||
@ -273,9 +252,8 @@
|
||||
<tbody>
|
||||
{{#each params}}
|
||||
<tr>
|
||||
<td class="code">
|
||||
{{{nestObject this}}}
|
||||
{{#if this.optional}}
|
||||
<td class="code">{{this.field}}
|
||||
{{#if optional}}
|
||||
<span class="label optional">{{__ "optional"}}</span>
|
||||
{{else}}
|
||||
{{#if ../template.showRequiredLabels}}
|
||||
@ -324,8 +302,7 @@
|
||||
<tbody>
|
||||
{{#each this}}
|
||||
<tr>
|
||||
<td class="code">
|
||||
{{{nestObject this}}}
|
||||
<td class="code">{{{splitFill field "." " "}}}
|
||||
{{#if optional}}
|
||||
<span class="label optional">{{__ "optional"}}</span>
|
||||
{{else}}
|
||||
@ -366,12 +343,7 @@
|
||||
<div class="tab-content">
|
||||
{{#each params.examples}}
|
||||
<div class="tab-pane{{#ifCond @index '==' 0}} active{{/ifCond}}" id="{{../section}}-examples-{{../id}}-{{@index}}">
|
||||
<pre
|
||||
data-type="{{type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{type}}">{{reformat content type}}</code></pre>
|
||||
<pre data-type="{{type}}"><code class="language-{{type}}">{{reformat content type}}</code></pre>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@ -441,13 +413,12 @@
|
||||
<div class="{{../id}}-sample-request-param-fields {{../id}}-sample-header-content-type-fields">
|
||||
{{#each this}}
|
||||
<div class="form-group">
|
||||
{{#ifNotObject type}}
|
||||
<label class="col-md-3 control-label" for="sample-request-param-field-{{field}}">{{field}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{{type}}}</div>
|
||||
{{#if allowedValues}}
|
||||
<div class="input-group-addon sample-request-select">
|
||||
<select class="form-control" data-name="{{dot2bracket this}}" data-family="query" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<select class="form-control" data-name="{{field}}" data-family="query" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<option value="" class="empty"><{{__ "No value"}}></option>
|
||||
{{#each allowedValues}}
|
||||
<option {{#ifCond ../defaultValue '===' this}} selected {{/ifCond}}value="{{{removeDblQuotes this}}}">{{{removeDblQuotes this}}}</option>
|
||||
@ -461,15 +432,14 @@
|
||||
class="{{#ifCond type '!==' 'Boolean'}}form-control{{/ifCond}} sample-request-param"
|
||||
type="{{setInputType type}}"
|
||||
value="{{#if defaultValue}}{{ defaultValue }}{{/if}}"
|
||||
placeholder="{{#if defaultValue}}{{ defaultValue }}{{/if}}"
|
||||
data-name="{{dot2bracket this}}"
|
||||
placeholder="{{#if defaultValue}}{{ defaultValue }}{{else}}{{field}}{{/if}}"
|
||||
data-name="{{field}}"
|
||||
data-family="query"
|
||||
data-group="{{@../index}}"
|
||||
{{#if optional}}data-optional="true"{{/if}}>
|
||||
</div></div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/ifNotObject}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@ -482,13 +452,12 @@
|
||||
<div class="{{../id}}-sample-request-param-fields {{../id}}-sample-header-content-type-fields">
|
||||
{{#each article.query}}
|
||||
<div class="form-group">
|
||||
{{#ifNotObject type}}
|
||||
<label class="col-md-3 control-label" for="sample-request-param-field-{{field}}">{{field}}{{#if optional}} ({{__ "optional"}}){{/if}}</label>
|
||||
<div class="input-group col-md-6">
|
||||
<div class="input-group-addon">{{{type}}}</div>
|
||||
{{#if allowedValues}}
|
||||
<div class="input-group-addon sample-request-select">
|
||||
<select class="form-control" data-name="{{dot2bracket this}}" data-family="query" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<select class="form-control" data-name="{{field}}" data-family="query" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<option value="" class="empty"><{{__ "No value"}}></option>
|
||||
{{#each allowedValues}}
|
||||
<option {{#ifCond ../defaultValue '===' this}} selected {{/ifCond}}value="{{{removeDblQuotes this}}}">{{{removeDblQuotes this}}}</option>
|
||||
@ -502,15 +471,14 @@
|
||||
class="{{#ifCond type '!==' 'Boolean'}}form-control{{/ifCond}} sample-request-input"
|
||||
type="{{setInputType type}}"
|
||||
value="{{#if defaultValue}}{{ defaultValue }}{{/if}}"
|
||||
placeholder="{{#if defaultValue}}{{ defaultValue }}{{/if}}"
|
||||
data-name="{{dot2bracket this}}"
|
||||
placeholder="{{#if defaultValue}}{{ defaultValue }}{{else}}{{field}}{{/if}}"
|
||||
data-name="{{field}}"
|
||||
data-family="query"
|
||||
data-group="{{@../index}}"
|
||||
{{#if optional}}data-optional="true"{{/if}}>
|
||||
</div></div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/ifNotObject}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@ -543,13 +511,12 @@
|
||||
<div hidden class="col-md-9" id="sample-request-body-form-input-{{this.id}}">
|
||||
{{#each article.body}}
|
||||
<div class="form-group">
|
||||
{{#ifNotObject type}}
|
||||
<label class="col-md-3 control-label" for="sample-request-param-field-{{field}}">{{field}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{{type}}}</div>
|
||||
{{#if allowedValues}}
|
||||
<div class="input-group-addon sample-request-select">
|
||||
<select class="form-control" data-name="{{dot2bracket this}}" data-family="body" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<select class="form-control" data-name="{{field}}" data-family="body" data-group="{{@../index}}" {{#if optional}}data-optional="true"{{/if}}>
|
||||
<option value="" class="empty"><{{__ "No value"}}></option>
|
||||
{{#each allowedValues}}
|
||||
<option {{#ifCond ../defaultValue '===' this}} selected {{/ifCond}}value="{{{removeDblQuotes this}}}">{{{removeDblQuotes this}}}</option>
|
||||
@ -564,15 +531,14 @@
|
||||
type="{{setInputType type}}"
|
||||
value="{{#ifCond type '!==' 'Boolean'}}{{#if defaultValue}}{{ defaultValue }}{{/if}}{{/ifCond}}"
|
||||
{{#if checked}}checked{{/if}}
|
||||
placeholder="{{#if defaultValue}}{{ defaultValue }}{{/if}}"
|
||||
placeholder="{{field}}"
|
||||
data-family="body"
|
||||
data-name="{{dot2bracket this}}"
|
||||
data-name="{{field}}"
|
||||
data-content-type="form"
|
||||
{{#if optional}}data-optional="true"{{/if}}>
|
||||
</div></div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/ifNotObject}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@ -589,12 +555,7 @@
|
||||
{{__ "Response"}}
|
||||
<button class="btn btn-default btn-xs pull-right sample-request-clear">X</button>
|
||||
</h3>
|
||||
<pre
|
||||
data-type="json"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-json sample-request-response-json"></code></pre>
|
||||
<pre data-type="json"><code class="language-json sample-request-response-json"></code></pre>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
@ -636,13 +597,7 @@
|
||||
{{/if}}
|
||||
|
||||
<span class="method meth-{{toLowerCase compare.type}}">{{compare.type}}</span>
|
||||
<pre
|
||||
data-type="{{toLowerCase article.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
class="language-html"
|
||||
>{{{showDiff article.url compare.url}}}</pre>
|
||||
<pre data-type="{{toLowerCase article.type}}" class="language-html">{{{showDiff article.url compare.url}}}</pre>
|
||||
|
||||
{{subTemplate "article-compare-permission" article=article compare=compare}}
|
||||
|
||||
@ -650,19 +605,19 @@
|
||||
{{#each_compare_title article.examples compare.examples}}
|
||||
{{#if typeSame}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#compare-examples-{{../article.id}}-{{index}}" role="tab" data-toggle="tab">{{{showDiff source.title compare.title}}}</a>
|
||||
<a href="#compare-examples-{{../../article.id}}-{{index}}" role="tab" data-toggle="tab">{{{showDiff source.title compare.title}}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeIns}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#compare-examples-{{../article.id}}-{{index}}"><ins>{{{source.title}}}</ins></a>
|
||||
<a href="#compare-examples-{{../../article.id}}-{{index}}"><ins>{{{source.title}}}</ins></a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeDel}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#compare-examples-{{../article.id}}-{{index}}"><del>{{{compare.title}}}</del></a>
|
||||
<a href="#compare-examples-{{../../article.id}}-{{index}}"><del>{{{compare.title}}}</del></a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each_compare_title}}
|
||||
@ -672,45 +627,27 @@
|
||||
{{#each_compare_title article.examples compare.examples}}
|
||||
|
||||
{{#if typeSame}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{source.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-diff-{{source.type}} diff-highlight">{{{showDiff source.content compare.content "code"}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{source.type}}" class="language-{{source.type}}">{{{showDiff source.content compare.content}}}</pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeIns}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{source.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{source.type}}">{{{source.content}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{source.type}}" class="language-{{source.type}}">{{{source.content}}}</pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeDel}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{compare.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{source.type}}">{{{compare.content}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{compare.type}}" class="language-{{source.type}}">{{{compare.content}}}</pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{/each_compare_title}}
|
||||
</div>
|
||||
|
||||
{{subTemplate "article-compare-param-block" source=article.header compare=compare.header _hasType=_hasTypeInHeaderFields section="header"}}
|
||||
{{subTemplate "article-compare-param-block" source=article.parameter compare=compare.parameter _hasType=_hasTypeInParameterFields section="parameter"}}
|
||||
{{subTemplate "article-compare-query-block" source=article.query compare=compare.query _hasType=_hasTypeInParameterFields section="query"}}
|
||||
{{subTemplate "article-compare-body-block" source=article.body compare=compare.body _hasType=_hasTypeInParameterFields section="body"}}
|
||||
{{subTemplate "article-compare-param-block" source=article.success compare=compare.success _hasType=_hasTypeInSuccessFields section="success"}}
|
||||
{{subTemplate "article-compare-param-block" source=article.error compare=compare.error _col1="Name" _hasType=_hasTypeInErrorFields section="error"}}
|
||||
|
||||
@ -839,19 +776,19 @@
|
||||
{{#each_compare_title source.examples compare.examples}}
|
||||
{{#if typeSame}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#{{../section}}-compare-examples-{{../article.id}}-{{index}}" role="tab" data-toggle="tab">{{{showDiff source.title compare.title}}}</a>
|
||||
<a href="#{{../../section}}-compare-examples-{{../../article.id}}-{{index}}" role="tab" data-toggle="tab">{{{showDiff source.title compare.title}}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeIns}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#{{../section}}-compare-examples-{{../article.id}}-{{index}}"><ins>{{{source.title}}}</ins></a>
|
||||
<a href="#{{../../section}}-compare-examples-{{../../article.id}}-{{index}}"><ins>{{{source.title}}}</ins></a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeDel}}
|
||||
<li{{#ifCond index '==' 0}} class="active"{{/ifCond}}>
|
||||
<a href="#{{../section}}-compare-examples-{{../article.id}}-{{index}}"><del>{{{compare.title}}}</del></a>
|
||||
<a href="#{{../../section}}-compare-examples-{{../../article.id}}-{{index}}"><del>{{{compare.title}}}</del></a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each_compare_title}}
|
||||
@ -861,35 +798,20 @@
|
||||
{{#each_compare_title source.examples compare.examples}}
|
||||
|
||||
{{#if typeSame}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../section}}-compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{source.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-diff-{{source.type}} diff-highlight">{{{showDiff source.content compare.content "code"}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../../section}}-compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{source.type}}" class="language-{{source.type}}">{{{showDiff source.content compare.content}}}</pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeIns}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../section}}-compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{source.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{source.type}}">{{{source.content}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../../section}}-compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{source.type}}"><code class="language-{{source.type}}">{{{source.content}}}</code></pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if typeDel}}
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../section}}-compare-examples-{{../article.id}}-{{index}}">
|
||||
<pre
|
||||
data-type="{{compare.type}}"
|
||||
data-prismjs-copy="{{__ "Copy"}}"
|
||||
data-prismjs-copy-error="{{__ "Press Ctrl+C to copy"}}"
|
||||
data-prismjs-copy-success="{{__ "copied!"}}"
|
||||
><code class="language-{{source.type}}">{{{compare.content}}}</code></pre>
|
||||
<div class="tab-pane{{#ifCond index '==' 0}} active{{/ifCond}}" id="{{../../section}}-compare-examples-{{../../article.id}}-{{index}}">
|
||||
<pre data-type="{{compare.type}}"><code class="language-{{source.type}}">{{{compare.content}}}</code></pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each_compare_title}}
|
||||
@ -898,49 +820,13 @@
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
<script id="template-article-compare-query-block" type="text/x-handlebars-template">
|
||||
{{#if article.query}}
|
||||
<h2>{{__ "Query Parameter(s)"}}</h2>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 30%">{{#if ../_col1}}{{__ ../_col1}}{{else}}{{__ "Field"}}{{/if}}</th>
|
||||
{{#unless this.Type compare=null}}
|
||||
<th style="width: 10%">{{__ "Type"}}</th>
|
||||
{{/unless}}
|
||||
<th style="width: {{#if ../_hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{subTemplate "article-compare-param-block-body" source=source compare=compare _hasType=this.type}}
|
||||
</table>
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
<script id="template-article-compare-body-block" type="text/x-handlebars-template">
|
||||
{{#if article.body}}
|
||||
<h2>{{__ "Request Body"}}</h2>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 30%">{{#if ../_col1}}{{__ ../_col1}}{{else}}{{__ "Field"}}{{/if}}</th>
|
||||
{{#unless this.Type compare=null}}
|
||||
<th style="width: 10%">{{__ "Type"}}</th>
|
||||
{{/unless}}
|
||||
<th style="width: {{#if ../_hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{subTemplate "article-compare-param-block-body" source=source compare=compare _hasType=this.type}}
|
||||
</table>
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
<script id="template-article-compare-param-block-body" type="text/x-handlebars-template">
|
||||
<tbody>
|
||||
{{#each_compare_field source compare}}
|
||||
{{#if typeSame}}
|
||||
<tr>
|
||||
<td class="code">
|
||||
{{{nestObject source}}}
|
||||
{{{splitFill source.field "." " "}}}
|
||||
{{#if source.optional}}
|
||||
{{#if compare.optional}} <span class="label label-optional">{{__ "optional"}}</span>
|
||||
{{else}} <span class="label label-optional label-ins">{{__ "optional"}}</span>
|
||||
@ -973,7 +859,7 @@
|
||||
{{#if typeIns}}
|
||||
<tr class="ins">
|
||||
<td class="code">
|
||||
{{{nestObject source}}}
|
||||
{{{splitFill source.field "." " "}}}
|
||||
{{#if source.optional}} <span class="label label-optional label-ins">{{__ "optional"}}</span>{{/if}}
|
||||
</td>
|
||||
|
||||
@ -993,7 +879,7 @@
|
||||
{{#if typeDel}}
|
||||
<tr class="del">
|
||||
<td class="code">
|
||||
{{{nestObject compare}}}
|
||||
{{{splitFill compare.field "." " "}}}
|
||||
{{#if compare.optional}} <span class="label label-optional label-del">{{__ "optional"}}</span>{{/if}}
|
||||
</td>
|
||||
|
||||
@ -1015,9 +901,9 @@
|
||||
</script>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div id="sidenav" class="col-sm-3 col-lg-2"></div>
|
||||
<div id="content" class="col-sm-9 col-lg-10">
|
||||
<div class="row">
|
||||
<div id="sidenav" class="span2"></div>
|
||||
<div id="content">
|
||||
<div id="project"></div>
|
||||
<div id="header"></div>
|
||||
<div id="sections"></div>
|
||||
@ -1042,6 +928,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="assets/main.bundle.js?v=1691302932133"></script>
|
||||
<script src="assets/main.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
22
public/images/application/add-project.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#87D068;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M35.7,20.1c0-0.8-0.4-1.5-1.1-1.9l-8.9-5.1c-1-0.6-2.2-0.6-3.1,0l-9.1,5.2c-0.6,0.4-1,1-1,1.8s0.4,1.4,1,1.8
|
||||
l9.1,5.2c0.5,0.3,1,0.4,1.6,0.4c0.5,0,1.1-0.1,1.6-0.4l8.9-5.1C35.3,21.6,35.7,20.9,35.7,20.1z"/>
|
||||
<path class="st1" d="M24,29.7c-0.4,0-0.8-0.1-1.2-0.3l-9-5.1c-0.4-0.2-0.9-0.1-1.2,0.3c-0.2,0.4-0.1,0.9,0.3,1.2l9,5.1
|
||||
c0.6,0.4,1.3,0.6,2,0.6c0,0,0,0,0,0c0.5,0,0.9-0.4,0.9-0.9C24.9,30.1,24.5,29.7,24,29.7z"/>
|
||||
<path class="st1" d="M24,33.5c-0.6,0-1.3-0.2-1.8-0.5l-8.4-4.8c-0.4-0.2-0.9-0.1-1.2,0.3c-0.2,0.4-0.1,0.9,0.3,1.2l8.4,4.8
|
||||
c0.8,0.5,1.7,0.7,2.6,0.7c0,0,0,0,0,0c0.5,0,0.9-0.4,0.9-0.9C24.9,33.9,24.5,33.5,24,33.5z"/>
|
||||
<path class="st1" d="M34.8,30h-2.6v-2.6c0-0.5-0.4-0.9-0.9-0.9c-0.5,0-0.9,0.4-0.9,0.9V30h-2.6c-0.5,0-0.9,0.4-0.9,0.9
|
||||
s0.4,0.9,0.9,0.9h2.6v2.6c0,0.5,0.4,0.9,0.9,0.9c0.5,0,0.9-0.4,0.9-0.9v-2.6h2.6c0.5,0,0.9-0.4,0.9-0.9S35.3,30,34.8,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
29
public/images/application/add-task.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#87D068;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st1" cx="19.7" cy="26.6" r="0.9"/>
|
||||
<g>
|
||||
<path class="st1" d="M29,26.9c0.5,0,0.9,0.4,0.9,0.9l0,2.6l2.6,0c0.5,0,0.9,0.4,0.9,0.9c0,0.5-0.4,0.9-0.9,0.9l-2.6,0l0,2.6
|
||||
c0,0.5-0.4,0.9-0.9,0.9c-0.5,0-0.9-0.4-0.9-0.9l0-2.6l-2.6,0c-0.5,0-0.9-0.4-0.9-0.9c0-0.5,0.4-0.9,0.9-0.9l2.6,0l0-2.6
|
||||
C28.1,27.3,28.5,26.9,29,26.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M26.6,34.8l0-1.2l-1.2,0c0,0,0,0,0,0c-0.6,0-1.2-0.2-1.6-0.7c-0.4-0.4-0.7-1-0.7-1.6c0-0.6,0.2-1.2,0.7-1.6
|
||||
c0.4-0.4,1-0.7,1.6-0.7l1.2,0l0-1.2c0-1.3,1-2.3,2.3-2.3c0,0,0,0,0,0c1.3,0,2.3,1,2.3,2.3l0,1.2l1.2,0c0,0,0,0,0,0
|
||||
c0.3,0,0.6,0.1,0.9,0.2V14.7c0-1.3-1.1-2.3-2.3-2.3H17c-1.3,0-2.3,1.1-2.3,2.3v18.7c0,1.3,1,2.3,2.3,2.3h9.8
|
||||
C26.7,35.4,26.6,35.1,26.6,34.8z M19.7,29.3c-1.4,0-2.6-1.2-2.6-2.6s1.2-2.6,2.6-2.6s2.6,1.2,2.6,2.6S21.1,29.3,19.7,29.3z
|
||||
M22.6,17.9l-2.9,2.9c-0.2,0.2-0.4,0.3-0.6,0.3s-0.4-0.1-0.6-0.3l-1.2-1.2c-0.3-0.3-0.3-0.9,0-1.2s0.9-0.3,1.2,0l0.5,0.5l2.3-2.3
|
||||
c0.3-0.3,0.9-0.3,1.2,0S23,17.6,22.6,17.9z M24.9,17.6h4.7c0.5,0,0.9,0.4,0.9,0.9s-0.4,0.9-0.9,0.9h-4.7c-0.5,0-0.9-0.4-0.9-0.9
|
||||
S24.4,17.6,24.9,17.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
27
public/images/application/all-user.svg
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F57775;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M21.5,24.5c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6C27.6,21.8,24.9,24.5,21.5,24.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M28.8,35.5H14.3c-1.1,0-2-0.9-2-2v-4.1c0-1.7,1.4-3.1,3.1-3.1h12.2c1.7,0,3.1,1.4,3.1,3.1v4.1
|
||||
C30.7,34.6,29.9,35.5,28.8,35.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M29.6,22.5c-0.3,0-0.5-0.1-0.7-0.3c-0.2-0.3-0.2-0.7,0-1c0.6-0.8,0.9-1.7,0.9-2.7s-0.3-1.9-0.9-2.7
|
||||
c-0.2-0.3-0.2-0.7,0-1s0.6-0.4,0.9-0.3c1.7,0.6,2.9,2.2,2.9,4s-1.2,3.4-2.9,4C29.8,22.5,29.7,22.5,29.6,22.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M34,34.7h-0.7c-0.3,0-0.5-0.1-0.7-0.3s-0.2-0.5-0.1-0.7c0-0.1,0-0.1,0-0.1v-4c0-0.4-0.2-0.7-0.3-0.9
|
||||
c-0.2-0.2-0.2-0.6-0.1-0.9c0.1-0.3,0.4-0.5,0.7-0.5H33c1.4,0,2.6,1.2,2.6,2.6V33C35.7,34,34.9,34.7,34,34.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
public/images/application/app-push.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25679"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#9D95E5" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25679)"><g><path d="M35.6226,12.187076C35.9089,12.366451,36.0526,12.70563,35.9824,13.03611L32.5574,33.5856C32.4912,34.000299999999996,32.1282,34.3018,31.7084,34.290800000000004C31.599,34.289100000000005,31.4912,34.2646,31.3918,34.2188L25.333399999999997,31.7437L22.095599999999997,35.6866C21.9377,35.8896,21.69045,36.0025,21.43364,35.9888C21.33001,35.990700000000004,21.22712,35.9711,21.131439999999998,35.9313C20.96605,35.8728,20.82448,35.7615,20.72851,35.6147C20.62727,35.4715,20.57206,35.300799999999995,20.57021,35.1254L20.57021,30.4629L32.125699999999995,16.28835L17.821640000000002,28.6641L12.540347,26.4912C12.225567,26.3831,12.0117595,26.09,12.0050232,25.7573C11.9677587,25.428800000000003,12.140421,25.112299999999998,12.436736,24.9658L34.7016,12.115123C34.833200000000005,12.040216,34.981899999999996,12.000561138,35.1333,12C35.3072,12.0294109,35.4735,12.092995,35.6226,12.187076Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
public/images/application/approve.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25613"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#F57775" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25613)"><g><g><path d="M32.753299999999996,26.9593L30.357,26.9593C29.1345,26.957700000000003,28.1438,25.967100000000002,28.142200000000003,24.744500000000002C28.139499999999998,24.1851,28.3448,23.6446,28.7182,23.228099999999998C31.2206,20.597839999999998,31.1498,16.44632,28.5592,13.9029C25.9685,11.359486,21.816380000000002,11.365081,19.23258,13.91547C16.648789999999998,16.46586,16.58916,20.61755,19.09864,23.2411C19.45887,23.6577,19.65585,24.1909,19.65307,24.7416C19.65997,25.8988,18.7744,26.8659,17.62114,26.9608L15.40058,26.9608C14.07758,26.9608,13.00396661,28.0311,13,29.3541L13,31.5142C13,32.024,13.413276,32.4373,13.923077,32.4373L34.227900000000005,32.4373C34.737700000000004,32.4373,35.150999999999996,32.024,35.150999999999996,31.5142L35.150999999999996,29.3541C35.145399999999995,28.0327,34.0747,26.9633,32.753299999999996,26.9593Z" fill="#FFFFFF" fill-opacity="1"/></g><g><path d="M34.2308,35.999994833374025L13.923077,35.999994833374025C13.413276,35.999994833374025,13.000000054161,35.58672483337402,13.000000054161,35.07692183337402C13.000000054161,34.56712083337403,13.413276,34.15384483337402,13.923077,34.15384483337402L34.227900000000005,34.15384483337402C34.737700000000004,34.15384483337402,35.150999999999996,34.56712083337403,35.150999999999996,35.07692183337402C35.150999999999996,35.58672483337402,34.737700000000004,35.999994833374025,34.227900000000005,35.999994833374025L34.2308,35.999994833374025Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
19
public/images/application/calendar.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFAA64;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<path class="st1" d="M32.5,14.5h-4.3v-1c0-0.4-0.3-0.8-0.8-0.8s-0.8,0.3-0.8,0.8v1h-5.3v-1c0-0.4-0.3-0.8-0.8-0.8s-0.8,0.3-0.8,0.8
|
||||
v1h-4.3c-1.5,0-2.8,1.2-2.8,2.8v15.3c0,1.5,1.2,2.8,2.8,2.8h17c1.5,0,2.8-1.2,2.8-2.8V17.2C35.2,15.7,34,14.5,32.5,14.5z M15.5,16
|
||||
h4.3v1c0,0.4,0.3,0.8,0.8,0.8s0.8-0.3,0.8-0.8v-1h5.3v1c0,0.4,0.3,0.8,0.8,0.8s0.8-0.3,0.8-0.8v-1h4.3c0.7,0,1.2,0.6,1.2,1.2v2.9
|
||||
H14.2v-2.9C14.2,16.5,14.8,16,15.5,16z M18.3,28.1L18.3,28.1c0.6,0,1.1,0.5,1.1,1.1c0,0.6-0.5,1-1,1c-0.6,0-1.1-0.5-1.1-1
|
||||
C17.3,28.5,17.8,28.1,18.3,28.1z M17.3,25.1c0-0.6,0.5-1,1-1h0c0.6,0,1,0.5,1,1s-0.5,1-1,1C17.8,26.2,17.3,25.7,17.3,25.1z M24,28.1
|
||||
L24,28.1c0.6,0,1.1,0.5,1.1,1.1c0,0.6-0.5,1-1,1c-0.6,0-1.1-0.5-1.1-1C23,28.5,23.4,28.1,24,28.1z M23,25.1c0-0.6,0.5-1,1-1h0
|
||||
c0.6,0,1,0.5,1,1s-0.5,1-1,1C23.4,26.2,23,25.7,23,25.1z M29.7,28.1L29.7,28.1c0.6,0,1.1,0.5,1.1,1.1c0,0.6-0.5,1-1,1
|
||||
c-0.6,0-1.1-0.5-1.1-1C28.6,28.5,29.1,28.1,29.7,28.1z M28.6,25.1c0-0.6,0.5-1,1-1h0c0.6,0,1,0.5,1,1s-0.5,1-1,1
|
||||
C29.1,26.2,28.6,25.7,28.6,25.1z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
17
public/images/application/file.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFAA64;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M28.7,18.4h3.8c0.5,0,0.8-0.6,0.4-1l-4.7-4.7c-0.4-0.4-1-0.1-1,0.4V17C27.3,17.8,27.9,18.4,28.7,18.4z"/>
|
||||
<path class="st1" d="M28.7,20.2c-1.8,0-3.2-1.4-3.2-3.2v-4c0-0.3-0.3-0.6-0.6-0.6H17c-1.3,0-2.3,1.1-2.3,2.3v18.7
|
||||
c0,1.3,1,2.3,2.3,2.3h14c1.3,0,2.3-1,2.3-2.3V20.7c0-0.3-0.3-0.6-0.6-0.6H28.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 890 B |
1
public/images/application/ldap.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25667"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#FFC835" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25667)"><g><path d="M33.400099999999995,12C34.0625,12,34.599599999999995,12.537033,34.599599999999995,13.1995L34.599599999999995,34.799099999999996C34.6004,35.4621,34.0631,36,33.400099999999995,36L16.59993,36C14.61174,36,13,34.3883,13,32.400099999999995L13,15.59993C13,13.61174,14.61174,12,16.59993,12L33.400099999999995,12ZM32.1991,31.1991L16.59993,31.1991C15.953240000000001,31.2215,15.440570000000001,31.7523,15.440570000000001,32.3994C15.440570000000001,33.0464,15.953240000000001,33.577200000000005,16.59993,33.599599999999995L32.1991,33.599599999999995L32.1991,31.1991ZM23.799799999999998,22.799799999999998C21.8116,22.799799999999998,20.19986,24.4115,20.19986,26.3997L27.3997,26.3997C27.3997,24.4115,25.788,22.799799999999998,23.799799999999998,22.799799999999998ZM23.799799999999998,16.799419999999998C22.47406,16.799419999999998,21.39935,17.87413,21.39935,19.19986C21.39935,20.525579999999998,22.47406,21.60029,23.799799999999998,21.60029C25.125500000000002,21.60029,26.200200000000002,20.525579999999998,26.200200000000002,19.19986C26.1994,17.87446,25.1252,16.80022,23.799799999999998,16.799419999999998Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
public/images/application/mail.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25401"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#F57775" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25401)"><g><path d="M36,19.35553L36,31.6471C36,32.8166,35.0519,33.764700000000005,33.882400000000004,33.764700000000005L14.11765,33.764700000000005C12.948108,33.764700000000005,12.00000549316,32.8166,12.00000549316,31.6471L12.00000549316,19.35553L20.804470000000002,26.8202C22.6481,28.3834,25.3519,28.3834,27.1955,26.8202L36,19.35553ZM33.882400000000004,14.000000646254C34.1404,14.000286291,34.3963,14.0471559,34.6376,14.138353C34.984700000000004,14.270521,35.2905,14.492136,35.5242,14.780706C35.6509,14.935896,35.7549,15.10818,35.8334,15.29247C35.925200000000004,15.50988,35.9816,15.74565,35.9958,15.99341L36,16.11765L36,16.823529999999998L25.3744,25.8871C24.6211,26.5295,23.5233,26.5644,22.730800000000002,25.9711L22.625700000000002,25.886400000000002L12.00000517004,16.823529999999998L12.00000517004,16.11765C11.9982451,15.318200000000001,12.448325,14.586376,13.16259,14.227294C13.45869,14.0776132,13.78587,13.999747961,14.11765,14.000000646254L33.882400000000004,14.000000646254Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
public/images/application/meeting-create.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25658"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#72A1F7" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25658)"><g><path d="M33.1767,19.46395L30.5723,21.34133L30.5723,19.01332C30.5723,17.34516,29.217,15.99442094,27.5489,16L15.01332,16C13.34911,15.999999801611,12,17.34911,12,19.01332L12,29.5822C12,31.2464,13.34911,32.595600000000005,15.01332,32.595600000000005L27.5489,32.595600000000005C29.217,32.6011,30.5723,31.2504,30.5723,29.5822L30.5723,27.2542L33.182500000000005,29.1259C33.7237,29.5146,34.436800000000005,29.5683,35.0302,29.2651C35.623599999999996,28.9619,35.9979,28.3525,36,27.6861L36,20.907980000000002C36.0011,20.23879,35.626599999999996,19.62559,35.0308,19.32086C34.4351,19.01614,33.7187,19.07142,33.1767,19.46395Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
20
public/images/application/meeting-join.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#53CBAE;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M35.8,18.3l-2.6,2.2c-0.3,0.3-0.5,0.6-0.5,1v4.8c0,0.4,0.2,0.8,0.5,1l2.6,2.2c0.9,0.8,2.2,0.1,2.2-1v-9.3
|
||||
C38,18.2,36.6,17.6,35.8,18.3z"/>
|
||||
<path class="st1" d="M28.8,14.6H12c-1.1,0-2,0.9-2,2v14.8c0,1.1,0.9,2,2,2h16.8c1.1,0,2-0.9,2-2V16.6
|
||||
C30.8,15.5,29.9,14.6,28.8,14.6z M23.4,24.7h-2.2V27c0,0.4-0.3,0.7-0.7,0.7c-0.4,0-0.7-0.3-0.7-0.7v-2.2h-2.2
|
||||
c-0.4,0-0.7-0.3-0.7-0.7s0.3-0.7,0.7-0.7h2.2V21c0-0.4,0.3-0.7,0.7-0.7c0.4,0,0.7,0.3,0.7,0.7v2.2h2.2c0.4,0,0.7,0.3,0.7,0.7
|
||||
S23.8,24.7,23.4,24.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
public/images/application/meeting.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25658"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#72A1F7" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25658)"><g><path d="M33.1767,19.46395L30.5723,21.34133L30.5723,19.01332C30.5723,17.34516,29.217,15.99442094,27.5489,16L15.01332,16C13.34911,15.999999801611,12,17.34911,12,19.01332L12,29.5822C12,31.2464,13.34911,32.595600000000005,15.01332,32.595600000000005L27.5489,32.595600000000005C29.217,32.6011,30.5723,31.2504,30.5723,29.5822L30.5723,27.2542L33.182500000000005,29.1259C33.7237,29.5146,34.436800000000005,29.5683,35.0302,29.2651C35.623599999999996,28.9619,35.9979,28.3525,36,27.6861L36,20.907980000000002C36.0011,20.23879,35.626599999999996,19.62559,35.0308,19.32086C34.4351,19.01614,33.7187,19.07142,33.1767,19.46395Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
public/images/application/okr-analyze.svg
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
1
public/images/application/okr.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="52" height="52" viewBox="0 0 52 52"><defs><clipPath id="master_svg0_3138_29732"><rect x="12" y="12" width="28" height="28" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="52" height="52" rx="12" fill="#84C56A" fill-opacity="1"/><g clip-path="url(#master_svg0_3138_29732)"><g><g><path d="M27.126664663848878,28.231620556030272C26.25417466384888,29.10411055603027,24.854894663848878,29.10411055603027,23.98241466384888,28.231620556030272C23.126384663848878,27.359130556030273,23.126384663848878,25.959850556030275,23.98241466384888,25.087360556030273L29.085604663848876,19.984124556030274C28.032074663848878,19.424413556030274,26.813884663848874,19.078710556030273,25.513384663848875,19.078710556030273C21.39786466384888,19.078710556030273,18.039604663848877,22.420510556030273,18.039604663848877,26.55249055603027C18.039604663848877,30.684510556030276,21.39786466384888,34.009810556030274,25.513384663848875,34.009810556030274C29.62890466384888,34.009810556030274,32.98720466384888,30.668010556030275,32.98720466384888,26.536020556030273C32.98720466384888,25.301370556030275,32.69080466384888,24.149020556030273,32.16400466384888,23.128380556030272L27.126664663848878,28.231620556030272Z" fill="#FFFFFF" fill-opacity="1"/></g><g><g><path d="M36.49362605285644,15.83566C36.29602605285645,15.80274,36.147826052856445,15.65458,36.11492605285645,15.45703L35.489426052856444,12L32.21344605285645,15.27595L31.752506052856447,15.736889999999999L31.390346052856444,16.09905C31.291566052856446,16.19783,31.242186052856447,16.34599,31.258646052856445,16.51061L31.604346052856446,18.93053L31.768976052856445,19.09515L24.920750052856445,25.9434C24.558585452856445,26.305500000000002,24.558585452856445,26.8982,24.920750052856445,27.2603C25.282915052856445,27.622500000000002,25.875546052856446,27.622500000000002,26.237716052856445,27.2603L33.02008605285644,20.41211L33.135316052856446,20.41211L35.50582605285645,20.691969999999998C35.637526052856444,20.70843,35.78572605285645,20.65905,35.884526052856444,20.56027L40.00002605285644,16.44476L36.49362605285644,15.83566Z" fill="#FFFFFF" fill-opacity="1"/></g></g><g><path d="M37.876400000000004,21.926598541641233L37.827,21.778438541641236L34.9955,22.832008541641237L35.0449,22.980168541641234C35.5882,24.395898541641238,35.7857,25.877498541641238,35.6869,27.375498541641235C35.5882,28.807698541641237,35.1766,30.190598541641236,34.5017,31.458098541641235C33.8267,32.725698541641236,32.9048,33.845098541641235,31.769,34.73409854164123C30.5837,35.65599854164124,29.2667,36.31439854164124,27.7851,36.66009854164123C26.32,37.005798541641234,24.822,37.07169854164124,23.3568,36.77539854164124C21.941110000000002,36.51199854164123,20.62415,35.952298541641234,19.43888,35.11269854164124C18.23715,34.28959854164124,17.26588,33.25249854164123,16.50863,32.017798541641234C15.71845,30.733798541641235,15.22459,29.350998541641236,15.05997,27.836498541641234C14.87889,26.338398541641233,15.02704,24.840398541641235,15.48798,23.424598541641235C15.932459999999999,22.058288541641236,16.62386,20.823638541641238,17.61159,19.720678541641234C18.56639,18.650638541641236,19.71873,17.794618541641235,21.01923,17.185518541641237C22.3856,16.559958541641237,23.8342,16.247178541641237,25.3488,16.247178541641237C26.287100000000002,16.247178541641237,27.209,16.378878541641235,28.1473,16.609348541641236L28.2955,16.658728541641235L29.0856,13.744946541641236L28.9375,13.695560541641235C27.7851,13.382781541641235,26.567,13.218160641641235,25.3488,13.201698541641235C23.3898,13.201698541641235,21.5131,13.629712541641235,19.76812,14.436348541641236C18.10545,15.226538541641236,16.6074,16.345958541641235,15.37275,17.728768541641237C14.12163,19.128038541641235,13.21622,20.741328541641234,12.640045,22.502768541641235C12.0474104,24.330098541641235,11.866328,26.256098541641236,12.0967967,28.198598541641235C12.327266,30.124698541641234,12.969286,31.951998541641235,13.97347,33.59819854164124C14.94473,35.178598541641236,16.22878,36.52839854164124,17.75975,37.581998541641234C19.29072,38.63559854164124,21.002769999999998,39.359898541641236,22.8301,39.72209854164123C23.669600000000003,39.88669854164124,24.5257,39.968998541641234,25.3652,39.968998541641234C26.418799999999997,39.968998541641234,27.5053,39.83729854164123,28.5424,39.590398541641235C30.4355,39.11299854164123,32.180499999999995,38.273398541641235,33.695,37.08819854164123C35.1601,35.93579854164123,36.329,34.52009854164123,37.2179,32.87389854164124C38.0904,31.227698541641235,38.6007,29.449798541641236,38.7324,27.589498541641234C38.8477,25.663498541641236,38.5513,23.753898541641234,37.876400000000004,21.926598541641233Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
1
public/images/application/report.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25545"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#9D95E5" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25545)"><g><g><path d="M27.3699,31.3292C26.4274,32.2528,24.9169,32.2452,23.983800000000002,31.3121C23.0507,30.379,23.043100000000003,28.8686,23.9667,27.926099999999998L32.3201,19.578400000000002L32.3201,15.27301C32.3201,13.46482,30.8539,11.999210349,29.0457,12L15.27301,12C13.46538,11.999999784513,12,13.46538,12,15.27301L12,32.6318C11.999209911,34.44,13.46482,35.9063,15.27301,35.9063L29.0457,35.9063C30.8541,35.9063,32.3201,34.4403,32.3201,32.6318L32.3201,26.3789L27.3699,31.3292ZM17.74958,20.06886C17.25443,20.06886,16.85304,19.66746,16.85304,19.17232C16.85304,18.67717,17.25443,18.27578,17.74958,18.27578L23.1288,18.27578C23.624000000000002,18.27578,24.025399999999998,18.67717,24.025399999999998,19.17232C24.025399999999998,19.66746,23.624000000000002,20.06886,23.1288,20.06886L17.74958,20.06886Z" fill="#FFFFFF" fill-opacity="1"/></g><g transform="matrix(0.7071067690849304,0.7071067690849304,-0.7071067690849304,0.7071067690849304,23.826460884525744,-18.843463462634503)"><rect x="34.65930366516113" y="19.33935022354126" width="1.8960309028625488" height="14.49763011932373" rx="0.9480154514312744" fill="#FFFFFF" fill-opacity="1"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
public/images/application/robot.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25405"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#FFC835" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25405)"><g><g><rect x="12" y="26.31494140625" width="1.8119423389434814" height="7.173644542694092" rx="0.9059711694717407" fill="#FFFFFF" fill-opacity="1"/></g><g><rect x="34.18804931640625" y="26.31494140625" width="1.8119423389434814" height="7.173644542694092" rx="0.9059711694717407" fill="#FFFFFF" fill-opacity="1"/></g><g><path d="M29.53465,20.54139L31.35485,17.38422C31.41525,17.38422,31.47695,17.39383,31.53875,17.39383C32.931349999999995,17.39648,33.97485,16.118949999999998,33.69415,14.75489C33.41345,13.390835,31.95045,12.629057,30.67195,13.181321C29.393549999999998,13.733585,28.94525,15.32101,29.74605,16.4604L27.76795,19.89211C25.287950000000002,19.2077,22.669629999999998,19.20201,20.18666,19.87564L18.21274,16.46315C19.0135,15.32376,18.56525,13.73633,17.28679,13.184066C16.00834,12.631803,14.545278,13.393581,14.2646052,14.75764C13.983932,16.1217,15.02738,17.39923,16.42001,17.39657C16.48179,17.39657,16.542180000000002,17.39657,16.60258,17.386960000000002L18.417270000000002,20.529040000000002C16.05625,21.62718,14.483158,23.3979,14.36648,25.4172L14.356871,25.4172L14.356871,33.289500000000004C14.356871,34.7254,15.52087,35.889399999999995,16.95673,35.889399999999995L30.96905,35.889399999999995C32.40495,35.889399999999995,33.56895,34.7254,33.56895,33.289500000000004L33.56895,25.4172L33.559349999999995,25.4172C33.444050000000004,23.4048,31.88195,21.636789999999998,29.53465,20.54139ZM27.063850000000002,29.5105L20.86888,29.5105C19.89243,29.5105,19.10087,28.718899999999998,19.10087,27.7425C19.10087,26.766,19.89243,25.9745,20.86888,25.9745L27.05695,25.9745C28.03335,25.9745,28.82495,26.766,28.82495,27.7425C28.82495,28.718899999999998,28.03335,29.5105,27.05695,29.5105L27.063850000000002,29.5105Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
41
public/images/application/scan.svg
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#72A1F7;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M20.3,35.8h-4.7c-1.9,0-3.4-1.5-3.4-3.4v-4.7c0-0.4,0.3-0.8,0.8-0.8s0.8,0.3,0.8,0.8v4.7
|
||||
c0,1.1,0.9,1.9,1.9,1.9h4.7c0.4,0,0.8,0.3,0.8,0.8S20.7,35.8,20.3,35.8z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M13,21.1c-0.4,0-0.8-0.3-0.8-0.8v-4.7c0-1.9,1.5-3.4,3.4-3.4h4.7c0.4,0,0.8,0.3,0.8,0.8s-0.3,0.8-0.8,0.8
|
||||
h-4.7c-1.1,0-1.9,0.9-1.9,1.9v4.7C13.8,20.7,13.4,21.1,13,21.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M35,21.1c-0.4,0-0.8-0.3-0.8-0.8v-4.7c0-1.1-0.9-1.9-1.9-1.9h-4.7c-0.4,0-0.8-0.3-0.8-0.8s0.3-0.8,0.8-0.8
|
||||
h4.7c1.9,0,3.4,1.5,3.4,3.4v4.7C35.8,20.7,35.4,21.1,35,21.1z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M32.3,35.8h-4.7c-0.4,0-0.8-0.3-0.8-0.8s0.3-0.8,0.8-0.8h4.7c1.1,0,1.9-0.9,1.9-1.9v-4.7
|
||||
c0-0.4,0.3-0.8,0.8-0.8s0.8,0.3,0.8,0.8v4.7C35.8,34.2,34.2,35.8,32.3,35.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M29.5,16.5H18.5c-1.1,0-1.9,0.9-1.9,1.9v11.1c0,1.1,0.9,1.9,1.9,1.9h11.1c1.1,0,1.9-0.9,1.9-1.9V18.5
|
||||
C31.5,17.4,30.6,16.5,29.5,16.5z M27.7,24.8h-7.3c-0.4,0-0.8-0.3-0.8-0.8s0.3-0.8,0.8-0.8h7.3c0.4,0,0.8,0.3,0.8,0.8
|
||||
S28.1,24.8,27.7,24.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
18
public/images/application/setting.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#72A1F7;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<path class="st1" d="M34.6,26.5c-1.9-1.1-1.9-3.8,0-4.9c0.6-0.3,0.8-1.1,0.5-1.7l-1.9-3.3c-0.3-0.6-1.1-0.8-1.7-0.5
|
||||
c-1.9,1.1-4.3-0.3-4.3-2.5c0-0.7-0.6-1.3-1.3-1.3h-3.8c-0.7,0-1.3,0.6-1.3,1.3c0,2.2-2.4,3.6-4.3,2.5l0,0c-0.6-0.3-1.4-0.1-1.7,0.5
|
||||
L13,19.8c-0.3,0.6-0.1,1.4,0.5,1.7l0,0c1.9,1.1,1.9,3.8,0,4.9c-0.6,0.3-0.8,1.1-0.5,1.7l1.9,3.3c0.3,0.6,1.1,0.8,1.7,0.5
|
||||
c1.9-1.1,4.3,0.3,4.3,2.5v0c0,0.7,0.6,1.3,1.3,1.3h3.8c0.7,0,1.3-0.6,1.3-1.3v0c0-2.2,2.4-3.6,4.3-2.5h0c0.6,0.3,1.4,0.1,1.7-0.5
|
||||
l1.9-3.3C35.4,27.6,35.2,26.8,34.6,26.5z M24,26.6c-1.4,0-2.6-1.2-2.6-2.6c0-1.4,1.2-2.6,2.6-2.6c1.4,0,2.6,1.2,2.6,2.6
|
||||
C26.6,25.4,25.4,26.6,24,26.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
public/images/application/signin.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="48" height="48" viewBox="0 0 48 48"><defs><clipPath id="master_svg0_3054_25526"><rect x="12" y="12" width="24" height="24" rx="0"/></clipPath></defs><g><rect x="0" y="0" width="48" height="48" rx="12" fill="#72A1F7" fill-opacity="1"/><g clip-path="url(#master_svg0_3054_25526)"><g><g><path d="M34.0464,21.911920000000002C34.0464,16.439700000000002,29.336,12,23.523899999999998,12C17.71187,12,13,16.43682,13,21.911920000000002C13,24.689799999999998,14.21541,27.1998,16.16813,28.9999L23.5211,36L30.7962,29.0676C30.9402,28.9365,31.0842,28.8026,31.2196,28.6643C33.0192,26.8769,34.0359,24.4483,34.0464,21.911920000000002ZM23.397199999999998,26.7015C20.95156,26.6984,18.97124,24.7138,18.97336,22.2681C18.97548,19.82244,20.959229999999998,17.84126,23.404899999999998,17.84232C25.8506,17.84338,27.8326,19.82627,27.8326,22.271900000000002C27.8326,24.720599999999997,25.8459,26.704700000000003,23.397199999999998,26.7015Z" fill="#FFFFFF" fill-opacity="1"/></g><g><ellipse cx="23.397215843200684" cy="22.271930694580078" rx="2.733229160308838" ry="2.733229160308838" fill="#FFFFFF" fill-opacity="1"/></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/avatar/default_meeting.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
2
public/language/web/de.js
vendored
2
public/language/web/en.js
vendored
2
public/language/web/fr.js
vendored
2
public/language/web/id.js
vendored
2
public/language/web/ja.js
vendored
2
public/language/web/key.js
vendored
2
public/language/web/ko.js
vendored
2
public/language/web/zh-CHT.js
vendored
2
public/language/web/zh.js
vendored
@ -1 +1 @@
|
||||
if(typeof window.LANGUAGE_DATA==="undefined")window.LANGUAGE_DATA={};window.LANGUAGE_DATA["zh"]=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]
|
||||
if(typeof window.LANGUAGE_DATA==="undefined")window.LANGUAGE_DATA={};window.LANGUAGE_DATA["zh"]=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]
|
||||
9
public/site/css/common.css
vendored
@ -1222,22 +1222,17 @@ footer {
|
||||
}
|
||||
|
||||
.footer_beian {
|
||||
float: left;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin: 0px 0px 0px 5px;
|
||||
margin-left: 5px;
|
||||
color: #939393;
|
||||
}
|
||||
|
||||
.footer_beian_a {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin: 0px 0px 0px 5px;
|
||||
margin-left: 5px;
|
||||
color: #939393;
|
||||
text-decoration: underline;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.footer_copyright {
|
||||
|
||||
16
public/site/css/download.css
vendored
@ -150,4 +150,20 @@
|
||||
.btn-padding a{
|
||||
display: block;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
/* 弹框样式 */
|
||||
.BulletBox{
|
||||
position: fixed;
|
||||
display: none;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
padding: 8px;
|
||||
background-color: var(--txt-theme-color);
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
z-index: 9999;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
}
|
||||
16
public/site/css/rem.css
vendored
@ -215,8 +215,15 @@
|
||||
.card-ul-item.active{
|
||||
max-height: 307px !important;
|
||||
}
|
||||
.footer_copyright{
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 768px) and (min-width: 768px){
|
||||
.download-ul-item:nth-of-type(2){
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px){
|
||||
img{
|
||||
max-width: 100% !important;
|
||||
@ -399,6 +406,7 @@
|
||||
}
|
||||
.collaboration{
|
||||
margin-bottom: 56px !important;
|
||||
max-height: inherit !important;
|
||||
}
|
||||
.footer-layut{
|
||||
border-bottom: none !important;
|
||||
@ -791,4 +799,10 @@
|
||||
.footer_copyright{
|
||||
flex-direction: column;
|
||||
}
|
||||
#cookieConsent{
|
||||
width: 90% !important;
|
||||
right: 0 !important;
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@
|
||||
<link rel="stylesheet" href="../css/download.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="BulletBox"></div>
|
||||
<div id="layout">
|
||||
<!-- 页头区域 -->
|
||||
<header class="head dow">
|
||||
@ -100,7 +101,7 @@
|
||||
<h4 class="txt-4001830 topics-h4 mb-64 topics-h4-en">Also supports iOS, Android, macOS, Windows versions</h4>
|
||||
<ul class="download-ul">
|
||||
<li class="download-ul-item dow-animate-box" style="--delay: 0s;" onmouseover='handleMouseover(0)' onmouseout='handleMouseout(0)'>
|
||||
<a class="normal" href="https://apps.apple.com/cn/app/dootask/id1624855111" target="_blank">
|
||||
<a class="normal" href="https://apps.apple.com/cn/app/dootask/id1624855111" target="_blank" id="ios">
|
||||
<img class="icon mb-8" src="../img/dow_ios.svg" alt="ios">
|
||||
<i class="txt-4001624 txt">ios</i>
|
||||
</a>
|
||||
@ -110,7 +111,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<li class="download-ul-item dow-animate-box" style="--delay: 0.1s;" onmouseover='handleMouseover(1)' onmouseout='handleMouseout(1)'>
|
||||
<a class="normal" href="https://www.dootask.com/desktop/publish/latest?platform=android" target="_blank">
|
||||
<a class="normal" href="https://www.dootask.com/desktop/publish/latest?platform=android" target="_blank" id="Android">
|
||||
<img class="icon mb-8" src="../img/dow_android.svg" alt="Android">
|
||||
<i class="txt-4001624 txt">Android</i>
|
||||
</a>
|
||||
@ -343,16 +344,90 @@
|
||||
<script src="//cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
|
||||
<script src="../js/common.js"></script>
|
||||
<script>
|
||||
/* 下载应用的hover处理函数 */
|
||||
const isMobile = 'ontouchstart' in window
|
||||
const androidDOM = document.getElementById("Android")
|
||||
const iosDOM = document.getElementById("ios")
|
||||
// 判断是否为ios
|
||||
const isIos = /iPad|iPhone|iPod/.test(window.navigator.userAgent);
|
||||
// 判断是否为安卓
|
||||
const isAndroid = /Android/.test(window.navigator.userAgent);
|
||||
// 判断是否为windows
|
||||
const isWindows = /Win64/.test(window.navigator.userAgent);
|
||||
/* 下载应用的hover处理函数 */
|
||||
const download = document.querySelector('.download-ul');
|
||||
const downloadItems = download.querySelectorAll('.download-ul-item');
|
||||
const handleMouseover = (val)=>{
|
||||
downloadItems[val].children[0].style.display = 'none'
|
||||
downloadItems[val].children[1].style.display = 'flex'
|
||||
if(isIos||isAndroid){
|
||||
return;
|
||||
}else{
|
||||
downloadItems[val].children[0].style.display = 'none'
|
||||
downloadItems[val].children[1].style.display = 'flex'
|
||||
}
|
||||
}
|
||||
const handleMouseout = (val)=>{
|
||||
downloadItems[val].children[0].style.display = 'flex'
|
||||
downloadItems[val].children[1].style.display = 'none'
|
||||
if(isIos||isAndroid){
|
||||
return;
|
||||
}else{
|
||||
downloadItems[val].children[0].style.display = 'flex'
|
||||
downloadItems[val].children[1].style.display = 'none'
|
||||
}
|
||||
}
|
||||
/* 对于ios与Android pc端点击时a链接直接跳转 移动端点击时需要阻止a链接直接跳转 */
|
||||
androidDOM.addEventListener('click',function(e){
|
||||
if(isMobile){
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
iosDOM.addEventListener('click',function(e){
|
||||
if(isMobile){
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
// 对于不同类型的移动端进行处理
|
||||
function movieHandle(flag=true){
|
||||
if(flag){
|
||||
downloadItems.forEach((item,index)=>{
|
||||
item.addEventListener('touchstart',function(){
|
||||
if(index==2||index==3){
|
||||
return showBox("Not supported on current device")
|
||||
}
|
||||
if(index==0){
|
||||
if(isIos){
|
||||
// Safari
|
||||
if (navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1 && navigator.userAgent.indexOf('Edge') === -1) {
|
||||
return (window.open(item.children[0].href,"_blank"));
|
||||
}
|
||||
return window.open(item.children[0].href,"_blank")
|
||||
}
|
||||
return showBox("Not supported on current device")
|
||||
}
|
||||
if(index==1){
|
||||
if(isAndroid){
|
||||
return window.open(item.children[0].href,"_blank")
|
||||
}
|
||||
return showBox("Not supported on current device")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
// 移动端
|
||||
/* 显示/隐藏提示弹框 */
|
||||
function showBox(text){
|
||||
const box = document.querySelector('.BulletBox')
|
||||
box.style.display = 'block'
|
||||
box.innerHTML = text
|
||||
setTimeout(()=>{
|
||||
box.style.display = 'none'
|
||||
},1000)
|
||||
}
|
||||
// 是否是移动端
|
||||
if(isMobile){
|
||||
if(isAndroid||isIos){
|
||||
movieHandle()
|
||||
}else if(isWindows){
|
||||
movieHandle(false)
|
||||
}
|
||||
}
|
||||
const localStorageHandle = (val)=>{
|
||||
localStorage.setItem('update_log_num',val)
|
||||
@ -405,7 +480,6 @@ if(!logsItem) {
|
||||
localStorage.setItem('logs_dowmload_en', JSON.stringify(record))
|
||||
updates.innerHTML = releases;
|
||||
}).catch(err=>{
|
||||
console.log(err,"err");
|
||||
})
|
||||
}else{
|
||||
updates.innerHTML = logsItem;
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
<link rel="stylesheet" href="../css/download.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="BulletBox"></div>
|
||||
<div id="layout">
|
||||
<!-- 页头区域 -->
|
||||
<header class="head dow">
|
||||
@ -100,7 +101,7 @@
|
||||
<h4 class="txt-4001830 topics-h4 mb-64">同时支持iOS、Android、macOS、Windows版本</h4>
|
||||
<ul class="download-ul">
|
||||
<li class="download-ul-item dow-animate-box" style="--delay: 0s;" onmouseover='handleMouseover(0)' onmouseout='handleMouseout(0)'>
|
||||
<a class="normal" href="https://apps.apple.com/cn/app/dootask/id1624855111" target="_blank">
|
||||
<a class="normal" href="https://apps.apple.com/cn/app/dootask/id1624855111" target="_blank" id="ios">
|
||||
<img class="icon mb-8" src="../img/dow_ios.svg" alt="ios">
|
||||
<i class="txt-4001624 txt">ios</i>
|
||||
</a>
|
||||
@ -110,7 +111,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<li class="download-ul-item dow-animate-box" style="--delay: 0.1s;" onmouseover='handleMouseover(1)' onmouseout='handleMouseout(1)'>
|
||||
<a class="normal" href="https://www.dootask.com/desktop/publish/latest?platform=android" target="_blank">
|
||||
<a class="normal" href="https://www.dootask.com/desktop/publish/latest?platform=android" target="_blank" id="Android">
|
||||
<img class="icon mb-8" src="../img/dow_android.svg" alt="Android">
|
||||
<i class="txt-4001624 txt">Android</i>
|
||||
</a>
|
||||
@ -341,16 +342,90 @@
|
||||
<script src="//cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
|
||||
<script src="../js/common.js"></script>
|
||||
<script>
|
||||
const isMobile = 'ontouchstart' in window
|
||||
const androidDOM = document.getElementById("Android")
|
||||
const iosDOM = document.getElementById("ios")
|
||||
// 判断是否为ios
|
||||
const isIos = /iPad|iPhone|iPod/.test(window.navigator.userAgent);
|
||||
// 判断是否为安卓
|
||||
const isAndroid = /Android/.test(window.navigator.userAgent);
|
||||
// 判断是否为windows
|
||||
const isWindows = /Win64/.test(window.navigator.userAgent);
|
||||
/* 下载应用的hover处理函数 */
|
||||
const download = document.querySelector('.download-ul');
|
||||
const downloadItems = download.querySelectorAll('.download-ul-item');
|
||||
const handleMouseover = (val)=>{
|
||||
downloadItems[val].children[0].style.display = 'none'
|
||||
downloadItems[val].children[1].style.display = 'flex'
|
||||
if(isIos||isAndroid){
|
||||
return;
|
||||
}else{
|
||||
downloadItems[val].children[0].style.display = 'none'
|
||||
downloadItems[val].children[1].style.display = 'flex'
|
||||
}
|
||||
}
|
||||
const handleMouseout = (val)=>{
|
||||
downloadItems[val].children[0].style.display = 'flex'
|
||||
downloadItems[val].children[1].style.display = 'none'
|
||||
if(isIos||isAndroid){
|
||||
return;
|
||||
}else{
|
||||
downloadItems[val].children[0].style.display = 'flex'
|
||||
downloadItems[val].children[1].style.display = 'none'
|
||||
}
|
||||
}
|
||||
/* 对于ios与Android pc端点击时a链接直接跳转 移动端点击时需要阻止a链接直接跳转 */
|
||||
androidDOM.addEventListener('click',function(e){
|
||||
if(isMobile){
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
iosDOM.addEventListener('click',function(e){
|
||||
if(isMobile){
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
// 对于不同类型的移动端进行处理
|
||||
function movieHandle(flag=true){
|
||||
if(flag){
|
||||
downloadItems.forEach((item,index)=>{
|
||||
item.addEventListener('touchstart',function(){
|
||||
if(index==2||index==3){
|
||||
return showBox("当前终端不支持")
|
||||
}
|
||||
if(index==0){
|
||||
if(isIos){
|
||||
// Safari
|
||||
if (navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1 && navigator.userAgent.indexOf('Edge') === -1) {
|
||||
return (window.open(item.children[0].href,"_blank"));
|
||||
}
|
||||
return window.open(item.children[0].href,"_blank")
|
||||
}
|
||||
return showBox("当前终端不支持")
|
||||
}
|
||||
if(index==1){
|
||||
if(isAndroid){
|
||||
return window.open(item.children[0].href,"_blank")
|
||||
}
|
||||
return showBox("当前终端不支持")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
// 移动端
|
||||
/* 显示/隐藏提示弹框 */
|
||||
function showBox(text){
|
||||
const box = document.querySelector('.BulletBox')
|
||||
box.style.display = 'block'
|
||||
box.innerHTML = text
|
||||
setTimeout(()=>{
|
||||
box.style.display = 'none'
|
||||
},1000)
|
||||
}
|
||||
// 是否是移动端
|
||||
if(isMobile){
|
||||
if(isAndroid||isIos){
|
||||
movieHandle()
|
||||
}else if(isWindows){
|
||||
movieHandle(false)
|
||||
}
|
||||
}
|
||||
const localStorageHandle = (val)=>{
|
||||
localStorage.setItem('update_log_num',val)
|
||||
@ -403,7 +478,6 @@ if(!logsItem) {
|
||||
localStorage.setItem('logs_dowmload_zh', JSON.stringify(record))
|
||||
updates.innerHTML = releases;
|
||||
}).catch(err=>{
|
||||
console.log(err,"err");
|
||||
})
|
||||
}else{
|
||||
updates.innerHTML = logsItem;
|
||||
|
||||
@ -334,18 +334,20 @@ export default {
|
||||
switch (act) {
|
||||
// 获取用户信息
|
||||
case "getInfo":
|
||||
const isTourist = (uuid+'').indexOf('88888') !== -1;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/basic',
|
||||
url: isTourist ? 'users/meeting/tourist' : 'users/basic',
|
||||
data: {
|
||||
userid: [ (uuid+"").substring(6) ]
|
||||
userid: uuid,
|
||||
tourist_id: uuid,
|
||||
}
|
||||
}).then(({data}) => {
|
||||
$A.eeuiAppSendMessage({
|
||||
action: 'updateMeetingInfo',
|
||||
infos: {
|
||||
uuid: uuid,
|
||||
avatar: data[0]?.userimg,
|
||||
username: data[0]?.nickname,
|
||||
avatar: isTourist ? data?.userimg : data[0]?.userimg,
|
||||
username: isTourist ? data?.nickname : data[0]?.nickname,
|
||||
}
|
||||
});
|
||||
}).catch(({msg}) => {
|
||||
|
||||
14
resources/assets/js/app.js
vendored
@ -1,6 +1,9 @@
|
||||
const isElectron = !!(window && window.process && window.process.type);
|
||||
const isEEUiApp = window && window.navigator && /eeui/i.test(window.navigator.userAgent);
|
||||
|
||||
import microappInit from "./microapp"
|
||||
microappInit()
|
||||
|
||||
import {switchLanguage as $L} from "./language";
|
||||
|
||||
import './functions/common'
|
||||
@ -90,6 +93,17 @@ if (!isElectron && !isEEUiApp) {
|
||||
ViewUI.LoadingBar._load = true;
|
||||
ViewUI.LoadingBar.start();
|
||||
}, 300)
|
||||
if (to.query?.theme) {
|
||||
store.dispatch("setTheme", typeof to.query?.theme == 'string' ? to.query?.theme : to.query?.theme[0])
|
||||
}
|
||||
if (to.query?.lang) {
|
||||
let lang = typeof to.query?.lang == 'string' ? to.query?.lang : to.query?.lang[0]
|
||||
if (window.localStorage.getItem("__language:type__") != lang) {
|
||||
window.localStorage.setItem("__language:type__", to.query?.lang);
|
||||
window.location.reload();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
router.afterEach(() => {
|
||||
|
||||
@ -5,12 +5,13 @@
|
||||
:closable="escClosable"
|
||||
:mask-closable="maskClosable"
|
||||
:footer-hide="true"
|
||||
:transition-names="[$A.isAndroid() ? '' : `drawer-slide-${placement}`, '']"
|
||||
:transition-names="[$A.isAndroid() ? '' : `drawer-slide-${transitionName}`, '']"
|
||||
:beforeClose="beforeClose"
|
||||
fullscreen
|
||||
:class-name="modalClass">
|
||||
<DrawerOverlayView
|
||||
:placement="placement"
|
||||
<slot v-if="isFullscreen" />
|
||||
<DrawerOverlayView v-else
|
||||
:placement="transitionName"
|
||||
:size="size"
|
||||
:minSize="minSize"
|
||||
:resize="resize"
|
||||
@ -20,17 +21,9 @@
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
body {
|
||||
.ivu-modal-wrap {
|
||||
&.common-drawer-overlay {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import DrawerOverlayView from "./view";
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'DrawerOverlay',
|
||||
@ -74,6 +67,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
show: this.value,
|
||||
isFullscreen: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -82,17 +76,30 @@ export default {
|
||||
},
|
||||
show(v) {
|
||||
this.value !== v && this.$emit("input", v)
|
||||
},
|
||||
windowWidth(val){
|
||||
this.isFullscreen = val < 500 && this.placement != 'bottom'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState([ 'windowWidth' ]),
|
||||
transitionName(){
|
||||
return this.isFullscreen ? 'bottom' : this.placement
|
||||
},
|
||||
modalClass() {
|
||||
if(this.isFullscreen){
|
||||
return "common-drawer-modal"
|
||||
}
|
||||
if (this.className) {
|
||||
return `common-drawer-overlay ${this.className} ${this.placement}`
|
||||
return `common-drawer-overlay ${this.className} ${this.transitionName}`
|
||||
} else {
|
||||
return `common-drawer-overlay ${this.placement}`
|
||||
return `common-drawer-overlay ${this.transitionName}`
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isFullscreen = this.windowWidth < 500 && this.placement != 'bottom'
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.$refs.modal.close();
|
||||
|
||||
163
resources/assets/js/components/MicroApps.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div class="page-microapp">
|
||||
<transition name="microapp-load">
|
||||
<div class="microapp-load">
|
||||
<Loading />
|
||||
</div>
|
||||
</transition>
|
||||
<micro-app v-if="url && !loading"
|
||||
:name='name'
|
||||
:url='url'
|
||||
inline
|
||||
keep-alive
|
||||
disableSandbox
|
||||
:data='appData'
|
||||
@created='handleCreate'
|
||||
@beforemount='handleBeforeMount'
|
||||
@mounted='handleMount'
|
||||
@unmount='handleUnmount'
|
||||
@error='handleError'
|
||||
@datachange='handleDataChange'
|
||||
></micro-app>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import store from '../store/index'
|
||||
import { mapState } from "vuex";
|
||||
import { EventCenterForMicroApp, unmountAllApps } from '@micro-zoe/micro-app'
|
||||
import DialogWrapper from '../pages/manage/components/DialogWrapper.vue'
|
||||
import UserSelect from "./UserSelect.vue";
|
||||
import { languageList, languageType } from "../language";
|
||||
import { DatePicker } from 'view-design-hi';
|
||||
|
||||
export default {
|
||||
name: "MicroApps",
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: "micro-app"
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
data:{
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
appUrl: '',
|
||||
appData: {}
|
||||
}
|
||||
},
|
||||
deactivated() {
|
||||
},
|
||||
mounted() {
|
||||
this.appData = this.getAppData
|
||||
},
|
||||
watch: {
|
||||
url(val) {
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false;
|
||||
let url = $A.apiUrl(val)
|
||||
if (url.indexOf('http') == -1) {
|
||||
url = window.location.origin + url
|
||||
}
|
||||
this.appUrl = import.meta.env.VITE_OKR_WEB_URL || url
|
||||
})
|
||||
},
|
||||
path(val) {
|
||||
this.appData = { path: val }
|
||||
},
|
||||
data: {
|
||||
handler(info) {
|
||||
this.appData = info
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
'$route': {
|
||||
handler(to) {
|
||||
if(to.name == 'manage-apps'){
|
||||
this.appData = {
|
||||
path: to.hash
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
userToken(val) {
|
||||
this.appData = this.getAppData;
|
||||
if(!val){
|
||||
unmountAllApps({ destroy: true })
|
||||
this.loading = true;
|
||||
}else{
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'userInfo',
|
||||
'themeMode',
|
||||
]),
|
||||
getAppData(){
|
||||
return {
|
||||
type: 'init',
|
||||
vues: {
|
||||
Vue,
|
||||
store,
|
||||
components: {
|
||||
DialogWrapper,
|
||||
UserSelect,
|
||||
DatePicker
|
||||
}
|
||||
},
|
||||
theme: this.themeMode,
|
||||
languages: {
|
||||
languageList,
|
||||
languageType,
|
||||
},
|
||||
userInfo: this.userInfo,
|
||||
path: this.path
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCreate(e) {
|
||||
// 创建前
|
||||
window.eventCenterForAppNameVite = new EventCenterForMicroApp(this.name)
|
||||
this.appData = this.getAppData
|
||||
},
|
||||
handleBeforeMount(e) {
|
||||
// 加载前
|
||||
},
|
||||
handleMount(e) {
|
||||
// 加载完成
|
||||
this.appData = this.data;
|
||||
if(this.path){
|
||||
this.appData.path = this.path
|
||||
}
|
||||
},
|
||||
handleUnmount(e) {
|
||||
// 卸载
|
||||
window.dispatchEvent(new Event('apps-unmount'));
|
||||
},
|
||||
handleError(e) {
|
||||
console.error("子应用加载出错了",e.detail.error)
|
||||
},
|
||||
handleDataChange(e) {
|
||||
// console.log('来自子应用 child-vite 的数据:', e.detail.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -205,7 +205,7 @@
|
||||
components: {IFrame},
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
type: undefined,
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
<div class="more-item">
|
||||
<i class="taskfont" v-html="item.icon"></i>
|
||||
<div class="tabbar-title">{{$L(item.label)}}</div>
|
||||
<Badge v-if="item.name === 'workReport'" class="tabbar-badge" :overflow-count="999" :count="reportUnreadNumber"/>
|
||||
<Badge v-if="item.name === 'workReport'" class="tabbar-badge" :overflow-count="999" :count="reportUnreadNumber + approveUnreadNumber"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -30,8 +30,11 @@
|
||||
<template v-else-if="item.name === 'dialog'">
|
||||
<Badge class="tabbar-badge" :overflow-count="999" :text="msgUnreadMention"/>
|
||||
</template>
|
||||
<template v-else-if="item.name === 'application'">
|
||||
<Badge class="tabbar-badge" :overflow-count="999" :count="reportUnreadNumber + approveUnreadNumber"/>
|
||||
</template>
|
||||
<template v-else-if="item.name === 'more'">
|
||||
<Badge class="tabbar-badge" :overflow-count="999" :count="reportUnreadNumber"/>
|
||||
<Badge class="tabbar-badge" :overflow-count="999" :count="reportUnreadNumber + approveUnreadNumber"/>
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
@ -68,7 +71,8 @@ export default {
|
||||
{icon: '', name: 'project', label: '项目'},
|
||||
{icon: '', name: 'dialog', label: '消息'},
|
||||
{icon: '', name: 'contacts', label: '通讯录'},
|
||||
{icon: '', name: 'more', label: '更多'},
|
||||
{icon: '', name: 'application', label: '应用'},
|
||||
// {icon: '', name: 'more', label: '更多'},
|
||||
],
|
||||
navMore: [
|
||||
[
|
||||
@ -85,6 +89,7 @@ export default {
|
||||
[
|
||||
{icon: '', name: 'workReport', label: '工作报告'},
|
||||
{icon: '', name: 'approve', label: '审批中心'},
|
||||
{icon: '', name: 'okrManage', label: 'OKR管理'},
|
||||
]
|
||||
],
|
||||
|
||||
@ -100,6 +105,7 @@ export default {
|
||||
}
|
||||
if (this.userIsAdmin) {
|
||||
this.navMore[2].splice(0, 0, {icon: '', name: 'allUser', label: '团队管理'})
|
||||
this.navMore[2].push({icon: '', name: 'okrAnalyze', label: 'OKR结果分析'})
|
||||
}
|
||||
},
|
||||
|
||||
@ -112,7 +118,7 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['userIsAdmin', 'cacheDialogs', 'reportUnreadNumber']),
|
||||
...mapState(['userIsAdmin', 'cacheDialogs', 'reportUnreadNumber', 'approveUnreadNumber']),
|
||||
...mapGetters(['dashboardTask']),
|
||||
|
||||
routeName() {
|
||||
@ -200,8 +206,9 @@ export default {
|
||||
},
|
||||
|
||||
activeName() {
|
||||
if (this.isMore || ['manage-calendar', 'manage-file', 'manage-setting'].includes(this.routeName)) {
|
||||
return 'more';
|
||||
if (this.isMore || ['manage-calendar', 'manage-file', 'manage-setting', 'manage-application', 'manage-approve', 'manage-apps'].includes(this.routeName)) {
|
||||
// return 'more';
|
||||
return 'application';
|
||||
}
|
||||
|
||||
if (this.routeName === 'manage-dashboard') {
|
||||
@ -283,6 +290,16 @@ export default {
|
||||
case 'contacts':
|
||||
location = {name: 'manage-messenger', params: {dialogAction: 'contacts'}};
|
||||
break;
|
||||
|
||||
case 'okrManage':
|
||||
case 'okrAnalyze':
|
||||
this.goForward({
|
||||
path:'/manage/apps/' + ( path == 'okrManage' ? '/#/list' : '/#/analysis') ,
|
||||
query: {
|
||||
baseUrl: this.okrUrl
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
||||
default:
|
||||
location = {name: 'manage-' + path};
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
<style lang="scss" scoped>
|
||||
.task-editor {
|
||||
position: relative;
|
||||
word-break: break-all;
|
||||
.task-editor-operate {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
<i v-else-if="item.group_type=='department'" class="taskfont icon-avatar department"></i>
|
||||
<i v-else-if="item.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="item.group_type=='task'" class="taskfont icon-avatar task"></i>
|
||||
<i v-else-if="item.group_type=='okr'" class="taskfont icon-avatar task"></i>
|
||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||
</template>
|
||||
<UserAvatar v-else :userid="item.userid" tooltip-disabled/>
|
||||
@ -112,6 +113,7 @@
|
||||
<i v-else-if="item.group_type=='department'" class="taskfont icon-avatar department"></i>
|
||||
<i v-else-if="item.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="item.group_type=='task'" class="taskfont icon-avatar task"></i>
|
||||
<i v-else-if="item.group_type=='okr'" class="taskfont icon-avatar task"></i>
|
||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||
<div class="avatar-name">
|
||||
<span>{{item.name}}</span>
|
||||
@ -252,6 +254,12 @@ export default {
|
||||
default: false
|
||||
},
|
||||
|
||||
// 是否禁用
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
// 提交前的回调
|
||||
beforeSubmit: Function
|
||||
},
|
||||
@ -312,7 +320,7 @@ export default {
|
||||
} else {
|
||||
this.searchKey = ""
|
||||
}
|
||||
this.$emit("on-show-change",value)
|
||||
this.$emit("on-show-change",value,this.values)
|
||||
},
|
||||
|
||||
searchKey() {
|
||||
@ -582,6 +590,9 @@ export default {
|
||||
},
|
||||
|
||||
onSelection() {
|
||||
if(this.disable){
|
||||
return
|
||||
}
|
||||
this.$nextTick(_ => {
|
||||
this.selects = $A.cloneJSON(this.values)
|
||||
this.showModal = true
|
||||
|
||||
13
resources/assets/js/functions/web.js
vendored
@ -734,10 +734,23 @@
|
||||
text = text.replace(atReg, `<span class="mention me" data-id="${userid}">`)
|
||||
// 处理内容连接
|
||||
if (/https*:\/\//.test(text)) {
|
||||
const urlMatch = $.apiUrl('../').match(/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n]+)/im);
|
||||
const theme = window.localStorage.getItem("__theme:mode__")
|
||||
const lang = window.localStorage.getItem("__language:type__")
|
||||
text = text.split(/(<[^>]*>)/g).map(string => {
|
||||
if (string && !/<[^>]*>/.test(string)) {
|
||||
string = string.replace(/(^|[^'"])((https*:\/\/)((\w|=|\?|\.|\/|&|-|:|\+|%|;|#|@|,|!)+))/g, "$1<a href=\"$2\" target=\"_blank\">$2</a>")
|
||||
}
|
||||
//
|
||||
const href = string.match(/href="([^"]+)"/)?.[1] || ''
|
||||
if (urlMatch?.[1] && href.indexOf(urlMatch[1]) !== -1) {
|
||||
const searchParams = new URLSearchParams()
|
||||
href.indexOf("theme=") === -1 && searchParams.append('theme', theme);
|
||||
href.indexOf("lang=") === -1 && searchParams.append('lang', lang);
|
||||
const prefix = searchParams.toString() ? (href.indexOf("?") === -1 ? '?' : '&') : '';
|
||||
string = string.replace(/(href="[^"]*)/g, '$1' + prefix + searchParams.toString())
|
||||
}
|
||||
//
|
||||
return string;
|
||||
}).join("")
|
||||
}
|
||||
|
||||
51
resources/assets/js/microapp.js
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
import microApp from '@micro-zoe/micro-app'
|
||||
|
||||
const getUrl = (s) => {
|
||||
let url = $A.apiUrl(s)
|
||||
if (url.indexOf('http') == -1) {
|
||||
url = window.location.origin + url
|
||||
}
|
||||
return import.meta.env.VITE_OKR_WEB_URL || url;
|
||||
}
|
||||
|
||||
export default function() {
|
||||
let urls = "";
|
||||
let route = "/";
|
||||
let modules = {};
|
||||
let obj = {
|
||||
loader(code,url) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const match = /^https?:\/\/([^:/]+)(?::(\d+))?/.exec(url);
|
||||
if( match && match[0] && url.indexOf('@vite/client') !== -1 ){
|
||||
urls = url.replace("@vite/client","");
|
||||
route = urls.replace(match[0].replace("@vite/client",""),"");
|
||||
}
|
||||
// 这里 /basename/ 需要和子应用vite.config.js中base的配置保持一致
|
||||
code = code.replace( eval(`/(from|import)(\\s*['"])(${route.replace(/\//g,"\\/")})/g`) , all => {
|
||||
return all.replace(route, urls)
|
||||
})
|
||||
}
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
// 微应用名称
|
||||
modules["micro-app"] = [obj]
|
||||
modules["okr-details"] = [obj]
|
||||
|
||||
// 微应用
|
||||
microApp.start({
|
||||
plugins: {
|
||||
modules: modules
|
||||
}
|
||||
})
|
||||
|
||||
//预加载
|
||||
microApp.preFetch([
|
||||
{
|
||||
name: 'micro-app',
|
||||
url: getUrl("/apps/okr"),
|
||||
disableSandbox: true
|
||||
}
|
||||
])
|
||||
}
|
||||
@ -11,8 +11,7 @@
|
||||
<UserAvatar :userid="userId" :size="36" tooltipDisabled/>
|
||||
</div>
|
||||
<span>{{userInfo.nickname}}</span>
|
||||
<Badge v-if="(reportUnreadNumber + approveUnreadNumber) > 0" class="manage-box-top-report" :overflow-count="999" :count="reportUnreadNumber + approveUnreadNumber"/>
|
||||
<Badge v-else-if="!!clientNewVersion" class="manage-box-top-report" dot/>
|
||||
<Badge v-if="!!clientNewVersion" class="manage-box-top-report" dot/>
|
||||
<div class="manage-box-arrow">
|
||||
<Icon type="ios-arrow-up" />
|
||||
<Icon type="ios-arrow-down" />
|
||||
@ -57,18 +56,11 @@
|
||||
<DropdownItem :divided="!!item.divided">
|
||||
<div class="manage-menu-flex">
|
||||
{{$L(item.name)}}
|
||||
<Badge v-if="reportUnreadNumber > 0" class="manage-menu-report-badge" :overflow-count="999" :count="reportUnreadNumber"/>
|
||||
<Icon v-else type="ios-arrow-forward"></Icon>
|
||||
<Icon type="ios-arrow-forward"></Icon>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem name="allUser">{{$L('团队管理')}}</DropdownItem>
|
||||
<DropdownItem name="workReport">
|
||||
<div class="manage-menu-flex">
|
||||
{{$L('工作报告')}}
|
||||
<Badge v-if="reportUnreadNumber > 0" class="manage-menu-report-badge" :overflow-count="999" :count="reportUnreadNumber"/>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
<DropdownItem name="exportTask">{{$L('导出任务统计')}}</DropdownItem>
|
||||
<DropdownItem name="exportOverdueTask">{{$L('导出超期任务')}}</DropdownItem>
|
||||
<DropdownItem name="exportApprove">{{$L('导出审批数据')}}</DropdownItem>
|
||||
@ -123,6 +115,11 @@
|
||||
<i class="taskfont"></i>
|
||||
<div class="menu-title">{{$L('文件')}}</div>
|
||||
</li>
|
||||
<li @click="toggleRoute('application')" :class="classNameRoute('application')">
|
||||
<i class="taskfont"></i>
|
||||
<div class="menu-title">{{$L('应用')}}</div>
|
||||
<Badge class="menu-badge" :overflow-count="999" :text="String((reportUnreadNumber + approveUnreadNumber) || '')"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ref="menuProject" class="menu-project">
|
||||
@ -200,7 +197,7 @@
|
||||
|
||||
<div class="manage-box-main">
|
||||
<keep-alive>
|
||||
<router-view class="manage-box-view"></router-view>
|
||||
<router-view class="manage-box-view" @on-click="onTabbarClick"></router-view>
|
||||
</keep-alive>
|
||||
</div>
|
||||
|
||||
@ -302,6 +299,9 @@
|
||||
</transition>
|
||||
<MobileBack :showTabbar="showMobileTabbar"/>
|
||||
<MobileNotification ref="mobileNotification"/>
|
||||
|
||||
<!-- okr明细 -->
|
||||
<MicroApps v-show="false" v-if="$route.name != 'manage-apps'" name="okr-details" :url="okrUrl" :data="okrWindow"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -325,6 +325,7 @@ import TaskExport from "./manage/components/TaskExport";
|
||||
import ApproveExport from "./manage/components/ApproveExport";
|
||||
import notificationKoro from "notification-koro1";
|
||||
import {Store} from "le5le-store";
|
||||
import MicroApps from "../components/MicroApps.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -342,7 +343,9 @@ export default {
|
||||
DrawerOverlay,
|
||||
ProjectManagement,
|
||||
TeamManagement,
|
||||
ProjectArchived},
|
||||
ProjectArchived,
|
||||
MicroApps
|
||||
},
|
||||
directives: {longpress},
|
||||
data() {
|
||||
return {
|
||||
@ -459,6 +462,8 @@ export default {
|
||||
|
||||
'reportUnreadNumber',
|
||||
'approveUnreadNumber',
|
||||
|
||||
'okrWindow'
|
||||
]),
|
||||
|
||||
...mapGetters(['dashboardTask']),
|
||||
@ -467,6 +472,15 @@ export default {
|
||||
return this.$route.name
|
||||
},
|
||||
|
||||
// okr路由
|
||||
okrUrl() {
|
||||
let url = $A.apiUrl("/apps/okr")
|
||||
if (url.indexOf('http') == -1) {
|
||||
url = window.location.origin + url
|
||||
}
|
||||
return import.meta.env.VITE_OKR_WEB_URL || url
|
||||
},
|
||||
|
||||
/**
|
||||
* 综合数(未读、提及、待办)
|
||||
* @returns {string|string}
|
||||
@ -564,12 +578,10 @@ export default {
|
||||
{path: 'archivedProject', name: '已归档的项目'},
|
||||
|
||||
{path: 'team', name: '团队管理', divided: true},
|
||||
{path: 'approve', name: '审批中心'},
|
||||
])
|
||||
} else {
|
||||
array.push(...[
|
||||
{path: 'personal', name: '个人设置', divided: true},
|
||||
{path: 'approve', name: '审批中心'},
|
||||
{path: 'version', name: '更新版本', divided: true, visible: !!this.clientNewVersion},
|
||||
|
||||
{path: 'workReport', name: '工作报告', divided: true},
|
||||
@ -625,7 +637,7 @@ export default {
|
||||
if (this.routeName === 'manage-project' && !/^\d+$/.test(this.$route.params.projectId)) {
|
||||
return true;
|
||||
}
|
||||
return ['manage-dashboard', 'manage-calendar', 'manage-messenger', 'manage-file', 'manage-setting'].includes(this.routeName)
|
||||
return ['manage-dashboard','manage-messenger', 'manage-application'].includes(this.routeName)
|
||||
},
|
||||
},
|
||||
|
||||
@ -771,11 +783,17 @@ export default {
|
||||
this.goForward('index');
|
||||
}
|
||||
return;
|
||||
case 'approve':
|
||||
case 'approve':
|
||||
if (this.menu.findIndex((m) => m.path == path) > -1) {
|
||||
this.goForward({name: 'manage-approve'});
|
||||
}
|
||||
return;
|
||||
case 'okrManage':
|
||||
case 'okrAnalyze':
|
||||
this.goForward({
|
||||
path:'/manage/apps/' + ( path == 'okrManage' ? '/#/list' : '/#/analysis'),
|
||||
});
|
||||
return;
|
||||
case 'logout':
|
||||
$A.modalConfirm({
|
||||
title: '退出登录',
|
||||
@ -818,8 +836,12 @@ export default {
|
||||
},
|
||||
|
||||
classNameRoute(path) {
|
||||
let routeName = this.routeName
|
||||
if(routeName == 'manage-approve' || routeName == 'manage-apps'){
|
||||
routeName = `manage-application`
|
||||
}
|
||||
return {
|
||||
"active": this.routeName === `manage-${path}`,
|
||||
"active": routeName === `manage-${path}`,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
501
resources/assets/js/pages/manage/application.vue
Normal file
@ -0,0 +1,501 @@
|
||||
<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 applyListTypes">
|
||||
<div v-if="isExistAdminList" class="apply-row-title">
|
||||
{{ t == 'base' ? $L('常用') : $L('管理员') }}
|
||||
</div>
|
||||
<Row :gutter="16">
|
||||
<Col v-for="(item, key) in applyList" :key="key"
|
||||
v-if="((t=='base' && !item.type) || item.type == t) && item.show !== false"
|
||||
:xs="{ span: 8 }"
|
||||
:sm="{ span: 8 }"
|
||||
:lg="{ span: 6 }"
|
||||
:xl="{ span: 4 }"
|
||||
:xxl="{ span: 3 }"
|
||||
>
|
||||
<div class="apply-col">
|
||||
<div @click="applyClick(item)">
|
||||
<img :src="getLogoPath(item.value)" />
|
||||
<p>{{ $L(item.label) }}</p>
|
||||
<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>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--工作报告-->
|
||||
<DrawerOverlay v-model="workReportShow" placement="right" :size="1200">
|
||||
<Report v-if="workReportShow" v-model="workReportTabs" @on-read="$store.dispatch('getReportUnread', 1000)" />
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--AI机器人-->
|
||||
<DrawerOverlay v-model="aibotShow" placement="right" :size="600">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('AI机器人') }}
|
||||
<p @click="aibotType = aibotType == 1 ? 2 : 1" v-if="userIsAdmin">
|
||||
{{ aibotType == 1 ? $L('机器人设置') : $L('返回') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<ul class="ivu-modal-wrap-ul" v-if="aibotType == 1">
|
||||
<li v-for="(item, key) in aibotList" @click="onGoToChat(item.value)" :key="key">
|
||||
<img :src="item.src">
|
||||
<h4>{{ item.label }}</h4>
|
||||
<p>{{ item.desc }}</p>
|
||||
<p class="btn">{{ $L('去聊天') }}</p>
|
||||
<div class="load" v-if="aibotDialogSearchLoad == item.value">
|
||||
<Loading />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<Tabs v-else v-model="aibotTabAction">
|
||||
<TabPane label="ChatGPT" name="opanai">
|
||||
<div class="aibot-warp">
|
||||
<SystemAibot type="ChatGPT" v-if="aibotTabAction == 'opanai'" />
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane label="Claude" name="claude">
|
||||
<div class="aibot-warp">
|
||||
<SystemAibot type="Claude" v-if="aibotTabAction == 'claude'" />
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('文心一言')" name="wenxin">
|
||||
<div class="aibot-warp">
|
||||
<SystemAibot type="Wenxin" v-if="aibotTabAction == 'wenxin'" />
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('通义千问')" name="qianwen">
|
||||
<div class="aibot-warp">
|
||||
<SystemAibot type="Qianwen" v-if="aibotTabAction == 'qianwen'" />
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--签到-->
|
||||
<DrawerOverlay v-model="signInShow" placement="right" :size="700">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('签到管理') }}
|
||||
<p @click="signType = signType == 1 ? 2 : 1" v-if="userIsAdmin">
|
||||
{{ signType == 1 ? $L('系统设置') : $L('返回') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<Checkin v-if="signType == 1" />
|
||||
<SystemCheckin v-else />
|
||||
</div>
|
||||
</div>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!-- 会议 -->
|
||||
<DrawerOverlay v-model="meetingShow" placement="right" :size="600">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('会议') }}
|
||||
<p @click="meetingType = meetingType == 1 ? 2 : 1">
|
||||
{{ meetingType == 1 ? $L('会议设置') : $L('返回') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<ul class="ivu-modal-wrap-ul" v-if="meetingType == 1">
|
||||
<li @click="onMeeting('createMeeting')">
|
||||
<img :src="getLogoPath('meeting')">
|
||||
<h4>{{ $L('新会议') }}</h4>
|
||||
<p>{{ $L('创建一个全新的会议视频会议,与会者可以在实时中进行面对面的视听交流。通过视频会议平台,参与者可以分享屏幕、共享文档,并与其他与会人员进行讨论和协。作') }}</p>
|
||||
<p class="btn">{{ $L('新建会议') }}</p>
|
||||
</li>
|
||||
<li @click="onMeeting('joinMeeting')">
|
||||
<img :src="getLogoPath('meeting-join')">
|
||||
<h4>{{ $L('加入会议') }}</h4>
|
||||
<p>{{ $L('加入视频会议,参与已经创建的会议,在会议过程中与其他参会人员进行远程实时视听交流和协作。') }}</p>
|
||||
<p class="btn">{{ $L('加入会议') }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<SystemMeeting v-else />
|
||||
</div>
|
||||
</div>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--LDAP-->
|
||||
<DrawerOverlay v-model="ldapShow" placement="right" :size="700">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('LDAP设置') }}
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<SystemThirdAccess />
|
||||
</div>
|
||||
</div>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--邮件-->
|
||||
<DrawerOverlay v-model="mailShow" placement="right" :size="700">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('邮件管理') }}
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<SystemEmailSetting />
|
||||
</div>
|
||||
</div>
|
||||
</DrawerOverlay>
|
||||
|
||||
<!--app推送-->
|
||||
<DrawerOverlay v-model="appPushShow" placement="right" :size="700">
|
||||
<div class="ivu-modal-wrap-apply">
|
||||
<div class="ivu-modal-wrap-apply-title">
|
||||
{{ $L('APP推送') }}
|
||||
</div>
|
||||
<div class="ivu-modal-wrap-apply-body">
|
||||
<SystemAppPush />
|
||||
</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>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import DrawerOverlay from "../../components/DrawerOverlay";
|
||||
import UserSelect from "../../components/UserSelect";
|
||||
import Report from "../manage/components/Report";
|
||||
import SystemAibot from "./setting/components/SystemAibot";
|
||||
import SystemCheckin from "./setting/components/SystemCheckin";
|
||||
import Checkin from "./setting/checkin";
|
||||
import SystemMeeting from "./setting/components/SystemMeeting";
|
||||
import SystemThirdAccess from "./setting/components/SystemThirdAccess";
|
||||
import SystemEmailSetting from "./setting/components/SystemEmailSetting";
|
||||
import SystemAppPush from "./setting/components/SystemAppPush";
|
||||
import { Store } from "le5le-store";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UserSelect,
|
||||
DrawerOverlay,
|
||||
Report,
|
||||
SystemAibot,
|
||||
SystemCheckin,
|
||||
Checkin,
|
||||
SystemMeeting,
|
||||
SystemThirdAccess,
|
||||
SystemEmailSetting,
|
||||
SystemAppPush
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
applyList: [],
|
||||
applyListTypes: ['base', 'admin'],
|
||||
//
|
||||
workReportShow: false,
|
||||
workReportTabs: "my",
|
||||
//
|
||||
aibotList: [
|
||||
{
|
||||
value: "openai",
|
||||
label: "ChatGPT",
|
||||
src: $A.apiUrl('../images/avatar/default_openai.png'),
|
||||
desc: this.$L('我是一个人工智能助手,为用户提供问题解答和指导。我没有具体的身份,只是一个程序。您有什么问题可以问我哦?')
|
||||
},
|
||||
{
|
||||
value: "claude",
|
||||
label: "Claude",
|
||||
src: $A.apiUrl('../images/avatar/default_claude.png'),
|
||||
desc: this.$L('我是Claude,一个由Anthropic公司创造出来的AI助手机器人。我的工作是帮助人类,与人对话并给出解答。')
|
||||
},
|
||||
{
|
||||
value: "wenxin",
|
||||
label: "Wenxin",
|
||||
src: $A.apiUrl('../avatar/Wenxin.png'),
|
||||
desc: this.$L('我是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。')
|
||||
},
|
||||
{
|
||||
value: "qianwen",
|
||||
label: "Qianwen",
|
||||
src: $A.apiUrl('../avatar/%E9%80%9A%E4%B9%89%E5%8D%83%E9%97%AE.png'),
|
||||
desc: this.$L('我是达摩院自主研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码。')
|
||||
},
|
||||
],
|
||||
aibotTabAction: "opanai",
|
||||
aibotShow: false,
|
||||
aibotType: 1,
|
||||
aibotDialogSearchLoad: "",
|
||||
//
|
||||
signInShow: false,
|
||||
signType: 1,
|
||||
//
|
||||
meetingShow: false,
|
||||
meetingType: 1,
|
||||
//
|
||||
ldapShow: false,
|
||||
//
|
||||
mailType: 1,
|
||||
mailShow: false,
|
||||
//
|
||||
appPushType: 1,
|
||||
appPushShow: false,
|
||||
//
|
||||
scanLoginShow: false,
|
||||
scanLoginLoad: false,
|
||||
scanLoginCode: '',
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
this.initList()
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'userIsAdmin',
|
||||
'reportUnreadNumber',
|
||||
'approveUnreadNumber',
|
||||
'cacheDialogs',
|
||||
'windowOrientation',
|
||||
]),
|
||||
isExistAdminList() {
|
||||
return this.applyList.map(h => h.type).indexOf('admin') !== -1;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
windowOrientation() {
|
||||
this.initList()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initList() {
|
||||
let applyList = [
|
||||
{ value: "approve", label: "审批中心" },
|
||||
{ value: "report", label: "工作报告" },
|
||||
{ value: "okr", label: "OKR管理" },
|
||||
{ value: "robot", label: "AI机器人" },
|
||||
{ value: "signin", label: "签到" },
|
||||
{ value: "meeting", label: "会议" }
|
||||
];
|
||||
// wap模式
|
||||
let appApplyList = this.windowOrientation != 'portrait' ? [] : [
|
||||
{ value: "calendar", label: "日历" },
|
||||
{ value: "file", label: "文件" },
|
||||
{ value: "addProject", label: "创建项目" },
|
||||
{ value: "addTask", label: "添加任务" },
|
||||
{ value: "scan", label: "扫一扫", show: $A.isEEUiApp },
|
||||
{ value: "setting", label: "设置" }
|
||||
];
|
||||
// 管理员
|
||||
let adminApplyList = !this.userIsAdmin ? [] : [
|
||||
{ value: "okrAnalyze", label: "OKR结果分析" },
|
||||
{ value: "ldap", label: "LDAP" },
|
||||
{ value: "mail", label: "邮件" },
|
||||
{ value: "appPush", label: "APP推送" },
|
||||
{ value: "allUser", label: "团队管理" }
|
||||
].map((h) => {
|
||||
h.type = 'admin';
|
||||
return h;
|
||||
});
|
||||
//
|
||||
this.applyList = [...applyList, ...appApplyList, ...adminApplyList];
|
||||
},
|
||||
getLogoPath(name) {
|
||||
name = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
return $A.apiUrl(`../images/application/${name}.svg`)
|
||||
},
|
||||
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, area = '') {
|
||||
switch (item.value) {
|
||||
case 'approve':
|
||||
case 'calendar':
|
||||
case 'file':
|
||||
case 'setting':
|
||||
this.goForward({ name: 'manage-' + item.value });
|
||||
break;
|
||||
case 'okr':
|
||||
case 'okrAnalyze':
|
||||
this.goForward({
|
||||
path: '/manage/apps/' + (item.value == 'okr' ? '/#/list' : '/#/analysis'),
|
||||
});
|
||||
break;
|
||||
case 'report':
|
||||
this.workReportTabs = area == 'badge' ? 'receive' : 'my';
|
||||
this.workReportShow = true;
|
||||
break;
|
||||
case 'robot':
|
||||
this.aibotType = 1;
|
||||
this.aibotTabAction = "opanai";
|
||||
this.aibotShow = true;
|
||||
break;
|
||||
case 'signin':
|
||||
this.signInType = 1;
|
||||
this.signInShow = true;
|
||||
break;
|
||||
case 'meeting':
|
||||
this.meetingType = 1;
|
||||
this.meetingShow = true;
|
||||
break;
|
||||
case 'ldap':
|
||||
this.ldapShow = true;
|
||||
break;
|
||||
case 'mail':
|
||||
this.mailType = 1;
|
||||
this.mailShow = true;
|
||||
break;
|
||||
case 'appPush':
|
||||
this.appPushType = 1;
|
||||
this.appPushShow = true;
|
||||
break;
|
||||
case 'scan':
|
||||
$A.eeuiAppScan(this.scanResult);
|
||||
return;
|
||||
}
|
||||
this.$emit("on-click", item.value)
|
||||
},
|
||||
// 去聊天
|
||||
onGoToChat(type) {
|
||||
let dialogId = 0;
|
||||
let email = `ai-${type}@bot.system`;
|
||||
this.cacheDialogs.map(h => {
|
||||
if (h.email == email) {
|
||||
dialogId = h.id;
|
||||
}
|
||||
})
|
||||
if (dialogId) {
|
||||
if (this.windowOrientation == 'portrait') {
|
||||
this.$store.dispatch("openDialog", dialogId)
|
||||
} else {
|
||||
this.goForward({ name: 'manage-messenger', params: { dialog_id: dialogId } });
|
||||
}
|
||||
this.aibotShow = false;
|
||||
} else {
|
||||
this.aibotDialogSearchLoad = type;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'dialog/search',
|
||||
data: { key: email },
|
||||
}).then(({ data }) => {
|
||||
if (data?.length < 1) {
|
||||
$A.messageError('机器人暂未开启');
|
||||
this.aibotDialogSearchLoad = '';
|
||||
return;
|
||||
}
|
||||
this.$store.dispatch("openDialogUserid", data[0]?.dialog_user.userid).then(_ => {
|
||||
if (this.windowOrientation != 'portrait') {
|
||||
this.goForward({ name: 'manage-messenger' })
|
||||
}
|
||||
this.aibotShow = false;
|
||||
}).catch(({ msg }) => {
|
||||
$A.modalError(msg)
|
||||
}).finally(_ => {
|
||||
this.aibotDialogSearchLoad = '';
|
||||
});
|
||||
}).catch(_ => {
|
||||
this.aibotDialogSearchLoad = '';
|
||||
});
|
||||
}
|
||||
},
|
||||
// 会议
|
||||
onMeeting(name) {
|
||||
switch (name) {
|
||||
case 'createMeeting':
|
||||
Store.set('addMeeting', {
|
||||
type: 'create',
|
||||
userids: [this.userId],
|
||||
});
|
||||
break;
|
||||
case 'joinMeeting':
|
||||
Store.set('addMeeting', {
|
||||
type: 'join',
|
||||
});
|
||||
break;
|
||||
}
|
||||
this.meetingShow = false;
|
||||
},
|
||||
// 扫一扫
|
||||
scanResult(text) {
|
||||
const arr = (text + "").match(/^https*:\/\/(.*?)\/login\?qrcode=(.*?)$/)
|
||||
if (arr) {
|
||||
// 扫码登录
|
||||
this.scanLoginCode = arr[2];
|
||||
this.scanLoginShow = true;
|
||||
return
|
||||
}
|
||||
if (/^https*:\/\//i.test(text)) {
|
||||
// 打开链接
|
||||
$A.eeuiAppOpenPage({
|
||||
pageType: 'app',
|
||||
pageTitle: ' ',
|
||||
url: 'web.js',
|
||||
params: {
|
||||
url: text,
|
||||
browser: true,
|
||||
showProgress: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div class="approve-details" :style="{'z-index':modalTransferIndex}">
|
||||
<!-- 导航 -->
|
||||
<div class="approve-details-nav">
|
||||
<div class="common-nav-back" @click="goBack()">
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
<h2>{{$L('审批详情')}}</h2>
|
||||
</div>
|
||||
<!-- 审批详情 -->
|
||||
<div class="approve-details-box" ref="approveDetailsBox">
|
||||
<h2 class="approve-details-title">
|
||||
@ -282,9 +289,12 @@ export default {
|
||||
} else if (timeDiff < 3600 * 24) {
|
||||
const hours = Math.floor(timeDiff / 3600);
|
||||
return type == 2 ? `${hours}${this.$L('小时')}` : `${hours} ${this.$L('小时前')}`;
|
||||
} else {
|
||||
} else if (timeDiff < 3600 * 24 * 30) {
|
||||
const days = Math.floor(timeDiff / 3600 / 24);
|
||||
return type == 2 ? `${days + 1}${this.$L('天')}` : `${days + 1} ${this.$L('天')}`;
|
||||
return type == 2 ? `${days + 1}${this.$L('天')}` : `${days + 1} ${this.$L('天前')}`;
|
||||
} else {
|
||||
const days = Math.floor(timeDiff / 3600 / 720);
|
||||
return type == 2 ? `${days + 1}${this.$L('月')}` : `${days + 1} ${this.$L('月前')}`;
|
||||
}
|
||||
},
|
||||
// 时间转为周几
|
||||
@ -327,10 +337,8 @@ export default {
|
||||
}
|
||||
return item;
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.datas = data
|
||||
isScrollToBottom && this.scrollToBottom();
|
||||
})
|
||||
this.datas = data
|
||||
isScrollToBottom && this.scrollToBottom();
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
}).finally(_ => {
|
||||
@ -424,14 +432,7 @@ export default {
|
||||
}
|
||||
}).then(({msg}) => {
|
||||
$A.messageSuccess("添加成功");
|
||||
if (this.$route.name == 'manage-approve-details' || this.$route.name == 'manage-messenger') {
|
||||
this.getInfo(true)
|
||||
} else {
|
||||
this.$emit('approve')
|
||||
setTimeout(() => {
|
||||
this.scrollToBottom()
|
||||
}, 500);
|
||||
}
|
||||
this.getInfo(true)
|
||||
this.commentShow = false;
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
@ -441,11 +442,13 @@ export default {
|
||||
},
|
||||
// 滚动到容器底部
|
||||
scrollToBottom() {
|
||||
const container = this.$refs.approveDetailsBox
|
||||
container.scrollTo({
|
||||
top: container.scrollHeight + 1000,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
this.$nextTick(() => {
|
||||
const container = this.$refs.approveDetailsBox
|
||||
container.scrollTo({
|
||||
top: container.scrollHeight + 1000,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
})
|
||||
},
|
||||
// 获取内容
|
||||
getContent(content) {
|
||||
|
||||
@ -2,15 +2,34 @@
|
||||
<div class="page-approve">
|
||||
<PageTitle :title="$L('审批中心')"/>
|
||||
<div class="approve-wrapper" ref="fileWrapper">
|
||||
|
||||
<div class="approve-head">
|
||||
<div class="approve-nav">
|
||||
<div class="common-nav-back" @click="goBack()"><i class="taskfont"></i></div>
|
||||
<h1>{{$L('审批中心')}}</h1>
|
||||
</div>
|
||||
<Button :loading="addLoadIng" type="primary" @click="addApply">{{$L("添加申请")}}</Button>
|
||||
</div>
|
||||
|
||||
<Button v-show="showType == 1 && isShowIcon" @click="addApply" :loading="addLoadIng" type="primary" shape="circle" icon="md-add" class="ivu-btn-icon-only"></Button>
|
||||
<Button v-if="showType == 1 && !isShowIcon" :loading="addLoadIng" type="primary" @click="addApply">
|
||||
<span> {{$L("添加申请")}} </span>
|
||||
</Button>
|
||||
|
||||
<Tabs :value="tabsValue" @on-click="tabsClick" style="margin: 0 20px;height: 100%;" size="small">
|
||||
<Button v-show="showType == 1 && userIsAdmin && !isShowIcon" @click="exportApproveShow = true">
|
||||
<span> {{$L("导出审批数据")}} </span>
|
||||
</Button>
|
||||
<Button v-if="showType == 1 && userIsAdmin && isShowIcon" @click="exportApproveShow = true" shape="circle" class="ivu-btn-icon-only">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
|
||||
<Button v-if="userIsAdmin && !isShowIcon" @click="showType = showType == 1 ? 2 : 1">
|
||||
<span> {{ showType == 1 ? $L("流程设置") : $L("返回") }} </span>
|
||||
</Button>
|
||||
<Button v-if="userIsAdmin && isShowIcon" @click="showType = showType == 1 ? 2 : 1" shape="circle" class="ivu-btn-icon-only">
|
||||
<i v-if="showType == 1" class="taskfont"></i>
|
||||
<i v-if="showType == 2" class="taskfont"></i>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Tabs class="page-approve-tabs" v-if="showType==1" :value="tabsValue" @on-click="tabsClick" size="small">
|
||||
<TabPane :label="$L('待办') + (unreadTotal > 0 ? ('('+unreadTotal+')') : '')" name="unread" style="height: 100%;">
|
||||
<div class="approve-main-search">
|
||||
<div>
|
||||
@ -132,6 +151,8 @@
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
|
||||
<ApproveSetting v-else/>
|
||||
|
||||
</div>
|
||||
|
||||
<!--详情-->
|
||||
@ -206,6 +227,9 @@
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<!--导出审批数据-->
|
||||
<ApproveExport v-model="exportApproveShow"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -214,13 +238,18 @@ import list from "./list.vue";
|
||||
import listDetails from "./details.vue";
|
||||
import DrawerOverlay from "../../../components/DrawerOverlay";
|
||||
import ImgUpload from "../../../components/ImgUpload";
|
||||
import ApproveSetting from "./setting";
|
||||
import ApproveExport from "../components/ApproveExport";
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
components:{list,listDetails,DrawerOverlay,ImgUpload},
|
||||
components:{list,listDetails,DrawerOverlay,ImgUpload,ApproveSetting,ApproveExport},
|
||||
name: "approve",
|
||||
data() {
|
||||
return {
|
||||
showType: 1,
|
||||
exportApproveShow: false,
|
||||
isShowIcon: false,
|
||||
modalTransferIndex: window.modalTransferIndex,
|
||||
|
||||
minDate: new Date(2020, 0, 1),
|
||||
@ -240,8 +269,6 @@ export default {
|
||||
approvalType: "all",
|
||||
approvalList: [
|
||||
{ value: "all", label: this.$L("全部审批") },
|
||||
{ value: "请假", label: this.$L("请假") },
|
||||
{ value: "加班申请", label: this.$L("加班申请") },
|
||||
],
|
||||
searchState: "all",
|
||||
searchStateList: [
|
||||
@ -306,7 +333,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState([ 'wsMsg','userInfo','userIsAdmin' ]),
|
||||
...mapState([ 'wsMsg','userInfo','userIsAdmin','windowWidth' ]),
|
||||
departmentList(){
|
||||
let departmentNames = (this.userInfo.department_name || '').split(',');
|
||||
return (this.userInfo.department || []).map((h,index)=>{
|
||||
@ -320,16 +347,21 @@ export default {
|
||||
watch: {
|
||||
'$route' (to) {
|
||||
if(to.name == 'manage-approve'){
|
||||
this.tabsClick()
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
wsMsg: {
|
||||
handler(info) {
|
||||
const {type, action} = info;
|
||||
const {type, action, mode, data} = info;
|
||||
switch (type) {
|
||||
case 'approve':
|
||||
if (action == 'unread') {
|
||||
this.tabsClick()
|
||||
this.tabsClick();
|
||||
}
|
||||
break;
|
||||
case 'dialog':
|
||||
if (mode == 'add' && data?.msg?.text?.indexOf('open-approve-details') != -1) {
|
||||
this.tabsClick();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -340,16 +372,53 @@ export default {
|
||||
if(!val){
|
||||
this.addData.other = ""
|
||||
}
|
||||
},
|
||||
showType(val){
|
||||
if(val == 1){
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
windowWidth(val){
|
||||
this.isShowIcon = val < 515
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.tabsValue = "unread"
|
||||
this.tabsClick()
|
||||
this.getUnreadList()
|
||||
this.addData.department_id = this.userInfo.department[0] || 0;
|
||||
this.addData.startTime = this.addData.endTime = this.getCurrentDate();
|
||||
this.init()
|
||||
},
|
||||
methods:{
|
||||
|
||||
init() {
|
||||
this.tabsClick()
|
||||
this.getProcdefList()
|
||||
if(this.tabsValue != 'unread'){
|
||||
this.getUnreadList();
|
||||
}
|
||||
this.addData.department_id = this.userInfo.department[0] || 0;
|
||||
this.addData.startTime = this.addData.endTime = this.getCurrentDate();
|
||||
this.isShowIcon = this.windowWidth < 515
|
||||
},
|
||||
|
||||
// 获取流程列表
|
||||
getProcdefList() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'approve/procdef/all',
|
||||
method: 'post',
|
||||
}).then(({data}) => {
|
||||
this.procdefList = data.rows || [];
|
||||
this.approvalList = this.procdefList.map(h=>{
|
||||
return { value: h.name, label: h.name }
|
||||
})
|
||||
this.approvalList.unshift({ value: "all", label: this.$L("全部审批") })
|
||||
resolve()
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
reject()
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 获取当前时间
|
||||
getCurrentDate() {
|
||||
const today = new Date();
|
||||
@ -372,6 +441,9 @@ export default {
|
||||
if(val){
|
||||
this.approvalType = this.searchState = "all"
|
||||
}
|
||||
//
|
||||
this.detailsShow = false;
|
||||
//
|
||||
if(this.tabsValue == 'unread'){
|
||||
if(val === false){
|
||||
this.unreadPage = 1;
|
||||
@ -400,6 +472,7 @@ export default {
|
||||
}
|
||||
this.getInitiatedList();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// 列表点击事件
|
||||
@ -625,16 +698,11 @@ export default {
|
||||
skipAuthError: true
|
||||
}).then(({data}) => {
|
||||
this.addData.department_id = data[0]?.department[0] || 0;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'approve/procdef/all',
|
||||
method: 'post',
|
||||
}).then(({data}) => {
|
||||
this.procdefList = data.rows || [];
|
||||
this.getProcdefList().then(_ => {
|
||||
this.addTitle = this.$L("添加申请");
|
||||
this.addShow = true;
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
}).finally(_ => {
|
||||
this.addLoadIng = false;
|
||||
}).catch(_ => {
|
||||
this.addLoadIng = false;
|
||||
});
|
||||
}).catch(({msg}) => {
|
||||
@ -672,6 +740,7 @@ export default {
|
||||
this.addShow = false;
|
||||
this.$refs.initiateRef.resetFields();
|
||||
this.tabsValue = 'initiated';
|
||||
this.initiatedList.map(h=>{ h._active = false; })
|
||||
this.$nextTick(()=>{
|
||||
this.tabsClick();
|
||||
})
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="setting-item submit">
|
||||
<Row class="approve-row" :gutter="8">
|
||||
<Col :xxl="{ span: 6 }" :xl="{ span: 8 }" :lg="{ span: 12 }" :sm="{ span: 24 }" :xs="{ span: 24 }" >
|
||||
<div class="page-approve-setting">
|
||||
<Row class="approve-row" :gutter="16">
|
||||
<Col :xxl="{ span: 6 }" :xl="{ span: 8 }" :lg="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" >
|
||||
<div class="approve-col-box approve-col-add" @click="add">
|
||||
<Icon type="md-add" />
|
||||
</div>
|
||||
</Col>
|
||||
<Col v-for="(item, key) in list" :xxl="{ span: 6 }" :xl="{ span: 8 }" :lg="{ span: 12 }" :sm="{ span: 24 }" :xs="{ span: 24 }" :key="key">
|
||||
<Col v-for="(item, key) in list" :xxl="{ span: 6 }" :xl="{ span: 8 }" :lg="{ span: 12 }" :sm="{ span: 12 }" :xs="{ span: 24 }" :key="key">
|
||||
<div class="approve-col-box approve-col-for" @click="edit(item)">
|
||||
<p>{{$L('流程名称')}}:<span style="font-weight: 500;color: #135de6;">{{$L(item.name)}}</span></p>
|
||||
<Divider style="margin: 12px 0;margin-bottom: 9px;"/>
|
||||
<p>{{$L('流程名称')}}:<span class="approve-name">{{$L(item.name)}}</span></p>
|
||||
<Divider class="divider"/>
|
||||
<div class="approve-button-box" @click.stop="edit(item)">
|
||||
<p>{{$L('已发布')}}</p>
|
||||
<p @click.stop="change(item)" style="position: relative;">
|
||||
<p class="icon-warp" @click.stop="change(item)" >
|
||||
<Icon type="md-trash" size="16" class="delcon"/>
|
||||
</p>
|
||||
</div>
|
||||
@ -33,7 +33,7 @@ import DrawerOverlay from "../../../components/DrawerOverlay";
|
||||
import store from '../../../store/state'
|
||||
import {languageType} from "../../../language";
|
||||
export default {
|
||||
name: "approve",
|
||||
name: "ApproveSetting",
|
||||
components: {DrawerOverlay},
|
||||
data(){
|
||||
return{
|
||||
42
resources/assets/js/pages/manage/apps.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<MicroApps :url="appUrl" :path="path" v-if="!loading" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MicroApps from "../../components/MicroApps.vue";
|
||||
|
||||
export default {
|
||||
components: { MicroApps },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
appUrl: '',
|
||||
path: '',
|
||||
}
|
||||
},
|
||||
|
||||
deactivated() {
|
||||
this.loading = true;
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$route': {
|
||||
handler(to) {
|
||||
if (to.name == 'manage-apps') {
|
||||
this.loading = true;
|
||||
this.$nextTick(() => {
|
||||
this.loading = false;
|
||||
let url = $A.apiUrl("/apps/okr")
|
||||
if (url.indexOf('http') == -1) {
|
||||
url = window.location.origin + url
|
||||
}
|
||||
this.appUrl = import.meta.env.VITE_OKR_WEB_URL || url
|
||||
this.path = this.$route.query.path || '';
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -4,6 +4,7 @@
|
||||
<div class="calendar-head">
|
||||
<div class="calendar-titbox">
|
||||
<div class="calendar-title">
|
||||
<div class="common-nav-back portrait" @click="goBack()"><i class="taskfont"></i></div>
|
||||
<h1>{{rangeText}}</h1>
|
||||
</div>
|
||||
<ButtonGroup class="calendar-arrow" size="small">
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
</ul>
|
||||
</Scrollbar>
|
||||
</div>
|
||||
<ul v-if="!onlyEmoji" class="chat-emoji-menu">
|
||||
<ul v-if="!onlyEmoji" ref="chatEmojiMenuRef" class="chat-emoji-menu" :style="chatEmojiMenuStyle" @scroll="onHandleScroll">
|
||||
<li v-if="showEmojiMenuScrollLeftBtn" @click="onEmojiMenuScroll('left')" class="left-btn"><i class="taskfont"></i></li>
|
||||
<li :class="{active: type === 'emosearch'}" @click="type='emosearch'">
|
||||
<i class="taskfont"></i>
|
||||
</li>
|
||||
@ -33,6 +34,7 @@
|
||||
<li v-for="item in emoticonData" :class="{active: type === 'emoticon' && emoticonPath == item.path}" @click="onEmoticon(item.path)">
|
||||
<img :title="item.name" :alt="item.name" :src="item.src"/>
|
||||
</li>
|
||||
<li v-if="showEmojiMenuScrollRightBtn" @click="onEmojiMenuScroll('right')" class="right-btn"><i class="taskfont"></i></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
@ -77,10 +79,13 @@ export default {
|
||||
|
||||
emojiData: [],
|
||||
emoticonData: [],
|
||||
|
||||
emojiMenuScrollLeft: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initData()
|
||||
this.onMonitorWheel()
|
||||
},
|
||||
watch: {
|
||||
type() {
|
||||
@ -109,6 +114,20 @@ export default {
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
chatEmojiMenuStyle() {
|
||||
return {
|
||||
paddingLeft: this.showEmojiMenuScrollLeftBtn ? '34px' : 0,
|
||||
paddingRight: this.showEmojiMenuScrollRightBtn ? '34px' : 0,
|
||||
}
|
||||
},
|
||||
showEmojiMenuScrollLeftBtn(){
|
||||
return this.emojiMenuScrollLeft > 34
|
||||
},
|
||||
showEmojiMenuScrollRightBtn(){
|
||||
const container = this.$refs['chatEmojiMenuRef'];
|
||||
const liWidth = container?.querySelector('li')?.offsetWidth || 48;
|
||||
return this.emojiMenuScrollLeft < this.emoticonData.length * liWidth - 34
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -201,7 +220,27 @@ export default {
|
||||
} else {
|
||||
this.$emit('on-select', item)
|
||||
}
|
||||
},
|
||||
|
||||
onMonitorWheel() {
|
||||
const container = this.$refs['chatEmojiMenuRef'];
|
||||
container?.addEventListener("wheel", (event) =>{
|
||||
event.preventDefault();
|
||||
container.scrollLeft += event.deltaY;
|
||||
});
|
||||
},
|
||||
|
||||
onEmojiMenuScroll(type) {
|
||||
const container = this.$refs['chatEmojiMenuRef'];
|
||||
const containerWidth = container.offsetWidth - 68
|
||||
const scrollLeft = type == 'right' ? container.scrollLeft + containerWidth : container.scrollLeft - containerWidth
|
||||
container.scrollTo({ left: scrollLeft, behavior: "smooth" })
|
||||
},
|
||||
|
||||
onHandleScroll(event) {
|
||||
this.emojiMenuScrollLeft = event.target.scrollLeft;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -99,6 +99,7 @@ export default {
|
||||
if (group_type === 'task') return '任务群组'
|
||||
if (group_type === 'user') return '个人群组'
|
||||
if (group_type === 'all') return '全员群组'
|
||||
if (group_type === 'okr') return 'OKR群组'
|
||||
return '未知'
|
||||
},
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
<i v-else-if="dialogData.group_type=='department'" class="taskfont icon-avatar department"></i>
|
||||
<i v-else-if="dialogData.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="dialogData.group_type=='task'" class="taskfont icon-avatar task"></i>
|
||||
<i v-else-if="dialogData.group_type=='okr'" class="taskfont icon-avatar task"></i>
|
||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||
</template>
|
||||
<div v-else-if="dialogData.dialog_user" class="user-avatar">
|
||||
@ -804,6 +805,9 @@ export default {
|
||||
if (this.dialogData.group_type === 'task') {
|
||||
array.push({type: 'task', label: '打开任务'})
|
||||
}
|
||||
if (this.dialogData.group_type === 'okr') {
|
||||
array.push({type: 'okr', label: '打开OKR'})
|
||||
}
|
||||
return array
|
||||
},
|
||||
|
||||
@ -959,12 +963,9 @@ export default {
|
||||
return b.msg_id - a.msg_id
|
||||
})[0]
|
||||
if (this.allMsgs.findIndex(({id}) => id == item.msg_id) === -1) {
|
||||
if (item.label === '{UNREAD}') {
|
||||
return Object.assign(item, {
|
||||
'label': this.$L(`未读消息${unread}条`)
|
||||
})
|
||||
}
|
||||
return item
|
||||
return Object.assign(item, {
|
||||
'label': this.$L(`未读消息${unread}条`)
|
||||
})
|
||||
}
|
||||
return null
|
||||
},
|
||||
@ -1905,6 +1906,13 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
openOkr() {
|
||||
if (!this.dialogData.link_id) {
|
||||
return;
|
||||
}
|
||||
this.$store.dispatch("openOkr", this.dialogData.link_id);
|
||||
},
|
||||
|
||||
onPrevPage() {
|
||||
if (this.prevId === 0) {
|
||||
return
|
||||
@ -2261,6 +2269,10 @@ export default {
|
||||
this.openTask()
|
||||
break;
|
||||
|
||||
case 'okr':
|
||||
this.openOkr()
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this.loadMsg) {
|
||||
$A.messageWarning("正在加载,请稍后再试...")
|
||||
@ -2562,6 +2574,9 @@ export default {
|
||||
if (target.classList.contains('mention') && target.classList.contains('task')) {
|
||||
this.$store.dispatch("openTask", $A.runNum(target.getAttribute("data-id")));
|
||||
}
|
||||
if (target.classList.contains('mention') && target.classList.contains('okr')) {
|
||||
this.$store.dispatch("openOkr", $A.runNum(target.getAttribute("data-id")));
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -4,13 +4,17 @@
|
||||
<Modal
|
||||
v-model="addShow"
|
||||
:title="$L(addData.type === 'join' ? '加入会议' : '新会议')"
|
||||
:mask-closable="false">
|
||||
<Form ref="addForm" :model="addData" label-width="auto" @submit.native.prevent>
|
||||
:mask-closable="false"
|
||||
:closable="!addData.sharekey">
|
||||
<Form ref="addForm" :model="addData" :rules="addRule" label-width="auto" @submit.native.prevent>
|
||||
<template v-if="addData.type === 'join'">
|
||||
<!-- 加入会议 -->
|
||||
<FormItem v-if="addData.name" prop="userids" :label="$L('会议主题')">
|
||||
<Input v-model="addData.name" disabled/>
|
||||
</FormItem>
|
||||
<FormItem v-if="addData.sharekey" prop="username" :label="$L('你的姓名')">
|
||||
<Input v-model="addData.username" :placeholder="$L('请输入你的姓名')"/>
|
||||
</FormItem>
|
||||
<FormItem prop="meetingid" :label="$L('会议频道ID')">
|
||||
<Input v-model="addData.meetingid" :disabled="addData.meetingdisabled === true" :placeholder="$L('请输入会议频道ID')"/>
|
||||
</FormItem>
|
||||
@ -36,7 +40,7 @@
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="addShow=false">{{$L('取消')}}</Button>
|
||||
<Button type="default" @click="addShow=false" v-if="!addData.sharekey">{{$L('取消')}}</Button>
|
||||
<Button type="primary" :loading="loadIng > 0" @click="onSubmit">{{$L(addData.type === 'join' ? '加入会议' : '开始会议')}}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -56,7 +60,8 @@
|
||||
<ul>
|
||||
<li v-if="localUser.uid">
|
||||
<MeetingPlayer :player="localUser" isLocal/>
|
||||
</li><li v-for="user in remoteUsers">
|
||||
</li>
|
||||
<li v-for="user in remoteUsers">
|
||||
<MeetingPlayer :player="user"/>
|
||||
</li>
|
||||
</ul>
|
||||
@ -68,10 +73,10 @@
|
||||
<i class="taskfont" v-html="localUser.videoTrack ? '' : ''"></i>
|
||||
</Button>
|
||||
<template v-if="windowPortrait">
|
||||
<Button type="primary" @click="onInvitation('open')">
|
||||
<Button type="primary" :loading="linkCopyLoad" @click="onInvitation('open')">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
<Button type="primary" @click="meetingMini = true">
|
||||
<Button type="primary" v-if="!addData.sharekey" @click="meetingMini = true">
|
||||
<i class="taskfont"></i>
|
||||
</Button>
|
||||
<Button type="warning" :loading="loadIng > 0" @click="onClose">
|
||||
@ -80,7 +85,7 @@
|
||||
</template>
|
||||
<template v-else>
|
||||
<Button type="primary" @click="onInvitation('open')">{{$L('邀请')}}</Button>
|
||||
<Button type="primary" @click="meetingMini = true">{{$L('最小化')}}</Button>
|
||||
<Button type="primary" v-if="!addData.sharekey" @click="meetingMini = true">{{$L('最小化')}}</Button>
|
||||
<Button type="warning" :loading="loadIng > 0" @click="onClose">{{$L('离开会议')}}</Button>
|
||||
</template>
|
||||
</div>
|
||||
@ -108,7 +113,7 @@
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="invitationShow=false">{{$L('取消')}}</Button>
|
||||
<Button type="default" :loading="linkCopyLoad" @click="linkCopy">{{$L('复制链接')}}</Button>
|
||||
<Button type="primary" :loading="invitationLoad" @click="onInvitation('submit')">{{$L('发送邀请')}}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -118,13 +123,21 @@
|
||||
<script>
|
||||
import {Store} from "le5le-store";
|
||||
import {mapState} from 'vuex'
|
||||
import MeetingPlayer from "./MeetingPlayer";
|
||||
import MeetingPlayer from "./MeetingPlayer.vue";
|
||||
import DragBallComponent from "../../../components/DragBallComponent";
|
||||
import UserSelect from "../../../components/UserSelect.vue";
|
||||
|
||||
export default {
|
||||
name: "MeetingManager",
|
||||
components: {UserSelect, DragBallComponent, MeetingPlayer},
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return "meeting-player-" + Math.round(Math.random() * 10000);
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
@ -135,6 +148,11 @@ export default {
|
||||
userids: [],
|
||||
tracks: ['audio']
|
||||
},
|
||||
addRule: {
|
||||
username: [
|
||||
{ required: true, message: this.$L('请输入你的姓名!'), trigger: 'change' },
|
||||
]
|
||||
},
|
||||
|
||||
invitationShow: false,
|
||||
invitationLoad: false,
|
||||
@ -154,6 +172,8 @@ export default {
|
||||
audioTrack: null,
|
||||
videoTrack: null,
|
||||
},
|
||||
|
||||
linkCopyLoad: false,
|
||||
}
|
||||
},
|
||||
|
||||
@ -185,6 +205,16 @@ export default {
|
||||
this.addShow = val.show;
|
||||
this.loadIng = 0;
|
||||
break;
|
||||
case 'join':
|
||||
this.addShow = val.show;
|
||||
this.loadIng = 0;
|
||||
this.addData.type = 'join';
|
||||
if(val.meetingSharekey){
|
||||
this.addData.sharekey = val.meetingSharekey;
|
||||
this.addData.meetingid = val.meetingid || '';
|
||||
this.addData.meetingdisabled = val.meetingSharekey ? true : false;
|
||||
}
|
||||
break;
|
||||
case 'invitation':
|
||||
this.invitationShow = val.show;
|
||||
this.invitationLoad = false;
|
||||
@ -251,6 +281,8 @@ export default {
|
||||
}).then(({data}) => {
|
||||
this.$set(this.addData, 'name', data.name);
|
||||
this.$set(this.addData, 'meetingid', data.meetingid);
|
||||
this.$set(this.localUser, 'nickname', data.nickname);
|
||||
this.$set(this.localUser, 'userimg', data.userimg);
|
||||
this.$store.dispatch("saveDialogMsg", data.msgs);
|
||||
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
||||
delete data.name;
|
||||
@ -270,6 +302,7 @@ export default {
|
||||
video: this.addData.tracks.includes("video"),
|
||||
audio: this.addData.tracks.includes("audio"),
|
||||
meetingid: data.meetingid,
|
||||
sharelink: data.sharelink,
|
||||
alert: {
|
||||
title: this.$L('温馨提示'),
|
||||
message: this.$L('确定要离开会议吗?'),
|
||||
@ -314,6 +347,10 @@ export default {
|
||||
|
||||
onInvitation(type) {
|
||||
if (type === 'open') {
|
||||
if(this.addData.sharekey){
|
||||
this.linkCopy();
|
||||
return;
|
||||
}
|
||||
this.invitationData = {
|
||||
userids: [],
|
||||
meetingid: this.addData.meetingid
|
||||
@ -345,6 +382,10 @@ export default {
|
||||
okText: '退出',
|
||||
onOk: async _ => {
|
||||
await this.leave()
|
||||
if(this.addData.sharekey){
|
||||
this.addShow = true;
|
||||
this.loadIng = 0;
|
||||
}
|
||||
resolve()
|
||||
}
|
||||
});
|
||||
@ -496,7 +537,29 @@ export default {
|
||||
if (item) {
|
||||
await this.agoraClient.unsubscribe(user, mediaType);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
linkCopy() {
|
||||
this.linkCopyLoad = true;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/meeting/link',
|
||||
data: {
|
||||
meetingid: this.addData.meetingid || this.invitationData.meetingid,
|
||||
sharekey: this.addData.sharekey
|
||||
},
|
||||
}).then(({ data }) => {
|
||||
this.$copyText(data).then(_ => {
|
||||
$A.messageSuccess('已复制会议邀请链接');
|
||||
}).catch(_ => {
|
||||
$A.messageError('复制失败');
|
||||
});
|
||||
this.invitationShow = false;
|
||||
}).catch(({ msg }) => {
|
||||
$A.modalError(msg);
|
||||
}).finally(_ => {
|
||||
this.linkCopyLoad = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div v-if="userid" class="meeting-player">
|
||||
<div class="meeting-player">
|
||||
<div :id="id" class="player" :style="playerStyle"></div>
|
||||
<UserAvatar :userid="userid" :size="36" :borderWitdh="2"/>
|
||||
<UserAvatar v-if="userid" :userid="userid" :size="36" :borderWitdh="2"/>
|
||||
<div v-else-if="tourist.userimg" class="common-avatar avatar-wrapper">
|
||||
<div class="avatar-box online">
|
||||
<em></em>
|
||||
<EAvatar :size="36" :src="tourist.userimg"></EAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-state">
|
||||
<i v-if="!audio" class="taskfont"></i>
|
||||
<i v-if="!video" class="taskfont"></i>
|
||||
@ -32,7 +38,12 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timer: null
|
||||
timer: null,
|
||||
tourist: {
|
||||
uid: '',
|
||||
nickname: '',
|
||||
userimg: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -52,7 +63,11 @@ export default {
|
||||
...mapState(['cacheUserBasic']),
|
||||
userid() {
|
||||
if (this.player.uid) {
|
||||
return parseInt( (this.player.uid+"").substring(6) )
|
||||
if( (this.player.uid + '').indexOf('88888') !== -1 ){
|
||||
this.getTouristInfo();
|
||||
return 0;
|
||||
}
|
||||
return parseInt( (this.player.uid+"").substring(5) ) || 0
|
||||
}
|
||||
return 0
|
||||
},
|
||||
@ -62,6 +77,10 @@ export default {
|
||||
return {
|
||||
backgroundImage: `url("${user.userimg}")`
|
||||
}
|
||||
}else if(this.tourist.userimg){
|
||||
return {
|
||||
backgroundImage: `url("${this.tourist.userimg}")`
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@ -99,6 +118,18 @@ export default {
|
||||
console.log("Meeting Player Error", e);
|
||||
}
|
||||
})
|
||||
},
|
||||
getTouristInfo() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/meeting/tourist',
|
||||
data: {
|
||||
tourist_id: this.player.uid
|
||||
}
|
||||
}).then(({data}) => {
|
||||
this.tourist = data;
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
<div class="file-head">
|
||||
<div class="file-nav">
|
||||
<div class="common-nav-back portrait" @click="goForward({name: 'manage-application'},true)"><i class="taskfont"></i></div>
|
||||
<h1>{{$L('文件')}}</h1>
|
||||
<div v-if="loadIng == 0" class="file-refresh" @click="getFileList"><i class="taskfont"></i></div>
|
||||
</div>
|
||||
|
||||
@ -70,6 +70,7 @@
|
||||
<i v-else-if="dialog.group_type=='department'" class="taskfont icon-avatar department"></i>
|
||||
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task"></i>
|
||||
<i v-else-if="dialog.group_type=='okr'" class="taskfont icon-avatar task"></i>
|
||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||
</template>
|
||||
<div v-else-if="dialog.dialog_user" class="user-avatar"><UserAvatar :userid="dialog.dialog_user.userid" :size="42"/></div>
|
||||
@ -453,6 +454,14 @@ export default {
|
||||
if (['dialog', 'contacts'].includes(params.dialogAction)) {
|
||||
this.tabActive = params.dialogAction
|
||||
}
|
||||
if (params.dialog_id) {
|
||||
this.tabActive = 'dialog'
|
||||
const id = $A.runNum(params.dialog_id);
|
||||
if (id > 0) {
|
||||
this.openDialog(id)
|
||||
}
|
||||
this.clickAgainSubscribe = Store.subscribe('clickAgainDialog', this.shakeUnread);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
@ -536,7 +545,7 @@ export default {
|
||||
|
||||
methods: {
|
||||
listTouch() {
|
||||
if (this.$refs.navMenu.visible) {
|
||||
if (this.$refs.navMenu?.visible) {
|
||||
this.$refs.navMenu.hide()
|
||||
}
|
||||
},
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
<script>
|
||||
import CheckinCalendar from "../components/CheckinCalendar";
|
||||
export default {
|
||||
name: "ManageCheckin",
|
||||
components: {CheckinCalendar},
|
||||
|
||||
data() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="setting-component-item">
|
||||
<Form ref="formData" :model="formData" :rules="ruleData" label-width="auto" @submit.native.prevent>
|
||||
<div class="block-setting-box">
|
||||
<div class="block-setting-box" v-if="type=='all' || type=='ChatGPT'">
|
||||
<h3>ChatGPT</h3>
|
||||
<div class="form-box">
|
||||
<FormItem label="API Key" prop="openai_key">
|
||||
@ -14,7 +14,7 @@
|
||||
</FormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-setting-box">
|
||||
<div class="block-setting-box" v-if="type=='all' || type=='Claude'">
|
||||
<h3>Claude</h3>
|
||||
<div class="form-box">
|
||||
<FormItem label="Token" prop="claude_token">
|
||||
@ -27,7 +27,7 @@
|
||||
</FormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-setting-box">
|
||||
<div class="block-setting-box" v-if="type=='all' || type=='Wenxin'">
|
||||
<h3>文心一言 (Wenxin)</h3>
|
||||
<div class="form-box">
|
||||
<FormItem label="API Key" prop="wenxin_key">
|
||||
@ -47,7 +47,7 @@
|
||||
</FormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-setting-box">
|
||||
<div class="block-setting-box" v-if="type=='all' || type=='Qianwen'">
|
||||
<h3>通义千问 (Qianwen)</h3>
|
||||
<div class="form-box">
|
||||
<FormItem label="API Key" prop="qianwen_key">
|
||||
@ -74,6 +74,11 @@
|
||||
<script>
|
||||
export default {
|
||||
name: "SystemAibot",
|
||||
props: {
|
||||
type: {
|
||||
default: 'all'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
type="timerange"
|
||||
format="HH:mm"
|
||||
:placeholder="$L('请选择签到时间')"/>
|
||||
<Form @submit.native.prevent>
|
||||
<Form @submit.native.prevent class="block-setting-advance">
|
||||
<FormItem :label="$L('最早可提前')" prop="advance">
|
||||
<div class="input-number-box">
|
||||
<InputNumber v-model="formData.advance" :min="0" :step="1"/>
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
<Radio label="open">{{ $L('开启') }}</Radio>
|
||||
<Radio label="close">{{ $L('关闭') }}</Radio>
|
||||
</RadioGroup>
|
||||
<Form v-if="formData.notice_msg == 'open'" @submit.native.prevent>
|
||||
<Form v-if="formData.notice_msg == 'open'" @submit.native.prevent class="block-setting-msg-unread">
|
||||
<FormItem :label="$L('未读个人消息')" prop="msg_unread_user_minute">
|
||||
<div class="input-number-box">
|
||||
<InputNumber v-model="formData.msg_unread_user_minute" :min="0" :step="1"/>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<div class="setting-head">
|
||||
<div class="setting-titbox">
|
||||
<div class="setting-title">
|
||||
<div v-if="showMobileBox" class="common-nav-back portrait" @click="goForward({name: 'manage-application'},true)"><i class="taskfont"></i></div>
|
||||
<h1>{{settingTitleName}}</h1>
|
||||
<div v-if="!showMobileBox" class="setting-more" @click="toggleRoute('index')">
|
||||
<Icon type="md-close" />
|
||||
@ -74,7 +75,6 @@ export default {
|
||||
{path: 'personal', name: '个人设置'},
|
||||
{path: 'password', name: '密码设置'},
|
||||
{path: 'email', name: '修改邮箱'},
|
||||
{path: 'checkin', name: '签到设置', desc: ' (Beta)'},
|
||||
{path: 'language', name: '语言设置', divided: true},
|
||||
{path: 'theme', name: '主题设置'},
|
||||
]
|
||||
@ -93,7 +93,6 @@ export default {
|
||||
if (this.userIsAdmin) {
|
||||
menu.push(...[
|
||||
{path: 'system', name: '系统设置', divided: true},
|
||||
{path: 'approve', name: '审批设置', desc: ' (Beta)'},
|
||||
{path: 'license', name: 'License Key'},
|
||||
])
|
||||
}
|
||||
|
||||
@ -10,24 +10,6 @@
|
||||
<TabPane :label="$L('项目模板')" name="columnTemplate">
|
||||
<SystemColumnTemplate/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('AI机器人')" name="aibot">
|
||||
<SystemAibot/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('会议功能')" name="meeting">
|
||||
<SystemMeeting/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('签到功能')" name="checkin">
|
||||
<SystemCheckin/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('邮件设置')" name="emailSetting">
|
||||
<SystemEmailSetting/>
|
||||
</TabPane>
|
||||
<TabPane :label="$L('认证设置')" name="thirdAccess">
|
||||
<SystemThirdAccess/>
|
||||
</TabPane>
|
||||
<TabPane v-if="$A.isDooServer()" :label="$L('APP推送')" name="appPush">
|
||||
<SystemAppPush/>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</template>
|
||||
@ -36,20 +18,9 @@
|
||||
import SystemSetting from "./components/SystemSetting";
|
||||
import SystemTaskPriority from "./components/SystemTaskPriority";
|
||||
import SystemColumnTemplate from "./components/SystemColumnTemplate";
|
||||
import SystemEmailSetting from "./components/SystemEmailSetting";
|
||||
import SystemAppPush from "./components/SystemAppPush";
|
||||
import SystemMeeting from "./components/SystemMeeting";
|
||||
import SystemCheckin from "./components/SystemCheckin";
|
||||
import SystemThirdAccess from "./components/SystemThirdAccess";
|
||||
import SystemAibot from "./components/SystemAibot.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SystemAibot,
|
||||
SystemThirdAccess,
|
||||
SystemCheckin,
|
||||
SystemMeeting,
|
||||
SystemAppPush, SystemColumnTemplate, SystemTaskPriority, SystemSetting, SystemEmailSetting},
|
||||
components: {SystemColumnTemplate, SystemTaskPriority, SystemSetting},
|
||||
data() {
|
||||
return {
|
||||
tabAction: 'setting',
|
||||
|
||||
23
resources/assets/js/pages/meeting.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<MeetingManager/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MeetingManager from "./manage/components/MeetingManager.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MeetingManager,
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch("showMeetingWindow",{
|
||||
type: "join",
|
||||
meetingid: this.$route.params.meetingId,
|
||||
meetingSharekey: this.$route.params.sharekey,
|
||||
meetingdisabled: true,
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
22
resources/assets/js/routes.js
vendored
@ -9,6 +9,11 @@ export default [
|
||||
path: '/pro',
|
||||
component: () => import('./pages/pro.vue'),
|
||||
},
|
||||
{
|
||||
name: 'meeting',
|
||||
path: '/meeting/:meetingId?/:sharekey?',
|
||||
component: () => import('./pages/meeting.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage',
|
||||
path: '/manage',
|
||||
@ -39,6 +44,11 @@ export default [
|
||||
path: 'approve/details',
|
||||
component: () => import('./pages/manage/approve/details.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-apps',
|
||||
path: 'apps/*',
|
||||
component: () => import('./pages/manage/apps.vue')
|
||||
},
|
||||
{
|
||||
name: 'manage-setting',
|
||||
path: 'setting',
|
||||
@ -54,11 +64,6 @@ export default [
|
||||
path: 'checkin',
|
||||
component: () => import('./pages/manage/setting/checkin.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-setting-approve',
|
||||
path: 'approve',
|
||||
component: () => import('./pages/manage/setting/approve.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-setting-language',
|
||||
path: 'language',
|
||||
@ -116,6 +121,11 @@ export default [
|
||||
path: 'file/:folderId?/:fileId?',
|
||||
component: () => import('./pages/manage/file.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-application',
|
||||
path: 'application',
|
||||
component: () => import('./pages/manage/application.vue'),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -167,5 +177,5 @@ export default [
|
||||
name: '404',
|
||||
path: '*',
|
||||
component: () => import('./pages/404.vue')
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
41
resources/assets/js/store/actions.js
vendored
@ -112,6 +112,9 @@ export default {
|
||||
'version': window.systemInfo.version || "0.0.1",
|
||||
'platform': $A.Platform,
|
||||
}
|
||||
if(!state.userToken && state.meetingWindow?.meetingSharekey){
|
||||
header.sharekey = state.meetingWindow.meetingSharekey;
|
||||
}
|
||||
if ($A.isJson(params.header)) {
|
||||
params.header = Object.assign(header, params.header)
|
||||
} else {
|
||||
@ -3589,7 +3592,6 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
/** *****************************************************************************************/
|
||||
/** *************************************** meeting *********************************************/
|
||||
/** *****************************************************************************************/
|
||||
@ -3613,11 +3615,44 @@ export default {
|
||||
* @param type
|
||||
* @param meetingid
|
||||
*/
|
||||
showMeetingWindow({state}, {type, meetingid}) {
|
||||
showMeetingWindow({state}, {type, meetingid, meetingdisabled, meetingSharekey}) {
|
||||
state.meetingWindow = {
|
||||
show: true,
|
||||
type: type,
|
||||
meetingid: meetingid
|
||||
meetingid: meetingid,
|
||||
meetingdisabled: meetingdisabled,
|
||||
meetingSharekey: meetingSharekey
|
||||
};
|
||||
},
|
||||
|
||||
/** *****************************************************************************************/
|
||||
/** *************************************** okr *********************************************/
|
||||
/** *****************************************************************************************/
|
||||
|
||||
/**
|
||||
* 打开Okr详情页
|
||||
* @param state
|
||||
* @param dispatch
|
||||
* @param link_id
|
||||
*/
|
||||
openOkr({state}, link_id) {
|
||||
if (link_id > 0) {
|
||||
if (window.innerWidth < 910) {
|
||||
$A.goForward({
|
||||
path:'/manage/apps/#/okrDetails?data='+link_id,
|
||||
});
|
||||
}else{
|
||||
state.okrWindow = {
|
||||
type: 'okrDetails',
|
||||
show: true,
|
||||
id: link_id
|
||||
};
|
||||
setTimeout(()=>{
|
||||
state.okrWindow.show = false;
|
||||
state.okrWindow.id = 0;
|
||||
},10)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
9
resources/assets/js/store/state.js
vendored
@ -199,10 +199,17 @@ export default {
|
||||
// 审批待办未读数量
|
||||
approveUnreadNumber: 0,
|
||||
|
||||
// 会议窗口
|
||||
// 会议
|
||||
meetingWindow: {
|
||||
show: false,
|
||||
type: "",
|
||||
meetingid: 0
|
||||
},
|
||||
|
||||
// okr窗口
|
||||
okrWindow: {
|
||||
type: 'okrDetails',
|
||||
id: 0,
|
||||
show: false
|
||||
}
|
||||
};
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
|
||||
.overlay-close {
|
||||
flex-shrink: 0;
|
||||
|
||||
3
resources/assets/sass/components/report.scss
vendored
@ -69,6 +69,9 @@
|
||||
margin-bottom: 12px;
|
||||
padding: 20px 24px;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
@media (max-width: 500px) {
|
||||
padding-right: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-detail-context {
|
||||
|
||||
2
resources/assets/sass/pages/_.scss
vendored
@ -8,4 +8,6 @@
|
||||
@import "page-project";
|
||||
@import "page-setting";
|
||||
@import "page-approve";
|
||||
@import "page-microapp";
|
||||
@import "page-apply";
|
||||
@import "components/_";
|
||||
|
||||
35
resources/assets/sass/pages/common.scss
vendored
@ -743,3 +743,38 @@ body {
|
||||
transform: translate(100%, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/*全局 ivu-modal-wrap*/
|
||||
body {
|
||||
.ivu-modal-wrap {
|
||||
&.common-drawer-overlay {
|
||||
overflow: hidden;
|
||||
}
|
||||
&.common-drawer-modal{
|
||||
.ivu-modal-body{
|
||||
padding: 0 !important;
|
||||
}
|
||||
.ivu-modal-close{
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*全局返回按钮*/
|
||||
.common-nav-back{
|
||||
cursor: pointer;
|
||||
padding-right: 8px;
|
||||
&.portrait{
|
||||
display: none;
|
||||
}
|
||||
.taskfont{
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
body.window-portrait {
|
||||
.common-nav-back{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -339,7 +339,7 @@
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
border-radius: 8px;
|
||||
box-sizing: content-box;
|
||||
// box-sizing: content-box;
|
||||
> li {
|
||||
position: relative;
|
||||
&:before {
|
||||
@ -375,6 +375,7 @@
|
||||
.chat-emoji-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.chat-emoji-emosearch {
|
||||
flex-shrink: 0;
|
||||
@ -523,6 +524,24 @@
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
|
||||
.left-btn,.right-btn{
|
||||
position: absolute !important;
|
||||
height: 40px;
|
||||
background: #f2f4f7 !important;
|
||||
width: 34px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.left-btn{
|
||||
left: 0;
|
||||
box-shadow: 10px 0 10px -10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.right-btn{
|
||||
right: 0;
|
||||
box-shadow: -10px 0 10px -10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -860,7 +879,8 @@ body.window-portrait {
|
||||
border-radius: 0;
|
||||
background-color: #f8f8f8;
|
||||
padding: 4px;
|
||||
width: calc(100% - 8px);
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
> li {
|
||||
&.active {
|
||||
&:before {
|
||||
@ -868,6 +888,9 @@ body.window-portrait {
|
||||
}
|
||||
}
|
||||
}
|
||||
.left-btn,.right-btn{
|
||||
background: #f8f8f8 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,6 +320,10 @@
|
||||
background-image: url("../images/dialog/task.svg");
|
||||
}
|
||||
|
||||
&.okr i {
|
||||
background-image: url("../images/dialog/task.svg");
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
color: $primary-color;
|
||||
@ -707,7 +711,7 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.task {
|
||||
&.task,&.okr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@ -47,6 +47,14 @@ body {
|
||||
right: -8px;
|
||||
z-index: 2;
|
||||
}
|
||||
.avatar-box{
|
||||
em{
|
||||
transform: scale(1.0625);
|
||||
}
|
||||
.el-avatar--circle{
|
||||
border: 2px solid #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.project-panel {
|
||||
display: flex;
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
.project-titbox {
|
||||
width: 100%;
|
||||
|
||||
356
resources/assets/sass/pages/page-apply.scss
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
.page-apply {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.apply-wrapper {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-color: #fafafa;
|
||||
|
||||
.apply-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 16px;
|
||||
margin: 32px 32px 0 32px;
|
||||
border-bottom: 1px solid #F4F4F5;
|
||||
|
||||
.apply-nav {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
>h1 {
|
||||
color: $primary-title-color;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.apply-content {
|
||||
flex: 1;
|
||||
padding: 16px 30px;
|
||||
overflow: auto;
|
||||
|
||||
.apply-row-title{
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.apply-col {
|
||||
margin-bottom: 16px;
|
||||
|
||||
>div {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
background: #ffffff;
|
||||
color: #282828;
|
||||
border-radius: 8px;
|
||||
padding: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
border: 1px solid #f1f1f1;
|
||||
|
||||
@media (max-width: 510px) {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
>img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
@media (max-width: 510px) {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
>p{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
@media (max-width: 510px) {
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-box-top-report {
|
||||
position: absolute;
|
||||
right: -16px;
|
||||
top: -16px;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-modal-wrap-apply {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 100vw;
|
||||
overflow: auto;
|
||||
|
||||
.ivu-modal-wrap-apply-title {
|
||||
line-height: 40px;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
padding: 12px 30px;
|
||||
color: #303133;
|
||||
|
||||
>p {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
color: #2b85e4;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ivu-modal-wrap-apply-body {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 8px 30px;
|
||||
|
||||
//
|
||||
.setting-component-item,
|
||||
.setting-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
>.ivu-form {
|
||||
padding: 8px 30px;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
|
||||
.ivu-form-item {
|
||||
padding: 12px 0 0 0;
|
||||
.ivu-form-item .ivu-form-item-content {
|
||||
display: flex;
|
||||
|
||||
>.ivu-form {
|
||||
margin-bottom: 8px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.block-setting-box {
|
||||
position: relative;
|
||||
padding: 24px 24px 4px;
|
||||
margin: 24px 0 12px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eeeeee;
|
||||
transition: box-shadow 0.3s;
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.block-setting-advance{
|
||||
>.ivu-form-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ivu-form-item-label{
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 460px) {
|
||||
.block-setting-msg-unread{
|
||||
>.ivu-form-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ivu-form-item-label{
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 24px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #eeeeee;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
transform: translateY(-50%)
|
||||
}
|
||||
}
|
||||
|
||||
.setting-template {
|
||||
margin-bottom: 12px;
|
||||
|
||||
>div {
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.export-data>p {
|
||||
cursor: pointer;
|
||||
color: #2b85e4;
|
||||
}
|
||||
|
||||
.setting-footer {
|
||||
flex-shrink: 0;
|
||||
position: static;
|
||||
padding: 16px 26px;
|
||||
border-top: 1px solid #F4F4F5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.ivu-btn{
|
||||
min-width: 120px;
|
||||
height: 38px;
|
||||
line-height: 36px;
|
||||
@media (max-width: 500px) {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
.ivu-tabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
margin: 0 -30px;
|
||||
.ivu-tabs-bar{
|
||||
padding: 0 10px;
|
||||
}
|
||||
.ivu-tabs-content {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
.ivu-modal-wrap-ul {
|
||||
list-style-type: none;
|
||||
overflow: hidden;
|
||||
border-radius: 3px;
|
||||
margin-right: -10px;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
width: calc(50% - 10px);
|
||||
border: 1px solid #eeeeee;
|
||||
box-sizing: border-box;
|
||||
padding: 28px 20px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 16px;
|
||||
margin: 0 auto 12px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-style: normal;
|
||||
max-width: 100%;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #1b1b1b;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
padding: 0 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 4;
|
||||
@media (max-width: 510px) {
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
color: #2b85e4;
|
||||
margin: 26px auto 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.load {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #9797971c;
|
||||
line-height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 机器人
|
||||
.aibot-warp {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
.ivu-form {
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0 30px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body.window-portrait {
|
||||
.page-apply {
|
||||
.apply-head{
|
||||
margin: 24px 24px 0 24px;
|
||||
}
|
||||
.apply-content{
|
||||
padding: 16px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
115
resources/assets/sass/pages/page-approve.scss
vendored
@ -18,6 +18,7 @@
|
||||
margin: 32px 20px 16px;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #F4F4F5;
|
||||
gap: 16px;
|
||||
|
||||
.approve-nav {
|
||||
flex: 1;
|
||||
@ -62,6 +63,11 @@
|
||||
line-height: 150px;
|
||||
}
|
||||
|
||||
.page-approve-tabs{
|
||||
margin: 0 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.approve-mains {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
@ -177,6 +183,25 @@
|
||||
border: 1px solid #eeeeee;
|
||||
background: #fff;
|
||||
|
||||
.approve-details-nav{
|
||||
height: 52px;
|
||||
padding:0 8px;
|
||||
text-align: center;
|
||||
line-height: 52px;
|
||||
background-color: #f8f8f8;
|
||||
display: none;
|
||||
@media (max-width: 425px) {
|
||||
display: block;
|
||||
}
|
||||
.common-nav-back{
|
||||
float: left;
|
||||
}
|
||||
h2{
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.approve-details-box {
|
||||
flex: 1 1 auto;
|
||||
padding: 24px;
|
||||
@ -374,3 +399,93 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.page-approve-setting{
|
||||
|
||||
.approve-row {
|
||||
padding: 24px;
|
||||
overflow: auto;
|
||||
margin: 0 !important;
|
||||
|
||||
.ivu-col {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.approve-col-box {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eeeeee;
|
||||
transition: box-shadow 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px #e6ecfa;
|
||||
}
|
||||
}
|
||||
|
||||
.approve-col-add {
|
||||
height: 100%;
|
||||
font-size: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #ededed;
|
||||
min-height: 95px;
|
||||
}
|
||||
|
||||
.approve-col-for {
|
||||
padding: 16px;
|
||||
padding-bottom: 13px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.approve-name{
|
||||
font-weight: 500;
|
||||
color: #135de6;
|
||||
}
|
||||
|
||||
.divider{
|
||||
margin: 12px 0;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
.icon-warp{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
> p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.approve-button-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
> p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> i {
|
||||
font-size: 16px;
|
||||
margin-left: 8px;
|
||||
color: rgb(96, 98, 102);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
body.window-portrait {
|
||||
.page-approve{
|
||||
.approve-head {
|
||||
margin: 24px 16px 6px 16px;
|
||||
}
|
||||
.approve-mains {
|
||||
height: calc(100vh - 250px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,6 +194,7 @@
|
||||
body.window-portrait {
|
||||
.page-calendar {
|
||||
.calendar-head {
|
||||
margin: 24px 16px 16px;
|
||||
.calendar-titbox {
|
||||
.calendar-title {
|
||||
flex: 1;
|
||||
|
||||
2
resources/assets/sass/pages/page-file.scss
vendored
@ -709,7 +709,7 @@ body.window-portrait {
|
||||
.page-file {
|
||||
.file-wrapper {
|
||||
.file-head {
|
||||
margin: 24px 24px 16px;
|
||||
margin: 24px 16px 16px;
|
||||
}
|
||||
.file-navigator {
|
||||
margin: 0 24px 0;
|
||||
|
||||
9
resources/assets/sass/pages/page-microapp.scss
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.page-microapp {
|
||||
.microapp-load{
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
61
resources/assets/sass/pages/page-setting.scss
vendored
@ -349,65 +349,6 @@
|
||||
.setting-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.approve-row {
|
||||
padding: 24px 40px;
|
||||
overflow: auto;
|
||||
|
||||
.ivu-col {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.approve-col-box {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eeeeee;
|
||||
transition: box-shadow 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px #e6ecfa;
|
||||
}
|
||||
}
|
||||
|
||||
.approve-col-add {
|
||||
height: 100%;
|
||||
font-size: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #ededed;
|
||||
min-height: 95px;
|
||||
}
|
||||
|
||||
.approve-col-for {
|
||||
padding: 16px;
|
||||
padding-bottom: 13px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.approve-button-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
> p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> i {
|
||||
font-size: 16px;
|
||||
margin-left: 8px;
|
||||
color: rgb(96, 98, 102);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -434,7 +375,7 @@
|
||||
body.window-portrait {
|
||||
.page-setting {
|
||||
.setting-head {
|
||||
margin: 32px 32px 0;
|
||||
margin: 24px 16px 16px;
|
||||
.setting-titbox {
|
||||
.setting-title {
|
||||
.setting-more {
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#87D068;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M35.7,20.1c0-0.8-0.4-1.5-1.1-1.9l-8.9-5.1c-1-0.6-2.2-0.6-3.1,0l-9.1,5.2c-0.6,0.4-1,1-1,1.8s0.4,1.4,1,1.8
|
||||
l9.1,5.2c0.5,0.3,1,0.4,1.6,0.4c0.5,0,1.1-0.1,1.6-0.4l8.9-5.1C35.3,21.6,35.7,20.9,35.7,20.1z"/>
|
||||
<path class="st1" d="M24,29.7c-0.4,0-0.8-0.1-1.2-0.3l-9-5.1c-0.4-0.2-0.9-0.1-1.2,0.3c-0.2,0.4-0.1,0.9,0.3,1.2l9,5.1
|
||||
c0.6,0.4,1.3,0.6,2,0.6c0,0,0,0,0,0c0.5,0,0.9-0.4,0.9-0.9C24.9,30.1,24.5,29.7,24,29.7z"/>
|
||||
<path class="st1" d="M24,33.5c-0.6,0-1.3-0.2-1.8-0.5l-8.4-4.8c-0.4-0.2-0.9-0.1-1.2,0.3c-0.2,0.4-0.1,0.9,0.3,1.2l8.4,4.8
|
||||
c0.8,0.5,1.7,0.7,2.6,0.7c0,0,0,0,0,0c0.5,0,0.9-0.4,0.9-0.9C24.9,33.9,24.5,33.5,24,33.5z"/>
|
||||
<path class="st1" d="M34.8,30h-2.6v-2.6c0-0.5-0.4-0.9-0.9-0.9c-0.5,0-0.9,0.4-0.9,0.9V30h-2.6c-0.5,0-0.9,0.4-0.9,0.9
|
||||
s0.4,0.9,0.9,0.9h2.6v2.6c0,0.5,0.4,0.9,0.9,0.9c0.5,0,0.9-0.4,0.9-0.9v-2.6h2.6c0.5,0,0.9-0.4,0.9-0.9S35.3,30,34.8,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#87D068;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M36,48H12C5.4,48,0,42.6,0,36V12C0,5.4,5.4,0,12,0h24c6.6,0,12,5.4,12,12v24C48,42.6,42.6,48,36,48z"/>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st1" cx="19.7" cy="26.6" r="0.9"/>
|
||||
<g>
|
||||
<path class="st1" d="M29,26.9c0.5,0,0.9,0.4,0.9,0.9l0,2.6l2.6,0c0.5,0,0.9,0.4,0.9,0.9c0,0.5-0.4,0.9-0.9,0.9l-2.6,0l0,2.6
|
||||
c0,0.5-0.4,0.9-0.9,0.9c-0.5,0-0.9-0.4-0.9-0.9l0-2.6l-2.6,0c-0.5,0-0.9-0.4-0.9-0.9c0-0.5,0.4-0.9,0.9-0.9l2.6,0l0-2.6
|
||||
C28.1,27.3,28.5,26.9,29,26.9"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M26.6,34.8l0-1.2l-1.2,0c0,0,0,0,0,0c-0.6,0-1.2-0.2-1.6-0.7c-0.4-0.4-0.7-1-0.7-1.6c0-0.6,0.2-1.2,0.7-1.6
|
||||
c0.4-0.4,1-0.7,1.6-0.7l1.2,0l0-1.2c0-1.3,1-2.3,2.3-2.3c0,0,0,0,0,0c1.3,0,2.3,1,2.3,2.3l0,1.2l1.2,0c0,0,0,0,0,0
|
||||
c0.3,0,0.6,0.1,0.9,0.2V14.7c0-1.3-1.1-2.3-2.3-2.3H17c-1.3,0-2.3,1.1-2.3,2.3v18.7c0,1.3,1,2.3,2.3,2.3h9.8
|
||||
C26.7,35.4,26.6,35.1,26.6,34.8z M19.7,29.3c-1.4,0-2.6-1.2-2.6-2.6s1.2-2.6,2.6-2.6s2.6,1.2,2.6,2.6S21.1,29.3,19.7,29.3z
|
||||
M22.6,17.9l-2.9,2.9c-0.2,0.2-0.4,0.3-0.6,0.3s-0.4-0.1-0.6-0.3l-1.2-1.2c-0.3-0.3-0.3-0.9,0-1.2s0.9-0.3,1.2,0l0.5,0.5l2.3-2.3
|
||||
c0.3-0.3,0.9-0.3,1.2,0S23,17.6,22.6,17.9z M24.9,17.6h4.7c0.5,0,0.9,0.4,0.9,0.9s-0.4,0.9-0.9,0.9h-4.7c-0.5,0-0.9-0.4-0.9-0.9
|
||||
S24.4,17.6,24.9,17.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |