Commit a1e5f8ff authored by 张耀's avatar 张耀

feat:

工单管理开发
parent 3fbbf1d9
export const TIMEING_RULES = {
1: '手动下发',
2: '按周',
3: '自定义时间'
}
\ No newline at end of file
<template>
<el-form
:model="state.form"
ref="form"
:rules="state.rules"
label-width="80px"
:disabled="disabled"
>
<el-form :model="state.form" ref="form" :rules="state.rules" label-width="80px" :disabled="disabled">
<el-form-item label="通知方式" prop="method">
<el-checkbox-group v-model="state.form.method">
<el-checkbox v-for="(value, key) in METHODS" :key="key" :label="key">
......@@ -14,68 +8,59 @@
</el-checkbox-group>
</el-form-item>
<el-form-item label="" prop="lists" class="user-table bg-scroll">
<el-table :data="state.form.lists" stripe border>
<el-table-column type="index" label="序号" width="60px">
</el-table-column>
<el-table-column
v-for="header in headers"
:prop="header.prop"
:key="header.prop"
:label="header.label"
:width="header.width"
>
<template #default="{ $index }">
<div v-if="header.prop == 'user_id'">
<el-select
v-model="state.form.lists[$index].user_id"
placeholder="请选择"
filterable
@change="($event) => chooseUser($event, $index)"
>
<el-option
v-for="item in userOptions($index)"
:key="item.user_id"
:label="item.user_id"
:value="item.user_id"
>
</el-option>
</el-select>
</div>
<div v-else>
<el-input
v-model="state.form.lists[$index][header.prop]"
placeholder="请输入"
></el-input>
</div>
</template>
</el-table-column>
<el-table-column prop="" label="操作" width="125px">
<template #default="{ $index }">
<div class="table-operation">
<el-button
link
type="primary"
@click="Add($index)"
:disabled="
userLists.length <= state.form.lists.length ||
addTrue >= ADD_NUM
"
>
新增
</el-button>
<span class="line"></span>
<el-button
link
type="primary"
@click="Remove($index)"
:disabled="state.form.lists.length == 1"
>
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<el-form :model="state.form.lists" ref="table_form" :rules="table_rules" label-width="0">
<el-table :data="state.form.lists" stripe border>
<el-table-column type="index" label="序号" width="60px"> </el-table-column>
<el-table-column
v-for="header in headers"
:prop="header.prop"
:key="header.prop"
:label="header.label"
:width="header.width">
<template #default="{ $index }">
<div v-if="header.prop == 'user_id'">
<el-form-item :prop="`[${$index}].user_id`" :rules="state.tableRules.user_id">
<el-select
v-model="state.form.lists[$index].user_id"
placeholder="请选择"
filterable
@change="($event) => chooseUser($event, $index)">
<el-option
v-for="item in userOptions($index)"
:key="item.user_id"
:label="item.user_id"
:value="item.user_id">
</el-option>
</el-select>
</el-form-item>
</div>
<div v-else>
<el-form-item :prop="`[${$index}].${header.prop}`" :rules="state.tableRules[header.prop]">
<el-input v-model="state.form.lists[$index][header.prop]" placeholder="请输入"></el-input>
</el-form-item>
</div>
</template>
</el-table-column>
<el-table-column prop="" label="操作" width="125px">
<template #default="{ $index }">
<div class="table-operation">
<el-button
link
type="primary"
@click="Add($index)"
:disabled="userLists.length <= state.form.lists.length || addTrue >= ADD_NUM">
新增
</el-button>
<span class="line"></span>
<el-button link type="primary" @click="Remove($index)" :disabled="state.form.lists.length == 1">
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</el-form>
</el-form-item>
</el-form>
</template>
......@@ -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列表
const selectedUser = computed(() => {
......@@ -126,12 +116,18 @@ const headers = [
label: "联系方式",
},
];
const table_form = ref(null);
// 立即下发
const Submit = (cb = null) => {
form.value.validate((valid) => {
if (valid) {
console.log(state.form);
cb && cb();
table_form.value.validate((t_v) => {
if (t_v) {
cb && cb(state.form);
} else {
return false;
}
});
} else {
return false;
}
......@@ -223,9 +219,7 @@ const init = (history) => {
};
// 选择用户操作
const chooseUser = ($event, index) => {
let user = userLists.value.find(
(e) => e.user_id == state.form.lists[index].user_id
);
let user = userLists.value.find((e) => e.user_id == state.form.lists[index].user_id);
state.form.lists[index].user_name = user.user_name;
state.form.lists[index].phone = user.phone;
};
......
<template>
<el-dialog
v-model="show"
width="804px"
top="10vh"
:close-on-click-modal="false"
:before-close="beforeClose"
>
<el-dialog v-model="show" width="804px" top="10vh" :close-on-click-modal="false" :before-close="beforeClose">
<template #header>
<GapTitle title="手动下发"></GapTitle>
</template>
......@@ -14,9 +8,7 @@
</div>
<template #footer>
<el-button size="default" @click="Close">关闭</el-button>
<el-button type="primary" size="default" @click="Submit">
立即下发
</el-button>
<el-button type="primary" size="default" @click="Submit"> 立即下发 </el-button>
</template>
</el-dialog>
</template>
......@@ -88,7 +80,10 @@ const beforeClose = () => {
};
// 立即下发
const Submit = () => {
form.value.Submit(() => {
form.value.Submit(async (form) => {
let res = { ...form };
console.log("res: ", res);
await nextTick();
Close();
});
};
......
......@@ -175,8 +175,7 @@ const detailInfo = ref([
:deep(.gap-title) {
margin-bottom: 16px;
}
.info,
.feedback-info {
.info {
max-width: 1072px;
width: 100%;
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 @@
<div class="breadcrumb">
<bg-breadcrumb />
</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>
</template>
<script setup>
import { ref } from "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>
<style lang="scss" scoped>
......@@ -26,6 +276,44 @@ import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
background-color: #ffffff;
box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15);
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>
<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 @@
<bg-breadcrumb />
</div>
<div class="content">
<bg-filter-group
@search="changeSearch"
v-model="filter.key_word"
placeholder="请输入任务名称">
<bg-filter-group @search="changeSearch" v-model="filter.key_word" placeholder="请输入任务名称">
<template v-slot:left_action>
<div class="apaas_button">
<el-button type="primary" @click="AddWorkOrder">
<bg-icon
style="font-size: 12px; color: #fff; margin-right: 8px"
icon="#bg-ic-add"></bg-icon>
<el-button type="primary" @click="AddTicket">
<bg-icon style="font-size: 12px; color: #fff; margin-right: 8px" icon="#bg-ic-add"></bg-icon>
新增
</el-button>
<el-button type="primary" @click="delBatch"> 批量删除 </el-button>
......@@ -89,8 +84,8 @@
:select="true"
@selectAc="selectRows"
:stripe="true">
<template #work_order_name="{ row }">
<div class="href" @click="goTo(row)">{{ row.work_order_name || "-" }}</div>
<template #ticket_name="{ row }">
<div class="href" @click="goTo(row)">{{ row.ticket_name || "-" }}</div>
</template>
<template #status="{ row }">
<span>
......@@ -177,21 +172,17 @@ const ruleOptions = ref([
let headers = reactive([
{
label: "工单名称",
prop: "work_order_name",
prop: "ticket_name",
align: "left",
href: {
baseurl: "/ticket/business-ticket-manage/detail",
params: { id: "id", name: "work_order_name" },
},
},
{
label: "工单等级",
prop: "work_order_level",
prop: "ticket_level",
align: "left",
},
{
label: "实例工单数",
prop: "example_work_order_num",
prop: "example_ticket_num",
align: "left",
},
{
......@@ -228,9 +219,9 @@ let headers = reactive([
},
]);
let rows = ref([
{ work_order_name: 11, id: 111, status: 1, finish: 10, all: 10 },
{ work_order_name: 22, id: 222, status: 2, finish: 5, all: 10 },
{ work_order_name: 33, id: 333, status: 3, finish: 0, all: 10 },
{ 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 changeSize = (size) => {
filter.limit = size;
......@@ -276,6 +267,12 @@ const operation = (row) => {
// 编辑调用
const Edit = (row) => {
active_row.value = row;
router.push({
path: "/ticket/business-ticket-manage/edit",
query: {
id: row.id,
},
});
};
// 删除调用
const selectedItems = ref([]);
......@@ -291,7 +288,11 @@ const selectRows = ({ selection }) => {
selectedItems.value = selection;
};
// 新增
const AddWorkOrder = () => {};
const AddTicket = () => {
router.push({
path: "/ticket/business-ticket-manage/add",
});
};
// 批量删除
const delBatch = () => {
console.log(del_ids.value);
......@@ -301,6 +302,14 @@ const listtable = ref(null);
const clearSelected = () => {
listtable.value.clearTable();
};
const goTo = ({ id }) => {
router.push({
path: "/ticket/business-ticket-manage/detail",
query: {
id,
},
});
};
</script>
<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([
:deep(.gap-title) {
margin-bottom: 16px;
}
.info,
.feedback-info {
.info {
max-width: 1072px;
width: 100%;
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