build / build (push) Successful in 43s
- 色系:#2d8cf0 / #1d4ed8 整族换 #5979ea(hover #4864d8),覆盖今日方块、圆点、查看概览、展开、今日星期 - 列表区:268px(≈5 条) → calc(var(--wk-row) * 3) = 171px(正好 3 条 + 滚动),新增 --wk-row: 57px - 条目等高 57px;信息行(地点 · 负责人 · 出席对象)恒渲染,三者全空落「-」,不再留白 - 备注:无备注整块不渲染;超 2 行才出「展开」且贴第二行末尾;remarkText 加 trim;换周重置 remarkOverflow - 「查看概览 ›」→「查看概览」(去掉箭头字符) - 修 X 轴滚动条根因(views/index.vue):widgetOptions 的 scrollPanel 关掉 scrollingX 原 scrollingX=true 时 vuescroll 给 .__view 内联 width:fit-content,包含块被最长文本撑到 ≈425px ⇒ 面板 scrollWidth 561 > clientWidth 391,外框出 #333 横向条、日期条 7 列被裁成 5 列、长条目省略号失效 同时 .content { min-width: 0 } 兜底(flex 项默认 min-width:auto 会让 nowrap 文本不收缩)
555 lines
21 KiB
Vue
555 lines
21 KiB
Vue
<template>
|
||
<div class="used-app-wrap">
|
||
<div class="used-app-list" ref="refApplist">
|
||
<template v-for="item in appList" :key="item.id + ''">
|
||
<ContextMenu
|
||
class="app-container"
|
||
:title="item.name"
|
||
@on-change="onMenuChange"
|
||
@select="onMenuSel"
|
||
:menu="[
|
||
{
|
||
label: '从桌面删除',
|
||
appId: item.id,
|
||
id: '1',
|
||
},
|
||
{
|
||
label: '新窗口打开',
|
||
appId: item.appId,
|
||
id: '2',
|
||
},
|
||
]"
|
||
>
|
||
<a @click="openLinkPage(item)">
|
||
<template v-if="item.type == 1">
|
||
<AppIcon v-if="vectorIconOf(item)" :name="vectorIconOf(item)" scene="tile"
|
||
:tint="item.iconColor" />
|
||
<img v-else :src="$utils.appIconPath(item.icon)" />
|
||
</template>
|
||
<img
|
||
v-else-if="item.type == 2"
|
||
:src="$conf.fileHost + '/image/lightapp.default.png'"
|
||
v-real-img="$conf.serviceHost + item.icon"
|
||
/>
|
||
|
||
<div class="app-name">{{ item.name }}</div>
|
||
</a>
|
||
</ContextMenu>
|
||
</template>
|
||
</div>
|
||
<vue-drag-resize
|
||
v-if="isDragShowComp"
|
||
:class="{ 'widget-wrap__drag': dragObj.isDrag }"
|
||
contentClass="widget-wrap"
|
||
:x="dragPositionObj.xaxis"
|
||
:y="dragPositionObj.yaxis"
|
||
:w="dragPositionObj.width"
|
||
:h="dragPositionObj.height"
|
||
:parentW="dragObj.parentW"
|
||
:parentH="dragObj.parentH"
|
||
:minh="248"
|
||
:z="10"
|
||
:isActive="true"
|
||
:parentLimitation="true"
|
||
:isDraggable="dragObj.isDrag"
|
||
:isResizable="true"
|
||
:preventActiveBehavior="true"
|
||
:stickSize="5"
|
||
:sticks="['tm', 'bm']"
|
||
@clicked="onDragChange"
|
||
@dragstop="onDragResizestop($event, 'drag')"
|
||
@resizestop="onDragResizestop($event, 'resize')"
|
||
>
|
||
<div class="widget-header">
|
||
<Dropdown
|
||
placement="bottom-start"
|
||
:visible="dragObj.selVisible"
|
||
@on-click="onWidgetSelItemClick"
|
||
trigger="custom"
|
||
transfer-class-name="wg-dd"
|
||
>
|
||
<div class="operate-btn" @click="showWidgetSelClick">
|
||
<SvgIcon class="fl" name="widget-add" size="24" color="currentColor" />
|
||
</div>
|
||
<template #list>
|
||
<DropdownMenu style="min-width: 120px; max-height: 200px; overflow-y: auto">
|
||
<DropdownItem :key="item.k" :name="item.k" v-for="item in widgetSel">
|
||
<div class="fix">
|
||
<div class="fl">{{ item.v }}</div>
|
||
<SvgIcon
|
||
v-if="!!item.checked"
|
||
class="fr mt-3"
|
||
name="widget-checked"
|
||
color="currentColor"
|
||
size="14"
|
||
></SvgIcon>
|
||
</div>
|
||
</DropdownItem>
|
||
</DropdownMenu>
|
||
</template>
|
||
</Dropdown>
|
||
|
||
<div class="widget-header-drag" @mousedown="(e:any)=>dragObj.isDrag = e.buttons === 1"></div>
|
||
<div class="operate-btn" @click="onClickWidgetHide">
|
||
<SvgIcon class="fr" name="widget-sub" size="24" color="currentColor" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="widget-body" v-show="!dragObj.isDrag">
|
||
<vuescroll :ops="widgetOps" v-if="widgetAppList.length > 0">
|
||
<div class="widget-item pr" v-for="item in widgetAppList">
|
||
<div class="widget-app-header">
|
||
<span>{{ item.name }}</span>
|
||
<!-- 内置组件在 header 里的挂载点:组件用 <Teleport> 把自身控件放进来(如课表班级切换器) -->
|
||
<div class="widget-header-right">
|
||
<span class="widget-header-extra" :id="'wg-hdr-' + item.id"></span>
|
||
<SvgIcon
|
||
@click="onWidgetSelItemClick(item.id)"
|
||
class="fr"
|
||
name="widget-close"
|
||
size="18"
|
||
color="#999999"
|
||
hoverColor="#646566"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<!-- ① front 工程内置组件:内容在代码库,不走 iframe -->
|
||
<component
|
||
v-if="item.compType === 1 && widgetRegistry[item.code]"
|
||
:is="widgetRegistry[item.code]"
|
||
:widget-id="item.id"
|
||
:overview-url="item.overviewUrl"
|
||
@loaded="onWidgetLoaded(item.id, $event)"
|
||
/>
|
||
<template v-else>
|
||
<Skeleton
|
||
style="padding: 15px"
|
||
:loading="item.loading"
|
||
:title="false"
|
||
:paragraph="{ rows: 4 }"
|
||
animated
|
||
/>
|
||
<!-- ② 自定义 HTML 片段:内容来自 widget_catalog.content,srcdoc 内联,无外部地址 -->
|
||
<iframe
|
||
v-if="item.compType === 2 && !!item.content"
|
||
v-show="!item.loading"
|
||
:style="{ height: item.height + 'px' }"
|
||
:id="'iframe_widget_' + item.id"
|
||
:data-id="item.id"
|
||
@load="onIframeLoad(item.id)"
|
||
:srcdoc="widgetFragmentSrc(item)"
|
||
sandbox="allow-scripts allow-same-origin allow-forms"
|
||
class="widget-app-iframe"
|
||
></iframe>
|
||
<!-- ③ 兜底:注册表未命中 / 片段内容为空,渲染空态而非白屏(拉取途中交给骨架) -->
|
||
<div v-else-if="!isFragmentPending(item)" class="no-data">该小工具暂不可用</div>
|
||
</template>
|
||
</div>
|
||
</vuescroll>
|
||
<template v-if="widgetAppList.length == 0">
|
||
<div class="widget-empty-box">
|
||
<!-- 用 -vec(纯矢量,颜色跟随 currentColor);widget-empty 是内嵌 PNG 的假 SVG,颜色烤死 -->
|
||
<SvgIcon name="widget-empty-vec" color="currentColor" size="120"></SvgIcon>
|
||
<h4>单击 + 按钮可添加小工具。</h4>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</vue-drag-resize>
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import ContextMenu from "@/components/ContextMenu.vue";
|
||
import AppIcon from "@/components/AppIcon.vue";
|
||
import { appiconKeyOf } from "@/constants/appIconRules";
|
||
import { ref, reactive, onMounted, onUnmounted, computed, watch, watchEffect, nextTick } from "vue";
|
||
import BaseApi from "@/api/BaseApi";
|
||
// @ts-ignore
|
||
import VueDragResize from "vue-drag-resize/src";
|
||
import { useDefaultStore } from "@/store";
|
||
import SvgIcon from "@/components/SvgIcon.vue";
|
||
import { widgetRegistry } from "@/components/widgets";
|
||
import { cloneDeep, debounce, difference, includes, once, pick, remove } from "lodash";
|
||
import UserSettingApi from "@/api/UserSettingApi";
|
||
import { wrapFragment } from "@/utils/widgetFragment";
|
||
import { bschLinkPage } from "@/utils/bschLinkPage";
|
||
import {
|
||
BschLoadTypeEnum,
|
||
BschTransferRoleInfo,
|
||
IframePageParmas,
|
||
LinkOpenTypeEnum,
|
||
StateEnum,
|
||
WidgetPosition,
|
||
WidgetPositionResp,
|
||
} from "@/types";
|
||
import { bschRoleEncode } from "@/utils/bschRoleEncode";
|
||
import { useRouter, useRoute } from "vue-router";
|
||
import mittBus from "@/utils/mitt";
|
||
import vuescroll from "vuescroll";
|
||
import useCurrentInstance from "@/utils/hook/useCurrentInstance";
|
||
import { Message } from "view-ui-plus";
|
||
import { useDraggable } from "vue-draggable-plus";
|
||
|
||
const { $conf, $utils } = useCurrentInstance();
|
||
const store = useDefaultStore();
|
||
const route = useRoute();
|
||
const router = useRouter();
|
||
|
||
/**
|
||
* 矢量渲染判定(方案 §5.4 回退链,与 AppList.vue / SearchPanel.vue 同口径):
|
||
* icon_key 命中 → 矢量;有位图 URL → 位图(存量零回归);URL 空且关键词命中 → 矢量;否则默认图。
|
||
*/
|
||
function vectorIconOf(item: any): string {
|
||
if (item?.iconKey) return item.iconKey;
|
||
if (item?.icon) return "";
|
||
return appiconKeyOf(item?.name || "");
|
||
}
|
||
|
||
const refApplist = ref();
|
||
const isDragShow = ref(false),
|
||
isDesltopAppDefault = ref(false),
|
||
appList = ref<any[]>([]);
|
||
const dragObj = reactive({
|
||
isDrag: false,
|
||
selVisible: false,
|
||
parentW: 0,
|
||
parentH: 0,
|
||
});
|
||
|
||
/**
|
||
* vuescroll 面板参数。
|
||
* ⚠️ scrollingX 必须显式 false:vuescroll 默认 true,此时 native-panel 会给 .__view 内联
|
||
* `width: fit-content; min-width: 100%`,`.widget-item` 的包含块就被「最长的 nowrap 文本」
|
||
* 撑宽(白卡 357px → 内容 ≈425px)⇒ 列表条目 text-overflow 永不触发(文字顶到卡边被硬裁)、
|
||
* 七日条按更宽容器等分(六/日被裁),面板 scrollWidth > clientWidth ⇒ 外框出横向滚动条。
|
||
* 关掉后 .__view 走 `width: 100%` 分支。面板内组件均不依赖横向滚动:
|
||
* 课表自带 .tt-scroll(纵向)、自定义片段是 iframe width:100%。
|
||
*/
|
||
const widgetOps = {
|
||
vuescroll: {},
|
||
scrollPanel: {
|
||
scrollingX: false,
|
||
},
|
||
rail: {},
|
||
bar: {
|
||
background: "#333",
|
||
},
|
||
};
|
||
const widgetAppList = ref<any[]>([]);
|
||
const dragPositionObj = reactive<Partial<WidgetPosition>>({});
|
||
|
||
const isDragShowComp = computed(() => {
|
||
const tempObj = cloneDeep(store.getWidgetDragObj);
|
||
return tempObj.isWidgetShow && isDragShow.value;
|
||
});
|
||
|
||
const compMenuId = computed(() => {
|
||
let menuList = store.curUserMenuList.find(x => x.url == route.path);
|
||
return menuList ? menuList.id : -1;
|
||
});
|
||
|
||
watchEffect(() => {
|
||
const tempObj = cloneDeep(store.getWidgetDragObj);
|
||
let isOutRangeX = false,
|
||
isOutRangeY = false; //是否超出范围
|
||
if (tempObj.xaxis == 0 && tempObj.yaxis === 0) {
|
||
tempObj.xaxis = dragObj.parentW - 540;
|
||
tempObj.yaxis = 88;
|
||
isOutRangeX = dragObj.parentW < 900;
|
||
} else {
|
||
isOutRangeX = dragObj.parentW < tempObj.width + tempObj.xaxis;
|
||
isOutRangeY = dragObj.parentH < tempObj.height + tempObj.yaxis;
|
||
}
|
||
if (isOutRangeX) tempObj.xaxis = dragObj.parentW - tempObj.width - 10;
|
||
if (isOutRangeY) tempObj.yaxis = dragObj.parentH - tempObj.height - 10;
|
||
Object.assign(dragPositionObj, tempObj);
|
||
reloadDragWrap();
|
||
});
|
||
|
||
const draggable = useDraggable(refApplist, appList, {
|
||
animation: 150,
|
||
onStart() {
|
||
// console.log("start");
|
||
},
|
||
async onUpdate() {
|
||
let ids = appList.value.map(x => x.id);
|
||
let appIds = appList.value.map(x => x.appId);
|
||
if (isDesltopAppDefault.value) {
|
||
await UserSettingApi.sortUserDesktopApp(appIds);
|
||
isDesltopAppDefault.value = false;
|
||
} else await UserSettingApi.sortUserDesktopApp(ids);
|
||
// console.log("update");
|
||
},
|
||
});
|
||
onMounted(async () => {
|
||
await getAppList();
|
||
dragObj.parentW = window.innerWidth;
|
||
dragObj.parentH = window.innerHeight;
|
||
window.addEventListener("resize", cancalDebounce);
|
||
window.addEventListener("message", iframeCallback);
|
||
});
|
||
onUnmounted(() => {
|
||
window.removeEventListener("resize", cancalDebounce);
|
||
window.removeEventListener("message", iframeCallback);
|
||
});
|
||
|
||
const widgetSel = computed(() => store.getWidgetSel);
|
||
|
||
watch(() => store.curRoleUid, getAppList);
|
||
|
||
watch(
|
||
() => store.getWidgetAppList,
|
||
val => {
|
||
widgetAppList.value = val.map(x => {
|
||
return { ...x, loading: true, height: 20 };
|
||
});
|
||
widgetAppList.value.forEach(item => {
|
||
// 注册表未命中的内置项会落到空态分支,留日志便于发现两处(widgetRegistry / widget_catalog)不同步
|
||
if (item.compType === 1 && !widgetRegistry[item.code]) {
|
||
console.warn("[widget] 内置类型未命中注册表:", item.code);
|
||
}
|
||
if (item.compType === 2) loadFragmentContent(item);
|
||
});
|
||
},
|
||
{
|
||
immediate: true,
|
||
}
|
||
);
|
||
|
||
function onMenuChange(curDom: any, state: boolean) {
|
||
$(curDom).toggleClass("app-container__focus", state);
|
||
}
|
||
async function onMenuSel(item: any) {
|
||
if (item.id == 1) {
|
||
try {
|
||
const find = appList.value.find(x => x.id == item.appId);
|
||
await UserSettingApi.deleteUserDesktopAppById(find.id, find.appId);
|
||
Message.success("操作成功");
|
||
await getAppList();
|
||
} catch (error) {
|
||
Message.error("内部服务错误");
|
||
}
|
||
}
|
||
if (item.id == 2) {
|
||
let find = appList.value.find(x => x.appId == item.appId);
|
||
bschLinkPage({ url: find.url, type: LinkOpenTypeEnum.Open });
|
||
}
|
||
}
|
||
|
||
function onDragChange(e: any) {
|
||
var t: Element = e.target;
|
||
if (!!t && !includes(t.classList, "widget-header-drag")) dragObj.isDrag = false;
|
||
}
|
||
|
||
function onDragResizestop(opt: any, type: "drag" | "resize") {
|
||
const { left, top, width, height } = opt;
|
||
if (type === "drag") {
|
||
dragObj.isDrag = false;
|
||
if (left === dragPositionObj.xaxis && top === dragPositionObj.yaxis) return false;
|
||
} else {
|
||
}
|
||
let positionInfo: WidgetPositionResp = {
|
||
xaxis: left,
|
||
yaxis: top,
|
||
width,
|
||
height,
|
||
};
|
||
store.updateWidgetInfo(positionInfo);
|
||
debounceSaveUserWidget(positionInfo);
|
||
}
|
||
const debounceSaveUserWidget = debounce(saveUserWidget, 1000);
|
||
async function saveUserWidget(info: WidgetPositionResp) {
|
||
info.id = store.curUserSettingInfo?.id;
|
||
info.schId = store.getCurSchId;
|
||
await UserSettingApi.saveUserWidget(info);
|
||
}
|
||
|
||
const cancalDebounce = debounce(setDragWindowInfo, 150);
|
||
function setDragWindowInfo() {
|
||
dragObj.parentW = window.innerWidth;
|
||
dragObj.parentH = window.innerHeight;
|
||
}
|
||
|
||
function reloadDragWrap() {
|
||
if (!store.getWidgetDragObj.isWidgetShow) return;
|
||
isDragShow.value = false;
|
||
requestAnimationFrame(() => {
|
||
isDragShow.value = true;
|
||
});
|
||
}
|
||
|
||
async function onWidgetSelItemClick(appId: any) {
|
||
const curAppIdStrs = store.curUserSettingInfo.widgetAppIds;
|
||
const curAppIds = store.getWidgetAppIds;
|
||
let find = store.getWidgetSel.find(x => x.k == appId);
|
||
if (!find) return false;
|
||
let checkAppIds: number[] = [];
|
||
if (!!find.checked) {
|
||
if (curAppIdStrs == null) checkAppIds = difference(curAppIds, [find.k]);
|
||
else {
|
||
let tempArr = cloneDeep(curAppIds);
|
||
checkAppIds = remove(tempArr, (x: number) => x !== appId);
|
||
}
|
||
} else {
|
||
checkAppIds = [...curAppIds, find.k];
|
||
}
|
||
console.log(checkAppIds);
|
||
store.curUserSettingInfo.widgetAppIds = checkAppIds.join(",");
|
||
const id = store.curUserSettingInfo?.id;
|
||
await UserSettingApi.saveUserAppIds(id, checkAppIds.join(","));
|
||
console.log("后续操作");
|
||
}
|
||
function hideWidgetSel() {
|
||
dragObj.selVisible = false;
|
||
}
|
||
|
||
function showWidgetSelClick() {
|
||
dragObj.selVisible = true;
|
||
window.removeEventListener("click", hideWidgetSel);
|
||
requestAnimationFrame(() => {
|
||
window.addEventListener("click", hideWidgetSel, { once: true });
|
||
});
|
||
}
|
||
async function onClickWidgetHide() {
|
||
const id = store.curUserSettingInfo?.id;
|
||
if (!!store.curUserSettingInfo) store.curUserSettingInfo.isWidgetShow = false;
|
||
await UserSettingApi.toggleWidgetShow(id);
|
||
}
|
||
|
||
function onIframeLoad(id: number) {
|
||
const ele: any = document.getElementById("iframe_widget_" + id);
|
||
if (!ele) return false;
|
||
const msgObj = {
|
||
roleInfo: store.curRoleInfo,
|
||
id: id,
|
||
};
|
||
const msgStr = bschRoleEncode(msgObj);
|
||
ele.contentWindow.postMessage(msgStr, "*");
|
||
}
|
||
|
||
function iframeCallback(ev: MessageEvent<any>) {
|
||
const { id, height } = JSON.parse(ev.data);
|
||
let find = widgetAppList.value.find(x => x.id == id);
|
||
if (!find) return;
|
||
find.height = height;
|
||
requestAnimationFrame(() => {
|
||
find.loading = false;
|
||
});
|
||
//console.log(find, id, height);
|
||
}
|
||
|
||
/** 内置组件自报高度:与 iframeCallback 同一收口(find.height),不再走 postMessage */
|
||
function onWidgetLoaded(id: number, height: number) {
|
||
const find = widgetAppList.value.find(x => x.id == id);
|
||
if (!find) return;
|
||
find.height = height;
|
||
requestAnimationFrame(() => {
|
||
find.loading = false;
|
||
});
|
||
}
|
||
|
||
/** 片段正文按需拉一次:不进 getUserSettings,避免每次进桌面下发全部 HTML */
|
||
async function loadFragmentContent(item: any) {
|
||
try {
|
||
const data: any = await UserSettingApi.getWidgetContent(item.code);
|
||
item.content = (data && data.content) || "";
|
||
// 取数键随内容一起回:候选池载荷里没有 data_code,桥要用它才知道打哪个数据键
|
||
item.dataCode = (data && data.dataCode) || item.code;
|
||
} catch (e) {
|
||
console.warn("[widget] 片段内容拉取失败:", item.code, e);
|
||
item.content = "";
|
||
item.dataCode = item.code;
|
||
}
|
||
item.contentLoaded = true;
|
||
if (!item.content) {
|
||
const find = widgetAppList.value.find(x => x.id == item.id);
|
||
if (find) find.loading = false;
|
||
}
|
||
}
|
||
|
||
function isFragmentPending(item: any) {
|
||
return item.compType === 2 && !item.contentLoaded;
|
||
}
|
||
|
||
function widgetFragmentSrc(item: any) {
|
||
return wrapFragment(item.content || "", item.id, item.dataCode || item.code);
|
||
}
|
||
async function getAppList() {
|
||
appList.value = await UserSettingApi.getUserDesktopAppList();
|
||
let arr = cloneDeep(appList.value);
|
||
isDesltopAppDefault.value = arr.filter(x => x.id == null).length === arr.length;
|
||
}
|
||
|
||
async function openLinkPage(item: any) {
|
||
let options: Parameters<typeof bschLinkPage>[0];
|
||
options = {
|
||
url: item.url as string,
|
||
type: item.linkType,
|
||
title: item.name,
|
||
};
|
||
|
||
if (item.type == 1 && $conf.ifameAppIdArr.includes(item.appId)) {
|
||
options.type = LinkOpenTypeEnum.IFrame;
|
||
options.isHeader = true;
|
||
}
|
||
|
||
if (item.linkType == LinkOpenTypeEnum.Modal) {
|
||
if (!!item.layout) {
|
||
options.modalWidth = JSON.parse(item.layout).width;
|
||
options.modalHeight = JSON.parse(item.layout).height;
|
||
}
|
||
}
|
||
bschLinkPage(options);
|
||
//bschLinkPage
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import url("@/assets/styles/componets/_widget.scss");
|
||
.used-app-wrap {
|
||
height: calc(100% - 88px);
|
||
}
|
||
.used-app-list {
|
||
margin-left: 20px;
|
||
display: flex;
|
||
flex-flow: column wrap;
|
||
justify-content: flex-start;
|
||
height: 100%;
|
||
align-items: stretch;
|
||
align-content: flex-start;
|
||
}
|
||
</style>
|
||
<style lang="scss">
|
||
.widget-wrap .vdr-stick-tm,
|
||
.vdr-stick-bm {
|
||
width: 380px !important;
|
||
left: 0 !important;
|
||
opacity: 0;
|
||
}
|
||
|
||
.vdr.active::before {
|
||
content: none;
|
||
}
|
||
|
||
/* 「+」添加小组件下拉:与卡片同族(玻璃层)。下拉就地渲染在 .widget-wrap 内,可直接复用其玻璃令牌
|
||
(--wg-glass-*)保持同族;底色在同色相上加深一档,保证浮层层次与白字可读性。 */
|
||
.ivu-select-dropdown.wg-dd {
|
||
padding: 4px 0;
|
||
background-color: rgba(15, 23, 42, 0.72);
|
||
-webkit-backdrop-filter: blur(18px) saturate(140%);
|
||
backdrop-filter: blur(18px) saturate(140%);
|
||
border: 1px solid var(--wg-glass-border, rgba(255, 255, 255, 0.18));
|
||
border-radius: 6px;
|
||
box-shadow: var(--wg-glass-shadow, 0 10px 36px rgba(0, 0, 0, 0.3));
|
||
}
|
||
|
||
.ivu-select-dropdown.wg-dd .ivu-dropdown-item {
|
||
color: var(--wg-fg, rgba(255, 255, 255, 0.94));
|
||
text-shadow: var(--wg-fg-shadow, 0 1px 2px rgba(0, 0, 0, 0.35));
|
||
}
|
||
|
||
.ivu-select-dropdown.wg-dd .ivu-dropdown-item:hover {
|
||
background: rgba(255, 255, 255, 0.12);
|
||
}
|
||
</style>
|