Commit a1e5f8ff authored by 张耀's avatar 张耀

feat:

工单管理开发
parent 3fbbf1d9
export const TIMEING_RULES = {
1: '手动下发',
2: '按周',
3: '自定义时间'
}
\ No newline at end of file
<template> <template>
<el-form <el-form :model="state.form" ref="form" :rules="state.rules" label-width="80px" :disabled="disabled">
:model="state.form"
ref="form"
:rules="state.rules"
label-width="80px"
:disabled="disabled"
>
<el-form-item label="通知方式" prop="method"> <el-form-item label="通知方式" prop="method">
<el-checkbox-group v-model="state.form.method"> <el-checkbox-group v-model="state.form.method">
<el-checkbox v-for="(value, key) in METHODS" :key="key" :label="key"> <el-checkbox v-for="(value, key) in METHODS" :key="key" :label="key">
...@@ -14,68 +8,59 @@ ...@@ -14,68 +8,59 @@
</el-checkbox-group> </el-checkbox-group>
</el-form-item> </el-form-item>
<el-form-item label="" prop="lists" class="user-table bg-scroll"> <el-form-item label="" prop="lists" class="user-table bg-scroll">
<el-table :data="state.form.lists" stripe border> <el-form :model="state.form.lists" ref="table_form" :rules="table_rules" label-width="0">
<el-table-column type="index" label="序号" width="60px"> <el-table :data="state.form.lists" stripe border>
</el-table-column> <el-table-column type="index" label="序号" width="60px"> </el-table-column>
<el-table-column <el-table-column
v-for="header in headers" v-for="header in headers"
:prop="header.prop" :prop="header.prop"
:key="header.prop" :key="header.prop"
:label="header.label" :label="header.label"
:width="header.width" :width="header.width">
> <template #default="{ $index }">
<template #default="{ $index }"> <div v-if="header.prop == 'user_id'">
<div v-if="header.prop == 'user_id'"> <el-form-item :prop="`[${$index}].user_id`" :rules="state.tableRules.user_id">
<el-select <el-select
v-model="state.form.lists[$index].user_id" v-model="state.form.lists[$index].user_id"
placeholder="请选择" placeholder="请选择"
filterable filterable
@change="($event) => chooseUser($event, $index)" @change="($event) => chooseUser($event, $index)">
> <el-option
<el-option v-for="item in userOptions($index)"
v-for="item in userOptions($index)" :key="item.user_id"
:key="item.user_id" :label="item.user_id"
:label="item.user_id" :value="item.user_id">
:value="item.user_id" </el-option>
> </el-select>
</el-option> </el-form-item>
</el-select> </div>
</div> <div v-else>
<div v-else> <el-form-item :prop="`[${$index}].${header.prop}`" :rules="state.tableRules[header.prop]">
<el-input <el-input v-model="state.form.lists[$index][header.prop]" placeholder="请输入"></el-input>
v-model="state.form.lists[$index][header.prop]" </el-form-item>
placeholder="请输入" </div>
></el-input> </template>
</div> </el-table-column>
</template>
</el-table-column> <el-table-column prop="" label="操作" width="125px">
<el-table-column prop="" label="操作" width="125px"> <template #default="{ $index }">
<template #default="{ $index }"> <div class="table-operation">
<div class="table-operation"> <el-button
<el-button link
link type="primary"
type="primary" @click="Add($index)"
@click="Add($index)" :disabled="userLists.length <= state.form.lists.length || addTrue >= ADD_NUM">
:disabled=" 新增
userLists.length <= state.form.lists.length || </el-button>
addTrue >= ADD_NUM <span class="line"></span>
" <el-button link type="primary" @click="Remove($index)" :disabled="state.form.lists.length == 1">
> 删除
新增 </el-button>
</el-button> </div>
<span class="line"></span> </template>
<el-button </el-table-column>
link </el-table>
type="primary" </el-form>
@click="Remove($index)"
:disabled="state.form.lists.length == 1"
>
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
...@@ -106,6 +91,11 @@ const state = reactive({ ...@@ -106,6 +91,11 @@ const state = reactive({
}, },
], ],
}, },
tableRules: {
user_id: [{ required: true, message: "请选择", trigger: "change" }],
user_name: [{ required: true, message: "请输入", trigger: "blur" }],
phone: [{ required: true, message: "请输入", trigger: "blur" }],
},
}); });
// 已选中的用户id列表 // 已选中的用户id列表
const selectedUser = computed(() => { const selectedUser = computed(() => {
...@@ -126,12 +116,18 @@ const headers = [ ...@@ -126,12 +116,18 @@ const headers = [
label: "联系方式", label: "联系方式",
}, },
]; ];
const table_form = ref(null);
// 立即下发 // 立即下发
const Submit = (cb = null) => { const Submit = (cb = null) => {
form.value.validate((valid) => { form.value.validate((valid) => {
if (valid) { if (valid) {
console.log(state.form); table_form.value.validate((t_v) => {
cb && cb(); if (t_v) {
cb && cb(state.form);
} else {
return false;
}
});
} else { } else {
return false; return false;
} }
...@@ -223,9 +219,7 @@ const init = (history) => { ...@@ -223,9 +219,7 @@ const init = (history) => {
}; };
// 选择用户操作 // 选择用户操作
const chooseUser = ($event, index) => { const chooseUser = ($event, index) => {
let user = userLists.value.find( let user = userLists.value.find((e) => e.user_id == state.form.lists[index].user_id);
(e) => e.user_id == state.form.lists[index].user_id
);
state.form.lists[index].user_name = user.user_name; state.form.lists[index].user_name = user.user_name;
state.form.lists[index].phone = user.phone; state.form.lists[index].phone = user.phone;
}; };
......
<template> <template>
<el-dialog <el-dialog v-model="show" width="804px" top="10vh" :close-on-click-modal="false" :before-close="beforeClose">
v-model="show"
width="804px"
top="10vh"
:close-on-click-modal="false"
:before-close="beforeClose"
>
<template #header> <template #header>
<GapTitle title="手动下发"></GapTitle> <GapTitle title="手动下发"></GapTitle>
</template> </template>
...@@ -14,9 +8,7 @@ ...@@ -14,9 +8,7 @@
</div> </div>
<template #footer> <template #footer>
<el-button size="default" @click="Close">关闭</el-button> <el-button size="default" @click="Close">关闭</el-button>
<el-button type="primary" size="default" @click="Submit"> <el-button type="primary" size="default" @click="Submit"> 立即下发 </el-button>
立即下发
</el-button>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
...@@ -88,7 +80,10 @@ const beforeClose = () => { ...@@ -88,7 +80,10 @@ const beforeClose = () => {
}; };
// 立即下发 // 立即下发
const Submit = () => { const Submit = () => {
form.value.Submit(() => { form.value.Submit(async (form) => {
let res = { ...form };
console.log("res: ", res);
await nextTick();
Close(); Close();
}); });
}; };
......
...@@ -175,8 +175,7 @@ const detailInfo = ref([ ...@@ -175,8 +175,7 @@ const detailInfo = ref([
:deep(.gap-title) { :deep(.gap-title) {
margin-bottom: 16px; margin-bottom: 16px;
} }
.info, .info {
.feedback-info {
max-width: 1072px; max-width: 1072px;
width: 100%; width: 100%;
padding: 0 8px 0; padding: 0 8px 0;
......
<template>
<div class="add-ticket">
<div class="breadcrumb">
<bg-breadcrumb />
</div>
<div class="content bg-scroll">
<add-form></add-form>
</div>
</div>
</template>
<script setup>
import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import addForm from "../modules/add-form.vue";
</script>
<style lang="scss" scoped>
.add-ticket {
width: 100%;
height: 100%;
padding: 0 24px 16px;
.breadcrumb {
width: 100%;
height: 46px;
}
.content {
width: 100%;
height: calc(100% - 46px);
background-color: #ffffff;
box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15);
border-radius: 6px;
padding: 24px;
}
}
</style>
...@@ -3,12 +3,262 @@ ...@@ -3,12 +3,262 @@
<div class="breadcrumb"> <div class="breadcrumb">
<bg-breadcrumb /> <bg-breadcrumb />
</div> </div>
<div class="content"></div> <div class="content bg-scroll">
<gap-title :hasLine="true" title="基本信息"></gap-title>
<div class="info">
<Info :labelData="labelData" :valueData="info">
<template #status="{ item, valueData }">
<span class="status-body">
<span class="status" :class="`status-${valueData.status}`"></span>
<span>{{ STATUS_OBJ[valueData[item.prop]] }}</span>
</span>
</template>
</Info>
</div>
<gap-title :hasLine="true" title="推送方式"></gap-title>
<div class="info">
<Info :labelData="notificationMethod" :valueData="info">
<template #value="{ item, valueData }">
<span>{{ valueData[item.prop].map((e) => METHODS[e]).join("") }}</span>
</template>
</Info>
<div class="notification-lists">
<bg-table border ref="notification_table" :headers="headers" :rows="rows" height="100%" :isIndex="true">
</bg-table>
</div>
</div>
<gap-title :hasLine="true" title="定时规则"></gap-title>
<div class="info">
<Info :labelData="timeingRules" :valueData="info">
<template #value="{ item, valueData }">
<span>{{ TIMEING_RULES[valueData[item.prop]] }}</span>
</template>
</Info>
<div class="notification-lists">
<bg-table
border
ref="timeing_rules_table"
:headers="timeingRulesHeaders"
:rows="timeingRulesRows"
height="100%">
<template #daterange="{ row }">
{{ row.daterange.join(" ~ ") }}
</template>
</bg-table>
</div>
</div>
<gap-title :hasLine="true" title="实例工单"></gap-title>
<div>
<bg-table
ref="ticket_table"
:headers="ticketHeaders"
:rows="ticketRows"
:stripe="true"
:isIndex="true"
height="100%">
<template #status="{ row }">
<span class="status-body">
<span class="status" :class="`status-${row.status}`"></span>
<span>{{ ticketStatus[row.status] }}</span>
<span v-if="row.status != 3">{{ row.finish }}/{{ row.all }}</span>
</span>
</template>
<template #operation="{ row }">
<div class="table-operation">
<span class="primary-edit" @click="Detail(row)"> 详情 </span>
</div>
</template>
</bg-table>
</div>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import Info from "@/components/warn-detail/info.vue";
import gapTitle from "@/components/gap-title.vue";
import { METHODS } from "@/components/manual-distribution/env.js";
import { TIMEING_RULES } from "@/components/env.js";
import { useRouter } from "vue-router";
const router = useRouter();
const STATUS_OBJ = {
finish: "已完成",
close: "已关闭",
info: "待处置",
};
const labelData = [
[
{
label: "工单名称",
prop: "ticket_name",
},
{
label: "状态",
prop: "status",
},
],
[
{
label: "工单等级",
prop: "ticket_level",
},
{
label: "创建人",
prop: "create_by",
},
],
[
{
label: "工单描述",
prop: "description",
},
],
[
{
label: "创建时间",
prop: "create_time",
},
{
label: "完成时间",
prop: "finish_time",
},
],
];
const info = {
ticket_name: "7月常态化运维巡检任务",
status: "finish",
ticket_level: "紧急任务",
create_by: "管理员",
description: "请进行所有系统常态化月度巡检任务(每月定期常态运维巡检),将巡检结果上报!",
create_time: "2020-01-01 00:00:00",
finish_time: "2020-01-01 00:00:00",
notification_method: ["1", "2"],
timeing_rules: "3",
};
const notificationMethod = [
[
{
label: "通知方式",
prop: "notification_method",
},
],
];
const headers = [
{
prop: "user_id",
label: "账号",
},
{
prop: "user_name",
label: "姓名",
},
{
prop: "phone",
label: "联系方式",
},
];
const rows = ref([
{
user_id: "11",
user_name: "1111",
phone: "13211111111",
},
{
user_id: "22",
user_name: "2222",
phone: "13222222222",
},
{
user_id: "33",
user_name: "3333",
phone: "13233333333",
},
]);
const timeingRules = [
[
{
label: "定时规则",
prop: "timeing_rules",
},
],
];
const timeingRulesHeaders = [
{
prop: "daterange",
label: "日期范围",
},
{
prop: "time_point",
label: "时间点",
},
];
const timeingRulesRows = [
{
daterange: ["2023-11-22", "2023-11-25"],
time_point: "16:00:00",
},
{
daterange: ["2023-11-22", "2023-11-25"],
time_point: "16:00:00",
},
{
daterange: ["2023-11-22", "2023-11-25"],
time_point: "16:00:00",
},
];
const ticketStatus = {
1: "已完成",
2: "待处置",
3: "已关闭",
};
const ticketHeaders = [
{
prop: "ticket_level",
label: "工单等级",
},
{
prop: "status",
label: "工单状态",
},
{
prop: "distribute_target",
label: "下发对象",
},
{
prop: "create_by",
label: "创建人",
},
{
prop: "create_time",
label: "创建时间",
},
{
prop: "finish_time",
label: "完成时间",
},
{
label: "操作",
prop: "operation",
align: "left",
width: "80px",
},
];
const ticketRows = ref([
{ ticket_name: 11, id: 111, status: 1, finish: 10, all: 10 },
{ ticket_name: 22, id: 222, status: 2, finish: 5, all: 10 },
{ ticket_name: 33, id: 333, status: 3, finish: 0, all: 10 },
]);
const Detail = ({ id }) => {
router.push({
path: "/ticket/business-ticket-list/detail",
query: {
id,
},
});
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -26,6 +276,44 @@ import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; ...@@ -26,6 +276,44 @@ import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
background-color: #ffffff; background-color: #ffffff;
box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15); box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15);
border-radius: 6px; border-radius: 6px;
padding: 24px;
:deep(.gap-title) {
margin-bottom: 16px;
}
.info {
max-width: 1072px;
width: 100%;
padding: 0 8px 0;
&:not(:last-child) {
padding-bottom: 24px;
}
.status {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
margin-right: 8px;
$statusObj: (
finish: #48ad97,
close: #9e9e9e,
info: #3759be,
1: #48ad97,
2: #e56600,
);
@each $status, $color in $statusObj {
&-#{$status} {
background-color: $color;
}
}
}
.status-body {
display: flex;
align-items: center;
}
.notification-lists {
margin-top: 16px;
}
}
} }
} }
</style> </style>
<template>
<div class="edit-ticket">
<div class="breadcrumb">
<bg-breadcrumb />
</div>
<div class="content bg-scroll"></div>
</div>
</template>
<script setup>
import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
</script>
<style lang="scss" scoped>
.edit-ticket {
width: 100%;
height: 100%;
padding: 0 24px 16px;
.breadcrumb {
width: 100%;
height: 46px;
}
.content {
width: 100%;
height: calc(100% - 46px);
background-color: #ffffff;
box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15);
border-radius: 6px;
padding: 40px 54px;
}
}
</style>
...@@ -4,16 +4,11 @@ ...@@ -4,16 +4,11 @@
<bg-breadcrumb /> <bg-breadcrumb />
</div> </div>
<div class="content"> <div class="content">
<bg-filter-group <bg-filter-group @search="changeSearch" v-model="filter.key_word" placeholder="请输入任务名称">
@search="changeSearch"
v-model="filter.key_word"
placeholder="请输入任务名称">
<template v-slot:left_action> <template v-slot:left_action>
<div class="apaas_button"> <div class="apaas_button">
<el-button type="primary" @click="AddWorkOrder"> <el-button type="primary" @click="AddTicket">
<bg-icon <bg-icon style="font-size: 12px; color: #fff; margin-right: 8px" icon="#bg-ic-add"></bg-icon>
style="font-size: 12px; color: #fff; margin-right: 8px"
icon="#bg-ic-add"></bg-icon>
新增 新增
</el-button> </el-button>
<el-button type="primary" @click="delBatch"> 批量删除 </el-button> <el-button type="primary" @click="delBatch"> 批量删除 </el-button>
...@@ -89,8 +84,8 @@ ...@@ -89,8 +84,8 @@
:select="true" :select="true"
@selectAc="selectRows" @selectAc="selectRows"
:stripe="true"> :stripe="true">
<template #work_order_name="{ row }"> <template #ticket_name="{ row }">
<div class="href" @click="goTo(row)">{{ row.work_order_name || "-" }}</div> <div class="href" @click="goTo(row)">{{ row.ticket_name || "-" }}</div>
</template> </template>
<template #status="{ row }"> <template #status="{ row }">
<span> <span>
...@@ -177,21 +172,17 @@ const ruleOptions = ref([ ...@@ -177,21 +172,17 @@ const ruleOptions = ref([
let headers = reactive([ let headers = reactive([
{ {
label: "工单名称", label: "工单名称",
prop: "work_order_name", prop: "ticket_name",
align: "left", align: "left",
href: {
baseurl: "/ticket/business-ticket-manage/detail",
params: { id: "id", name: "work_order_name" },
},
}, },
{ {
label: "工单等级", label: "工单等级",
prop: "work_order_level", prop: "ticket_level",
align: "left", align: "left",
}, },
{ {
label: "实例工单数", label: "实例工单数",
prop: "example_work_order_num", prop: "example_ticket_num",
align: "left", align: "left",
}, },
{ {
...@@ -228,9 +219,9 @@ let headers = reactive([ ...@@ -228,9 +219,9 @@ let headers = reactive([
}, },
]); ]);
let rows = ref([ let rows = ref([
{ work_order_name: 11, id: 111, status: 1, finish: 10, all: 10 }, { ticket_name: 11, id: 111, status: 1, finish: 10, all: 10 },
{ work_order_name: 22, id: 222, status: 2, finish: 5, all: 10 }, { ticket_name: 22, id: 222, status: 2, finish: 5, all: 10 },
{ work_order_name: 33, id: 333, status: 3, finish: 0, all: 10 }, { ticket_name: 33, id: 333, status: 3, finish: 0, all: 10 },
]); ]);
const changeSize = (size) => { const changeSize = (size) => {
filter.limit = size; filter.limit = size;
...@@ -276,6 +267,12 @@ const operation = (row) => { ...@@ -276,6 +267,12 @@ const operation = (row) => {
// 编辑调用 // 编辑调用
const Edit = (row) => { const Edit = (row) => {
active_row.value = row; active_row.value = row;
router.push({
path: "/ticket/business-ticket-manage/edit",
query: {
id: row.id,
},
});
}; };
// 删除调用 // 删除调用
const selectedItems = ref([]); const selectedItems = ref([]);
...@@ -291,7 +288,11 @@ const selectRows = ({ selection }) => { ...@@ -291,7 +288,11 @@ const selectRows = ({ selection }) => {
selectedItems.value = selection; selectedItems.value = selection;
}; };
// 新增 // 新增
const AddWorkOrder = () => {}; const AddTicket = () => {
router.push({
path: "/ticket/business-ticket-manage/add",
});
};
// 批量删除 // 批量删除
const delBatch = () => { const delBatch = () => {
console.log(del_ids.value); console.log(del_ids.value);
...@@ -301,6 +302,14 @@ const listtable = ref(null); ...@@ -301,6 +302,14 @@ const listtable = ref(null);
const clearSelected = () => { const clearSelected = () => {
listtable.value.clearTable(); listtable.value.clearTable();
}; };
const goTo = ({ id }) => {
router.push({
path: "/ticket/business-ticket-manage/detail",
query: {
id,
},
});
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
<template>
<div class="add-form">
<el-form :model="state.form" ref="form" :rules="state.rules" label-width="80px">
<el-form-item label="工单名称" prop="ticket_name">
<el-input v-model="state.form.ticket_name" placeholder="请输入工单名称"></el-input>
</el-form-item>
<el-form-item label="工单等级" prop="ticket_level">
<el-select v-model="state.form.ticket_level" placeholder="请选择工单等级" clearable filterable style="flex: 1">
<el-option v-for="item in state.ticketLevelOptions" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="工单描述" prop="ticket_desc">
<el-input type="textarea" :rows="5" v-model="state.form.ticket_desc" placeholder="请输入工单描述"></el-input>
</el-form-item>
<el-form-item label="推送方式" prop="push_method">
<div style="flex: 1">
<ManualDistributionForm ref="manual_distribution_form" />
</div>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { computed, reactive, ref } from "vue";
import ManualDistributionForm from "@/components/manual-distribution/form.vue";
const manual_distribution_form = ref(null);
const TICKET_LEVEL_OPTIONS = [
{
id: 1,
name: "紧急任务",
},
{
id: 2,
name: "重要任务",
},
{
id: 3,
name: "一般任务",
},
];
const props = defineProps({
defaultValue: {
type: Object,
default: null,
},
});
const isEdit = computed(() => !!props.defaultValue);
console.log("isEdit: ", isEdit);
const state = reactive({
form: {
ticket_name: "",
ticket_level: "",
ticket_desc: "",
},
rules: {
ticket_name: [{ required: true, message: "请输入工单名称", trigger: "blur" }],
ticket_level: [{ required: true, message: "请选择工单等级", trigger: "change" }],
ticket_desc: [{ required: true, message: "请输入工单描述", trigger: "blur" }],
},
ticketLevelOptions: TICKET_LEVEL_OPTIONS,
});
</script>
<style lang="scss" scoped>
.add-form {
width: 100%;
max-width: 1050px;
}
</style>
...@@ -175,8 +175,7 @@ const detailInfo = ref([ ...@@ -175,8 +175,7 @@ const detailInfo = ref([
:deep(.gap-title) { :deep(.gap-title) {
margin-bottom: 16px; margin-bottom: 16px;
} }
.info, .info {
.feedback-info {
max-width: 1072px; max-width: 1072px;
width: 100%; width: 100%;
padding: 0 8px 0; padding: 0 8px 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment