feat(我的绩效): 开发我的绩效功能。
fix(加班申请、工作报告): 重构加班申请在审批时的样式,工作报告在新增时的对话框、报告详情页的样式。
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { Calendar } from '@element-plus/icons-vue';
|
||||
import isoWeek from 'dayjs/plugin/isoWeek';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import {
|
||||
type WorkReportPeriodOption,
|
||||
@@ -12,6 +14,8 @@ import {
|
||||
} from '../utils';
|
||||
import { WORK_REPORT_TYPE_LABEL, type WorkReportType } from '../types';
|
||||
|
||||
dayjs.extend(isoWeek);
|
||||
|
||||
defineOptions({ name: 'WorkReportCreateDialog' });
|
||||
|
||||
interface Props {
|
||||
@@ -44,11 +48,24 @@ const emit = defineEmits<{
|
||||
|
||||
const selectedPeriodKey = ref('');
|
||||
const selectedProjectId = ref('');
|
||||
const customWeekDate = ref('');
|
||||
const rawCustomWeekDate = ref('');
|
||||
const customMonth = ref('');
|
||||
const customProjectMonth = ref('');
|
||||
const customProjectFlag = ref(1);
|
||||
|
||||
// 自定义周报周期:无论用户点哪一天,都归一到该 ISO 周的周一,
|
||||
// 这样 ElDatePicker 使用内置 dayjs 的 ww(locale week)也能正确显示 ISO 周数。
|
||||
const customWeekDate = computed<string>({
|
||||
get: () => rawCustomWeekDate.value,
|
||||
set: val => {
|
||||
if (!val) {
|
||||
rawCustomWeekDate.value = val;
|
||||
return;
|
||||
}
|
||||
rawCustomWeekDate.value = dayjs(val).startOf('isoWeek').format('YYYY-MM-DD');
|
||||
}
|
||||
});
|
||||
|
||||
const selectedReportType = computed<WorkReportType>(() => {
|
||||
if (props.defaultReportType === 'project' && !props.projectVisible) return 'weekly';
|
||||
return props.defaultReportType;
|
||||
@@ -157,110 +174,113 @@ function handleConfirm() {
|
||||
:close-on-click-modal="false"
|
||||
@confirm="handleConfirm"
|
||||
>
|
||||
<div v-if="selectedReportType === 'project'" class="work-report-create-dialog__project-select">
|
||||
<label class="work-report-create-dialog__label">项目</label>
|
||||
<ElSelect v-model="selectedProjectId" class="w-full" placeholder="请选择项目" filterable>
|
||||
<ElOption
|
||||
v-for="item in props.projectOptions"
|
||||
:key="item.id"
|
||||
:label="item.projectCode ? `${item.projectName}(${item.projectCode})` : item.projectName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</div>
|
||||
|
||||
<div class="work-report-create-dialog__section">
|
||||
<div class="work-report-create-dialog__grid is-period">
|
||||
<button
|
||||
v-for="item in activePeriodOptions"
|
||||
:key="item.key"
|
||||
type="button"
|
||||
class="work-report-create-dialog__choice"
|
||||
:class="{ 'is-active': selectedPeriodKey === item.key }"
|
||||
@click="selectedPeriodKey = item.key"
|
||||
>
|
||||
<div class="work-report-create-dialog__choice-title">{{ item.label }}</div>
|
||||
<div class="work-report-create-dialog__choice-desc">{{ item.description }}</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="work-report-create-dialog__choice"
|
||||
:class="{ 'is-active': selectedPeriodKey === 'custom' }"
|
||||
@click="selectedPeriodKey = 'custom'"
|
||||
>
|
||||
<div class="work-report-create-dialog__choice-title">自定义周期</div>
|
||||
<div class="work-report-create-dialog__choice-desc">
|
||||
{{
|
||||
selectedReportType === 'weekly'
|
||||
? '选择某一周作为周报周期。'
|
||||
: selectedReportType === 'monthly'
|
||||
? '选择某一月作为月报周期。'
|
||||
: '选择某个月的上半月或下半月。'
|
||||
}}
|
||||
</div>
|
||||
</button>
|
||||
<!-- 必须用单根节点包裹:ElScrollbar 默认 slot 接收多根 Fragment 时,destroy-on-close 后 patch 会触发 null __vnode 错误 -->
|
||||
<div class="work-report-create-dialog__body">
|
||||
<div v-if="selectedReportType === 'project'" class="work-report-create-dialog__project-select">
|
||||
<label class="work-report-create-dialog__label">项目</label>
|
||||
<ElSelect v-model="selectedProjectId" class="w-full" placeholder="请选择项目" filterable>
|
||||
<ElOption
|
||||
v-for="item in props.projectOptions"
|
||||
:key="item.id"
|
||||
:label="item.projectCode ? `${item.projectName}(${item.projectCode})` : item.projectName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</ElSelect>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedPeriodKey === 'custom'" class="work-report-create-dialog__custom-period">
|
||||
<div v-if="selectedReportType === 'weekly'" class="work-report-create-dialog__custom-row">
|
||||
<div class="work-report-create-dialog__field work-report-create-dialog__field--inline">
|
||||
<label class="work-report-create-dialog__label">周报周期</label>
|
||||
<ElDatePicker
|
||||
v-model="customWeekDate"
|
||||
type="date"
|
||||
format="YYYY[年第]ww[周]"
|
||||
value-format="YYYY-MM-DD"
|
||||
popper-class="work-report-create-date-popper"
|
||||
placeholder="请选择周报周期"
|
||||
/>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
{{ customPeriodPreviewLabel }}
|
||||
<div class="work-report-create-dialog__section">
|
||||
<div class="work-report-create-dialog__grid is-period">
|
||||
<button
|
||||
v-for="item in activePeriodOptions"
|
||||
:key="item.key"
|
||||
type="button"
|
||||
class="work-report-create-dialog__choice"
|
||||
:class="{ 'is-active': selectedPeriodKey === item.key }"
|
||||
@click="selectedPeriodKey = item.key"
|
||||
>
|
||||
<div class="work-report-create-dialog__choice-title">{{ item.label }}</div>
|
||||
<div class="work-report-create-dialog__choice-desc">{{ item.description }}</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="work-report-create-dialog__choice"
|
||||
:class="{ 'is-active': selectedPeriodKey === 'custom' }"
|
||||
@click="selectedPeriodKey = 'custom'"
|
||||
>
|
||||
<div class="work-report-create-dialog__choice-title">自定义周期</div>
|
||||
<div class="work-report-create-dialog__choice-desc">
|
||||
{{
|
||||
selectedReportType === 'weekly'
|
||||
? '选择某一周作为周报周期。'
|
||||
: selectedReportType === 'monthly'
|
||||
? '选择某一月作为月报周期。'
|
||||
: '选择某个月的上半月或下半月。'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="selectedReportType === 'monthly'" class="work-report-create-dialog__custom-row">
|
||||
<div class="work-report-create-dialog__field work-report-create-dialog__field--inline">
|
||||
<label class="work-report-create-dialog__label">月报周期</label>
|
||||
<ElDatePicker
|
||||
v-model="customMonth"
|
||||
type="month"
|
||||
value-format="YYYY-MM"
|
||||
popper-class="work-report-create-date-popper"
|
||||
placeholder="请选择月份"
|
||||
/>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
{{ customPeriodPreviewLabel }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="work-report-create-dialog__custom-project">
|
||||
<div class="work-report-create-dialog__custom-project-grid">
|
||||
<div class="work-report-create-dialog__custom-project-item">
|
||||
<div class="work-report-create-dialog__custom-project-item-label">选择月份</div>
|
||||
<div v-if="selectedPeriodKey === 'custom'" class="work-report-create-dialog__custom-period">
|
||||
<div v-if="selectedReportType === 'weekly'" class="work-report-create-dialog__custom-row">
|
||||
<div class="work-report-create-dialog__field work-report-create-dialog__field--inline">
|
||||
<label class="work-report-create-dialog__label">周报周期</label>
|
||||
<ElDatePicker
|
||||
v-model="customProjectMonth"
|
||||
class="w-full"
|
||||
v-model="customWeekDate"
|
||||
type="date"
|
||||
format="YYYY[年第]ww[周]"
|
||||
value-format="YYYY-MM-DD"
|
||||
popper-class="work-report-create-date-popper"
|
||||
placeholder="请选择周报周期"
|
||||
/>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
{{ customPeriodPreviewLabel }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="selectedReportType === 'monthly'" class="work-report-create-dialog__custom-row">
|
||||
<div class="work-report-create-dialog__field work-report-create-dialog__field--inline">
|
||||
<label class="work-report-create-dialog__label">月报周期</label>
|
||||
<ElDatePicker
|
||||
v-model="customMonth"
|
||||
type="month"
|
||||
value-format="YYYY-MM"
|
||||
popper-class="work-report-create-date-popper"
|
||||
placeholder="请选择月份"
|
||||
/>
|
||||
</div>
|
||||
<div class="work-report-create-dialog__custom-project-item">
|
||||
<div class="work-report-create-dialog__custom-project-item-label">选择半月</div>
|
||||
<ElSegmented
|
||||
v-model="customProjectFlag"
|
||||
:options="projectHalfOptions"
|
||||
class="work-report-create-dialog__half-segmented"
|
||||
/>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
{{ customPeriodPreviewLabel }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
<ElIcon class="work-report-create-dialog__period-preview-icon"><Calendar /></ElIcon>
|
||||
<span class="work-report-create-dialog__period-preview-text">已选周期:</span>
|
||||
<span class="work-report-create-dialog__period-preview-value">{{ customPeriodPreviewLabel }}</span>
|
||||
|
||||
<div v-else class="work-report-create-dialog__custom-project">
|
||||
<div class="work-report-create-dialog__custom-project-grid">
|
||||
<div class="work-report-create-dialog__custom-project-item">
|
||||
<div class="work-report-create-dialog__custom-project-item-label">选择月份</div>
|
||||
<ElDatePicker
|
||||
v-model="customProjectMonth"
|
||||
class="w-full"
|
||||
type="month"
|
||||
value-format="YYYY-MM"
|
||||
popper-class="work-report-create-date-popper"
|
||||
placeholder="请选择月份"
|
||||
/>
|
||||
</div>
|
||||
<div class="work-report-create-dialog__custom-project-item">
|
||||
<div class="work-report-create-dialog__custom-project-item-label">选择半月</div>
|
||||
<ElSegmented
|
||||
v-model="customProjectFlag"
|
||||
:options="projectHalfOptions"
|
||||
class="work-report-create-dialog__half-segmented"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="customPeriodPreviewLabel" class="work-report-create-dialog__period-preview">
|
||||
<ElIcon class="work-report-create-dialog__period-preview-icon"><Calendar /></ElIcon>
|
||||
<span class="work-report-create-dialog__period-preview-text">已选周期:</span>
|
||||
<span class="work-report-create-dialog__period-preview-value">{{ customPeriodPreviewLabel }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -320,13 +340,13 @@ function handleConfirm() {
|
||||
}
|
||||
|
||||
.work-report-create-dialog__choice:hover {
|
||||
border-color: rgba(15, 118, 110, 0.28);
|
||||
border-color: var(--el-color-primary-light-3);
|
||||
box-shadow: 0 8px 20px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.work-report-create-dialog__choice.is-active {
|
||||
border-color: #0f766e;
|
||||
background: #ecfdf5;
|
||||
border-color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
|
||||
.work-report-create-dialog__choice-title {
|
||||
@@ -381,9 +401,9 @@ function handleConfirm() {
|
||||
.work-report-create-dialog__custom-period {
|
||||
margin-top: 14px;
|
||||
padding: 16px;
|
||||
border: 1px solid rgba(15, 118, 110, 0.18);
|
||||
border: 1px solid var(--el-color-primary-light-7);
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(180deg, #f8fffd 0%, #ffffff 100%);
|
||||
background: linear-gradient(180deg, var(--el-color-primary-light-9) 0%, #ffffff 100%);
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
@@ -422,7 +442,7 @@ function handleConfirm() {
|
||||
}
|
||||
|
||||
.work-report-create-dialog__custom-project-item:hover {
|
||||
border-color: rgba(15, 118, 110, 0.4);
|
||||
border-color: var(--el-color-primary-light-5);
|
||||
}
|
||||
|
||||
.work-report-create-dialog__custom-project-item-label {
|
||||
@@ -460,10 +480,10 @@ function handleConfirm() {
|
||||
gap: 6px;
|
||||
min-height: 32px;
|
||||
padding: 0 14px;
|
||||
border: 1px solid rgba(15, 118, 110, 0.18);
|
||||
border: 1px solid var(--el-color-primary-light-7);
|
||||
border-radius: 999px;
|
||||
background: #ecfdf5;
|
||||
color: #0f766e;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
@@ -472,7 +492,7 @@ function handleConfirm() {
|
||||
|
||||
.work-report-create-dialog__period-preview-icon {
|
||||
font-size: 14px;
|
||||
color: #0f766e;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.work-report-create-dialog__period-preview-text {
|
||||
@@ -481,7 +501,7 @@ function handleConfirm() {
|
||||
}
|
||||
|
||||
.work-report-create-dialog__period-preview-value {
|
||||
color: #0f766e;
|
||||
color: var(--el-color-primary);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@@ -529,6 +549,6 @@ function handleConfirm() {
|
||||
|
||||
:global(.work-report-create-date-popper .el-date-table td.current:not(.disabled) .el-date-table-cell__text),
|
||||
:global(.work-report-create-date-popper .el-month-table td.current:not(.disabled) .cell) {
|
||||
background-color: #0f766e;
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user