更新系统

This commit is contained in:
LiuQAQQWQ 2025-12-26 16:15:02 +08:00
parent 5a0246abfb
commit 57624139d0
617 changed files with 2365 additions and 44724 deletions

26
admin/src/api/config.ts Normal file
View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 学期配置列表
export function configLists(params?: Record<string, any>) {
return request.get({ url: '/config/list', params })
}
// 学期配置详情
export function configDetail(params: Record<string, any>) {
return request.get({ url: '/config/detail', params })
}
// 学期配置新增
export function configAdd(params: Record<string, any>) {
return request.post({ url: '/config/add', params })
}
// 学期配置编辑
export function configEdit(params: Record<string, any>) {
return request.post({ url: '/config/edit', params })
}
// 学期配置删除
export function configDelete(params: Record<string, any>) {
return request.post({ url: '/config/del', params })
}

View File

@ -57,3 +57,13 @@ export function courseUploadFile(formData: FormData) {
}
)
}
// 获取可排课时间段
export function courseAvailableSlots() {
return request.get({ url: '/course.schedule/time' })
}
// 获取当前人数可用教室
export function courseAvailableRooms(params: Record<string, any>) {
return request.get({ url: '/course.schedule/classroom', params })
}

41
admin/src/api/task.ts Normal file
View File

@ -0,0 +1,41 @@
import request from '@/utils/request'
// 教学任务主列表
export function taskLists(params?: Record<string, any>) {
return request.get({ url: '/task/list', params })
}
// 教学任务主详情
export function taskDetail(params: Record<string, any>) {
return request.get({ url: '/task/detail', params })
}
// 教学任务主新增
export function taskAdd(params: Record<string, any>) {
return request.post({ url: '/task/add', params })
}
// 教学任务主编辑
export function taskEdit(params: Record<string, any>) {
return request.post({ url: '/task/edit', params })
}
// 教学任务主删除
export function taskDelete(params: Record<string, any>) {
return request.post({ url: '/task/del', params })
}
// 班级教学任务查询
export function taskSearch(params: Record<string, any>) {
return request.get({ url: '/task.progress/detail', params })
}
// 班级教学任务课程列表
export function taskCourseList(params: Record<string, any>) {
return request.get({ url: '/task/course', params })
}
// 班级教学任务教师列表
export function taskTeacherList(params: Record<string, any>) {
return request.get({ url: '/task', params })
}

View File

