!115 Merge remote-tracking branch 'origin/develop' into develop
Merge pull request !115 from dvadmin/develop
This commit is contained in:
@@ -50,7 +50,7 @@ schema_view = get_schema_view(
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
public=True,
|
||||
permission_classes=(permissions.AllowAny,),
|
||||
permission_classes=(permissions.IsAuthenticated,),
|
||||
generator_class=CustomOpenAPISchemaGenerator,
|
||||
)
|
||||
# 前端页面映射
|
||||
|
||||
@@ -9,8 +9,8 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from application import dispatch
|
||||
from dvadmin.utils.models import CoreModel, table_prefix, get_custom_app_models
|
||||
|
||||
|
||||
class Role(CoreModel):
|
||||
from dvadmin3_flow.base_model import FlowBaseModel
|
||||
class Role(CoreModel,FlowBaseModel):
|
||||
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
|
||||
key = models.CharField(max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符")
|
||||
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
|
||||
@@ -122,6 +122,27 @@ class Dept(CoreModel):
|
||||
help_text="上级部门",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _recursion(cls, instance, parent, result):
|
||||
new_instance = getattr(instance, parent, None)
|
||||
res = []
|
||||
data = getattr(instance, result, None)
|
||||
if data:
|
||||
res.append(data)
|
||||
if new_instance:
|
||||
array = cls._recursion(new_instance, parent, result)
|
||||
res += array
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
def get_region_name(cls, obj):
|
||||
"""
|
||||
获取某个用户的递归所有部门名称
|
||||
"""
|
||||
dept_name_all = cls._recursion(obj, "parent", "name")
|
||||
dept_name_all.reverse()
|
||||
return "/".join(dept_name_all)
|
||||
|
||||
@classmethod
|
||||
def recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):
|
||||
"""
|
||||
|
||||
@@ -352,7 +352,7 @@ class UserViewSet(CustomModelViewSet):
|
||||
if new_pwd != new_pwd2:
|
||||
return ErrorResponse(msg="两次密码不匹配")
|
||||
else:
|
||||
request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest())
|
||||
request.user.password = make_password(new_pwd)
|
||||
request.user.pwd_change_count += 1
|
||||
request.user.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
|
||||
77
web/flowH5.config.ts
Normal file
77
web/flowH5.config.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import path, {resolve} from 'path';
|
||||
import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import vueSetupExtend from "vite-plugin-vue-setup-extend";
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import pxtorem from 'postcss-pxtorem';
|
||||
const pathResolve = (dir: string) => {
|
||||
return resolve(__dirname, '.', dir);
|
||||
};
|
||||
export default defineConfig({
|
||||
build: {
|
||||
// outDir: '../backend/static/previewer',
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, 'src/views/plugins/dvadmin3-flow-web/src/flowH5/index.ts'), // 库的入口文件
|
||||
name: 'previewer', // 库的全局变量名称
|
||||
fileName: (format) => `index.${format}.js`, // 输出文件名格式
|
||||
},
|
||||
rollupOptions: {
|
||||
input:{
|
||||
previewer: path.resolve(__dirname, 'src/views/plugins/dvadmin3-flow-web/src/flowH5/index.ts'),
|
||||
},
|
||||
external: ['vue','xe-utils'], // 指定外部依赖
|
||||
output:{
|
||||
// dir: '../backend/static/previewer', // 输出目录
|
||||
entryFileNames: 'index.[format].js', // 入口文件名格式
|
||||
format: 'commonjs',
|
||||
globals: {
|
||||
vue: 'Vue'
|
||||
},
|
||||
chunkFileNames: `[name].[hash].js`
|
||||
},
|
||||
plugins: [
|
||||
terser({
|
||||
compress: {
|
||||
drop_console: false, // 确保不移除 console.log
|
||||
},
|
||||
}),
|
||||
postcss({
|
||||
plugins: [
|
||||
pxtorem({
|
||||
rootValue: 37.5,
|
||||
unitPrecision: 5,
|
||||
propList: ['*'],
|
||||
selectorBlackList: [],
|
||||
replace: true,
|
||||
mediaQuery: false,
|
||||
minPixelValue: 0,
|
||||
exclude: /node_modules/i,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
vueSetupExtend(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'/@': path.resolve(__dirname, 'src'), // '@' 别名指向 'src' 目录
|
||||
'@views': pathResolve('./src/views'),
|
||||
'/src':path.resolve(__dirname, 'src')
|
||||
},
|
||||
},
|
||||
css:{
|
||||
postcss:{
|
||||
|
||||
}
|
||||
},
|
||||
define: {
|
||||
'process.env': {}
|
||||
}
|
||||
});
|
||||
@@ -26,6 +26,7 @@
|
||||
"axios": "^1.7.4",
|
||||
"countup.js": "^2.8.0",
|
||||
"cropperjs": "^1.6.2",
|
||||
"date-holidays": "^3.24.1",
|
||||
"e-icon-picker": "2.1.1",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-gl": "^2.0.9",
|
||||
@@ -37,6 +38,7 @@
|
||||
"js-table2excel": "^1.1.2",
|
||||
"jsplumb": "^2.15.6",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lunar-javascript": "^1.7.1",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.28",
|
||||
|
||||
403
web/src/components/calendar/index.vue
Normal file
403
web/src/components/calendar/index.vue
Normal file
@@ -0,0 +1,403 @@
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%;">
|
||||
<div class="selected-show" v-if="props.modelValue && props.selectable">
|
||||
<el-text>已选择:</el-text>
|
||||
<el-tag v-if="props.multiple" v-for="item in data" closable @close="handleTagClose(item)">
|
||||
{{ item.toLocaleDateString('en-CA') }}
|
||||
</el-tag>
|
||||
<el-tag v-else closable @close="handleTagClose(data)">{{ data?.toLocaleDateString('en-CA') }}</el-tag>
|
||||
<el-button v-if="props.modelValue" size="small" type="text" @click="clear">清空</el-button>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div>
|
||||
今天:<el-text size="large">{{ today.toLocaleDateString('en-CA') }}</el-text>
|
||||
</div>
|
||||
<!-- <div class="current-month">
|
||||
<el-tag size="large" type="primary">
|
||||
{{ currentCalendarDate.getFullYear() }}年{{ currentCalendarDate.getMonth() + 1 }}月
|
||||
</el-tag>
|
||||
</div> -->
|
||||
<div class="control-button" v-if="!(!!props.range && props.range[0] && props.range[1]) && props.showPageTurn">
|
||||
<el-button-group size="small" type="default" v-if="props.pageTurn">
|
||||
<el-popover trigger="click" width="160px">
|
||||
<template #reference>
|
||||
<el-button type="text" size="small">节假日设置</el-button>
|
||||
</template>
|
||||
<el-switch v-model="showHoliday" active-text="显示节日" inactive-text="关闭节日" inline-prompt />
|
||||
<el-checkbox v-model="showLunarHoliday" label="农历节日" />
|
||||
<el-checkbox v-model="showJieQi" label="节气" />
|
||||
<el-checkbox v-model="showDetailedHoliday" label="更多节日" />
|
||||
</el-popover>
|
||||
<el-button icon="DArrowLeft" @click="turnToPreY">上年</el-button>
|
||||
<el-button icon="ArrowLeft" @click="turnToPreM">上月</el-button>
|
||||
<el-button @click="turnToToday">今天</el-button>
|
||||
<el-button icon="ArrowRight" @click="turnToNextM">下月</el-button>
|
||||
<el-button icon="DArrowRight" @click="turnToNextY">下年</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider style="margin: 4px;" />
|
||||
<div class="calender">
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="calender-header" v-for="item, ind in ['日', '一', '二', '三', '四', '五', '六']" :key="ind">
|
||||
{{ item }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="week in calendarList">
|
||||
<td class="calender-td" v-for="item in week">
|
||||
<div class="calender-cell" :data-date="item.date.toLocaleDateString('en-CA')" :class="{
|
||||
'no-current-month': item.date.getMonth() !== currentCalendarDate.getMonth(),
|
||||
'today': item.date.toDateString() === today.toDateString(),
|
||||
'selected': item.selected,
|
||||
'disabled': item.disabled,
|
||||
}" @mouseenter="onCalenderCellHover" @mouseleave="onCalenderCellUnhover"
|
||||
@click="(e: MouseEvent) => item.disabled ? null : onCalenderCellClick(e)">
|
||||
<div class="calender-cell-header calender-cell-line">
|
||||
<span>{{ item.date.getDate() }}</span>
|
||||
<span v-if="item.selected">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 1024 1024">
|
||||
<path fill="currentColor"
|
||||
d="M77.248 415.04a64 64 0 0 1 90.496 0l226.304 226.304L846.528 188.8a64 64 0 1 1 90.56 90.496l-543.04 543.04-316.8-316.8a64 64 0 0 1 0-90.496z">
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="calender-cell-body calender-cell-line">
|
||||
<slot name="cell-body" v-bind="item">
|
||||
</slot>
|
||||
</div>
|
||||
<div class="calender-cell-footer calender-cell-line">
|
||||
<span>{{ item.holiday || ' ' }}</span>
|
||||
<el-text v-if="item.date.toDateString() === today.toDateString()" type="danger">今天</el-text>
|
||||
</div>
|
||||
<!-- {{ item }} -->
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="watermark" v-if="props.watermark" :style="watermarkPositionMap[props.watermarkPosition]">
|
||||
{{ (currentCalendarDate.toLocaleDateString('en-CA').split('-').slice(0, 2)).join('-') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUi } from '@fast-crud/fast-crud';
|
||||
import { ref, defineProps, PropType, watch, computed, onMounted } from 'vue';
|
||||
import Holidays from 'date-holidays';
|
||||
import Lunar from 'lunar-javascript';
|
||||
const LUNAR = Lunar.Lunar; // 农历
|
||||
const SOLAR = Lunar.Solar; // 阳历
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
// 日期多选
|
||||
multiple: { type: Boolean, default: false },
|
||||
// 日期范围
|
||||
range: { type: Object as PropType<[Date, Date]> },
|
||||
// 可以翻页
|
||||
pageTurn: { type: Boolean, default: true },
|
||||
// 跨页选择
|
||||
crossPage: { type: Boolean, default: false },
|
||||
// 显示年月水印和水印位置
|
||||
watermark: { type: Boolean, default: true },
|
||||
watermarkPosition: { type: Object as PropType<PositionType>, default: 'bottom-right' },
|
||||
// 显示翻页控件
|
||||
showPageTurn: { type: Boolean, default: true },
|
||||
// 是否可选
|
||||
selectable: { type: Boolean, default: true },
|
||||
// 验证日期是否有效
|
||||
validDate: { type: Object as PropType<ValidDateFunc>, default: () => ((d: Date) => true) }
|
||||
});
|
||||
type ValidDateFunc = (d: Date) => boolean;
|
||||
type PositionType = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center' | 'center-left' | 'center-right' | 'center-top';
|
||||
const today = new Date();
|
||||
const showHoliday = ref<boolean>(true); // 显示节日
|
||||
const showDetailedHoliday = ref<boolean>(false); // 显示详细的国际节日
|
||||
const showJieQi = ref<boolean>(true); // 显示节气
|
||||
const showLunarHoliday = ref<boolean>(true); // 显示农历节日
|
||||
const watermarkPositionMap: { [key: string]: any } = {
|
||||
'top-left': { top: '40px', left: 0, transformOrigin: '0 0' },
|
||||
'top-right': { top: '40px', right: 0, transformOrigin: '100% 0' },
|
||||
'bottom-left': { bottom: 0, left: 0, transformOrigin: '0 100%' },
|
||||
'bottom-right': { bottom: 0, right: 0, transformOrigin: '100% 100%' },
|
||||
'center': { top: '50%', left: '50%', transformOrigin: '50% 50%', transform: 'translate(-50%, -50%) scale(10)' },
|
||||
'center-left': { top: '50%', left: 0, transformOrigin: '0 50%' },
|
||||
'center-right': { top: '50%', right: 0, transformOrigin: '100% 50%' },
|
||||
'center-top': { top: 0, left: '50%', transformOrigin: '50% 0', transform: 'translate(-50%, 40px) scale(10)' },
|
||||
'center-bottom': { bottom: 0, left: '50%', transformOrigin: '50% 100%', transform: 'translate(-50%, 0) scale(10)' },
|
||||
};
|
||||
// 获取当月第一周的第一天(包括上个月)
|
||||
const calendarFirstDay = (current: Date = new Date()) => {
|
||||
let today = new Date(current); // 指定天
|
||||
let firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1); // 月初天
|
||||
let weekOfFirstDay = firstDayOfMonth.getDay(); // 周几,0日
|
||||
if (weekOfFirstDay === 0) return new Date(firstDayOfMonth); // 是周日则直接返回
|
||||
let firstDayOfWeek = new Date(firstDayOfMonth);
|
||||
// 月初减去周几,不+1是因为从日历周日开始
|
||||
firstDayOfWeek.setDate(firstDayOfMonth.getDate() - weekOfFirstDay);
|
||||
return new Date(firstDayOfWeek);
|
||||
};
|
||||
// 获取当月最后一周的最后一天(包括下个月)
|
||||
const calendarLastDay = (current: Date = new Date()) => {
|
||||
let today = new Date(current); // 指定天
|
||||
let lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1); // 月末天
|
||||
lastDayOfMonth.setDate(lastDayOfMonth.getDate() - 1);
|
||||
let weekOfFirstDay = lastDayOfMonth.getDay();
|
||||
if (weekOfFirstDay === 6) return new Date(lastDayOfMonth); // 是周六则直接返回
|
||||
let lastDayOfWeek = new Date(lastDayOfMonth);
|
||||
// 月末加剩下周几,要-1是因为日历到周六结束
|
||||
lastDayOfWeek.setDate(lastDayOfMonth.getDate() + (7 - weekOfFirstDay - 1));
|
||||
return new Date(lastDayOfWeek);
|
||||
};
|
||||
const generateDateList = (startDate: Date, endDate: Date): Date[] => { // 生成日期列表
|
||||
let dates = [];
|
||||
let s = new Date(startDate);
|
||||
let e = new Date(endDate);
|
||||
while (s <= e) {
|
||||
dates.push(new Date(s));
|
||||
s.setDate(s.getDate() + 1);
|
||||
}
|
||||
return dates;
|
||||
};
|
||||
// 日历当前页范围
|
||||
interface CalendarCell {
|
||||
date: Date;
|
||||
selected: boolean;
|
||||
disabled: boolean;
|
||||
currentMonth: boolean;
|
||||
holiday: string;
|
||||
};
|
||||
const currentCalendarDate = ref<Date>(new Date());
|
||||
const calendarList = computed(() => {
|
||||
let dates = (!!props.range && props.range[0] && props.range[1]) ?
|
||||
generateDateList(props.range[0], props.range[1]) :
|
||||
generateDateList(calendarFirstDay(currentCalendarDate.value), calendarLastDay(currentCalendarDate.value));
|
||||
let proce_dates: CalendarCell[] = dates.map((value) => {
|
||||
let solarDate = SOLAR.fromDate(value);
|
||||
let lunarDate = solarDate.getLunar();
|
||||
let solarHolidays: string[] = solarDate.getFestivals(); // 国历节日
|
||||
let lunarHolidays: string[] = lunarDate.getFestivals(); // 农历节日
|
||||
let jieQi: string = lunarDate.getJieQi(); // 节气
|
||||
// 农历节日、国际节日、节气三选一
|
||||
let holiday = showHoliday.value ? ((showLunarHoliday.value ? lunarHolidays[0] : '') || (showJieQi.value ? jieQi : '') ||
|
||||
(showDetailedHoliday.value ? solarHolidays[0] : yearHolidays.value[value.toLocaleDateString('en-CA')])) : ''; // yearHolidays国际的
|
||||
return {
|
||||
date: value,
|
||||
selected: props.multiple ?
|
||||
(data.value as Date[]).findIndex((v) => v.toLocaleDateString('en-CA') === value.toLocaleDateString('en-CA')) !== -1 :
|
||||
data.value?.toLocaleDateString('en-CA') === value.toLocaleDateString('en-CA'),
|
||||
disabled: !props.validDate(value),
|
||||
currentMonth: value.getMonth() === currentCalendarDate.value.getMonth(),
|
||||
// 农历节日、节气、法定日三选一
|
||||
holiday: holiday
|
||||
}
|
||||
});
|
||||
let res: CalendarCell[][] = [];
|
||||
for (let i = 0; i < 6; i++) res.push(proce_dates.slice(i * 7, (i + 1) * 7));
|
||||
return res;
|
||||
});
|
||||
// 控件
|
||||
const turnToPreM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() - 1, 1);
|
||||
const turnToNextM = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear(), currentCalendarDate.value.getMonth() + 1, 1);
|
||||
const turnToPreY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() - 1, currentCalendarDate.value.getMonth(), 1);
|
||||
const turnToNextY = () => currentCalendarDate.value = new Date(currentCalendarDate.value.getFullYear() + 1, currentCalendarDate.value.getMonth(), 1);
|
||||
const turnToToday = () => currentCalendarDate.value = new Date();
|
||||
// 如果禁止跨页则跨页时清空选择
|
||||
watch(
|
||||
() => currentCalendarDate.value,
|
||||
(v, ov) => props.crossPage ? {} :
|
||||
(v.toLocaleDateString('en-CA') === ov.toLocaleDateString('en-CA') ? {} : clear())
|
||||
);
|
||||
// 单元格事件
|
||||
const onCalenderCellHover = ({ target }: MouseEvent) => (target as HTMLElement).classList.add('onhover');
|
||||
const onCalenderCellUnhover = ({ target }: MouseEvent) => (target as HTMLElement).classList.remove('onhover');
|
||||
const onCalenderCellClick = (e: MouseEvent) => {
|
||||
if (!props.selectable) return;
|
||||
let strValue = (e.target as HTMLElement).dataset.date as string;
|
||||
if (strValue === undefined) return;
|
||||
let value = new Date(strValue);
|
||||
if (props.multiple) {
|
||||
let d = (data.value as Date[]).map((v) => v.toLocaleDateString('en-CA'));
|
||||
let ind = d.findIndex((v) => v === strValue);
|
||||
if (ind === -1) d.push(strValue);
|
||||
else d.splice(ind, 1);
|
||||
onDataChange(d);
|
||||
}
|
||||
// 这里阻止了点击取消选中,需要通过tag的x来取消
|
||||
else (data.value?.toLocaleDateString('en-CA') === strValue ? {} : onDataChange(value));
|
||||
};
|
||||
// 选择回显
|
||||
const handleTagClose = (d: Date) => {
|
||||
let strValue = d.toLocaleDateString('en-CA');
|
||||
if (props.multiple) {
|
||||
let d = (data.value as Date[]).map((v) => v.toLocaleDateString('en-CA'));
|
||||
d.splice(d.findIndex((v) => v === strValue), 1);
|
||||
onDataChange(d);
|
||||
}
|
||||
else onDataChange(null);
|
||||
};
|
||||
// 节假日
|
||||
const holidays = new Holidays('CN');
|
||||
const yearHolidays = computed(() => {
|
||||
let h = holidays.getHolidays(currentCalendarDate.value.getFullYear());
|
||||
let proce_h: { [key: string]: string } = {};
|
||||
let _h: string[] = [];
|
||||
for (let i of h) {
|
||||
let d = i.date.split(' ')[0];
|
||||
let hn = i.name.split(' ')[0];
|
||||
if (_h.includes(hn)) continue;
|
||||
proce_h[d] = hn;
|
||||
_h.push(hn);
|
||||
}
|
||||
return proce_h
|
||||
});
|
||||
|
||||
// fs-crud部分
|
||||
const data = ref<any>();
|
||||
const emit = defineEmits(['update:modelValue', 'onSave', 'onClose', 'onClosed']);
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val === undefined) data.value = props.multiple ? [] : null;
|
||||
else data.value = props.multiple ? (val as Date[]).map((v: Date) => new Date(v)) : val;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
const { ui } = useUi();
|
||||
const formValidator = ui.formItem.injectFormItemContext();
|
||||
const onDataChange = (value: any) => {
|
||||
emit('update:modelValue', value);
|
||||
formValidator.onChange();
|
||||
formValidator.onBlur();
|
||||
};
|
||||
const reset = () => { // 重置日历
|
||||
currentCalendarDate.value = new Date();
|
||||
onDataChange(props.multiple ? [] : null);
|
||||
};
|
||||
const clear = () => onDataChange(props.multiple ? [] : null); // 清空数据
|
||||
defineExpose({
|
||||
data,
|
||||
onDataChange,
|
||||
reset,
|
||||
clear,
|
||||
showHoliday,
|
||||
showDetailedHoliday,
|
||||
showJieQi,
|
||||
showLunarHoliday
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selected-show {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.calender {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
|
||||
.watermark {
|
||||
position: absolute;
|
||||
font-size: 16px;
|
||||
transform: scale(10);
|
||||
color: #aaa;
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
table {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.calender-header {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.calender-td {
|
||||
border: 1px solid #eee;
|
||||
width: calc(100% / 7);
|
||||
}
|
||||
|
||||
.calender-cell {
|
||||
min-height: 96px;
|
||||
min-width: 100px;
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
|
||||
&.today {
|
||||
color: var(--el-color-warning) !important;
|
||||
background-color: var(--el-color-warning-light-9) !important;
|
||||
}
|
||||
|
||||
&.onhover {
|
||||
color: var(--el-color-primary);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: #bbb;
|
||||
background: none;
|
||||
}
|
||||
|
||||
&.no-current-month {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: var(--el-color-primary);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
}
|
||||
|
||||
.calender-cell-line {
|
||||
min-height: 0px;
|
||||
|
||||
&.calender-cell-header {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.calender-cell-body {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.calender-cell-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -22,4 +22,13 @@ export const scanAndInstallPlugins = (app: any) => {
|
||||
}
|
||||
pluginsAll = Array.from(pluginNames);
|
||||
console.log('已发现插件:', pluginsAll);
|
||||
for (const pluginName of pluginsAll) {
|
||||
const plugin = import(`./${pluginName}/index.ts`);
|
||||
plugin.then((module) => {
|
||||
app.use(module.default)
|
||||
console.log(`${pluginName}插件已加载`)
|
||||
}).catch((error) => {
|
||||
console.log(`${pluginName}插件下无index.ts`)
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user