【总结管理】 新增# 总结模板和总结记录

main
kaeery 2025-02-24 19:58:50 +08:00
parent 1d7dfd3ec3
commit 00a6296aa9
7 changed files with 441 additions and 0 deletions

View File

@ -0,0 +1,55 @@
<template>
<div class="flex items-center gap-[6px] mb-[10px]">
<span>{{ index + 1 }}.</span>
<div class="bg-primary-light-10 p-[16px] rounded-[6px] flex-1">
<el-form-item label="表单类型">
<el-radio-group v-model="item.formType">
<el-radio v-for="type in formTypes" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="表单标题">
<template v-if="item.formType === 1">
<el-input v-model="item.formTitle" placeholder="请输入表单标题" maxlength="50" show-word-limit />
</template>
<template v-if="item.formType === 2">
<el-input v-model="item.formTitle" type="textarea" placeholder="请输入表单标题" maxlength="250" show-word-limit />
</template>
</el-form-item>
</div>
<div class="flex flex-col items-end">
<el-button type="primary" link @click="handleCopyItem"></el-button>
<el-button type="primary" link @click="handleDeleteItem"></el-button>
</div>
</div>
</template>
<script setup lang="ts">
import type { PropType } from 'vue'
import type { Item } from './template-drawer.vue'
const props = defineProps({
item: {
type: Object as PropType<Item>,
default: () => ({
formType: 1,
formTitle: ''
})
},
index: {
type: Number,
default: 0
}
})
const emit = defineEmits(['handleCopyItem', 'handleDeleteItem'])
const formTypes = ref([
{ label: '单行文本', value: 1 },
{ label: '多行文本', value: 2 }
])
const handleCopyItem = () => {
emit('handleCopyItem', props.index)
}
const handleDeleteItem = () => {
emit('handleDeleteItem', props.index)
}
</script>
<style scoped></style>

View File