@ -39,3 +39,13 @@ export function teacherCourseAdd(params: Record<string, any>) {
export function teacherCourseDelete(params: Record<string, any>) {
return request.post({ url: '/teacher/course/del', params })
}
// 配置教师角色
export function teacherConfigRole(params: Record<string, any>) {
return request.post({ url: '/teacher/config', params })
}
// 获取教师角色配置
export function teacherGetConfig() {
return request.get({ url: '/teacher/get.config' })
}

21
admin/src/api/time.ts Normal file
View File

@ -0,0 +1,21 @@
import request from '@/utils/request'
// 获取当前学年信息
export function timeAcademicYear() {
return request.get({ url: '/time/academicYear' })
}
// 获取当前日期时间
export function timeCurrentDate() {
return request.get({ url: '/time/currentDate' })
}
// 获取当前学期信息
export function timeCurrentSemester() {
return request.get({ url: '/time/currentSemester' })
}
// 获取刷新配置
export function timeRefreshConfig() {
return request.get({ url: '/time/refreshConfig' })
}

View File

@ -32,6 +32,9 @@
<full-screen />
</el-tooltip>
</div>
<div class="navbar-item">
<Time />
</div>
<div class="navbar-item">
<user-drop-down />
</div>
@ -63,6 +66,7 @@ import Fold from './fold.vue'
import FullScreen from './full-screen.vue'
import MultipleTabs from './multiple-tabs.vue'
import Refresh from './refresh.vue'
import Time from './time.vue'
import UserDropDown from './user-drop-down.vue'
const appStore = useAppStore()

View File

@ -0,0 +1,113 @@
<template>
<el-tooltip class="box-item" effect="dark" :content="tooltipContent" placement="bottom">
<div class="time h-full cursor-pointer flex items-center px-2">
<div class="time-info">
<div class="date-time">{{ dateTime }}</div>
<div class="semester-week">{{ semesterName }}{{ weekNumber }}</div>
</div>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { timeCurrentDate, timeCurrentSemester } from '@/api/time'
//
interface DateInfo {
dateTime: string
date: string
dayOfWeek: string
weekOfYear: number
}
interface SemesterInfo {
semesterName: string
displayName: string
weekNumber: number
}
//
const dateTime = ref('')
const semesterName = ref('')
const weekNumber = ref(0)
// tooltip
const tooltipContent = computed(() => `当前时间:${dateTime.value}`)
//
const fetchDateTime = async () => {
try {
const res = await timeCurrentDate()
if (res) {
const data = res as DateInfo
dateTime.value = `${data.date} ${data.dayOfWeek}`
}
} catch (error) {
console.error('获取时间失败', error)
}
}
//
const fetchSemester = async () => {
try {
const res = await timeCurrentSemester()
if (res) {
const data = res as SemesterInfo
semesterName.value = data.displayName
weekNumber.value = data.weekNumber
}
} catch (error) {
console.error('获取学期信息失败', error)
}
}
//
let timer: number | null = null
onMounted(() => {
fetchDateTime()
fetchSemester()
timer = window.setInterval(fetchDateTime, 60000)
})
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
</script>
<style lang="scss" scoped>
.time {
.time-info {
text-align: right;
line-height: 1.2;
.date-time {
font-size: 14px;
color: var(--text-color-primary);
}
.semester-week {
font-size: 12px;
color: var(--text-color-secondary);
}
}
}
//
@media (max-width: 768px) {
.time {
.time-info {
.date-time {
font-size: 12px;
}
.semester-week {
font-size: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,176 @@
<template>
<div class="edit-popup">
<popup
ref="popupRef"
:title="popupTitle"
:async="true"
width="550px"
:clickModalClose="true"
@confirm="handleSubmit"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
<el-form-item label="" prop="id">
<el-input v-model="formData.id" placeholder="请输入" />
</el-form-item>
<el-form-item label="学年2025-2026" prop="academicYear">
<el-input v-model="formData.academicYear" placeholder="请输入学年2025-2026" />
</el-form-item>
<el-form-item label="学期代码SPRING/AUTUMN" prop="semesterCode">
<el-input v-model="formData.semesterCode" placeholder="请输入学期代码SPRING/AUTUMN" />
</el-form-item>
<el-form-item label="学期名称" prop="semesterName">
<el-input v-model="formData.semesterName" placeholder="请输入学期名称" />
</el-form-item>
<el-form-item label="学期开始日期" prop="startDate">
<el-date-picker
class="flex-1 !flex"
v-model="formData.startDate"
type="datetime"
clearable
value-format="YYYY-MM-DD hh:mm:ss"
placeholder="请选择学期开始日期"
/>
</el-form-item>
<el-form-item label="学期结束日期" prop="endDate">
<el-date-picker
class="flex-1 !flex"
v-model="formData.endDate"
type="datetime"
clearable
value-format="YYYY-MM-DD hh:mm:ss"
placeholder="请选择学期结束日期"
/>
</el-form-item>
<el-form-item label="状态1-有效0-无效" prop="status">
<el-radio-group v-model="formData.status" placeholder="请选择状态1-有效0-无效">
<el-radio label="0">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import type { PropType } from 'vue'
import { configAdd, configDetail, configEdit } from '@/api/config'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑学期配置' : '新增学期配置'
})
const formData = reactive({
id: '',
academicYear: '',
semesterCode: '',
semesterName: '',
startDate: '',
endDate: '',
status: '',
})
const formRules = {
id: [
{
required: true,
message: '请输入',
trigger: ['blur']
}
],
academicYear: [
{
required: true,
message: '请输入学年2025-2026',
trigger: ['blur']
}
],
semesterCode: [
{
required: true,
message: '请输入学期代码SPRING/AUTUMN',
trigger: ['blur']
}
],
semesterName: [
{
required: true,
message: '请输入学期名称',
trigger: ['blur']
}
],
startDate: [
{
required: true,
message: '请选择学期开始日期',
trigger: ['blur']
}
],
endDate: [
{
required: true,
message: '请选择学期结束日期',
trigger: ['blur']
}
],
status: [
{
required: true,
message: '请选择状态1-有效0-无效',
trigger: ['blur']
}
],
}
const handleSubmit = async () => {
await formRef.value?.validate()
const data: any = { ...formData }
mode.value == 'edit' ? await configEdit(data) : await configAdd(data)
popupRef.value?.close()
feedback.msgSuccess('操作成功')
emit('success')
}
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
const setFormData = async (data: Record<string, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
}
const getDetail = async (row: Record<string, any>) => {
const data = await configDetail({
id: row.id
})
setFormData(data)
}
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script>

View File

@ -0,0 +1,139 @@
<template>
<div class="index-lists">
<el-card class="!border-none" shadow="never">
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
<el-form-item label="学年2025-2026" prop="academicYear">
<el-input class="w-[280px]" v-model="queryParams.academicYear" />
</el-form-item>
<el-form-item label="学期代码SPRING/AUTUMN" prop="semesterCode">
<el-input class="w-[280px]" v-model="queryParams.semesterCode" />
</el-form-item>
<el-form-item label="学期名称" prop="semesterName">
<el-input class="w-[280px]" v-model="queryParams.semesterName" />
</el-form-item>
<el-form-item label="学期开始日期" prop="startDate">
<daterange-picker
v-model:startTime="queryParams.createTimeStart"
v-model:endTime="queryParams.createTimeEnd"
/>
</el-form-item>
<el-form-item label="学期结束日期" prop="endDate">
<daterange-picker
v-model:startTime="queryParams.createTimeStart"
v-model:endTime="queryParams.createTimeEnd"
/>
</el-form-item>
<el-form-item label="状态1-有效0-无效" prop="status">
<el-select
v-model="queryParams.status"
class="w-[280px]"
clearable
>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div>
<el-button v-perms="['config:add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<el-table
class="mt-4"
size="large"
v-loading="pager.loading"
:data="pager.lists"
>
<el-table-column label="学年2025-2026" prop="academicYear" min-width="100" />
<el-table-column label="学期代码SPRING/AUTUMN" prop="semesterCode" min-width="100" />
<el-table-column label="学期名称" prop="semesterName" min-width="100" />
<el-table-column label="学期开始日期" prop="startDate" min-width="100" />
<el-table-column label="学期结束日期" prop="endDate" min-width="100" />
<el-table-column label="状态1-有效0-无效" prop="status" min-width="100" />
<el-table-column label="" prop="createTime" min-width="100" />
<el-table-column label="" prop="updateTime" min-width="100" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['config:edit']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-perms="['config:del']"
type="danger"
link
@click="handleDelete(row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="config">
import { configDelete, configLists } from '@/api/config'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const showEdit = ref(false)
const queryParams = reactive({
academicYear: '',
semesterCode: '',
semesterName: '',
startDateStart: '',
startDateEnd: '',
endDateStart: '',
endDateEnd: '',
status: '',
createTimeStart: '',
createTimeEnd: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: configLists,
params: queryParams
})
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.getDetail(data)
}
const handleDelete = async (id: number) => {
await feedback.confirm('确定要删除?')
await configDelete({ id })
feedback.msgSuccess('删除成功')
getLists()
}
getLists()
</script>

View File

@ -8,6 +8,22 @@
</template>
新增
</el-button>
<el-select v-model="teacher.id" class="w-[280px] ml-10" clearable>
<el-option
v-for="cole in getRoleLists"
:key="cole.id"
:value="cole.id"
:label="cole.name"
/>
</el-select>
<el-button
v-perms="['teacher/config']"
class="ml-1"
type="primary"
@click="configTeacher"
>
配置教师角色
</el-button>
</div>
<div class="mt-4" v-loading="pager.loading">
<div>
@ -64,7 +80,8 @@
</template>
<script lang="ts" setup name="role">
import { roleDelete, roleLists } from '@/api/perms/role'
import { roleAll, roleDelete, roleLists } from '@/api/perms/role'
import { teacherConfigRole, teacherGetConfig } from '@/api/teacher'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
@ -75,9 +92,27 @@ const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const authRef = shallowRef<InstanceType<typeof AuthPopup>>()
const showEdit = ref(false)
const showAuth = ref(false)
const getRoleLists = ref<Array<{ id: number; name: string }>>([])
const teacher = reactive({
id: ''
})
const { pager, getLists } = usePaging({
fetchFun: roleLists
})
const fetchRoleLists = async () => {
try {
const res = await roleAll(null)
const config = await teacherGetConfig()
teacher.id = config.id
console.log('res:', res)
getRoleLists.value = res
console.log('getRoleLists:', getRoleLists)
} catch (err) {
feedback.msgError('获取学期列表失败')
}
}
const handleAdd = async () => {
showEdit.value = true
await nextTick()
@ -105,5 +140,10 @@ const handleDelete = async (id: number) => {
getLists()
}
const configTeacher = async () => {
await teacherConfigRole(teacher)
}
getLists()
fetchRoleLists()
</script>

View File

@ -0,0 +1,570 @@
<template>
<div class="index-lists">
<el-card class="!border-none" shadow="never">
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
<el-form-item label="班级" prop="classId">
<el-select
v-model="queryParams.classId"
placeholder="请输入班级名称搜索"
:remote="true"
:remote-method="handleClassRemoteSearch"
:loading="classSearchLoading"
filterable
clearable
remote-show-suffix
class="w-[280px]"
@change="handleClassChange"
>
<el-option
v-for="item in getClassLists.lists"
:key="item.id"
:value="item.id"
:label="item.className"
@click="handleStudentClick(item)"
>
<template #default>
<span
style="color: var(--el-text-color-secondary); font-size: 13px"
>
{{ item.classCode }}
</span>
<span style="margin-left: 8px">{{ item.className }}</span>
</template>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="学期" prop="semesterId">
<el-select
v-model="queryParams.semesterId"
class="w-[280px]"
clearable
@change="handleSemesterChange"
>
<el-option
v-for="college in getConfigLists.lists"
:key="college.id"
:value="college.id"
:label="college.config"
/>
</el-select>
</el-form-item>
</el-form>
</el-card>
<div class="flex">
<el-card class="!border-none mt-4 mr-4" shadow="never" style="width: 75%">
<el-table class="mb-4" size="large" v-loading="loading" :data="tableData" border>
<!-- 序号列包含时间类型状态 -->
<el-table-column label="节次" width="50" class-name="first-column" align="left">
<template #default="{ $index }">
<div class="index-info">
<div class="index-details">
<div class="index-number">{{ $index + 1 }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="时间" width="80" class-name="first-column" align="left">
<template #default="{ row }">
<div class="index-info">
<div class="index-details">
<div class="flex justify-center" style="font-size: 12px">
{{ getRowStartTime(row) }}
</div>
<div class="flex justify-center" style="font-size: 6px"></div>
<div class="flex justify-center" style="font-size: 12px">
{{ getRowEndTime(row) }}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="星期一" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[1]" />
</template>
</el-table-column>
<el-table-column label="星期二" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[2]" />
</template>
</el-table-column>
<el-table-column label="星期三" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[3]" />
</template>
</el-table-column>
<el-table-column label="星期四" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[4]" />
</template>
</el-table-column>
<el-table-column label="星期五" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[5]" />
</template>
</el-table-column>
<el-table-column label="星期六" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[6]" />
</template>
</el-table-column>
<el-table-column label="星期日" min-width="80" align="center">
<template #default="{ row }">
<div v-if="row[7]" />
</template>
</el-table-column>
</el-table>
</el-card>
<el-card class="mt-4" shadow="never" style="width: 24%">
<!-- 改为标签页 -->
<el-tabs v-model="activeTab" style="margin-top: -10px">
<el-tab-pane label="课程列表" name="course" class="course-list-container">
<div class="mb-4">
<h3 class="text-lg font-semibold">课程列表</h3>
<p class="text-sm text-gray-500 mt-1">当前班级和学期下的可用课程</p>
</div>
<div
v-if="getCourseLists.lists.length === 0"
class="text-center py-8 text-gray-400"
>
暂无课程数据请选择班级和学期
</div>
<div v-else class="space-y-4 max-h-[700px] overflow-y-auto">
<el-card
v-for="item in getCourseLists.lists"
:key="item.id"
shadow="hover"
class="cursor-pointer hover:bg-blue-50 transition-colors duration-200"
@click="handleCourseClick(item)"
>
<div class="p-0">
<div class="flex justify-between items-start">
<div>
<h4 class="font-medium text-sm">
课程{{ item.courseName }}
</h4>
</div>
</div>
<div class="flex justify-between text-xs text-gray-600">
<span>教师: {{ item.teacherName }}</span>
<span>周学时: {{ item.totalWeeks }}</span>
</div>
<div
v-if="selectedCourseId === item.id"
class="pt-3 border-t border-gray-100"
>
<div class="text-xs text-gray-700">
<div class="flex items-center mb-1">
<span class="font-medium">总学时:</span>
<span>{{ item.totalHours }}</span>
</div>
<div class="flex items-center">
<span class="font-medium">周数:</span>
<span>{{ item.totalWeeks }}</span>
</div>
<p
class="text-xs text-gray-500"
style="color: darkgray"
>
{{ item.taskCode }}
</p>
</div>
</div>
</div>
</el-card>
</div>
<div class="flex justify-end mt-6">
<pagination
layout="prev, pager, next"
v-model="pager"
@change="getLists"
/>
</div>
</el-tab-pane>
<el-tab-pane label="教室列表" name="classroom" class="course-list-container">
<div class="mb-4">
<h3 class="text-lg font-semibold">教室列表</h3>
<p class="text-sm text-gray-500 mt-1">当前可用的教室资源</p>
</div>
<div
v-if="getRoomLists.lists.length === 0"
class="text-center py-8 text-gray-400"
>
暂无教室数据
</div>
<div v-else class="space-y-4 max-h-[700px] overflow-y-auto">
<el-card
v-for="item in getRoomLists.lists"
:key="item.id"
shadow="hover"
class="cursor-pointer hover:bg-blue-50 transition-colors duration-200"
@click="handleClassroomClick(item)"
>
<div class="p-0">
<div class="flex justify-between items-start">
<div>
<h4 class="font-medium text-sm">
教室{{ item.classroomName }}
</h4>
</div>
</div>
<div class="flex justify-between text-xs text-gray-600">
<span>类型: {{ item.classroomTypeName }}</span>
<span>容量: {{ item.capacity }}</span>
</div>
<div
v-if="selectedRoomId === item.id"
class="pt-3 border-t border-gray-100"
>
<div class="text-xs text-gray-700">
<div class="flex items-center mb-1">
<span class="font-medium">编号:</span>
<span>{{ item.classroomCode }}</span>
</div>
<div class="flex items-center">
<span class="font-medium">位置:</span>
<span>{{ item.location }}</span>
</div>
</div>
</div>
</div>
</el-card>
</div>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, reactive, ref } from 'vue'
import { classLists } from '@/api/class'
import { configLists } from '@/api/config'
import { courseAvailableRooms, courseAvailableSlots } from '@/api/course'
import { taskLists } from '@/api/task'
import { timeCurrentSemester } from '@/api/time'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
const getConfigLists = ref<{
lists: Array<{
id: number
academicYear: string
semesterCode: string
config: string
startDate: string
endDate: string
}>
}>({ lists: [] })
const getClassLists = ref<{
lists: Array<{ id: number; className: string; classCode: string; maxStudentCount: number }>
}>({ lists: [] })
const classSearchLoading = ref(false)
const classSearchTimer = ref<number | null>(null)
const activeTab = ref('course')
//
const getTimeData = ref<{
lists: Array<{
timeSlotId: number
classId: number
classroomId: number
courseId: number
semesterId: number
teacherId: number
}>
}>({ lists: [] })
//
const getCourseLists = ref<{
lists: Array<{
id: number
courseId: number
courseName: string
taskCode: string
totalHours: number
teacherId: number
teacherName: string
totalWeeks: number
}>
}>({ lists: [] })
//
const courseLoading = ref(false)
// ID
const selectedCourseId = ref<number | null>(null)
//
const getRoomLists = ref<{
lists: Array<{
id: number
classroomName: string
classroomCode: string
classroomTypeName: string
location: string
capacity: number
}>
}>({ lists: [] })
//
const roomLoading = ref(false)
// ID
const selectedRoomId = ref<number | null>(null)
const loading = ref(false)
const queryParams = reactive({
classId: '',
semesterId: '',
maxStudentCount: 0
})
//
const handleClassChange = async () => {
if (queryParams.classId && queryParams.semesterId) {
await fetchCourseLists()
await fetchRoomLists()
}
}
const handleStudentClick = (item: any) => {
queryParams.maxStudentCount = item.maxStudentCount || 0
}
//
const handleSemesterChange = async () => {
if (queryParams.classId && queryParams.semesterId) {
await fetchCourseLists()
}
}
//
const fetchClassLists = async (params: string) => {
try {
const res = await classLists({
className: params.trim()
})
getClassLists.value = res
} catch (err) {
feedback.msgError('获取课程列表失败')
getClassLists.value = { lists: [] }
} finally {
classSearchLoading.value = false
}
}
const handleClassRemoteSearch = (keyword: string) => {
if (classSearchTimer.value) clearTimeout(classSearchTimer.value)
classSearchTimer.value = setTimeout(async () => {
classSearchLoading.value = true
await fetchClassLists(keyword)
}, 300)
}
//
const fetchConfigLists = async () => {
try {
const res = await configLists()
const handleData = JSON.parse(JSON.stringify(res))
handleData.lists = handleData.lists.map((item: any) => ({
...item,
config: `${item.academicYear}${item.semesterCode == 'SPRING' ? ' 春' : ' 秋'}`
}))
getConfigLists.value = handleData
await fetchSemester()
} catch (err) {
feedback.msgError('获取学期列表失败')
}
}
const fetchSemester = async () => {
try {
const res = await timeCurrentSemester()
if (res) {
queryParams.semesterId = res.id
}
} catch (error) {
console.error('获取学期信息失败', error)
}
}
//
const fetchCourseLists = async () => {
try {
courseLoading.value = true
// 使taskLists
const response = await taskLists({
classId: queryParams.classId,
semesterId: queryParams.semesterId
})
//
const mappedCourses = response.lists.map(
(task: {
id: any
courseId: any
courseName: any
taskCode: any
weeklyHours: number
totalWeeks: number
teacherId: any
teacherName: any
}) => ({
id: task.id,
courseId: task.courseId,
courseName: task.courseName,
taskCode: task.taskCode,
totalHours: task.weeklyHours * task.totalWeeks, // =×
teacherId: task.teacherId,
teacherName: task.teacherName,
totalWeeks: task.totalWeeks
})
)
getCourseLists.value = { lists: mappedCourses }
} catch (err) {
console.log('获取课程列表失败', err)
feedback.msgError('获取课程列表失败')
getCourseLists.value = { lists: [] }
} finally {
courseLoading.value = false
}
}
//
const handleCourseClick = (course: any) => {
selectedCourseId.value = selectedCourseId.value === course.id ? null : course.id
}
//
const fetchRoomLists = async () => {
try {
roomLoading.value = true
// 使taskLists
const response = await courseAvailableRooms({
num: queryParams.maxStudentCount
})
//
const mappedRooms = response.map(
(task: {
id: number
classroomName: string
classroomCode: string
classroomTypeName: string
location: string
capacity: number
}) => ({
id: task.id,
classroomName: task.classroomName,
classroomCode: task.classroomCode,
classroomTypeName: task.classroomTypeName,
location: task.location,
capacity: task.capacity
})
)
getRoomLists.value = { lists: mappedRooms }
} catch (err) {
console.log('获取教室列表失败', err)
feedback.msgError('获取教室列表失败')
getRoomLists.value = { lists: [] }
} finally {
roomLoading.value = false
}
}
//
const handleClassroomClick = (classroom: any) => {
selectedRoomId.value = selectedRoomId.value === classroom.id ? null : classroom.id
}
//
onBeforeUnmount(() => {
if (classSearchTimer.value) clearTimeout(classSearchTimer.value)
})
//
const allLists = ref<any[]>([])
const { pager, getLists } = usePaging({
fetchFun: taskLists,
params: queryParams,
size: 7
})
//
const getTimeLists = async () => {
loading.value = true
try {
const res = await courseAvailableSlots()
allLists.value = res
return Promise.resolve(res)
} catch (err) {
return Promise.reject(err)
} finally {
loading.value = false
}
}
//
const tableData = computed(() => {
const timeSlotMap = new Map<string, Record<number, any>>()
allLists.value.forEach((item) => {
const key = `${item.startTime}-${item.endTime}`
if (!timeSlotMap.has(key)) {
timeSlotMap.set(key, {})
}
const slotGroup = timeSlotMap.get(key)!
slotGroup[item.dayOfWeek] = item
})
return Array.from(timeSlotMap.values()).sort((a, b) => {
const aTime = Object.values(a)[0]?.startTime || ''
const bTime = Object.values(b)[0]?.startTime || ''
return aTime.localeCompare(bTime)
})
})
const getRowBaseInfo = (row: Record<number, any>) => {
return Object.values(row).find((item) => item) || {}
}
const getRowStartTime = (row: Record<number, any>) => {
const baseInfo = getRowBaseInfo(row)
const start = baseInfo?.startTime
if (start == null) return ''
const s = String(start)
return s.length > 3 ? s.slice(0, -3) : ''
}
const getRowEndTime = (row: Record<number, any>) => {
const baseInfo = getRowBaseInfo(row)
const end = baseInfo?.endTime
if (end == null) return ''
const s = String(end)
return s.length > 3 ? s.slice(0, -3) : ''
}
//
getTimeLists()
fetchClassLists('')
fetchConfigLists()
</script>
<style scoped>
:deep(.first-column) {
background-color: #f8f8f8;
}
.course-list-container {
height: auto;
display: flex;
flex-direction: column;
}
.course-list-container .el-card {
border: 1px solid #e4e7ed;
}
.course-list-container .el-card:hover {
border-color: #409eff;
}
:deep(.el-tag) {
height: 24px;
line-height: 22px;
}
</style>

View File

@ -37,7 +37,12 @@
<el-input class="w-[280px]" v-model="queryParams.headTeacherId" />
</el-form-item>
<el-form-item label="班级状态" prop="classStatus">
<el-select v-model="queryParams.classStatus" class="w-[280px]" clearable>
<el-select
v-model="queryParams.classStatus"
class="w-[280px]"
clearable
@change="getLists"
>
<el-option label="在读" :value="1" />
<el-option label="毕业" :value="2" />
</el-select>
@ -49,21 +54,17 @@
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div>
<el-button v-perms="['class:add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
<el-table
class="mt-4 large-table clickable-row-table"
size="large"
v-loading="pager.loading"
:data="pager.lists"
@row-click="(row: any) => handleRowClick(row)"
>
<el-table-column label="学院名称" prop="collegeName" min-width="100" />
<el-table-column label="专业名称" prop="majorName" min-width="100" />
<el-table-column label="班级代码" prop="classCode" min-width="100" />
<el-table-column label="班级名称" prop="className" min-width="100" />
<el-table-column label="学生人数" prop="studentCount" min-width="100" />
<el-table-column label="最大学生数" prop="maxStudentCount" min-width="100" />
<el-table-column label="入学年份" prop="enrollmentYear" min-width="100" />
<el-table-column label="预计毕业年份" prop="graduationYear" min-width="100" />
<el-table-column
@ -72,26 +73,11 @@
min-width="100"
:formatter="formatClassStatus"
/>
<el-table-column label="创建时间" prop="createTime" min-width="100" />
<el-table-column label="更新时间" prop="updateTime" min-width="100" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['class:edit']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-perms="['class:del']"
type="danger"
link
@click="handleDelete(row.id)"
>
删除
</el-button>
<el-table-column label="任务进度" min-width="100">
<template #default="scope">
<span :class="getProgressClass(scope.row.progress)">
{{ formatClassProgress(scope.row.progress) }}
</span>
</template>
</el-table-column>
</el-table>
@ -99,22 +85,25 @@
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="class">
import { classDelete, classLists } from '@/api/class'
import { useRouter } from 'vue-router'
import { classLists } from '@/api/class'
import { collegeLists } from '@/api/college'
import { majorLists } from '@/api/major'
import { taskSearch } from '@/api/task'
import { usePaging } from '@/hooks/usePaging'
import { getRoutePath } from '@/router'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const getCollegeLists = ref<{ lists: Array<{ id: number; collegeName: string }> }>({ lists: [] })
const getMajorLists = ref<{ lists: Array<{ id: number; majorName: string }> }>({ lists: [] })
const showEdit = ref(false)
const router = useRouter()
const queryParams = reactive({
id: '',
collegeName: '',
majorName: '',
classCode: '',
@ -124,11 +113,25 @@ const queryParams = reactive({
headTeacherId: '',
enrollmentYear: '',
graduationYear: '',
classStatus: null
classStatus: 1
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: classLists,
fetchFun: async (params) => {
const classData = await classLists(params)
//
for (const cls of classData.lists) {
try {
const progressRes = await taskSearch({ classId: cls.id })
// progressResstatus
cls.progress = progressRes.arrangementProgress
} catch (err) {
console.error(`获取班级${cls.id}进度失败`, err)
cls.progress = 'unknown'
}
}
return classData
},
params: queryParams
})
@ -158,27 +161,115 @@ const formatClassStatus = (row: any, column: any, cellValue: any) => {
return statusMap[String(cellValue)] || cellValue
}
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
const formatClassProgress = (progressValue: any) => {
const statusMap: Record<string, string> = {
draft: '草稿',
confirmed: '确认',
published: '发布',
archived: '归档',
unknown: '未知'
}
return statusMap[String(progressValue)] || progressValue
}
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.getDetail(data)
// CSS
const getProgressClass = (progressValue: any) => {
const progress = String(progressValue)
const classMap: Record<string, string> = {
draft: 'progress-draft',
confirmed: 'progress-confirmed',
published: 'progress-published',
archived: 'progress-archived',
unknown: 'progress-unknown'
}
return classMap[progress] || 'progress-default'
}
const handleDelete = async (id: number) => {
await feedback.confirm('确定要删除?')
await classDelete({ id })
feedback.msgSuccess('删除成功')
getLists()
const handleRowClick = (row: any) => {
router.push({
path: getRoutePath('task/list'),
query: { classId: row.id }
})
}
getLists()
fetchCollegeLists()
fetchMajorLists()
</script>
<style scoped>
:deep(.clickable-row-table .el-table__row) {
cursor: default;
transition: background-color 0.2s ease;
}
:deep(.clickable-row-table .el-table__row:hover) {
cursor: pointer;
background-color: #f0f9ff !important;
border-left: 3px solid #409eff;
}
:deep(.clickable-row-table .el-table__row.current-row) {
background-color: #e6f7ff !important;
}
:deep(.el-table tbody tr:hover > td) {
background-color: transparent !important;
}
/* 进度样式 */
:deep(.progress-draft) {
color: #909399;
font-weight: 500;
background-color: #f4f4f5;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
}
:deep(.progress-confirmed) {
color: #e6a23c;
font-weight: 600;
background-color: #fdf6ec;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
}
:deep(.progress-published) {
color: #67c23a;
font-weight: 600;
background-color: #f0f9eb;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
}
:deep(.progress-archived) {
color: #909399;
font-weight: 500;
background-color: #f4f4f5;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
opacity: 0.7;
}
:deep(.progress-unknown) {
color: #f56c6c;
font-weight: 500;
background-color: #fef0f0;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
}
:deep(.progress-default) {
color: #409eff;
font-weight: 500;
background-color: #ecf5ff;
padding: 4px 8px;
border-radius: 4px;
display: inline-block;
}
</style>

View File

@ -0,0 +1,542 @@
<template>
<div class="edit-popup">
<popup
ref="popupRef"
:title="popupTitle"
:async="true"
width="550px"
:clickModalClose="true"
@confirm="handleSubmit"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
<el-form-item label="任务编号" prop="taskCode">
<span>{{ formData.taskCode }}</span>
</el-form-item>
<el-form-item label="学期" prop="semesterId">
<el-select
v-model="formData.semesterId"
class="w-[280px]"
@change="fetchConfigChange"
>
<el-option
v-for="college in getConfigLists.lists"
:key="college.id"
:value="college.id"
:label="college.config"
/>
</el-select>
</el-form-item>
<el-form-item label="课程" prop="courseId">
<el-select
v-model="formData.courseId"
class="w-[280px]"
clearable
@change="fetchCourseChange"
>
<el-option
v-for="item in getCourseLists.lists"
:key="item.id"
:value="item.id"
:label="item.courseName"
>
<template #default>
<span
style="color: var(--el-text-color-secondary); font-size: 13px"
>{{ item.courseCode }}</span
>
<span style="margin-left: 8px">{{ item.courseName }}</span>
</template>
</el-option>
</el-select>
<span
style="
color: var(--el-text-color-secondary);
font-size: 13px;
margin-left: 24px;
"
>
学分:{{ fromCourse.credits }} 总学时:{{ fromCourse.totalHours }}
</span>
</el-form-item>
<el-form-item label="教师" prop="teacherId">
<div style="display: flex; align-items: center; gap: 12px">
<el-select
v-model="formData.teacherId"
class="w-[280px]"
clearable
:loading="teacherSearchLoading"
>
<el-option
v-for="item in getTeacherLists.lists"
:key="item.id"
:value="item.id"
:label="item.name"
>
<template #default>
<span
style="
color: var(--el-text-color-secondary);
font-size: 13px;
"
>{{ item.teacherCode }}</span
>
<span style="margin-left: 8px">{{ item.name }}</span>
</template>
</el-option>
</el-select>
<el-switch
v-model="ignoreCourseSwitch"
active-text="忽略课程"
active-value="true"
inactive-value="false"
@change="fetchTeacherLists"
/>
</div>
</el-form-item>
<el-form-item label="周学时" prop="weeklyHours">
<el-input-number
v-model="formData.weeklyHours"
:min="1"
:max="30"
controls-position="right"
/>
<span
style="
color: var(--el-text-color-secondary);
font-size: 13px;
margin-left: 24px;
"
>
请输入周学时范围 1-30
</span>
</el-form-item>
<el-form-item label="总周数" prop="totalWeeks">
<el-input-number
v-model="formData.totalWeeks"
:min="1"
:max="20"
controls-position="right"
/>
<span
style="
color: var(--el-text-color-secondary);
font-size: 13px;
margin-left: 24px;
"
>
请输入总周数范围 1-20
</span>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="formData.remark"
placeholder="请输入备注"
type="textarea"
:autosize="{ minRows: 4, maxRows: 6 }"
/>
</el-form-item>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import type { PropType } from 'vue'
import { classDetail } from '@/api/class'
import { configDetail, configLists } from '@/api/config'
import { courseDetail } from '@/api/course'
import { taskAdd, taskCourseList, taskDetail, taskEdit, taskTeacherList } from '@/api/task'
import { teacherDetail } from '@/api/teacher'
import { timeCurrentSemester } from '@/api/time'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const getConfigLists = ref<{
lists: Array<{ id: number; academicYear: string; semesterCode: string; config: string }>
}>({ lists: [] })
const getCourseLists = ref<{
lists: Array<{
id: number
courseName: string
courseCode: string
credits: number
totalHours: number
}>
}>({ lists: [] })
const getTeacherLists = ref<{
lists: Array<{ id: number; name: string; teacherCode: string }>
}>({ lists: [] })
const courseSearchLoading = ref(false)
const courseSearchTimer = ref<number | null>(null)
const teacherSearchLoading = ref(false)
const teacherSearchTimer = ref<number | null>(null)
const ignoreCourseSwitch = ref<string>('true')
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑教学任务' : '新增教学任务'
})
const formData = reactive({
id: '',
collegeId: '',
semesterId: '',
courseId: '',
teacherId: '',
classId: 0,
weeklyHours: 0,
totalWeeks: 0,
remark: '',
taskCode: ''
})
const formCode = reactive({
semesterCode: '',
courseCode: '',
classCode: ''
})
const fromCourse = reactive({
totalHours: 0,
credits: 0
})
const formRules = {
id: [
{
required: true,
message: '请输入唯一主键',
trigger: ['blur']
}
],
semesterId: [
{
required: true,
message: '请输入学期ID',
trigger: ['blur']
}
],
courseId: [
{
required: true,
message: '请输入课程ID',
trigger: ['blur']
}
],
teacherId: [
{
required: true,
message: '请输入教师ID',
trigger: ['blur']
}
],
classId: [
{
required: true,
message: '请输入班级ID',
trigger: ['blur']
}
],
weeklyHours: [
{
required: true,
message: '请输入周学时,范围 1-30',
trigger: ['blur']
}
],
totalWeeks: [
{
required: true,
message: '请输入总周数,范围 1-20',
trigger: ['blur']
}
]
}
const fetchConfigChange = async () => {
fetchTaskCode()
await fetchCourseLists()
}
const fetchConfigLists = async () => {
try {
const res = await configLists()
const handleData = JSON.parse(JSON.stringify(res))
handleData.lists = handleData.lists.map((item: any) => ({
...item,
config: `${item.academicYear}${item.semesterCode == 'SPRING' ? ' 春' : ' 秋'}`
}))
getConfigLists.value = handleData
await fetchSemester()
} catch (err) {
feedback.msgError('获取学期列表失败')
}
}
const fetchSemester = async () => {
try {
const res = await timeCurrentSemester()
if (res) {
formData.semesterId = res.id
}
} catch (error) {
console.error('获取学期信息失败', error)
}
}
const fetchSemesterCode = async () => {
try {
const res = await configDetail({ id: formData.semesterId })
if (res) {
formCode.semesterCode = `${res.academicYear}${
res.semesterCode == 'SPRING' ? '-1' : '-2'
}`
console.log('formCode.semesterCode', formCode.semesterCode)
}
} catch (error) {
console.error('获取学期代码失败', error)
}
}
const fetchCourseChange = async () => {
const selectedCourse = getCourseLists.value.lists.find(
(item) => item.id === Number(formData.courseId)
)
if (selectedCourse) {
fromCourse.credits = selectedCourse.credits
fromCourse.totalHours = selectedCourse.totalHours
} else {
fromCourse.credits = 0
fromCourse.totalHours = 0
if (formData.courseId) {
try {
const res = await courseDetail({ id: formData.courseId })
fromCourse.credits = res.credits
fromCourse.totalHours = res.totalHours
} catch (err) {
console.error('获取选中课程详情失败', err)
feedback.msgError('获取课程学分/总学时失败')
}
}
}
await fetchTaskCode()
await fetchTeacherLists()
}
const fetchCourseLists = async () => {
try {
courseSearchLoading.value = true
const courseIdRes = await taskCourseList({
classId: formData.classId,
semesterId: formData.semesterId
})
const courseIds = courseIdRes
if (!Array.isArray(courseIds) || courseIds.length === 0) {
getCourseLists.value = { lists: [] }
return
}
const courseDetailPromises = courseIds.map(async (courseId) => {
const realId = courseId
const detail = await courseDetail({ id: realId })
return {
id: detail.id,
courseName: detail.courseName,
courseCode: detail.courseCode,
credits: detail.credits,
totalHours: detail.totalHours
}
})
const settledResults = await Promise.allSettled(courseDetailPromises)
const courseDetails = settledResults.reduce(
(acc, result, index) => {
if (result.status === 'fulfilled') {
acc.push(result.value)
} else {
console.error(`获取课程ID ${courseIds[index]} 详情失败:`, result.reason)
}
return acc
},
[] as {
id: number
courseName: string
courseCode: string
credits: number
totalHours: number
}[]
)
console.log('获取课程列表', courseDetails)
getCourseLists.value = { lists: courseDetails }
if (formData.courseId) {
const selectedCourse = courseDetails.find(
(item) => item.id === Number(formData.courseId)
)
if (selectedCourse) {
fromCourse.credits = selectedCourse.credits
fromCourse.totalHours = selectedCourse.totalHours
}
}
} catch (err) {
console.log('获取课程列表失败')
feedback.msgError('获取课程列表失败')
getCourseLists.value = { lists: [] }
} finally {
courseSearchLoading.value = false
}
await fetchTeacherLists()
}
const fetchCourseCode = async () => {
try {
if (
formData.courseId == null ||
formData.courseId === undefined ||
formData.courseId === ''
) {
formCode.courseCode = '?'
return
}
const res = await courseDetail({ id: formData.courseId })
if (res) {
formCode.courseCode = res.courseCode
console.log('formCode.courseCode', formCode.courseCode)
}
} catch (error) {
console.error('获取课程代码失败', error)
}
}
const fetchTeacherLists = async () => {
try {
teacherSearchLoading.value = true
const teacherIdRes = await taskTeacherList({
collegeId: formData.collegeId,
courseId: formData.courseId,
ignoreCourse: ignoreCourseSwitch.value === 'true'
})
console.log('教师IDs', teacherIdRes)
const teacherIds = teacherIdRes
if (!Array.isArray(teacherIds) || teacherIds.length === 0) {
getTeacherLists.value = { lists: [] }
return
}
const teacherDetailPromises = teacherIds.map(async (teacherId) => {
const realId = teacherId
const detail = await teacherDetail({ id: realId })
return {
id: detail.id,
name: detail.name,
teacherCode: detail.teacherCode
}
})
const settledResults = await Promise.allSettled(teacherDetailPromises)
const courseDetails = settledResults.reduce((acc, result, index) => {
if (result.status === 'fulfilled') {
acc.push(result.value)
} else {
console.error(`获取教师ID ${teacherIds[index]} 详情失败:`, result.reason)
}
return acc
}, [] as { id: number; name: string; teacherCode: string }[])
console.log('获取教师列表', courseDetails)
getTeacherLists.value = { lists: courseDetails }
} catch (err) {
console.log('获取教师列表失败')
feedback.msgError('获取教师列表失败')
getTeacherLists.value = { lists: [] }
} finally {
teacherSearchLoading.value = false
}
}
onBeforeUnmount(() => {
if (courseSearchTimer.value) clearTimeout(courseSearchTimer.value)
if (teacherSearchTimer.value) clearTimeout(teacherSearchTimer.value)
})
const fetchTaskCode = async () => {
await fetchSemesterCode()
await fetchCourseCode()
formData.taskCode = formCode.semesterCode + '-' + formCode.courseCode + '-' + formCode.classCode
console.log('提交的教学任务编码', formData.taskCode)
}
const handleSubmit = async () => {
const validateResult = await formRef.value?.validate()
if (!validateResult) return
if (fromCourse.totalHours === 0) {
feedback.msgError('请先选择课程,获取课程总学时后再提交!')
return
}
const calcTotalHours = formData.weeklyHours * formData.totalWeeks
if (calcTotalHours !== fromCourse.totalHours) {
feedback.msgError(
`学时校验失败!周学时(${formData.weeklyHours}) × 总周数(${formData.totalWeeks}) = ${calcTotalHours},与课程总学时(${fromCourse.totalHours})不相等,请修正!`
)
return
}
await fetchTaskCode()
await formRef.value?.validate()
const data: any = { ...formData }
mode.value == 'edit' ? await taskEdit(data) : await taskAdd(data)
popupRef.value?.close()
feedback.msgSuccess('操作成功')
emit('success')
}
const open = async (type = 'add') => {
mode.value = type
await fetchConfigLists()
await fetchCourseLists()
popupRef.value?.open()
}
const setFormData = async (data: Record<string, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
}
const getClassDetail = async (classId: number) => {
try {
const data = await classDetail({ id: classId })
formData.classId = data.id
formData.collegeId = data.collegeId
formCode.classCode = data.classCode
return data
} catch (err) {
feedback.msgError('获取班级详情失败')
return null
}
}
const getDetail = async (row: Record<string, any>) => {
const data = await taskDetail({
id: row.id
})
setFormData(data)
}
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail,
getClassDetail
})
</script>

View File

@ -0,0 +1,321 @@
<template>
<div class="index-lists">
<el-card class="!border-none" shadow="never">
<div style="display: flex; align-items: center; margin-bottom: 16px">
<div style="font-size: 18px; font-weight: 500">
{{ classData.className }}
</div>
<div style="font-size: 16px; font-weight: 400; margin-left: 32px; color: #606266">
状态{{ formatClassProgress(classData.classProgress) }}
</div>
</div>
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
<el-form-item label="教学任务业务编号" prop="taskCode">
<el-input class="w-[280px]" v-model="queryParams.taskCode" />
</el-form-item>
<el-form-item label="学期" prop="semesterId">
<el-select v-model="queryParams.semesterId" class="w-[280px]" clearable>
<el-option
v-for="college in getConfigLists.lists"
:key="college.id"
:value="college.id"
:label="college.config"
/>
</el-select>
</el-form-item>
<el-form-item label="课程" prop="courseId">
<el-select
v-model="queryParams.courseId"
placeholder="请输入课程名称搜索"
:remote="true"
:remote-method="handleCourseRemoteSearch"
:loading="courseSearchLoading"
filterable
clearable
remote-show-suffix
class="w-[280px]"
>
<el-option
v-for="item in getCourseLists.lists"
:key="item.id"
:value="item.id"
:label="item.courseName"
>
<template #default>
<span
style="color: var(--el-text-color-secondary); font-size: 13px"
>
{{ item.courseCode }}
</span>
<span style="margin-left: 8px">{{ item.courseName }}</span>
</template>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="教师" prop="teacherId">
<el-select
v-model="queryParams.teacherId"
placeholder="请输入教师名称搜索"
:remote="true"
:remote-method="handleTeacherRemoteSearch"
:loading="teacherSearchLoading"
filterable
clearable
remote-show-suffix
class="w-[280px]"
>
<el-option
v-for="item in getTeacherLists.lists"
:key="item.id"
:value="item.id"
:label="item.name"
>
<template #default>
<span
style="color: var(--el-text-color-secondary); font-size: 13px"
>
{{ item.teacherCode }}
</span>
<span style="margin-left: 8px">{{ item.name }}</span>
</template>
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div>
<el-button v-perms="['task:add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="教学任务业务编号" prop="taskCode" min-width="280" />
<el-table-column label="学期" prop="semesterName" min-width="210" />
<el-table-column label="课程" prop="courseName" min-width="100" />
<el-table-column label="教师" prop="teacherName" min-width="100" />
<el-table-column label="班级" prop="className" min-width="100" />
<el-table-column label="周学时" prop="weeklyHours" min-width="100" />
<el-table-column label="总周数" prop="totalWeeks" min-width="100" />
<el-table-column label="状态" prop="status" min-width="100" />
<el-table-column label="备注" prop="remark" min-width="100" />
<el-table-column label="创建人" prop="createrName" min-width="100" />
<el-table-column label="创建时间" prop="createdTime" min-width="100" />
<el-table-column label="最后更新人" prop="updaterName" min-width="100" />
<el-table-column label="最后更新时间" prop="updatedTime" min-width="100" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['task:edit']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-perms="['task:del']"
type="danger"
link
@click="handleDelete(row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="task">
import { classDetail } from '@/api/class'
import { configLists } from '@/api/config'
import { courseLists } from '@/api/course'
import { taskDelete, taskLists, taskSearch } from '@/api/task'
import { teacherLists } from '@/api/teacher'
import { timeCurrentSemester } from '@/api/time'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const getConfigLists = ref<{
lists: Array<{ id: number; academicYear: string; semesterCode: string; config: string }>
}>({ lists: [] })
const getCourseLists = ref<{
lists: Array<{ id: number; courseName: string; courseCode: string }>
}>({ lists: [] })
const getTeacherLists = ref<{
lists: Array<{ id: number; name: string; teacherCode: string }>
}>({ lists: [] })
const courseSearchLoading = ref(false)
const courseSearchTimer = ref<number | null>(null)
const teacherSearchLoading = ref(false)
const teacherSearchTimer = ref<number | null>(null)
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
const showEdit = ref(false)
const route = useRoute()
const queryParams = reactive({
taskCode: '',
semesterId: '',
courseId: '',
teacherId: '',
classId: '',
weeklyHours: '',
totalWeeks: '',
createdBy: '',
updatedBy: ''
})
const classData = reactive({
classCode: '',
className: '',
classProgress: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: taskLists,
params: queryParams
})
const fetchConfigLists = async () => {
try {
const res = await configLists()
const handleData = JSON.parse(JSON.stringify(res))
handleData.lists = handleData.lists.map((item: any) => ({
...item,
config: `${item.academicYear}${item.semesterCode == 'SPRING' ? ' 春' : ' 秋'}`
}))
getConfigLists.value = handleData
await fetchSemester()
} catch (err) {
feedback.msgError('获取学期列表失败')
}
}
const fetchSemester = async () => {
try {
const res = await timeCurrentSemester()
if (res) {
queryParams.semesterId = res.id
}
} catch (error) {
console.error('获取学期信息失败', error)
}
}
const fetchCourseLists = async (params: string) => {
try {
const res = await courseLists({
courseName: params.trim() //
})
getCourseLists.value = res
} catch (err) {
feedback.msgError('获取课程列表失败')
getCourseLists.value = { lists: [] } //
} finally {
courseSearchLoading.value = false //
}
}
const handleCourseRemoteSearch = (keyword: string) => {
if (courseSearchTimer.value) clearTimeout(courseSearchTimer.value)
courseSearchTimer.value = setTimeout(async () => {
courseSearchLoading.value = true
await fetchCourseLists(keyword)
}, 300)
}
const fetchTeacherLists = async (params: string) => {
try {
const res = await teacherLists({
name: params.trim() //
})
getTeacherLists.value = res
} catch (err) {
feedback.msgError('获取教师列表失败')
getTeacherLists.value = { lists: [] } //
} finally {
teacherSearchLoading.value = false //
}
}
const handleTeacherRemoteSearch = (keyword: string) => {
if (teacherSearchTimer.value) clearTimeout(teacherSearchTimer.value)
teacherSearchTimer.value = setTimeout(async () => {
teacherSearchLoading.value = true
await fetchTeacherLists(keyword)
}, 300)
}
onBeforeUnmount(() => {
if (courseSearchTimer.value) clearTimeout(courseSearchTimer.value)
if (teacherSearchTimer.value) clearTimeout(teacherSearchTimer.value)
})
const getClassDetail = async () => {
try {
console.log('route.query.classId', route.query.classId)
const res = await classDetail({
id: Number(route.query.classId),
semesterId: queryParams.semesterId
})
classData.classCode = res.classCode
classData.className = res.className
const progressRes = await taskSearch({ classId: Number(route.query.classId) })
console.log('progressRes', progressRes)
classData.classProgress = progressRes.arrangementProgress || '暂无进度信息'
} catch (err) {
feedback.msgError('获取班级详情失败')
return null
}
}
const formatClassProgress = (cellValue: any) => {
const statusMap: Record<string, string> = {
draft: '草稿',
confirmed: '确认',
published: '发布',
archived: '归档',
default: '默认'
}
return statusMap[String(cellValue)] || cellValue
}
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
editRef.value?.getClassDetail(Number(route.query.classId))
}
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.getDetail(data)
}
const handleDelete = async (id: number) => {
await feedback.confirm('确定要删除?')
await taskDelete({ id })
feedback.msgSuccess('删除成功')
getLists()
}
fetchConfigLists()
getClassDetail()
fetchCourseLists('')
fetchTeacherLists('')
getLists()
</script>

View File

@ -0,0 +1,65 @@
<template>
<div class="delete-popup">
<popup
ref="popupRef"
title="删除确认"
:async="true"
width="400px"
:clickModalClose="true"
@confirm="handleSubmit"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="120px" :rules="formRules">
<el-form-item label="删除数量" prop="count">
<el-input-number
v-model="formData.count"
placeholder="请输入删除数量"
:min="1"
:max="9999"
/>
</el-form-item>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import { slotDelete } from '@/api/slot'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const formData = reactive({
count: 1
})
const formRules = {
count: [
{ required: true, message: '请输入删除数量', trigger: ['blur'] },
{ type: 'number', min: 1, message: '数量必须大于0', trigger: ['blur'] }
]
}
const handleSubmit = async () => {
await formRef.value?.validate()
await slotDelete({ count: formData.count })
popupRef.value?.close()
feedback.msgSuccess('删除成功')
emit('success')
}
const open = () => {
formRef.value?.resetFields()
popupRef.value?.open()
}
const handleClose = () => {
emit('close')
}
defineExpose({ open })
</script>

View File

@ -0,0 +1,139 @@
<template>
<div class="edit-popup">
<popup
ref="popupRef"
:title="popupTitle"
:async="true"
width="550px"
:clickModalClose="true"
@confirm="handleSubmit"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="164px" :rules="formRules">
<el-form-item label="开始时间" prop="startTime">
<el-time-picker
class="flex-1 !flex"
v-model="formData.startTime"
is-arrow-control
clearable
format="HH:mm"
value-format="HH:mm"
placeholder="请选择开始时间"
/>
</el-form-item>
<el-form-item v-if="mode == 'edit'" label="结束时间" prop="endTime">
<el-time-picker
class="flex-1 !flex"
v-model="formData.endTime"
is-arrow-control
clearable
format="HH:mm"
value-format="HH:mm"
placeholder="请选择结束时间"
/>
</el-form-item>
<el-form-item v-if="mode == 'add'" label="节次时长(分钟)" prop="duration">
<el-input-number v-model="formData.duration" :max="9999" />
</el-form-item>
<el-form-item
v-if="mode == 'add'"
label="节次间隔时长(分钟)"
prop="intervalDuration"
>
<el-input-number v-model="formData.intervalDuration" :max="9999" />
</el-form-item>
<el-form-item v-if="mode == 'add'" label="连续添加节次数量" prop="num">
<el-input-number
v-model="formData.num"
placeholder="请输入连续添加节次数量"
:max="9999"
/>
</el-form-item>
<el-form-item label="是否排课" prop="isScheduled">
<el-switch
v-model="formData.isScheduled"
:active-value="1"
:inactive-value="0"
/>
</el-form-item>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import type { PropType } from 'vue'
import { slotEdit, slotInsert } from '@/api/slot'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑节次' : '新增节次'
})
const formData = reactive({
startTime: '',
endTime: '',
duration: '',
section: '',
intervalDuration: '',
isScheduled: 1,
num: 1
})
const formRules = {
startTime: [
{
required: true,
message: '请选择开始时间',
trigger: ['blur']
}
]
}
const handleSubmit = async () => {
await formRef.value?.validate()
const data: any = { ...formData }
mode.value == 'edit' ? await slotEdit(data) : await slotInsert(data)
popupRef.value?.close()
feedback.msgSuccess('操作成功')
emit('success')
}
const open = (type = 'add', defaultStartTime = '') => {
mode.value = type
formRef.value?.resetFields()
if (type === 'add' && defaultStartTime) {
formData.startTime = defaultStartTime
}
popupRef.value?.open()
}
const setFormData = async (data: Record<string, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
}
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData
})
</script>

