perf: 添加任务模板

This commit is contained in:
kuaifan 2024-12-02 07:17:14 +08:00
parent 6bafa0a6dd
commit e3312c97a7
5 changed files with 89 additions and 30 deletions

View File

@ -2718,7 +2718,6 @@ class ProjectController extends AbstractController
return Base::retError('参数错误');
}
$templates = ProjectTaskTemplate::where('project_id', $projectId)
->orderBy('sort')
->orderByDesc('id')
->get();
return Base::retSuccess('success', $templates);
@ -2782,7 +2781,6 @@ class ProjectController extends AbstractController
if ($templateCount >= 20) {
return Base::retError('每个项目最多添加20个模板');
}
$data['sort'] = ProjectTaskTemplate::where('project_id', $projectId)->max('sort') + 1;
$template = ProjectTaskTemplate::create($data);
}
return Base::retSuccess('保存成功', $template);

View File

@ -10,7 +10,7 @@ namespace App\Models;
* @property string $name 模板名称
* @property string|null $title 任务标题
* @property string|null $content 任务内容
* @property int $sort 排序
* @property int $sort 排序(预留)
* @property bool $is_default 是否默认模板
* @property int $userid 创建人
* @property \Illuminate\Support\Carbon|null $created_at

View File

@ -12,7 +12,8 @@
<div class="content">
<div v-if="!templates.length" class="empty">
<div class="empty-text">{{$L('暂无任务模板')}}</div>
<div class="empty-text">{{$L('当前项目暂无任务模板')}}</div>
<Button type="primary" icon="md-add" @click="handleAdd">{{$L('新建模板')}}</Button>
</div>
<div v-else class="template-list">
<div v-for="item in templates" :key="item.id" class="template-item">
@ -53,15 +54,16 @@
v-bind="formOptions"
@submit.native.prevent>
<FormItem prop="name" :label="$L('模板名称')">
<Input ref="templateName" v-model="editingTemplate.name" :placeholder="$L('请输入模板名称')"/>
<Input ref="templateName" v-model="editingTemplate.name" :disabled="systemTemplateIsMultiple" :placeholder="$L('请输入模板名称')"/>
</FormItem>
<FormItem prop="title" :label="$L('任务标题')">
<Input v-model="editingTemplate.title" :placeholder="$L('请输入任务标题')"/>
<Input v-model="editingTemplate.title" :disabled="systemTemplateIsMultiple" :placeholder="$L('请输入任务标题')"/>
</FormItem>
<FormItem prop="content" :label="$L('任务内容')">
<Input
type="textarea"
v-model="editingTemplate.content"
:disabled="systemTemplateIsMultiple"
:placeholder="$L('请输入任务内容')"
:autosize="{ minRows: 4, maxRows: 12 }"/>
</FormItem>
@ -69,14 +71,27 @@
<div class="project-task-template-system">
<div v-if="!systemTemplateShow" @click="onSystemTemplate" class="tip-title">{{$L('使用示例模板')}}</div>
<ul v-else>
<li v-for="(item, index) in systemTemplateData" :key="index" @click="useSystemTemplate(item)">{{item.name}}</li>
<li
:class="{selected:systemTemplateIsMultiple}"
@click="systemTemplateIsMultiple=!systemTemplateIsMultiple">
<i class="taskfont" v-html="systemTemplateIsMultiple ? '&#xe627;' : '&#xe625;'"></i>
{{$L('多选')}}
</li>
<li
v-for="(item, index) in systemTemplateData"
:key="index"
:class="{selected:systemTemplateIsMultiple && systemTemplateMultipleData.indexOf(item)!==-1}"
@click="useSystemTemplate(item)">{{item.name}}</li>
</ul>
</div>
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="showEditModal=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="loading" @click="handleSave">{{$L('保存')}}</Button>
<Button type="primary" :loading="loading" @click="handleSave">
{{ $L('保存') }}
{{ systemTemplateIsMultiple && systemTemplateMultipleData.length > 0 ? ` (${systemTemplateMultipleData.length})` : '' }}
</Button>
</div>
</Modal>
</div>
@ -111,6 +126,8 @@ export default {
systemTemplateShow: false,
systemTemplateData: [],
systemTemplateIsMultiple: false,
systemTemplateMultipleData: [],
}
},
computed: {
@ -176,22 +193,40 @@ export default {
$A.messageWarning('请输入模板名称')
return
}
let savePromises = []
if (this.systemTemplateIsMultiple) {
if (this.systemTemplateMultipleData.length === 0) {
$A.messageWarning('请选择示例模板')
return
}
savePromises = this.systemTemplateMultipleData.map(item => {
const template = { ...this.editingTemplate, id: null, name: item.name, title: item.title, content: item.content }
return this.handleSaveCall(template)
})
} else {
savePromises.push(this.handleSaveCall(this.editingTemplate))
}
try {
await this.$store.dispatch("call", {
url: 'project/task/template_save',
data: this.editingTemplate,
method: 'post',
spinner: 300
})
$A.messageSuccess('保存成功')
const results = await Promise.all(savePromises)
$A.messageSuccess(results.length === 1 ? results[0].msg : '全部保存成功')
this.showEditModal = false
this.loadTemplates()
} catch ({msg}) {
$A.messageError(msg || '保存失败')
} catch (error) {
$A.messageError(error.msg || '保存失败')
}
},
//
async handleSaveCall(data) {
return this.$store.dispatch("call", {
url: 'project/task/template_save',
data,
method: 'post',
spinner: 300
})
},
//
async handleDelete(template) {
$A.modalConfirm({
@ -199,14 +234,14 @@ export default {
content: '确定要删除该模板吗?',
onOk: async () => {
try {
await this.$store.dispatch("call", {
const {msg} = await this.$store.dispatch("call", {
url: 'project/task/template_delete',
data: {
id: template.id
},
spinner: 300
})
$A.messageSuccess('删除成功')
$A.messageSuccess(msg || '删除成功')
this.loadTemplates()
} catch ({msg}) {
$A.messageError(msg || '删除失败')
@ -218,7 +253,7 @@ export default {
//
async handleSetDefault(template) {
try {
await this.$store.dispatch("call", {
const {msg} = await this.$store.dispatch("call", {
url: 'project/task/template_default',
data: {
id: template.id,
@ -226,7 +261,7 @@ export default {
},
spinner: 300
})
$A.messageSuccess('设置成功')
$A.messageSuccess(msg || '设置成功')
this.loadTemplates()
} catch ({msg}) {
$A.messageError(msg || '设置失败')
@ -244,6 +279,15 @@ export default {
this.editingTemplate.name = item.name
this.editingTemplate.title = item.title
this.editingTemplate.content = item.content
//
if (this.systemTemplateIsMultiple) {
const index = this.systemTemplateMultipleData.indexOf(item)
if (index === -1) {
this.systemTemplateMultipleData.push(item)
} else {
this.systemTemplateMultipleData.splice(index, 1)
}
}
}
}
}

View File

@ -631,4 +631,14 @@ body.dark-mode-reverse {
}
}
}
.project-task-template-system {
ul {
> li {
&.selected {
color: black;
}
}
}
}
}

View File

@ -4,11 +4,12 @@
flex-direction: column;
.header {
padding: 20px 20px 10px;
height: 60px;
padding: 10px 20px;
display: flex;
align-items: center;
justify-content: flex-start;
@media screen and (min-width: 500px) {
justify-content: space-between;
}
@ -30,15 +31,15 @@
.empty {
text-align: center;
padding: 40px 0;
color: $primary-text-color;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.empty-text {
font-size: 14px;
flex-direction: column;
padding: 20px;
color: $primary-text-color;
> button {
margin-top: 18px;
}
}
}
@ -86,11 +87,12 @@
}
.template-actions {
margin-top: 12px;
margin-top: 4px;
text-align: right;
> button {
margin-right: 12px;
margin-top: 8px;
margin-right: 8px;
height: 28px;
padding: 0 12px;
font-size: 13px;
@ -128,6 +130,11 @@
&:hover {
background-color: #e0e0e0;
}
&.selected {
background-color: $primary-color;
color: white;
}
}
}
}