Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions app/departments/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { departmentApi, type Department, type PaginatedResponse, type Pagination
import { useAppContext } from "@/lib/app-context"
import { Pagination, usePagination } from "@/components/pagination"
import { LoadingInline } from "@/components/loading"
import { AxiosError } from "axios"

export default function DepartmentsPage() {
const { Confirm } = useAppContext()
const { Confirm, Alert } = useAppContext()
const [departments, setDepartments] = useState<Department[]>([])
const [loading, setLoading] = useState(true)
const [dialogOpen, setDialogOpen] = useState(false)
Expand Down Expand Up @@ -94,8 +95,13 @@ export default function DepartmentsPage() {
try {
await departmentApi.delete(id)
fetchDepartments()
} catch (error) {
} catch (error: unknown) {
console.error("删除部门失败:", error)
if (error instanceof AxiosError) {
Alert("删除失败", error.response?.data?.error || "删除部门失败,请重试")
} else {
Alert("删除失败", "删除部门失败,请重试")
}
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions app/employees/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { employeeApi, departmentApi, type Employee, type Department, type Pagina
import { useAppContext } from "@/lib/app-context"
import { Pagination, usePagination } from "@/components/pagination"
import { LoadingInline } from "@/components/loading"
import { AxiosError } from "axios"

export default function EmployeesPage() {
const { Confirm } = useAppContext()
const { Confirm, Alert } = useAppContext()
const [employees, setEmployees] = useState<Employee[]>([])
const [departments, setDepartments] = useState<Department[]>([])
const [managers, setManagers] = useState<Employee[]>([])
Expand Down Expand Up @@ -147,8 +148,13 @@ export default function EmployeesPage() {
try {
await employeeApi.delete(id)
fetchEmployees()
} catch (error) {
} catch (error: unknown) {
console.error("删除员工失败:", error)
if (error instanceof AxiosError) {
Alert("删除失败", error.response?.data?.error || "删除员工失败,请重试")
} else {
Alert("删除失败", "删除员工失败,请重试")
}
}
}
}
Expand Down
144 changes: 140 additions & 4 deletions app/evaluations/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { Pagination, usePagination } from "@/components/pagination"
import { LoadingInline } from "@/components/loading"
import { toast } from "sonner"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { AxiosError } from "axios"

export default function EvaluationsPage() {
const { Alert, Confirm, getStatusBadge, isTouch } = useAppContext()
Expand All @@ -78,6 +79,12 @@ export default function EvaluationsPage() {
const [statusFilter, setStatusFilter] = useState<string>("all")
const [employeeFilter, setEmployeeFilter] = useState<string>("all")

// 周期筛选相关状态
const [periodFilter, setPeriodFilter] = useState<string>("")
const [yearFilter, setYearFilter] = useState<string>("")
const [monthFilter, setMonthFilter] = useState<string>("")
const [quarterFilter, setQuarterFilter] = useState<string>("")

// 添加绩效视图Tab相关状态
const [viewTab, setViewTab] = useState<"my" | "team">("my") // 默认显示我的绩效

Expand Down Expand Up @@ -142,6 +149,20 @@ export default function EvaluationsPage() {
params.status = statusFilter
}

// 周期筛选参数
if (periodFilter) {
params.period = periodFilter
}
if (yearFilter) {
params.year = yearFilter
}
if (monthFilter) {
params.month = monthFilter
}
if (quarterFilter) {
params.quarter = quarterFilter
}

// 根据Tab和角色设置员工筛选
if (viewTab === "my") {
// 我的绩效:只显示自己的
Expand Down Expand Up @@ -177,7 +198,7 @@ export default function EvaluationsPage() {
} finally {
setLoading(false)
}
}, [currentUser, currentPage, pageSize, statusFilter, employeeFilter, viewTab, isHR, isManager, refreshUnreadEvaluations])
}, [currentUser, currentPage, pageSize, statusFilter, employeeFilter, periodFilter, yearFilter, monthFilter, quarterFilter, viewTab, isHR, isManager, refreshUnreadEvaluations])

// 获取模板列表
const fetchTemplates = async () => {
Expand Down Expand Up @@ -401,6 +422,10 @@ export default function EvaluationsPage() {
setViewTab(tab)
setStatusFilter("all")
setEmployeeFilter("all")
setPeriodFilter("")
setYearFilter("")
setMonthFilter("")
setQuarterFilter("")
resetPagination()
}

Expand Down Expand Up @@ -451,9 +476,13 @@ export default function EvaluationsPage() {

// 成功提示
Alert("创建成功", `已为 ${formData.employee_ids.length} 个员工创建考核`)
} catch (error) {
} catch (error: unknown) {
console.error("创建评估失败:", error)
Alert("创建失败", "创建考核失败,请重试")
if (error instanceof AxiosError) {
Alert("创建失败", error.response?.data?.error || "创建考核失败,请重试")
} else {
Alert("创建失败", "创建考核失败,请重试")
}
}
}

Expand Down Expand Up @@ -1212,6 +1241,7 @@ export default function EvaluationsPage() {
{loading && <LoadingInline />}
</div>
<div className="flex flex-wrap items-center gap-3">
{/* 状态筛选 */}
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-auto">
<SelectValue placeholder="状态筛选" />
Expand All @@ -1225,6 +1255,8 @@ export default function EvaluationsPage() {
<SelectItem value="completed">已完成</SelectItem>
</SelectContent>
</Select>

{/* 员工筛选 */}
{viewTab === "team" && (
<EmployeeCombobox
value={employeeFilter}
Expand All @@ -1233,11 +1265,107 @@ export default function EvaluationsPage() {
className="min-w-24 justify-between"
/>
)}

{/* 周期筛选 */}
<Select
value={periodFilter || "all"}
onValueChange={(value) => {
setPeriodFilter(value === "all" ? "" : value)
setMonthFilter("")
setQuarterFilter("")
resetPagination()
}}
>
<SelectTrigger className="w-auto">
<SelectValue placeholder="周期筛选" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">全部周期</SelectItem>
<SelectItem value="monthly">月度</SelectItem>
<SelectItem value="quarterly">季度</SelectItem>
<SelectItem value="yearly">年度</SelectItem>
</SelectContent>
</Select>

{/* 年份筛选 */}
<Select
value={yearFilter || "all"}
onValueChange={(value) => {
setYearFilter(value === "all" ? "" : value)
resetPagination()
}}
>
<SelectTrigger className="w-auto">
<SelectValue placeholder="年份筛选" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">全部年份</SelectItem>
{Array.from({ length: 10 }, (_, i) => {
const year = new Date().getFullYear() - i
return (
<SelectItem key={year} value={year.toString()}>
{year}年
</SelectItem>
)
})}
</SelectContent>
</Select>

{/* 月份筛选 - 只在月度周期时显示 */}
{periodFilter === "monthly" && (
<Select
value={monthFilter || "all"}
onValueChange={(value) => {
setMonthFilter(value === "all" ? "" : value)
resetPagination()
}}
>
<SelectTrigger className="w-auto">
<SelectValue placeholder="月份筛选" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">全部月份</SelectItem>
{[...Array(12)].map((_, i) => (
<SelectItem key={i + 1} value={(i + 1).toString()}>
{i + 1}月
</SelectItem>
))}
</SelectContent>
</Select>
)}

{/* 季度筛选 - 只在季度周期时显示 */}
{periodFilter === "quarterly" && (
<Select
value={quarterFilter || "all"}
onValueChange={(value) => {
setQuarterFilter(value === "all" ? "" : value)
resetPagination()
}}
>
<SelectTrigger className="w-auto">
<SelectValue placeholder="季度筛选" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">全部季度</SelectItem>
<SelectItem value="1">第一季度</SelectItem>
<SelectItem value="2">第二季度</SelectItem>
<SelectItem value="3">第三季度</SelectItem>
<SelectItem value="4">第四季度</SelectItem>
</SelectContent>
</Select>
)}

{/* 重置筛选 */}
<Button
variant="outline"
onClick={() => {
setStatusFilter("all")
setEmployeeFilter("all")
setPeriodFilter("")
setYearFilter("")
setMonthFilter("")
setQuarterFilter("")
resetPagination()
}}
>
Expand Down Expand Up @@ -1313,7 +1441,15 @@ export default function EvaluationsPage() {
<TableCell>{evaluation.template?.name}</TableCell>
<TableCell>{getPeriodValue(evaluation)}</TableCell>
<TableCell>
<div className="text-lg font-semibold">{formatScore(evaluation.total_score)}</div>
<div className="text-lg font-semibold">
{formatScore(
evaluation.scores?.reduce(
(acc, score) =>
acc +
(score.final_score ?? score.hr_score ?? score.manager_score ?? score.self_score ?? 0), 0
)
)}
</div>
</TableCell>
<TableCell>{getStatusBadge(evaluation.status)}</TableCell>
<TableCell className="text-right">
Expand Down
6 changes: 6 additions & 0 deletions lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,12 @@ export interface PaginationParams {
export interface EvaluationPaginationParams extends PaginationParams {
status?: string
employee_id?: string
department_id?: string
// 周期筛选参数
period?: string
year?: string
month?: string
quarter?: string
}

// 员工API
Expand Down
2 changes: 0 additions & 2 deletions server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dootask/tools/server/go v0.0.0-20250716160050-ecb1e6de2b73 h1:h77oVnQjMiuTTjnLCiJQrUUl9GfiTgK1hP9E2vzClQg=
github.com/dootask/tools/server/go v0.0.0-20250716160050-ecb1e6de2b73/go.mod h1:QTdgJGF8hr4pPTl7200zQbYJ2K0ag7UX5l2Tlm6LhgU=
github.com/dootask/tools/server/go v0.0.0-20250717040353-7e9cc89be08c h1:TaUYF5MtdSoBg0tzNEqq5Xf2XZzhyw2zZSPrBgmC/UA=
github.com/dootask/tools/server/go v0.0.0-20250717040353-7e9cc89be08c/go.mod h1:QTdgJGF8hr4pPTl7200zQbYJ2K0ag7UX5l2Tlm6LhgU=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
Expand Down
2 changes: 1 addition & 1 deletion server/handlers/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ func ExportPeriodToExcel(c *gin.Context) {
}
}

sheetName := fmt.Sprintf("%s", evaluation.Employee.Name)
sheetName := evaluation.Employee.Name
// Excel工作表名称有字符限制,如果名称过长或有特殊字符,使用简化名称
if len(sheetName) > 31 {
sheetName = fmt.Sprintf("员工%d", idx+1)
Expand Down
Loading