View File

@ -129,7 +129,7 @@
/>
</div>
</template>
<script lang="ts" setup name="slot">
<script lang="ts" setup name="slot1">
import { computed, nextTick, reactive, ref, shallowRef } from 'vue'
import { slotLists, slotUniform } from '@/api/slot'
@ -148,7 +148,7 @@ const queryParams = reactive({
slotName: '',
slotType: '',
isScheduled: '',
duration: '',
duration: 40,
intervalDuration: ''
})
@ -275,6 +275,7 @@ getLists()
:deep(.el-table tbody tr:hover > td) {
background-color: transparent !important;
pointer-events: none;
}
.cell-content {

View File

@ -1,3 +0,0 @@
NODE_ENV = 'production'
# Base API
VITE_APP_BASE_URL=''

View File

@ -1,4 +0,0 @@
.vscode
.idea
dist/
node_modules/

View File

@ -1,44 +0,0 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
ignorePatterns: ['/auto-imports.d.ts', '/components.d.ts'],
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript/recommended',
'@vue/eslint-config-prettier',
'./.eslintrc-auto-import.json'
],
plugins: ['simple-import-sort'],
rules: {
'simple-import-sort/imports': 'error', // 强制导入语句排序
'prettier/prettier': [
'warn',
{
semi: false,
singleQuote: true,
printWidth: 100,
proseWrap: 'preserve',
bracketSameLine: false,
endOfLine: 'lf',
tabWidth: 4,
useTabs: false,
trailingComma: 'none'
}
],
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'no-undef': 'off',
'vue/prefer-import-from-vue': 'off',
'no-prototype-builtins': 'off',
'prefer-spread': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off'
},
globals: {
module: 'readonly'
}
}

36
syn/admin/.gitignore vendored
View File

@ -1,36 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
# unplugin-auto-import
auto-imports.d.ts
components.d.ts
.eslintrc-auto-import.json
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# .env
.env.development
.env.production

View File

@ -1,4 +0,0 @@
.vscode
.idea
dist/
node_modules/

View File

@ -1,11 +0,0 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 100,
"proseWrap": "preserve",
"bracketSameLine": false,
"endOfLine": "lf",
"tabWidth": 4,
"useTabs": false,
"trailingComma": "none"
}

View File