@ -0,0 +1,86 @@
<template>
<ProDrawer ref="proDrawerRef" @handle-cancel="handleCancel" @handle-confirm="handleConfirm">
<el-form v-model="form">
<el-form-item label="设置为默认模板">
<el-switch v-model="form.isDefault" :active-value="1" :inactive-value="0" />
</el-form-item>
<el-form-item label="模板名称">
<el-input v-model="form.templateName" placeholder="请输入" maxlength="20" show-word-limit />
</el-form-item>
<el-form-item label="模板类型">
<el-radio-group v-model="form.templateType">
<el-radio v-for="type in types" :key="type.value" :label="type.value">{{ type.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="模板内容">
<el-button type="primary" plain @click="handleAddItem"></el-button>
</el-form-item>
<add-item
v-for="(item, index) in form.templateItems"
:key="index"
:item="item"
:index="index"
@handle-copy-item="handleCopyItem"
@handle-delete-item="handleDeleteItem"
/>
</el-form>
</ProDrawer>
</template>
<script setup lang="ts">
import ProDrawer, { type IParams } from '@/components/ProDrawer/index.vue'
import addItem from './add-item.vue'
export interface Item {
formType: number
formTitle: string
}
interface IForm {
templateName: string
templateType: number
isDefault: number
templateItems: Item[]
}
const emit = defineEmits(['refreshList'])
const proDrawerRef = ref<InstanceType<typeof ProDrawer>>()
const types = ref([
{ label: '电销', value: 1 },
{ label: '招生', value: 2 }
])
const form = ref<IForm>({
templateName: '',
templateType: 1,
isDefault: 1,
templateItems: []
})
const handleAddItem = () => {
form.value.templateItems.push({
formType: 1,
formTitle: ''
})
}
const handleCopyItem = (index: number) => {
form.value.templateItems.splice(index, 0, {
formType: 1,
formTitle: ''
})
}
const handleDeleteItem = (index: number) => {
form.value.templateItems.splice(index, 1)
}
const openDrawer = (params: IParams) => {
proDrawerRef.value?.openDrawer(params)
}
const handleCancel = (callback: () => void) => {
callback()
}
const handleConfirm = (callback: () => void) => {
callback()
emit('refreshList')
}
defineExpose({
openDrawer
})
</script>
<style scoped></style>

View File

@ -0,0 +1,65 @@
<template>
<component :is="componentName" v-model="queryParams[activeTab]" @reset-page="resetPage" @reset-params="resetParams" />
<el-card shadow="never" class="!border-none mt-4 summary">
<el-tabs v-model="activeTab">
<el-tab-pane label="总结模板" name="template">
<summary-template v-if="activeTab === 'template'" ref="summaryTemplateRef" :queryParams="queryParams[activeTab]" />
</el-tab-pane>
<el-tab-pane label="总结记录" name="record">
<summary-record v-if="activeTab === 'record'" ref="summaryRecordRef" :queryParams="queryParams[activeTab]" />
</el-tab-pane>
</el-tabs>
</el-card>
</template>
<script setup lang="ts">
import templateSearchForm from './modules/template-search-form.vue'
import recordSearchForm from './modules/record-search-form.vue'
import summaryTemplate from './modules/summary-template.vue'
import summaryRecord from './modules/summary-record.vue'
const queryParams = ref<Record<string, any>>({
template: {
name: '',
type: '',
status: null
},
record: {
submitName: '',
submitDate: ''
}
})
const componentName = computed(() => (activeTab.value == 'template' ? templateSearchForm : recordSearchForm))
const activeTab = ref('template')
const summaryTemplateRef = ref<InstanceType<typeof summaryTemplate>>()
const summaryRecordRef = ref<InstanceType<typeof summaryRecord>>()
const resetPage = () => {
switch (activeTab.value) {
case 'template':
summaryTemplateRef.value?.resetPage()
break
case 'record':
summaryRecordRef.value?.resetPage()
break
}
}
const resetParams = () => {
switch (activeTab.value) {
case 'template':
summaryTemplateRef.value?.resetParams()
break
case 'record':
summaryRecordRef.value?.resetParams()
break
}
}
</script>
<style scoped lang="scss">
.summary {
:deep(.el-card__body) {
padding-top: 0;
}
}
</style>

View File

@ -0,0 +1,36 @@
<template>
<el-card shadow="never" class="!border-none">
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
<el-form-item label="提交人">
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.submitName" clearable @keyup.enter="$emit('resetPage')" />
</el-form-item>
<el-form-item label="提交时间">
<el-date-picker
v-model="modelValue.submitDate"
type="datetimerange"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="$emit('resetPage')"></el-button>
<el-button @click="$emit('resetParams')"></el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script setup lang="ts">
defineProps({
modelValue: {
type: Object,
default: () => ({
submitName: '',
submitDate: ''
})
}
})
defineEmits(['resetPage', 'resetParams'])
</script>
<style scoped></style>

View File

@ -0,0 +1,38 @@
<template>
<ProTable ref="proTableRef" :columns="columns" :tableData="pager.lists" :loading="pager.loading" :maxHeight="530" />
</template>
<script setup lang="ts">
import { postLists } from '@/api/org/post'
import { usePaging } from '@/hooks/usePaging'
const props = defineProps({
queryParams: {
type: Object,
default: () => ({
submitName: '',
submitDate: ''
})
}
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: postLists,
params: props.queryParams
})
getLists()
const proTableRef = ref()
const columns = reactive([
{ prop: 'name', label: '提交人', width: 180 },
{ prop: 'type', label: '岗位', width: 180 },
{ prop: 'type', label: '提交时间', width: 180 },
{ prop: 'type', label: '总结情况', width: 180 }
])
defineExpose({
resetPage,
resetParams,
getLists
})
</script>
<style scoped></style>

View File

@ -0,0 +1,114 @@
<template>
<el-space direction="vertical" alignment="normal" :size="16">
<div>
<el-button type="primary" @click="handleAdd"></el-button>
<el-button type="danger" @click="handleBatchDelete" plain :disabled="isDisabled">批量删除</el-button>
</div>
<ProTable ref="proTableRef" :columns="columns" :tableData="pager.lists" :loading="pager.loading" :maxHeight="530">
<template #name="{ row }">
<el-space>
<span>{{ row.name }}</span>
<span>{{ tagName(row) }}</span>
</el-space>
</template>
<template #status="{ row }">
<el-switch v-model="row.status" :active-value="1" :inactive-value="0" :before-change="() => handleBeforeChange(row)" />
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="handleEdit(row)"></el-button>
<el-button type="primary" link @click="handleDelete(row)"></el-button>
</template>
</ProTable>
</el-space>
<template-drawer ref="templateDrawerRef" @refreshList="getLists" />
</template>
<script setup lang="ts">
import useHandleData from '@/hooks/useHandleData'
import templateDrawer from '../components/template-drawer.vue'
import { usePaging } from '@/hooks/usePaging'
import { postLists } from '@/api/org/post'
import feedback from '@/utils/feedback'
const props = defineProps({
queryParams: {
type: Object,
default: () => ({
name: '',
type: '',
status: null
})
}
})
const emit = defineEmits(['handleEdit', 'handleDelete'])
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: postLists,
params: props.queryParams
})
getLists()
const proTableRef = ref()
const columns = reactive([
{ type: 'selection', width: 70 },
{ prop: 'name', label: '模板名称', width: 180 },
{ prop: 'type', label: '模板类型', width: 180 },
{ prop: 'status', label: '模板状态', width: 180 },
{ prop: 'createTime', label: '创建时间', width: 180 },
{ prop: 'updateTime', label: '更新时间', width: 180 },
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
])
const enumType: Record<number, string> = {
1: '电销',
2: '招生'
}
const typeName = computed(() => row => enumType[row.type])
const tagName = computed(() => row => row.isDefault == 1 ? `默认${typeName.value(row)}模板` : '')
const templateDrawerRef = ref<InstanceType<typeof templateDrawer>>()
const handleAdd = () => {
templateDrawerRef.value?.openDrawer({
title: '新增模板',
width: 500,
data: {}
})
}
const handleEdit = row => {
templateDrawerRef.value?.openDrawer({
title: '新增模板',
width: 500,
data: { ...row }
})
}
const isDisabled = computed(() => proTableRef?.value?.selectedListIds?.length == 0)
const handleDelete = row => {
deleteCommon(row)
}
const handleBatchDelete = () => {
deleteCommon()
}
const deleteCommon = async (row?: any) => {
if (row) proTableRef.value.tableRef.toggleRowSelection(row, true)
const ids = proTableRef.value.selectedListIds
const message = '是否要删除选中的?'
const flag = await useHandleData(message)
if (flag) {
console.log(ids)
}
proTableRef.value.tableRef.clearSelection()
}
const handleBeforeChange = row => {
const { id, status } = row
return new Promise(async resolve => {
try {
const text = '确定' + `${status === 1 ? '停用' : '启用'}该模板?`
await feedback.confirm(text)
return resolve(true)
} catch (error) {}
})
}
defineExpose({
resetPage,
resetParams,
getLists
})
</script>
<style scoped></style>

View File

@ -0,0 +1,47 @@
<template>
<el-card shadow="never" class="!border-none">
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
<el-form-item label="模板名称">
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
</el-form-item>
<el-form-item label="模板类型">
<el-select class="w-[280px]" v-model="modelValue.type">
<el-option v-for="option in typeOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
<el-form-item label="模板状态">
<el-select class="w-[280px]" v-model="modelValue.status">
<el-option v-for="option in statusOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="$emit('resetPage')"></el-button>
<el-button @click="$emit('resetParams')"></el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script setup lang="ts">
defineProps({
modelValue: {
type: Object,
default: () => ({
name: '',
type: '',
status: null
})
}
})
defineEmits(['resetPage', 'resetParams'])
const typeOptions = ref([
{ label: '电销', value: 1 },
{ label: '招生', value: 2 }
])
const statusOptions = ref([
{ label: '启用', value: 1 },
{ label: '停用', value: 2 }
])
</script>
<style scoped lang="scss"></style>