@ -1,46 +0,0 @@
# vue-project
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```

View File

@ -1 +0,0 @@
/// <reference types="vite/client" />

View File

@ -1,65 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理系统</title>
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

16723
syn/admin/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
{
"name": "vue-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"dev": "vite",
"preview": "vite preview --port 4173",
"build": "vite build && node scripts/release.mjs",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@highlightjs/vue-plugin": "^2.1.0",
"@vue/shared": "^3.4.38",
"@vueuse/core": "^11.0.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^0.27.2",
"css-color-function": "^1.3.3",
"echarts": "^5.5.1",
"element-plus": "2.2.27",
"highlight.js": "^11.10.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.2.2",
"vue": "^3.4.38",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.7.3",
"vue-router": "^4.4.3",
"vue3-video-play": "1.3.1-beta.6",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.10.4",
"@types/lodash-es": "^4.17.12",
"@types/node": "^16.18.105",
"@types/nprogress": "^0.2.3",
"@vitejs/plugin-legacy": "^2.3.1",
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/tsconfig": "^0.1.3",
"autoprefixer": "^10.4.20",
"consola": "^2.15.3",
"eslint": "^8.57.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^9.27.0",
"execa": "^6.1.0",
"fs-extra": "^10.1.0",
"postcss": "^8.4.41",
"prettier": "^2.8.8",
"sass": "^1.77.8",
"tailwindcss": "^3.4.10",
"terser": "^5.31.6",
"typescript": "~4.7.4",
"unplugin-auto-import": "^0.9.5",
"unplugin-vue-components": "^0.19.9",
"vite": "^3.2.10",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.38.9"
}
}

View File

@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}

View File

@ -1,36 +0,0 @@
import fsExtra from 'fs-extra'
import path from 'path'
const { existsSync, remove, copy } = fsExtra
const cwd = process.cwd()
//打包发布路径,谨慎改动
const releaseRelativePath = '../public/admin'
const distPath = path.resolve(cwd, 'dist')
const releasePath = path.resolve(cwd, releaseRelativePath)
async function build() {
if (existsSync(releasePath)) {
await remove(releasePath)
}
console.log(`文件正在复制 ==> ${releaseRelativePath}`)
try {
await copyFile(distPath, releasePath)
} catch (error) {
console.log(`\n ${error}`)
}
console.log(`文件已复制 ==> ${releaseRelativePath}`)
}
function copyFile(sourceDir, targetDir) {
return new Promise((resolve, reject) => {
copy(sourceDir, targetDir, (err) => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
}
build()

View File

@ -1,48 +0,0 @@
<script setup lang="ts">
import { useDark, useThrottleFn, useWindowSize } from '@vueuse/core'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { ScreenEnum } from './enums/appEnums'
import useAppStore from './stores/modules/app'
import useSettingStore from './stores/modules/setting'
const appStore = useAppStore()
const settingStore = useSettingStore()
const elConfig = {
zIndex: 3000,
locale: zhCn
}
const isDark = useDark()
onMounted(async () => {
//
settingStore.setTheme(isDark.value)
})
const { width } = useWindowSize()
watch(
width,
useThrottleFn((value) => {
if (value > ScreenEnum.SM) {
appStore.setMobile(false)
appStore.toggleCollapsed(false)
} else {
appStore.setMobile(true)
appStore.toggleCollapsed(true)
}
if (value < ScreenEnum.MD) {
appStore.toggleCollapsed(true)
}
}),
{
immediate: true
}
)
</script>
<template>
<el-config-provider :locale="elConfig.locale" :z-index="elConfig.zIndex">
<router-view />
</el-config-provider>
</template>
<style></style>

View File

@ -1,16 +0,0 @@
import request from '@/utils/request'
// 配置
export function getConfig() {
return request.get({ url: '/config/getConfig' })
}
// 工作台主页
export function getWorkbench() {
return request.get({ url: '/workbench/index' })
}
//字典数据
export function getDictData(params: any) {
return request.get({ url: '/config/dict', params })
}

View File

@ -1,10 +0,0 @@
import request from '@/utils/request'
export function getRechargeConfig() {
return request.get({ url: '/recharge.recharge/getConfig' })
}
// 设置
export function setRechargeConfig(params: any) {
return request.post({ url: '/recharge.recharge/setConfig', params })
}

View File

@ -1,69 +0,0 @@
import request from '@/utils/request'
// 文章分类列表
export function articleCateLists(params?: any) {
return request.get({ url: '/article.articleCate/lists', params })
}
// 文章分类列表
export function articleCateAll(params?: any) {
return request.get({ url: '/article.articleCate/all', params })
}
// 添加文章分类
export function articleCateAdd(params: any) {
return request.post({ url: '/article.articleCate/add', params })
}
// 编辑文章分类
export function articleCateEdit(params: any) {
return request.post({ url: '/article.articleCate/edit', params })
}
// 删除文章分类
export function articleCateDelete(params: any) {
return request.post({ url: '/article.articleCate/delete', params })
}
// 文章分类详情
export function articleCateDetail(params: any) {
return request.get({ url: '/article.articleCate/detail', params })
}
// 文章分类状态
export function articleCateStatus(params: any) {
return request.post({ url: '/article.articleCate/updateStatus', params })
}
// 文章列表
export function articleLists(params?: any) {
return request.get({ url: '/article.article/lists', params })
}
// 文章列表
export function articleAll(params?: any) {
return request.get({ url: '/article/all', params })
}
// 添加文章
export function articleAdd(params: any) {
return request.post({ url: '/article.article/add', params })
}
// 编辑文章
export function articleEdit(params: any) {
return request.post({ url: '/article.article/edit', params })
}
// 删除文章
export function articleDelete(params: any) {
return request.post({ url: '/article.article/delete', params })
}
// 文章详情
export function articleDetail(params: any) {
return request.get({ url: '/article.article/detail', params })
}
// 文章分类状态
export function articleStatus(params: any) {
return request.post({ url: '/article.article/updateStatus', params })
}

View File

@ -1,11 +0,0 @@
import request from '@/utils/request'
// H5渠道配置保存
export function setH5Config(params: any) {
return request.post({ url: '/channel.web_page_setting/setConfig', params })
}
// H5渠道配置详情
export function getH5Config() {
return request.get({ url: '/channel.web_page_setting/getConfig' })
}

View File

@ -1,11 +0,0 @@
import request from '@/utils/request'
// 微信开发平台配置保存
export function setOpenSettingConfig(params: any) {
return request.post({ url: '/channel.open_setting/setConfig', params })
}
// 微信开发平台配置详情
export function getOpenSettingConfig() {
return request.get({ url: '/channel.open_setting/getConfig' })
}

View File

@ -1,11 +0,0 @@
import request from '@/utils/request'
// 微信小程序配置保存
export function setWeappConfig(params: any) {
return request.post({ url: '/channel.mnp_settings/setConfig', params })
}
// 微信小程序配置详情
export function getWeappConfig() {
return request.get({ url: '/channel.mnp_settings/getConfig' })
}

View File

@ -1,110 +0,0 @@
import request from '@/utils/request'
// 微信公众号配置保存
export function setOaConfig(params: any) {
return request.post({ url: '/channel.official_account_setting/setConfig', params })
}
// 微信公众号配置详情
export function getOaConfig() {
return request.get({ url: '/channel.official_account_setting/getConfig' })
}
export interface Menu {
name: string
has_menu?: boolean
type?: string
url?: string
appid?: string
pagepath?: string
sub_button: Menu[] | any
}
/**
* @return { Promise }
* @description
*/
export function getOaMenu() {
return request.get({ url: '/channel.official_account_menu/detail' })
}
/**
* @return { Promise }
* @param { Menu } Menu
* @description
*/
export function setOaMenuSave(params: Menu | any) {
return request.post({ url: '/channel.official_account_menu/save', params })
}
/**
* @return { Promise }
* @param { Menu } Menu
* @description
*/
export function setOaMenuPublish(params: Menu | any) {
return request.post({ url: '/channel.official_account_menu/saveAndPublish', params })
}
/**
* @return { Promise }
* @param { string } reply_type
* @description
*/
export function getOaReplyList(params: { reply_type: string }) {
return request.get({ url: '/channel.official_account_reply/lists', params })
}
/**
* @return { Promise }
* @param { number } id
* @description
*/
export function oaReplyDel(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/delete', params })
}
/**
* @return { Promise }
* @param { number } id
* @description
*/
export function changeOaReplyStatus(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/status', params })
}
export interface Reply {
content: string // 内容
content_type: number // 内容类型: 1=文本
keyword?: string // 关键词
matching_type?: number // 匹配方式: [1=全匹配, 2=模糊匹配]
name: string // 规则名称
status: number // 状态: 1=开启, 0=关闭
reply_type: number // 类型: 回复类型 1-关注回复 2-关键词回复 3-默认回复
reply_num: number // 回复数量`
sort: number // 排序
}
/**
* @return { Promise }
* @description
*/
export function oaReplyAdd(params: Reply) {
return request.post({ url: '/channel.official_account_reply/add', params })
}
/**
* @return { Promise }
* @description
*/
export function oaReplyEdit(params: Reply) {
return request.post({ url: '/channel.official_account_reply/edit', params })
}
/**
* @return { Promise }
* @param { string } type
* @description
*/
export function getOaReplyDetail(params: { id: number }) {
return request.get({ url: '/channel.official_account_reply/detail', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 班级列表
export function classLists(params?: Record<string, any>) {
return request.get({ url: '/class/list', params })
}
// 班级详情
export function classDetail(params: Record<string, any>) {
return request.get({ url: '/class/detail', params })
}
// 班级新增
export function classAdd(params: Record<string, any>) {
return request.post({ url: '/class/add', params })
}
// 班级编辑
export function classEdit(params: Record<string, any>) {
return request.post({ url: '/class/edit', params })
}
// 班级删除
export function classDelete(params: Record<string, any>) {
return request.post({ url: '/class/del', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 教室列表
export function classroomLists(params?: Record<string, any>) {
return request.get({ url: '/classroom/list', params })
}
// 教室详情
export function classroomDetail(params: Record<string, any>) {
return request.get({ url: '/classroom/detail', params })
}
// 教室新增
export function classroomAdd(params: Record<string, any>) {
return request.post({ url: '/classroom/add', params })
}
// 教室编辑
export function classroomEdit(params: Record<string, any>) {
return request.post({ url: '/classroom/edit', params })
}
// 教室删除
export function classroomDelete(params: Record<string, any>) {
return request.post({ url: '/classroom/del', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 学院列表
export function collegeLists(params?: Record<string, any>) {
return request.get({ url: '/college/list', params })
}
// 学院详情
export function collegeDetail(params: Record<string, any>) {
return request.get({ url: '/college/detail', params })
}
// 学院新增
export function collegeAdd(params: Record<string, any>) {
return request.post({ url: '/college/add', params })
}
// 学院编辑
export function collegeEdit(params: Record<string, any>) {
return request.post({ url: '/college/edit', params })
}
// 学院删除
export function collegeDelete(params: Record<string, any>) {
return request.post({ url: '/college/del', params })
}

View File

@ -1,21 +0,0 @@
import request from '@/utils/request'
// 用户列表
export function getUserList(params: any) {
return request.get({ url: '/user.user/lists', params }, { ignoreCancelToken: true })
}
// 用户详情
export function getUserDetail(params: any) {
return request.get({ url: '/user.user/detail', params })
}
// 用户编辑
export function userEdit(params: any) {
return request.post({ url: '/user.user/edit', params })
}
// 用户编辑
export function adjustMoney(params: any) {
return request.post({ url: '/user.user/adjustMoney', params })
}

View File

@ -1,59 +0,0 @@
import request from '@/utils/request'
// 课程列表
export function courseLists(params?: Record<string, any>) {
return request.get({ url: '/course/list', params })
}
// 课程详情
export function courseDetail(params: Record<string, any>) {
return request.get({ url: '/course/detail', params })
}
// 课程新增
export function courseAdd(params: Record<string, any>) {
return request.post({ url: '/course/add', params })
}
// 课程编辑
export function courseEdit(params: Record<string, any>) {
return request.post({ url: '/course/edit', params })
}
// 课程删除
export function courseDelete(params: Record<string, any>) {
return request.post({ url: '/course/del', params })
}
// 获取导入模板
export function courseTemplate() {
return request.get({ url: '/course/template' })
}
// 上传导入模板
export function courseUpTemplate(formData: FormData) {
return request.post({
url: '/course/upload.template',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
// 上传导入文件
export function courseUploadFile(formData: FormData) {
return request.post(
{
url: '/course/batch.add',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
},
{
// 配置返回完整响应对象包含服务器返回的code
isReturnDefaultResponse: true
}
)
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 课程类型列表
export function typeLists(params?: Record<string, any>) {
return request.get({ url: '/course.type/list', params })
}
// 课程类型详情
export function typeDetail(params: Record<string, any>) {
return request.get({ url: '/course.type/detail', params })
}
// 课程类型新增
export function typeAdd(params: Record<string, any>) {
return request.post({ url: '/course.type/add', params })
}
// 课程类型编辑
export function typeEdit(params: Record<string, any>) {
return request.post({ url: '/course.type/edit', params }, { isTransformResponse: false })
}
// 课程类型删除
export function typeDelete(params: Record<string, any>) {
return request.post({ url: '/course.type/del', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 专业培养计划列表
export function curriculumLists(params?: Record<string, any>) {
return request.get({ url: '/curriculum/list', params })
}
// 专业培养计划详情
export function curriculumDetail(params: Record<string, any>) {
return request.get({ url: '/curriculum/detail', params })
}
// 专业培养计划新增
export function curriculumAdd(params: Record<string, any>) {
return request.post({ url: '/curriculum/add', params })
}
// 专业培养计划编辑
export function curriculumEdit(params: Record<string, any>) {
return request.post({ url: '/curriculum/edit', params })
}
// 专业培养计划删除
export function curriculumDelete(params: Record<string, any>) {
return request.post({ url: '/curriculum/del', params })
}

View File

@ -1,31 +0,0 @@
import request from '@/utils/request'
// 页面装修详情
export function getDecoratePages(params: any) {
return request.get({ url: '/decorate.page/detail', params }, { ignoreCancelToken: true })
}
// 页面装修保存
export function setDecoratePages(params: any) {
return request.post({ url: '/decorate.page/save', params })
}
// 获取首页文章数据
export function getDecorateArticle(params?: any) {
return request.get({ url: '/decorate.data/article', params })
}
// 底部导航详情
export function getDecorateTabbar(params?: any) {
return request.get({ url: '/decorate.tabbar/detail', params })
}
// 底部导航保存
export function setDecorateTabbar(params: any) {
return request.post({ url: '/decorate.tabbar/save', params })
}
// pc装修数据
export function getDecoratePc() {
return request.get({ url: '/decorate.data/pc' })
}

View File

@ -1,42 +0,0 @@
import request from '@/utils/request'
export function fileCateAdd(params: Record<string, any>) {
return request.post({ url: '/file/addCate', params })
}
export function fileCateEdit(params: Record<string, any>) {
return request.post({ url: '/file/editCate', params })
}
// 文件分类删除
export function fileCateDelete(params: Record<string, any>) {
return request.post({ url: '/file/delCate', params })
}
// 文件分类列表
export function fileCateLists(params: Record<string, any>) {
return request.get({ url: '/file/listCate', params })
}
// 文件列表
export function fileList(params: Record<string, any>) {
return request.get(
{ url: '/file/lists', params },
{ ignoreCancelToken: true, isOpenRetry: false }
)
}
// 文件删除
export function fileDelete(params: Record<string, any>) {
return request.post({ url: '/file/delete', params })
}
// 文件移动
export function fileMove(params: Record<string, any>) {
return request.post({ url: '/file/move', params })
}
// 文件重命名
export function fileRename(params: { id: number; name: string }) {
return request.post({ url: '/file/rename', params })
}

View File

@ -1,41 +0,0 @@
import request from '@/utils/request'
// 余额明细
export function accountLog(params?: any) {
return request.get({ url: '/finance.account_log/lists', params })
}
// 充值记录
export function rechargeLists(params?: any) {
return request.get({ url: '/recharge.recharge/lists', params }, { ignoreCancelToken: true })
}
// 余额变动类型
export function getUmChangeType(params?: any) {
return request.get({ url: '/finance.account_log/getUmChangeType', params })
}
//退款
export function refund(params?: any) {
return request.post({ url: '/recharge.recharge/refund', params })
}
//重新退款
export function refundAgain(params?: any) {
return request.post({ url: '/recharge.recharge/refundAgain', params })
}
//退款记录
export function refundRecord(params?: any) {
return request.get({ url: '/finance.refund/record', params })
}
//退款日志
export function refundLog(params?: any) {
return request.get({ url: '/finance.refund/log', params })
}
//退款统计
export function refundStat(params?: any) {
return request.get({ url: '/finance.refund/stat', params })
}

View File

@ -1,31 +0,0 @@
import request from '@/utils/request'
// 学生信息列表
export function infoLists(params?: Record<string, any>) {
return request.get({ url: '/info/list', params })
}
// 学生信息详情
export function infoDetail(params: Record<string, any>) {
return request.get({ url: '/info/detail', params })
}
// 学生信息新增
export function infoAdd(params: Record<string, any>) {
return request.post({ url: '/info/add', params })
}
// 学生信息编辑
export function infoEdit(params: Record<string, any>) {
return request.post({ url: '/info/edit', params })
}
// 学生信息删除
export function infoDelete(params: Record<string, any>) {
return request.post({ url: '/info/del', params })
}
// 添加随机学生(测试用)
export function infoAddStudent(params: Record<string, any>) {
return request.post({ url: '/info/create.random.info', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 专业列表
export function majorLists(params?: Record<string, any>) {
return request.get({ url: '/major/list', params })
}
// 专业详情
export function majorDetail(params: Record<string, any>) {
return request.get({ url: '/major/detail', params })
}
// 专业新增
export function majorAdd(params: Record<string, any>) {
return request.post({ url: '/major/add', params })
}
// 专业编辑
export function majorEdit(params: Record<string, any>) {
return request.post({ url: '/major/edit', params })
}
// 专业删除
export function majorDelete(params: Record<string, any>) {
return request.post({ url: '/major/del', params })
}

View File

@ -1,31 +0,0 @@
import request from '@/utils/request'
// 通知设置列表
export function noticeLists(params: any) {
return request.get({ url: '/notice.notice/settingLists', params })
}
// 通知设置详情
export function noticeDetail(params: any) {
return request.get({ url: '/notice.notice/detail', params })
}
// 通知设置保存
export function setNoticeConfig(params: any) {
return request.post({ url: '/notice.notice/set', params })
}
// 短信设置列表
export function smsLists() {
return request.get({ url: '/notice.sms_config/getConfig' })
}
// 短信设置详情
export function smsDetail(params: any) {
return request.get({ url: '/notice.sms_config/detail', params })
}
// 短信设置保存
export function setSmsConfig(params: any) {
return request.post({ url: '/notice.sms_config/setConfig', params })
}

View File

@ -1,31 +0,0 @@
import request from '@/utils/request'
// 部门列表
export function deptLists(params?: any) {
return request.get({ url: '/dept.dept/lists', params })
}
// 添加部门
export function deptAdd(params: any) {
return request.post({ url: '/dept.dept/add', params })
}
// 编辑部门
export function deptEdit(params: any) {
return request.post({ url: '/dept.dept/edit', params })
}
// 删除部门
export function deptDelete(params: any) {
return request.post({ url: '/dept.dept/delete', params })
}
// 部门详情
export function deptDetail(params: any) {
return request.get({ url: '/dept.dept/detail', params })
}
// 部门列表全部
export function deptAll() {
return request.get({ url: '/dept.dept/all' })
}

View File

@ -1,31 +0,0 @@
import request from '@/utils/request'
// 岗位列表
export function jobsLists(params: any) {
return request.get({ url: '/dept.jobs/lists', params }, { ignoreCancelToken: true })
}
// 岗位列表全部
export function jobsAll(params: any) {
return request.get({ url: '/dept.jobs/all', params })
}
// 添加岗位
export function jobsAdd(params: any) {
return request.post({ url: '/dept.jobs/add', params })
}
// 编辑岗位
export function jobsEdit(params: any) {
return request.post({ url: '/dept.jobs/edit', params })
}
// 删除岗位
export function jobsDelete(params: any) {
return request.post({ url: '/dept.jobs/delete', params })
}
// 岗位详情
export function jobsDetail(params: any) {
return request.get({ url: '/dept.jobs/detail', params })
}

View File

@ -1,29 +0,0 @@
import request from '@/utils/request'
// 管理员列表
export function adminLists(params: any) {
return request.get({ url: '/auth.admin/lists', params }, { ignoreCancelToken: true })
}
// 管理员列表全部
export function adminAll(params: any) {
return request.get({ url: '/auth.admin/all', params })
}
// 管理员添加
export function adminAdd(params: any) {
return request.post({ url: '/auth.admin/add', params })
}
// 管理员编辑
export function adminEdit(params: any) {
return request.post({ url: '/auth.admin/edit', params })
}
// 管理员删除
export function adminDelete(params: any) {
return request.post({ url: '/auth.admin/delete', params })
}
// 管理员详情
export function adminDetail(params: any) {
return request.get({ url: '/auth.admin/detail', params })
}

View File

@ -1,36 +0,0 @@
import request from '@/utils/request'
// 菜单列表
export function menuLists(params: Record<string, any>) {
return request.get({ url: '/auth.menu/lists', params })
}
// 菜单全部
export function menuAll(params?: Record<string, any>) {
return request.get({ url: '/auth.menu/all', params })
}
// 添加菜单
export function menuAdd(params: Record<string, any>) {
return request.post({ url: '/auth.menu/add', params })
}
// 编辑菜单
export function menuEdit(params: Record<string, any>) {
return request.post({ url: '/auth.menu/edit', params })
}
// 菜单删除
export function menuDelete(params: Record<string, any>) {
return request.post({ url: '/auth.menu/delete', params })
}
// 菜单详情
export function menuDetail(params: Record<string, any>) {
return request.get({ url: '/auth.menu/detail', params })
}
// 菜单列表
export function systemMenuLists(params: Record<string, any>) {
return request.get({ url: '/auth.menu/systemMenuLists', params })
}

View File

@ -1,27 +0,0 @@
import request from '@/utils/request'
// 角色列表
export function roleLists(params: any) {
return request.get({ url: '/auth.role/lists', params })
}
// 角色列表全部
export function roleAll(params: any) {
return request.get({ url: '/auth.role/all', params })
}
// 添加角色
export function roleAdd(params: any) {
return request.post({ url: '/auth.role/add', params })
}
// 编辑角色
export function roleEdit(params: any) {
return request.post({ url: '/auth.role/edit', params })
}
// 删除角色
export function roleDelete(params: any) {
return request.post({ url: '/auth.role/delete', params })
}
// 角色详情
export function roleDetail(params: any) {
return request.get({ url: '/auth.role/detail', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 设备要求列表
export function requirementLists(params?: Record<string, any>) {
return request.get({ url: '/requirement/list', params })
}
// 设备要求详情
export function requirementDetail(params: Record<string, any>) {
return request.get({ url: '/requirement/detail', params })
}
// 设备要求新增
export function requirementAdd(params: Record<string, any>) {
return request.post({ url: '/requirement/add', params })
}
// 设备要求编辑
export function requirementEdit(params: Record<string, any>) {
return request.post({ url: '/requirement/edit', params })
}
// 设备要求删除
export function requirementDelete(params: Record<string, any>) {
return request.post({ url: '/requirement/del', params })
}

View File

@ -1,61 +0,0 @@
import request from '@/utils/request'
// 字典类型列表
export function dictTypeLists(params: any) {
return request.get({ url: '/setting.dict.dict_type/lists', params })
}
// 字典类型列表全部
export function dictTypeAll(params: any) {
return request.get({ url: '/setting.dict.dict_type/all', params })
}
// 添加字典类型
export function dictTypeAdd(params: any) {
return request.post({ url: '/setting.dict.dict_type/add', params })
}
// 编辑字典类型
export function dictTypeEdit(params: any) {
return request.post({ url: '/setting.dict.dict_type/edit', params })
}
// 删除字典类型
export function dictTypeDelete(params: any) {
return request.post({ url: '/setting.dict.dict_type/delete', params })
}
// 字典类型详情
export function dictTypeDetail(params: any) {
return request.get({ url: '/setting.dict.dict_type/detail', params })
}
// 字典数据列表
export function dictDataLists(params: any) {
return request.get(
{ url: '/setting.dict.dict_data/lists', params },
{
ignoreCancelToken: true
}
)
}
// 添加字典数据
export function dictDataAdd(params: any) {
return request.post({ url: '/setting.dict.dict_data/add', params })
}
// 编辑字典数据
export function dictDataEdit(params: any) {
return request.post({ url: '/setting.dict.dict_data/edit', params })
}
// 删除字典数据
export function dictDataDelete(params: any) {
return request.post({ url: '/setting.dict.dict_data/delete', params })
}
// 字典数据详情
export function dictDataDetail(params: any) {
return request.get({ url: '/setting.dict.dict_data/detail', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 获取支付方式
export function getPayWay() {
return request.get({ url: '/setting.pay.pay_way/getPayWay' })
}
// 设置支付方式
export function setPayWay(params: any) {
return request.post({ url: '/setting.pay.pay_way/setPayWay', params })
}
// 获取支付方式
export function getPayConfigLists() {
return request.get({ url: '/setting.pay.pay_config/lists' })
}
// 设置支付方式
export function setPayConfig(params: any) {
return request.post({ url: '/setting.pay.pay_config/setConfig', params })
}
// 设置支付方式
export function getPayConfig(params: any) {
return request.get({ url: '/setting.pay.pay_config/getConfig', params })
}

View File

@ -1,27 +0,0 @@
import request from '@/utils/request'
/**
* @return { Promise }
* @description
*/
export function getSearch() {
return request.get({ url: '/setting.hot_search/getConfig' })
}
export interface List {
name: string // 搜索关键字
sort: number // 热门搜索排序
}
export interface Search {
status: number // 是否开启搜索0/1
data: List[]
}
/**
* @return { Promise }
* @param { Search } Search
* @description
*/
export function setSearch(params: Search) {
return request.post({ url: '/setting.hot_search/setConfig', params })
}

View File

@ -1,21 +0,0 @@
import request from '@/utils/request'
// 获取存储引擎列表
export function storageLists() {
return request.get({ url: '/setting.storage/lists' })
}
// 设置存储引擎信息
export function storageChange(params: any) {
return request.post({ url: '/setting.storage/change', params })
}
// 设置存储引擎信息
export function storageSetup(params: any) {
return request.post({ url: '/setting.storage/setup', params })
}
// 获取存储配置信息
export function storageDetail(params: any) {
return request.get({ url: '/setting.storage/detail', params })
}

View File

@ -1,51 +0,0 @@
import request from '@/utils/request'
// 获取系统环境
export function systemInfo() {
return request.get({ url: '/setting.system.system/info' })
}
// 获取系统日志列表
export function systemLogLists(params: any) {
return request.get({ url: '/setting.system.log/lists', params }, { ignoreCancelToken: true })
}
// 清除系统缓存
export function systemCacheClear() {
return request.post({ url: '/setting.system.cache/clear' })
}
// 定时任务列表
export function crontabLists(params: any) {
return request.get({ url: '/crontab.crontab/lists', params })
}
// 添加定时任务
export function crontabAdd(params: any) {
return request.post({ url: '/crontab.crontab/add', params })
}
// 定时任务详情
export function crontabDetail(params: any) {
return request.get({ url: '/crontab.crontab/detail', params })
}
// 编辑定时任务
export function crontabEdit(params: any) {
return request.post({ url: '/crontab.crontab/edit', params })
}
// 删除定时任务
export function crontabDel(params: any) {
return request.post({ url: '/crontab.crontab/delete', params })
}
// 获取规则执行时间
export function crontabExpression(params: any) {
return request.get({ url: '/crontab.crontab/expression', params })
}
// 操作定时任务
export function srontabOperate(params: any) {
return request.post({ url: '/crontab.crontab/operate', params })
}

View File

@ -1,43 +0,0 @@
import request from '@/utils/request'
/**
* @return { Promise }
* @description
*/
export function getUserSetup() {
return request.get({ url: '/setting.user.user/getConfig' })
}
/**
* @return { Promise }
* @param { string } default_avatar
* @description
*/
export function setUserSetup(params: { default_avatar: string }) {
return request.post({ url: '/setting.user.user/setConfig', params })
}
/**
* @return { Promise }
* @description
*/
export function getLogin() {
return request.get({ url: '/setting.user.user/getRegisterConfig' })
}
export interface LoginSetup {
login_way: number[] | any // 登录方式, 逗号隔开
coerce_mobile: number // 强制绑定手机 0/1
login_agreement: number // 是否开启协议 0/1
third_auth: number // 第三方登录 0/1
wechat_auth: number // 微信授权登录 0-关闭 1-开启
qq_auth: number // qq授权登录 0-关闭 1-开启
}
/**
* @return { Promise }
* @param { LoginSetup } LoginSetup
* @description
*/
export function setLogin(params: LoginSetup) {
return request.post({ url: '/setting.user.user/setRegisterConfig', params })
}

View File

@ -1,36 +0,0 @@
import request from '@/utils/request'
// 获取备案信息
export function getCopyright() {
return request.get({ url: '/setting.web.web_setting/getCopyright' })
}
// 设置备案信息
export function setCopyright(params: any) {
return request.post({ url: '/setting.web.web_setting/setCopyright', params })
}
// 获取网站信息
export function getWebsite() {
return request.get({ url: '/setting.web.web_setting/getWebsite' })
}
// 设置网站信息
export function setWebsite(params: any) {
return request.post({ url: '/setting.web.web_setting/setWebsite', params })
}
// 获取政策协议
export function getProtocol() {
return request.get({ url: '/setting.web.web_setting/getAgreement' })
}
// 设置政策协议
export function setProtocol(params: any) {
return request.post({ url: '/setting.web.web_setting/setAgreement', params })
}
// 获取站点统计信息
export function getSiteStatistics() {
return request.get({ url: '/setting.web.web_setting/getSiteStatistics' })
}
// 设置网站信息
export function setSiteStatistics(params: any) {
return request.post({ url: '/setting.web.web_setting/setSiteStatistics', params })
}

View File

@ -1,41 +0,0 @@
import request from '@/utils/request'
// 教师信息扩展列表
export function teacherLists(params?: Record<string, any>) {
return request.get({ url: '/teacher/list', params })
}
// 教师信息扩展详情
export function teacherDetail(params: Record<string, any>) {
return request.get({ url: '/teacher/detail', params })
}
// 教师信息扩展新增
export function teacherAdd(params: Record<string, any>) {
return request.post({ url: '/teacher/add', params })
}
// 教师信息扩展编辑
export function teacherEdit(params: Record<string, any>) {
return request.post({ url: '/teacher/edit', params })
}
// 教师信息扩展删除
export function teacherDelete(params: Record<string, any>) {
return request.post({ url: '/teacher/del', params })
}
// 教师可授课程列表
export function teacherCourseList(params: Record<string, any>) {
return request.get({ url: '/teacher/course/list', params })
}
// 教师可授课程新增
export function teacherCourseAdd(params: Record<string, any>) {
return request.post({ url: '/teacher/course/add', params })
}
// 教师可授课程删除
export function teacherCourseDelete(params: Record<string, any>) {
return request.post({ url: '/teacher/course/del', params })
}

View File

@ -1,75 +0,0 @@
import request from '@/utils/request'
// 代码生成已选数据表列表接口
export function generateTable(params: any) {
return request.get({ url: '/gen/list', params })
}
// 数据表列表接口
export function dataTable(params: any) {
return request.get({ url: '/gen/db', params })
}
// 数据表所有列表接口
export function dataTableAll() {
return request.get({ url: '/gen/dbAll' })
}
//表名查字段
export function dataTableToColumn(params: any) {
return request.get({ url: '/gen/dbColumn', params })
}
//选择要生成代码的数据表
export function selectTable(params: any) {
return request.post(
{ url: '/gen/importTable', params },
{
isParamsToData: false
}
)
}
// 已选择的数据表详情
export function tableDetail(params: any) {
return request.get({ url: '/gen/detail', params })
}
//同步字段
export function syncColumn(params: any) {
return request.post(
{ url: '/gen/syncTable', params },
{
isParamsToData: false
}
)
}
//删除已选择的数据表
export function generateDelete(params: any) {
return request.post({ url: '/gen/delTable', params })
}
//编辑已选表字段
export function generateEdit(params: any) {
return request.post({ url: '/gen/editTable', params })
}
//预览代码
export function generatePreview(params: any) {
return request.get({ url: '/gen/previewCode', params })
}
//生成代码
export function generateCode(params: any) {
return request.get({ url: '/gen/genCode', params })
}
//下载代码
export function downloadCode(params: any) {
return request.get(
{ responseType: 'blob', url: '/gen/downloadCode', params },
{
isTransformResponse: false
}
)
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 教室类型列表
export function typeLists(params?: Record<string, any>) {
return request.get({ url: '/type/list', params })
}
// 教室类型详情
export function typeDetail(params: Record<string, any>) {
return request.get({ url: '/type/detail', params })
}
// 教室类型新增
export function typeAdd(params: Record<string, any>) {
return request.post({ url: '/type/add', params })
}
// 教室类型编辑
export function typeEdit(params: Record<string, any>) {
return request.post({ url: '/type/edit', params })
}
// 教室类型删除
export function typeDelete(params: Record<string, any>) {
return request.post({ url: '/type/del', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 教师不可用时间列表
export function unavailableLists(params?: Record<string, any>) {
return request.get({ url: '/unavailable/list', params })
}
// 教师不可用时间详情
export function unavailableDetail(params: Record<string, any>) {
return request.get({ url: '/unavailable/detail', params })
}
// 教师不可用时间新增
export function unavailableAdd(params: Record<string, any>) {
return request.post({ url: '/unavailable/add', params })
}
// 教师不可用时间编辑
export function unavailableEdit(params: Record<string, any>) {
return request.post({ url: '/unavailable/edit', params })
}
// 教师不可用时间删除
export function unavailableDelete(params: Record<string, any>) {
return request.post({ url: '/unavailable/del', params })
}

View File

@ -1,22 +0,0 @@
import config from '@/config'
import request from '@/utils/request'
// 登录
export function login(params: Record<string, any>) {
return request.post({ url: '/login/account', params: { ...params, terminal: config.terminal } })
}
// 退出登录
export function logout() {
return request.post({ url: '/login/logout' })
}
// 用户信息
export function getUserInfo() {
return request.get({ url: '/auth.admin/mySelf' })
}
// 编辑管理员信息
export function setUserInfo(params: any) {
return request.post({ url: '/auth.admin/editSelf', params })
}

View File

@ -1,26 +0,0 @@
import request from '@/utils/request'
// 培养方案版本列表
export function versionLists(params?: Record<string, any>) {
return request.get({ url: '/version/list', params })
}
// 培养方案版本详情
export function versionDetail(params: Record<string, any>) {
return request.get({ url: '/version/detail', params })
}
// 培养方案版本新增
export function versionAdd(params: Record<string, any>) {
return request.post({ url: '/version/add', params })
}
// 培养方案版本编辑
export function versionEdit(params: Record<string, any>) {
return request.post({ url: '/version/edit', params })
}
// 培养方案版本删除
export function versionDelete(params: Record<string, any>) {
return request.post({ url: '/version/del', params })
}

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M502.869333 201.408a32.853333 32.853333 0 0 1 0 45.44L276.906667 480h544.384a32 32 0 0 1 0 64H276.885333l225.984 233.130667a32.853333 32.853333 0 0 1 0 45.44 30.485333 30.485333 0 0 1-44.053333 0L179.776 534.741333a32.128 32.128 0 0 1-6.848-10.688 32.213333 32.213333 0 0 1-0.085333-23.808l0.106666-0.32c1.514667-3.861333 3.797333-7.488 6.826667-10.624L458.837333 201.386667a30.485333 30.485333 0 0 1 44.053334 0z" /></svg>

Before

Width:  |  Height:  |  Size: 689 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M853.333333 170.666667a85.333333 85.333333 0 0 1 85.333334 85.333333v426.666667a85.333333 85.333333 0 0 1-85.333334 85.333333H576v42.666667h74.666667a32 32 0 0 1 0 64h-277.333334a32 32 0 0 1 0-64H448v-42.666667H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333333V256a85.333333 85.333333 0 0 1 85.333334-85.333333h682.666666z m-127.957333 213.333333c-37.056 0.277333-77.824 17.258667-77.824 58.666667 0 45.12 37.909333 56.042667 78.976 60.928 26.709333 2.88 46.506667 10.666667 46.506667 29.632 0 21.845333-22.4 30.186667-46.229334 30.186666-24.405333 0-47.658667-9.792-56.576-31.914666l-31.573333 16.384c14.933333 36.8 46.506667 49.450667 87.573333 49.450666 44.8 0 84.437333-19.264 84.437334-64.106666 0-46.506667-36.650667-58.24-77.056-63.616l-3.925334-0.512c-24.106667-2.88-44.8-7.765333-44.8-25.301334 0-14.933333 13.504-26.730667 41.642667-26.730666 21.824 0 40.768 10.922667 47.658667 22.421333l30.165333-15.530667C789.12 392.917333 756.672 384 725.376 384z m-280 7.189333H401.706667v201.258667h37.909333v-146.346667l64.042667 87.68h7.466666l65.472-87.381333v146.048h37.909334v-201.258667h-43.370667l-62.890667 86.549334-62.890666-86.549334z m-194.133333-0.298666H213.333333v201.258666h37.909334V503.04l84.138666 89.109333h46.805334v-2.282666l-96.768-101.504 89.301333-96.32v-1.152h-47.082667l-76.394666 85.12v-85.12z" /></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M385.6 371.242667c12.16 113.578667 92.906667 206.634667 200 236.949333l1.664 0.448-2.453333 2.005333-317.888 237.418667c-12.16 9.066667-28.8 8.533333-40.32-0.917333l-2.410667-2.154667-28.928-28.885333c0.213333 1.898667 0.490667 3.797333 0.810667 5.717333 6.186667 35.754667 31.338667 57.962667 79.808 49.322667 26.986667-4.821333 44.117333-11.242667 63.509333-22.464l6.336-3.776 11.541333-7.168 5.397334-3.285334c35.562667-21.248 64.96-29.909333 117.973333-30.442666 69.909333-0.704 129.088 21.056 175.701333 65.173333a32.853333 32.853333 0 0 1 1.28 46.4 32.746667 32.746667 0 0 1-46.293333 1.28c-33.898667-32.042667-76.608-47.744-130.026667-47.210667-40.597333 0.426667-59.029333 5.632-84.864 21.056l-17.642666 10.88c-28.266667 17.216-53.461333 27.413333-91.413334 34.176-87.808 15.658667-144-33.92-155.882666-102.741333a151.765333 151.765333 0 0 1 4.522666-72.042667l1.066667-2.965333-20.778667-20.736a32.853333 32.853333 0 0 1-3.968-41.706667l2.048-2.688 268.437334-318.72c0.874667-1.045333 1.813333-2.005333 2.773333-2.922666z m4.181333 169.344l-2.474666 2.24-46.357334 46.421333-2.24 2.496a32.853333 32.853333 0 0 0 2.24 43.925333 32.746667 32.746667 0 0 0 43.861334 2.24l2.496-2.24 46.336-46.421333 2.261333-2.496a32.853333 32.853333 0 0 0-2.261333-43.925333 32.746667 32.746667 0 0 0-43.861334-2.24zM661.333333 85.333333c141.376 0 256 114.624 256 256s-114.624 256-256 256-256-114.624-256-256S519.957333 85.333333 661.333333 85.333333z" /></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M579.2 874.666667a21.333333 21.333333 0 0 1 14.421333 37.056C574.037333 929.685333 546.837333 938.666667 512 938.666667s-62.037333-8.981333-81.621333-26.944A21.333333 21.333333 0 0 1 444.821333 874.666667h134.357334z m28.8-85.333334a32 32 0 0 1 0 64h-192a32 32 0 0 1 0-64h192zM512 85.333333c176.725333 0 320 143.274667 320 320 0 114.090667-59.733333 214.250667-149.610667 270.912A85.333333 85.333333 0 0 1 597.333333 768h-170.666666a85.333333 85.333333 0 0 1-85.098667-91.776C251.733333 619.584 192 519.424 192 405.333333c0-176.725333 143.274667-320 320-320z m29.098667 106.666667a29.098667 29.098667 0 1 0 0 58.176 126.08 126.08 0 0 1 126.058666 126.08 29.098667 29.098667 0 1 0 58.176 0A184.234667 184.234667 0 0 0 541.098667 192z" /></svg>

Before

Width:  |  Height:  |  Size: 1008 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m25.408 67.178667l-1.792 1.450666c-52.693333 41.813333-163.456 91.882667-290.389334 109.802667l-4.416 0.597333v342.976l0.149334 5.866667c0.746667 15.104 4.864 29.866667 12.074666 43.221333 80.96 149.845333 188.714667 201.962667 278.826667 204.544l5.568 0.085334c92.522667 0 201.92-51.989333 284.373333-204.629334a101.546667 101.546667 0 0 0 12.224-48.277333V276.245333l-16.277333-2.325333c-120.938667-18.048-227.904-67.690667-278.954667-108.416l-1.386666-1.109333z m161.194666 250.517333a32.853333 32.853333 0 0 1 0 46.186667l-187.306666 190.656a32.256 32.256 0 0 1-45.845334 0l-89.173333-91.157334a32.853333 32.853333 0 0 1 0-46.208 32.256 32.256 0 0 1 45.845333 0l51.029334 52.416a21.333333 21.333333 0 0 0 30.165333 0.426667l0.341333-0.362667 149.077334-151.957333a32.256 32.256 0 0 1 45.866666 0z" /></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m186.602666 317.696a32.256 32.256 0 0 0-45.866666 0l-149.077334 151.957333-0.341333 0.341334a21.333333 21.333333 0 0 1-30.165333-0.405334l-51.029334-52.416a32.256 32.256 0 0 0-45.866666 0 32.853333 32.853333 0 0 0 0 46.208l89.194666 91.157334a32.256 32.256 0 0 0 45.866667 0l187.285333-190.656a32.853333 32.853333 0 0 0 0-46.186667z" /></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m186.602666 317.696a32.256 32.256 0 0 0-45.866666 0l-149.077334 151.957333-0.341333 0.341334a21.333333 21.333333 0 0 1-30.165333-0.405334l-51.029334-52.416a32.256 32.256 0 0 0-45.866666 0 32.853333 32.853333 0 0 0 0 46.208l89.194666 91.157334a32.256 32.256 0 0 0 45.866667 0l187.285333-190.656a32.853333 32.853333 0 0 0 0-46.186667z" /></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 107.136v707.093333l-221.248 99.434667a32 32 0 0 1-44.586667-34.986667l41.834667-227.413333-182.826667-195.84a32 32 0 0 1 18.474667-53.461333l228.586667-35.733334 141.226666-248.298666A21.333333 21.333333 0 0 1 512 107.136z" /></svg>

Before

Width:  |  Height:  |  Size: 503 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m-10.026667 256.213333h-122.090667v346.026667h38.442667V389.845333h45.205333c-9.045333 30.997333-21.845333 65.493333-38.058666 104.234667 24.490667 32.170667 36.906667 61.226667 36.906666 87.189333 0 6.186667-1.493333 10.453333-4.117333 12.8-3.029333 2.304-9.045333 3.861333-17.706667 4.629334-5.290667 0-12.053333-0.768-20.352-2.325334l12.437334 40.32c26.752-0.405333 45.589333-5.44 56.874666-15.509333 7.552-8.149333 11.306667-21.333333 11.306667-39.914667-2.261333-26.346667-14.293333-57.344-36.906667-93.397333a1520.768 1520.768 0 0 0 38.037334-104.234667v-30.208z m155.946667 148.8c-11.306667 58.112-24.106667 107.306667-39.168 147.626667h-132.608v38.741333h226.773333v-38.741333h-55.744c15.445333-40.32 28.629333-85.632 39.189333-136.789333l-38.442666-10.837334z m-121.685334 11.221334l-33.514666 11.626666c12.8 34.88 23.722667 71.68 32 110.058667l33.92-8.533333c-9.813333-42.624-20.352-80.213333-32.405334-113.152z m59.904-13.952l-33.514666 11.626666c11.306667 33.706667 20.330667 68.970667 27.861333 106.176l33.536-8.917333c-8.277333-41.066667-17.322667-77.098667-27.882667-108.885333z m21.12-158.869334h-34.688c-23.338667 51.541333-57.258667 93.397333-101.333333 125.930667l19.968 31.786667c13.568-9.685333 26.752-20.928 39.189333-33.322667v20.522667h120.533334v-19.370667a338.133333 338.133333 0 0 0 38.826666 32.554667l21.461334-33.706667c-49.344-35.648-84.010667-77.12-103.978667-124.373333z m-17.344 39.530667a279.530667 279.530667 0 0 0 44.821334 68.970667h-90.026667a370.410667 370.410667 0 0 0 45.205333-68.970667z" /></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M789.333333 486.250667V746.666667c0 58.901333-124.16 106.666667-277.333333 106.666666-150.570667 0-273.109333-46.144-277.226667-103.68L234.666667 746.666667V486.250667l260.053333 115.285333a42.666667 42.666667 0 0 0 30.848 1.450667l3.733333-1.450667L789.333333 486.250667zM529.28 166.464l398.592 176.704a21.333333 21.333333 0 0 1 0 38.997333L874.666667 405.76 874.666667 603.093333A42.666667 42.666667 0 1 1 832 603.029333v-178.410666l-302.72 134.229333a42.666667 42.666667 0 0 1-34.56 0L96.106667 382.165333a21.333333 21.333333 0 0 1 0-38.997333l398.570666-176.704a42.666667 42.666667 0 0 1 34.602667 0z" /></svg>

Before

Width:  |  Height:  |  Size: 880 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M864 832a32 32 0 0 1 0 64h-704a32 32 0 0 1 0-64h704zM710.613333 152.533333l3.541334 3.413334 89.92 89.898666a95.36 95.36 0 0 1 3.370666 131.285334l-3.370666 3.562666-332.309334 332.309334c-9.386667 9.386667-21.077333 16.042667-33.856 19.349333l-4.842666 1.088-178.261334 33.642667a52.970667 52.970667 0 0 1-62.464-57.984l0.576-3.904L226.56 526.933333c2.453333-13.013333 8.362667-25.130667 17.045333-35.072l3.392-3.626666L579.306667 155.946667a95.36 95.36 0 0 1 131.285333-3.370667z m-83.946666 46.165334l-2.410667 2.176-332.309333 332.309333a10.602667 10.602667 0 0 0-2.517334 3.989333l-0.405333 1.536-30.741333 162.986667 119.978666-22.634667-51.968-51.968a31.786667 31.786667 0 1 1 44.949334-44.949333l70.72 70.72 317.141333-317.12a31.786667 31.786667 0 0 0 2.197333-42.538667l-2.197333-2.410666-89.898667-89.92a31.786667 31.786667 0 0 0-42.538666-2.176z" /></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.701333 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333z m-145.173333 471.338667A180.970667 180.970667 0 0 0 512 693.333333a180.650667 180.650667 0 0 0 128.746667-53.653333c5.888-5.930667 11.370667-12.266667 16.384-18.944a32 32 0 0 1 51.2 38.421333c-6.784 9.024-14.186667 17.578667-22.122667 25.6A244.629333 244.629333 0 0 1 512 757.333333c-78.208 0-150.357333-36.906667-196.373333-98.261333a32 32 0 1 1 51.2-38.4zM341.333333 384a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z m341.333334 0a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z" /></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512.042667 213.333333c82.752 0 161.088 24.106667 234.88 71.786667l53.525333-53.482667a32 32 0 1 1 45.248 45.248L287.573333 835.029333a32 32 0 1 1-45.248-45.248l44.693334-44.714666c-62.72-38.528-122.154667-93.909333-178.261334-165.802667a108.522667 108.522667 0 0 1-3.093333-130.56l3.136-4.202667 6.805333-8.64C233.045333 288.533333 365.546667 213.333333 512.042667 213.333333z m334.506666 153.216a842.88 842.88 0 0 1 68.693334 78.08 108.522667 108.522667 0 0 1 3.029333 130.688l-3.136 4.202667-6.826667 8.64C790.570667 735.466667 658.133333 810.666667 512.042667 810.666667a410.88 410.88 0 0 1-97.898667-11.733334l53.013333-52.970666a344.32 344.32 0 0 0 44.885334 2.901333c120.896 0 233.088-62.229333 337.408-189.482667l6.784-8.405333 6.613333-8.341333a49.344 49.344 0 0 0 0-61.226667 787.370667 787.370667 0 0 0-61.205333-69.973333l44.906666-44.885334z m-334.506666-91.413333c-121.28 0-233.493333 62.229333-337.557334 189.44l-6.784 8.405333-6.570666 8.341334a49.344 49.344 0 0 0 0.042666 61.205333c54.954667 70.442667 112.106667 122.581333 171.562667 156.8l92.864-92.885333a128 128 0 1 1 180.842667-180.842667l94.976-94.933333c-60.650667-37.184-123.733333-55.530667-189.376-55.530667zM512 443.072a68.906667 68.906667 0 0 0-44.522667 121.536l97.130667-97.130667A68.778667 68.778667 0 0 0 512 443.072z" /></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M384 554.666667a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667z m245.333333 213.333333a32 32 0 0 1 32 32v42.666667a32 32 0 0 1-64 0v-42.666667a32 32 0 0 1 32-32z m192-21.333333a32 32 0 0 1 32 32v64a32 32 0 0 1-64 0v-64a32 32 0 0 1 32-32zM384 618.666667h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L192 640v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L213.333333 832h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L405.333333 810.666667v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L384 618.666667z m245.333333-42.666667a32 32 0 0 1 32 32v85.333333a32 32 0 0 1-64 0v-85.333333a32 32 0 0 1 32-32z m192 0a32 32 0 0 1 32 32v64a32 32 0 0 1-64 0v-64a32 32 0 0 1 32-32zM384 128a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667z m426.666667 0a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667zM384 192h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L192 213.333333v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L213.333333 405.333333h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L405.333333 384v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L384 192z m426.666667 0h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L618.666667 213.333333v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L640 405.333333h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L832 384v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L810.666667 192z" /></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m265.9 713.9a377.2 377.2 0 0 1-119.6 80.6 377.5 377.5 0 0 1-292.6 0 377.1 377.1 0 0 1-200.2-200.2 377.5 377.5 0 0 1 0-292.6 377.1 377.1 0 0 1 200.2-200.2 377.5 377.5 0 0 1 292.6 0 377.1 377.1 0 0 1 200.2 200.2 377.5 377.5 0 0 1 0 292.6 377.2 377.2 0 0 1-80.6 119.6zM651.3 258.8a3.9 3.9 0 0 0-5.6 0L512 392.5 378.3 258.8a3.9 3.9 0 0 0-5.6 0l-39.6 39.6a3.9 3.9 0 0 0 0 5.6l102.3 102.4H376a4 4 0 0 0-4 4v56a4 4 0 0 0 4 4h104v80H376a4 4 0 0 0-4 4v56a4 4 0 0 0 4 4h104v148a4 4 0 0 0 4 4h56a4 4 0 0 0 4-4v-148h104a4 4 0 0 0 4-4v-56a4 4 0 0 0-4-4H544v-80h104a4 4 0 0 0 4-4v-56a4 4 0 0 0-4-4h-59.4L690.9 304a3.9 3.9 0 0 0 0-5.6z" /></svg>

Before

Width:  |  Height:  |  Size: 981 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M511 64C263.6 64 63 264.6 63 512s200.6 448 448 448 448-200.6 448-448S758.4 64 511 64z m265.9 713.9a377.2 377.2 0 0 1-119.6 80.6 377.5 377.5 0 0 1-292.6 0 377.1 377.1 0 0 1-200.2-200.2 377.5 377.5 0 0 1 0-292.6 377.1 377.1 0 0 1 200.2-200.2 377.5 377.5 0 0 1 292.6 0 377.1 377.1 0 0 1 200.2 200.2 377.5 377.5 0 0 1 0 292.6 377.2 377.2 0 0 1-80.6 119.6zM513.8 288.6a3.9 3.9 0 0 0-5.6 0L287.6 509.2a3.9 3.9 0 0 0 0 5.6l220.6 220.6a3.9 3.9 0 0 0 5.6 0l220.6-220.6a3.9 3.9 0 0 0 0-5.6zM511 636.5L386.5 512 511 387.5 635.5 512z" /></svg>

Before

Width:  |  Height:  |  Size: 796 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M285.8 406.9l137.3 83.7a7.7 7.7 0 0 0 11.8-6.6v-51.7h175a68.1 68.1 0 0 1 67.9 64.1 4.1 4.1 0 0 0 4 3.9h56.1a4.1 4.1 0 0 0 4-4.2c-2.2-70.8-60.6-127.8-132-127.8h-175v-51.8a7.7 7.7 0 0 0-11.8-6.6l-137.3 83.7a7.8 7.8 0 0 0 0 13.3z m452.4 210.2l-137.3-83.7a7.7 7.7 0 0 0-11.8 6.6v51.7h-175a68.1 68.1 0 0 1-67.9-64.1 4.1 4.1 0 0 0-4-3.9h-56.1a4.1 4.1 0 0 0-4 4.2c2.2 70.8 60.6 127.8 132 127.8h175v51.8a7.7 7.7 0 0 0 11.8 6.6l137.3-83.7a7.8 7.8 0 0 0 0-13.3zM856 128H168a40 40 0 0 0-40 40v688a40 40 0 0 0 40 40h688a40 40 0 0 0 40-40V168a40 40 0 0 0-40-40z m-32 696H200V200h624z" /></svg>

Before

Width:  |  Height:  |  Size: 845 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 106.666667c103.68 0 192.96 61.632 233.194667 150.250666C853.717333 266.944 938.666667 358.186667 938.666667 469.333333c0 95.509333-62.762667 176.362667-149.333334 203.562667V832a85.333333 85.333333 0 0 1-85.333333 85.333333H320a85.333333 85.333333 0 0 1-85.333333-85.333333v-180.437333C148.117333 624.384 85.333333 543.530667 85.333333 448c0-114.986667 90.944-208.704 204.8-213.162667A255.893333 255.893333 0 0 1 512 106.666667z m-104.725333 583.893333a25.557333 25.557333 0 0 0-36.949334 0 27.605333 27.605333 0 0 0 0 38.186667c78.250667 80.789333 205.098667 80.789333 283.349334 0a27.605333 27.605333 0 0 0 0-38.186667 25.557333 25.557333 0 0 0-36.949334 0 144.810667 144.810667 0 0 1-209.450666 0z" /></svg>

Before

Width:  |  Height:  |  Size: 981 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32z m-40 656H184V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v584zM688 420h-55.2c-5.1 0-10 2.5-13 6.6L468.9 634.4l-64.7-89c-3-4.1-7.8-6.6-13-6.6H336c-6.5 0-10.3 7.4-6.5 12.7l126.4 174c6.4 8.8 19.6 8.8 26 0l212.6-292.7c3.8-5.4 0-12.8-6.5-12.8z" /></svg>

Before

Width:  |  Height:  |  Size: 775 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M332.202667 347.136c12.16 12.373333 12.16 32.426667 0 44.821333-12.16 12.373333-31.893333 12.373333-44.053334 0l-151.04-115.584a32.085333 32.085333 0 0 1 0-44.842666l151.04-115.584c12.16-12.373333 31.893333-12.373333 44.053334 0 12.16 12.373333 12.16 32.448 0 44.842666l-85.290667 61.589334H565.333333c182.613333 0 330.666667 146.026667 330.666667 326.144 0 177.92-144.426667 322.538667-323.925333 326.08L565.333333 874.666667h-213.333333a31.786667 31.786667 0 0 1-32-31.573334c0-16.384 12.693333-29.866667 28.928-31.402666l3.072-0.149334h213.333333c147.285333 0 266.666667-117.76 266.666667-263.018666 0-143.082667-115.84-259.477333-260.096-262.933334l-6.570667-0.064-318.442666-0.021333 85.333333 61.632z" /></svg>

Before

Width:  |  Height:  |  Size: 982 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M853.333333 338.944V537.6c-32-16.362667-68.266667-25.6-106.666666-25.6-129.6 0-234.666667 105.066667-234.666667 234.666667 0 79.381333 39.424 149.546667 99.754667 192.021333L256 938.666667a85.333333 85.333333 0 0 1-85.333333-85.333334V338.965333a510.229333 510.229333 0 0 0 257.216 123.498667 85.312 85.312 0 0 0 168.192 0 510.165333 510.165333 0 0 0 257.28-123.52zM768 85.333333a85.333333 85.333333 0 0 1 85.333333 85.333334l0.021334 108.778666a468.437333 468.437333 0 0 1-260.842667 140.330667 85.354667 85.354667 0 0 0-161.088 0 468.373333 468.373333 0 0 1-260.778667-140.330667L170.666667 170.666667a85.333333 85.333333 0 0 1 85.333333-85.333334h512z m-21.354667 469.333334a191.957333 191.957333 0 0 1 168.597334 100.053333L746.666667 746.666667l135.765333 135.744A192 192 0 1 1 746.645333 554.666667z m32 106.666666a32 32 0 1 0 0-64 32 32 0 0 0 0 64z" /></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M103.082667 632.704c1.493333 1.130667 3.093333 2.176 4.778666 3.136l2.56 1.344L490.666667 822.421333a49.066667 49.066667 0 0 0 38.976 1.621334l3.690666-1.621334 380.224-185.237333c2.624-1.28 5.077333-2.773333 7.36-4.458667 17.216 12.650667 22.954667 35.477333 12.544 54.4a45.162667 45.162667 0 0 1-19.904 18.752L533.333333 891.093333a49.024 49.024 0 0 1-42.666666 0L110.442667 705.877333c-22.784-11.093333-31.701333-37.482667-19.904-58.922666 3.072-5.546667 7.338667-10.410667 12.544-14.250667z m0-153.6c1.493333 1.130667 3.093333 2.176 4.778666 3.136l2.56 1.344L490.666667 668.821333a49.066667 49.066667 0 0 0 38.976 1.621334l3.690666-1.621334 380.224-185.237333c2.624-1.28 5.077333-2.773333 7.36-4.458667 17.216 12.650667 22.954667 35.477333 12.544 54.4a45.162667 45.162667 0 0 1-19.904 18.752L533.333333 737.493333a49.024 49.024 0 0 1-42.666666 0L110.442667 552.277333c-22.784-11.093333-31.701333-37.482667-19.904-58.922666 3.072-5.546667 7.338667-10.410667 12.544-14.250667zM533.333333 132.970667l380.224 187.968c22.784 11.264 31.701333 38.037333 19.904 59.776a45.44 45.44 0 0 1-19.904 19.008L533.333333 587.733333c-13.376 6.613333-29.290667 6.613333-42.666666 0L110.442667 399.722667c-22.784-11.264-31.701333-38.016-19.904-59.776a45.44 45.44 0 0 1 19.904-18.986667L490.666667 132.949333a48.362667 48.362667 0 0 1 42.666666 0z" /></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M11.28 9.53L8.81 12l2.47 2.47a.749.749 0 0 1-.326 1.275a.75.75 0 0 1-.734-.215l-3-3a.75.75 0 0 1 0-1.06l3-3a.749.749 0 0 1 1.275.326a.75.75 0 0 1-.215.734"/><path fill="currentColor" d="M3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25V3.75C2 2.784 2.784 2 3.75 2M3.5 3.75v16.5c0 .138.112.25.25.25H15v-17H3.75a.25.25 0 0 0-.25.25m13 16.75h3.75a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25H16.5Z"/></svg>

Before

Width:  |  Height:  |  Size: 565 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M857.770667 163.882667c75.157333 75.136 72.448 209.237333 6.122666 346.944-17.792 36.309333-41.130667 72.725333-69.248 107.904a64 64 0 1 0 48.533334 41.792 697.173333 697.173333 0 0 0 51.328-72.682667c33.962667 109.098667 24.277333 208.938667-36.736 269.930667-67.84 67.84-183.701333 72.234667-306.922667 23.658666l-1.642667-0.938666-2.816-1.237334a475.690667 475.690667 0 0 1-34.410666-14.784v-0.021333c-40.170667-19.093333-80.64-44.842667-119.530667-76.288a32 32 0 0 0-40.234667 49.792c26.368 21.312 53.504 40.32 80.96 56.746667-108.842667 33.728-208.426667 23.957333-269.290666-36.906667-73.749333-73.749333-72.533333-204.309333-9.749334-339.328l3.434667-7.253333c19.882667-34.432 45.141333-68.693333 74.986667-101.482667a64 64 0 1 0-43.733334-46.997333 688.085333 688.085333 0 0 0-60.394666 75.093333c-35.477333-110.656-26.304-212.202667 35.456-273.941333 75.136-75.157333 209.237333-72.448 346.944-6.122667 137.706667-66.325333 271.808-69.034667 346.944 6.122667z m-347.306667 261.248a85.333333 85.333333 0 1 0 0 170.666666 85.333333 85.333333 0 0 0 0-170.666666z" /></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M683.918222 910.222222h-341.333333a227.555556 227.555556 0 0 1-227.555556-227.555555V341.333333a227.555556 227.555556 0 0 1 227.555556-227.555555h341.333333a227.555556 227.555556 0 0 1 227.555556 227.555555v341.333334a227.555556 227.555556 0 0 1-227.555556 227.555555z m-341.333333-728.177778a159.288889 159.288889 0 0 0-159.288889 159.288889v341.333334a159.288889 159.288889 0 0 0 159.288889 159.288889h341.333333a159.288889 159.288889 0 0 0 159.288889-159.288889V341.333333a159.288889 159.288889 0 0 0-159.288889-159.288889z" /><path d="M513.251556 711.111111a199.111111 199.111111 0 1 1 199.111111-199.111111 199.395556 199.395556 0 0 1-199.111111 199.111111z m0-329.955555a130.844444 130.844444 0 1 0 130.844444 130.844444 130.844444 130.844444 0 0 0-130.844444-130.901333z" /></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.701333 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333z" /></svg>

Before

Width:  |  Height:  |  Size: 639 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.701333 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333z m0 149.333334c117.824 0 213.333333 95.509333 213.333333 213.333333s-95.509333 213.333333-213.333333 213.333333-213.333333-95.509333-213.333333-213.333333 95.509333-213.333333 213.333333-213.333333z" /></svg>

Before

Width:  |  Height:  |  Size: 837 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M714.666667 106.666667a74.666667 74.666667 0 0 1 74.56 70.570666L789.333333 181.333333V213.333333h10.666667a117.333333 117.333333 0 0 1 117.248 112.618667L917.333333 330.666667v320a117.333333 117.333333 0 0 1-112.618666 117.248L800 768H789.333333v10.666667a117.333333 117.333333 0 0 1-117.333333 117.333333h-320a117.333333 117.333333 0 0 1-117.333333-117.333333V768h-10.666667a117.333333 117.333333 0 0 1-117.248-112.618667L106.666667 650.666667v-320a117.333333 117.333333 0 0 1 112.618666-117.248L224 213.333333h10.666667V181.333333a74.666667 74.666667 0 0 1 70.570666-74.56L309.333333 106.666667h405.333334z m-42.666667 490.666666h-320a53.333333 53.333333 0 0 0-53.333333 53.333334v128a53.333333 53.333333 0 0 0 53.333333 53.333333h320a53.333333 53.333333 0 0 0 53.333333-53.333333v-128a53.333333 53.333333 0 0 0-53.333333-53.333334z m128-320h-576a53.333333 53.333333 0 0 0-53.226667 49.834667L170.666667 330.666667v320a53.333333 53.333333 0 0 0 49.834666 53.226666L224 704h10.666667v-53.333333a117.333333 117.333333 0 0 1 117.333333-117.333334h320a117.333333 117.333333 0 0 1 117.333333 117.333334V704h10.666667a53.333333 53.333333 0 0 0 53.226667-49.834667L853.333333 650.666667v-320a53.333333 53.333333 0 0 0-49.834666-53.226667L800 277.333333z m-42.666667 64a32 32 0 0 1 0 64h-42.666666a32 32 0 0 1 0-64h42.666666z m-42.666666-170.666666h-405.333334a10.666667 10.666667 0 0 0-10.496 8.746666L298.666667 181.333333V213.333333h426.666666V181.333333a10.666667 10.666667 0 0 0-8.746666-10.496L714.666667 170.666667z" /></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

Some files were not shown because too many files have changed in this diff Show More