• 三.运维平台之工单系统


    一.工单系统需求分析

     

     

     

    二.工单系统后端

    (python36env) [vagrant@CentOS devops]$ django-admin startapp workorder
    (python36env) [vagrant@CentOS devops]$ mv workorder apps/
    
    settings.py:
    INSTALLED_APPS = [
        .....
        'workorder',
        .......
    ]

    (1)apps/workorder/models.py:

    from django.db import models
    from users.models import User
    
    class WorkOrder(models.Model):
        TYPE = (
            (0, '数据库'),
            (1, 'WEB服务'),
            (2, '计划任务'),
            (3, '配置文件'),
            (4, '其它'),
        )
        STATUS = (
            (0, '申请'),
            (1, '处理中'),
            (2, '完成'),
            (3, '失败'),
        )
        title = models.CharField(max_length=100, verbose_name=u'工单标题')
        type = models.IntegerField(choices=TYPE, default=0, verbose_name=u'工单类型')
        order_contents = models.TextField(verbose_name='工单内容')
        applicant = models.ForeignKey(User, verbose_name=u'申请人', related_name='work_order_applicant',on_delete=models.CASCADE)
        assign_to = models.ForeignKey(User, verbose_name=u'指派给',on_delete=models.CASCADE)
        final_processor = models.ForeignKey(User, null=True, blank=True, verbose_name=u'最终处理人', related_name='final_processor',on_delete=models.CASCADE)
        status = models.IntegerField(choices=STATUS, default=0, verbose_name=u'工单状态')
        result_desc = models.TextField(verbose_name=u'处理结果', blank=True, null=True)
        apply_time = models.DateTimeField(auto_now_add=True, verbose_name=u'申请时间')
        complete_time = models.DateTimeField(auto_now=True, verbose_name=u'处理完成时间')
    
        def __str__(self):
            return self.title
    
        class Meta:
            verbose_name = '工单'
            verbose_name_plural = verbose_name
            ordering = ['-complete_time']

    (python36env) [vagrant@CentOS devops]$ python manage.py makemigrations workorder

    (python36env) [vagrant@CentOS devops]$ python manage.py migrate workorder

    (2)workorder/serializers.py:

    from rest_framework import serializers
    from django.contrib.auth import get_user_model
    from .models import WorkOrder
    from datetime import  datetime
    
    User = get_user_model()
    
    
    class WorkOrderSerializer(serializers.ModelSerializer):
        """
        工单序列化类
        """
        # 获取当前登陆用户,并将其赋值给数据库中对应的字段
        applicant = serializers.HiddenField(
            default=serializers.CurrentUserDefault())
        # 后端格式时间
        # apply_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
        # complete_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
    
        class Meta:
            model = WorkOrder
            fields = "__all__"
    
        def to_representation(self, instance):
            applicant_obj = instance.applicant
            assign_to_obj = instance.assign_to
            final_processor_obj = instance.final_processor
            type_value = instance.get_type_display()
            # print("new:", type_value)
            # print("old:", instance.type)
            status_value = instance.get_status_display()
            ret = super(WorkOrderSerializer, self).to_representation(instance)
            ret['type'] = {
                 "id": instance.type,
                 "name": type_value
            }
            ret['status'] = {
                "id": instance.status,
                "name": status_value
            }
            ret["applicant"] = {
                                   "id": applicant_obj.id,
                                   "name": applicant_obj.name
                               },
            ret["assign_to"] = {
                                   "id": assign_to_obj.id,
                                   "name": assign_to_obj.name
                               },
            if final_processor_obj:
                ret["final_processor"] = {
                                    "id": final_processor_obj.id,
                                    "name": final_processor_obj.name
                                },
            # print(ret)
            return ret
    
        # def create(self, validated_data):
        #     applicant = self.context['request'].user   #获取用户信息
        #     validated_data['applicant'] = applicant
        #     print(validated_data)
        #     instance = self.Meta.model.objects.create(**validated_data)
        #     instance.save()
        #     return instance
    
        # def update(self, instance, validated_data):
        #     final_processor = self.context['request'].user
        #     print(validated_data)
        #     validated_data['final_processor'] = final_processor
        #     instance = self.Meta.model.objects.filter(id=instance.id).update(**validated_data)
        #     return instance

    (3)workorder/views.py:

    from django.contrib.auth import get_user_model
    from rest_framework import viewsets, mixins,permissions, status
    from rest_framework.response import Response
    from rest_framework.pagination import PageNumberPagination
    from rest_framework import filters
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework.authentication import TokenAuthentication,BasicAuthentication,SessionAuthentication
    from rest_framework_jwt.authentication import JSONWebTokenAuthentication
    import    time
    
    from .serializers import WorkOrderSerializer
    from .models import WorkOrder
    
    User = get_user_model()
    
    
    class Pagination(PageNumberPagination):
        page_size = 10
        page_size_query_param = 'page_size'
        page_query_param = "page"
        max_page_size = 100
    
    
    class WorkOrderViewset(viewsets.ModelViewSet):
        """
        create:
        创建工单
        list:
        获取工单列表
        retrieve:
        获取工单信息
        update:
        更新更新信息
        delete:
        删除用户
        """
        authentication_classes = (JSONWebTokenAuthentication, TokenAuthentication, SessionAuthentication, BasicAuthentication)
        permission_classes = (permissions.IsAuthenticated, permissions.DjangoModelPermissions)
        queryset = WorkOrder.objects.all()
        serializer_class = WorkOrderSerializer
        pagination_class = Pagination
        filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
        search_fields = ('title', 'order_contents')
        ordering_fields = ('id',)
    
        def get_queryset(self):
            status = self.request.GET.get('status', None)
            applicant = self.request.user
            # 获取当前登陆用户所有组的信息, RBAC   用户-->组-->权限
            role = applicant.groups.all().values('name')
            # print(role)
            role_name = [r['name'] for r in role]
            # print(role_name)
            queryset = super(WorkOrderViewset, self).get_queryset()
    
            # 判断传来的status值判断是申请列表还是历史列表
            if status and int(status) == 1:
                queryset = queryset.filter(status__lte=int(status))
            elif status and int(status) == 2:
                queryset = queryset.filter(status__gte=int(status))
            else:
                pass
    
            # 判断登陆用户是否是管理员,是则显示所有工单,否则只显示自己的
            if "sa" not in role_name:
                queryset = queryset.filter(applicant=applicant)
            return queryset
    
        def partial_update(self, request, *args, **kwargs):
            pk = int(kwargs.get("pk"))
            print(pk)
            final_processor = self.request.user
            data = request.data
            data['final_processor'] = final_processor
            data['complete_time'] = time.strftime('%Y-%m-%d    %H:%M:%S', time.localtime(time.time()))
            print(data)
            WorkOrder.objects.filter(pk=pk).update(**data)
            return Response(status=status.HTTP_204_NO_CONTENT)

    (4)workorder/filters.py

    import django_filters
    
    from django.contrib.auth import get_user_model
    from.models import WorkOrder
    
    
    User = get_user_model()
    
    
    class WorkOrderFilter(django_filters.rest_framework.FilterSet):
        """
        工单过滤类
        """
        class Meta:
            model = WorkOrder
            fields = ['title']

    (5)workorder/router.py:

    from rest_framework.routers import DefaultRouter
    from .views import WorkOrderViewset
    
    workorder_router = DefaultRouter()
    workorder_router.register(r'workorder', WorkOrderViewset, basename="workorder")

    (6)devops/urls.py

    from workorder.router import workorder_router
    router.registry.extend(workorder_router.registry)

    效果如图:

     

    三.工单前端处理

    安装插件:

    F:devopsdatawebvueAdmin-template>npm install moment  --save

    1.工单基础页面实现

    (1)src/api/workorder/workorder.js

    import request from '@/utils/request'
    
    // 获取工单列表
    export function getWorkOrderList(params) {
      return request({
        url: '/api/workorder/',
        method: 'get',
        params
      })
    }
    
    // 创建工单
    export function createWorkOrder(data) {
      return request({
        url: '/api/workorder/',
        method: 'post',
        data
      })
    }
    
    // 修改工单
    export function updateWorkOrder(id, data) {
      return request({
        url: '/api/workorder/' + id + '/',
        method: 'patch',
        data
      })
    }
    
    // 删除工单
    export function deleteWorkOrder(id) {
      return request({
        url: '/api/workorder/' + id + '/',
        method: 'delete'
      })
    }

    (2)src/router/index.js

      {
        path: '/workorder',
        component: Layout,
        name: 'workorder',
        meta: { title: '工单系统', icon: 'form' },
        children: [
          {
            path: 'apply',
            name: '工单申请',
            meta: { title: '工单申请', icon: 'form' }
          },
          {
            path: 'list',
            name: '申请列表',
            component: () => import('@/views/workorder/list/index'),
            meta: { title: '申请列表', icon: 'table' }
          },
          {
            path: 'history',
            name: '工单历史',
            meta: { title: '工单历史', icon: 'table' }
          }
        ]
      },

    (3)views/workorder/list/index.vue

    <template>
      <div class="workorder">
        <div>
          <!--搜索-->
          <el-col :span="8">
            <el-input v-model="params.search" placeholder="搜索" @keyup.enter.native="searchClick">
              <el-button slot="append" icon="el-icon-search" @click="searchClick"/>
            </el-input>
          </el-col>
        </div>
    
        <!--表格-->
        <order-list :value="workorders" @rate="handleRate" @edit="handleEdit" @delete="handleDelete"/>
    
        <!--模态窗任务进度-->
        <el-dialog
          :title="currentValue.title"
          :visible.sync="dialogVisibleForRate"
          width="30%">
          <div style="height: 300px;">
            <el-steps :active="active" direction="vertical" finish-status="success" >
              <el-step
                v-for="(item,index) in rate"
                :title="item.title"
                :description="item.description"
                :key="index" />
            </el-steps>
          </div>
        </el-dialog>
    
        <!--模态窗工单处理-->
        <el-dialog
          :visible.sync="dialogVisibleForEdit"
          title="工单处理"
          width="50%">
          <order-form
            ref="workorderForm"
            :form="currentValue"
            @submit="handleSubmitEdit"
            @cancel="handleCancelEdit"/>
        </el-dialog>
    
        <!--分页-->
        <center>
          <el-pagination
            :page-size="pagesize"
            :total="totalNum"
            background
            layout="total, prev, pager, next, jumper"
            @current-change="handleCurrentChange"/>
        </center>
      </div>
    </template>
    
    <script>
      import { getWorkOrderList, updateWorkOrder } from '@/api/workorder/workorder'
      import OrderList from './table'
    
      export default {
        name: 'Workorder',
        components: {
          OrderList
        },
    
        data() {
          return {
            dialogVisibleForEdit: false,
            dialogVisibleForRate: false,
            currentValue: {},
            workorders: [],
            totalNum: 0,
            pagesize: 10,
            active: 1,
            apply: {},
            assign: {},
            final_processor: {},
            rate: [],
            params: {
              page: 1,
              search: '',
              status: 1
            }
          }
        },
    
        created() {
          this.fetchData()
        },
    
        methods: {
          fetchData() {
            getWorkOrderList(this.params).then(
              res => {
                this.workorders = res.results
                console.log(this.workorders)
                this.totalNum = res.count
              })
          },
          handleCurrentChange(val) {
            this.params.page = val
            this.fetchData()
          },
          searchClick() {
            this.fetchData()
          },
          /* 流程进度处理函数 */
          handleRate(value) {
            this.currentValue = { ...value }
            console.log(value)
            this.dialogVisibleForRate = true
            this.rate = []
            this.final_processor = {}
            this.apply['title'] = '任务申请: ' + value.applicant[0].name + ': ' + value.apply_time
            this.assign['title'] = '任务分配: ' + value.assign_to[0].name
            if (value.final_processor) {
              this.final_processor['title'] = '任务领取: ' + value.final_processor[0].name + ': ' + value.complete_time
              this.active = 3
            }
            this.rate.push(this.apply)
            this.rate.push(this.assign)
            this.rate.push(this.final_processor)
          },
    
          /*  处理工单,弹出模态窗、提交数据、取消 */
          handleEdit(value) {
            this.currentValue = { ...value }
            console.log(this.currentValue)
            const data = { 'status': 1 }
            const id = this.currentValue.id
            updateWorkOrder(id, data).then(res => {
              this.$message({
                message: '接受工单',
                type: 'success'
              })
              this.dialogVisibleForEdit = true
              this.fetchData()
            })
          },
    
          handleSubmitEdit(value) {
            const { id, ...params } = value // 很神奇,能把表单的值拆解成自己想要的样子
            console.log(params)
            const data = { 'status': 2, 'result_desc': params.result_desc }
            updateWorkOrder(id, data).then(res => {
              this.$message({
                message: '更新成功',
                type: 'success'
              })
              this.handleCancelEdit()
              this.fetchData()
            })
          },
          handleCancelEdit() {
            this.dialogVisibleForEdit = false
            this.$refs.workorderForm.$refs.form.resetFields()
          },
    
          /* 取消 */
          handleDelete(id) {
            const data = { 'status': 3 }
            updateWorkOrder(id, data).then(res => {
              this.$message({
                message: '取消成功',
                type: 'success'
              })
              this.fetchData()
            },
            err => {
              console.log(err.message)
            })
          }
        }
      }
    </script>
    
    <style lang='scss' scoped>
      .workorder {
        padding: 10px;
      }
    </style>

    (4)views/workorder/list/table.vue

    <template>
      <div class="workorder-list">
        <el-table
          :data="value"
          border
          stripe
          style=" 100%">
    
          <el-table-column type="expand">
            <template slot-scope="props">
              <span><pre>工单详情:{{ props.row.order_contents }}</pre></span>
            </template>
          </el-table-column>
    
          <el-table-column
            label="工单类型"
            prop="type.name"/>
    
          <el-table-column
            label="工单标题"
            prop="title"/>
    
          <el-table-column
            label="申请人"
            prop="applicant[0].name"/>
    
          <el-table-column
            label="工单状态"
            prop="status.name"/>
    
          <el-table-column
            label="任务进度"
            align="center">
            <template slot-scope="scope">
              <el-button type="text" size="small" @click="handleRate(scope.row)">
                {{ '任务进度' }}
              </el-button>
            </template>
          </el-table-column>
    
          <el-table-column
            :formatter="dateFormat"
            label="申请时间"
            prop="apply_time"
          />
    
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="primary"
                @click="handleEdit(scope.row)">处理</el-button>
    
              <el-button
                size="mini"
                type="danger"
                @click="handleDelete(scope.row)">取消</el-button>
            </template>
          </el-table-column>
    
        </el-table>
      </div>
    </template>
    
    <script>
    import moment from 'moment'
    
    export default {
      name: 'OrderList',
      props: {
        value: {
          type: Array,
          default: function() {
            return []
          }
        }
      },
      methods: {
        /* 点击编辑按钮,将子组件的事件传递给父组件 */
        handleEdit(value) {
          this.$emit('edit', value)
        },
    
        /* 流程进度 */
        handleRate(value) {
          this.$emit('rate', value)
        },
    
        /* 删除 */
        handleDelete(workorder) {
          const id = workorder.id
          const name = workorder.title
          this.$confirm(`此操作将删除: ${name}, 是否继续?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.$emit('delete', id)
          }).catch(() => {
            this.$message({
              type: 'info',
              message: '已取消删除'
            })
          })
        },
        dateFormat: function(row, column) {
          const date = row[column.property]
          if (date === undefined) {
            return ''
          }
          return moment(date).format('YYYY-MM-DD HH:mm:ss')
        }
    
      }
    }
    </script>
    
    <style lang='scss'>
    </style>

    效果如图:

     

     2.历史工单

    (1)src/router/index.js

        {
            path: 'history',
            name: '工单历史',
            component: () => import('@/views/workorder/history/index'),
            meta: { title: '工单历史', icon: 'table' }
          }

    (1)workorder/history/index.vue

    <template>
      <div class="workorder">
        <div>
          <!--搜索-->
          <el-col :span="8">
            <el-input v-model="params.search" placeholder="搜索" @keyup.enter.native="searchClick">
              <el-button slot="append" icon="el-icon-search" @click="searchClick"/>
            </el-input>
          </el-col>
        </div>
    
        <!--表格-->
        <order-list :value="workorders"/>
    
        <!--分页-->
        <center>
          <el-pagination
            :page-size="pagesize"
            :total="totalNum"
            background
            layout="total, prev, pager, next, jumper"
            @current-change="handleCurrentChange"/>
        </center>
      </div>
    </template>
    
    <script>
    import { getWorkOrderList } from '@/api/workorder/workorder'
    import OrderList from './table'
    
    export default {
      name: 'Workorder',
      components: {
        OrderList
      },
    
      data() {
        return {
          workorders: [],
          totalNum: 0,
          pagesize: 10,
          params: {
            page: 1,
            status: 2
          }
        }
      },
    
      created() {
        this.fetchData()
      },
    
      methods: {
        fetchData() {
          getWorkOrderList(this.params).then(
            res => {
              this.workorders = res.results
              console.log(this.workorders)
              this.totalNum = res.count
            })
        },
        handleCurrentChange(val) {
          this.params.page = val
          this.fetchData()
        },
        searchClick() {
          this.fetchData()
        }
    
      }
    
    }
    </script>
    
    <style lang='scss' scoped>
    .workorder {
      padding: 10px;
    }
    </style>

    (3)workorder/table.vue

    <template>
      <div class="workorder-list">
        <el-table
          :data="value"
          border
          stripe
          style=" 100%">
    
          <el-table-column type="expand">
            <template slot-scope="props">
              <span>工单详情:{{ props.row.order_contents }}</span>
              <br>
              <span>处理结果:{{ props.row.result_desc }}</span>
            </template>
          </el-table-column>
    
          <el-table-column
            label="工单类型"
            prop="type.name"/>
    
          <el-table-column
            label="工单标题"
            prop="title"/>
    
          <el-table-column
            label="申请人"
            prop="applicant[0].name"/>
    
          <el-table-column
            label="指派人"
            prop="assign_to[0].name"/>
    
          <el-table-column
            label="处理人"
            prop="final_processor[0].name"/>
    
          <el-table-column
            label="状态"
            prop="status.name"/>
    
          <el-table-column
            :formatter="dateFormat"
            label="申请时间"
            prop="apply_time"/>
    
          <el-table-column
            :formatter="dateFormat"
            label="完成时间"
            prop="complete_time"/>
    
        </el-table>
      </div>
    </template>
    
    <script>
    import moment from 'moment'
    export default {
      name: 'OrderList',
      props: {
        value: {
          type: Array,
          default: function() {
            return []
          }
        }
      },
      methods: {
        dateFormat: function(row, column) {
          var date = row[column.property]
          if (date === undefined) {
            return ''
          }
          return moment(date).format('YYYY-MM-DD HH:mm:ss')
        }
      }
    }
    </script>
    
    <style lang='scss'>
    .workorder-list {}
    </style>

    效果图:

     

    点击工单处理时报如错:

     

    jango.core.exceptions.ValidationError: ['’2020-07-21	22:55:55‘ 必须为合法的日期时间格式,请使用 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 格式。']

    解决:

    注掉workorder/views.py:
            # data['complete_time'] = time.strftime('%Y-%m-%d    %H:%M:%S', time.localtime(time.time()))
    并打开workorder/serializers.py:
    apply_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
    complete_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)

    3.工单状态流转及步骤条实现

    (1)workorder/list/form.vue

    <template>
      <div class="workorder-form">
        <el-form ref="form" :model="form" :rules="rules" label-width="100px" class="demo-form">
    
          <el-form-item label="工单标题" prop="title">
            <el-input v-model="form.title" readonly/>
          </el-form-item>
    
          <el-form-item label="工单内容" prop="order_contents">
            <el-input v-model="form.order_contents" type="textarea" rows="8" readonly/>
          </el-form-item>
    
          <el-form-item label="处理结果" prop="result_desc">
            <el-input v-model="form.result_desc"/>
          </el-form-item>
    
          <el-form-item>
            <div class="btn-wrapper">
              <el-button size="small" @click="cancel">取消</el-button>
              <el-button size="small" type="primary" @click="submitForm">保存</el-button>
            </div>
          </el-form-item>
    
        </el-form>
      </div>
    </template>
    
    <script>
    
    export default {
      name: 'OrderForm',
      props: {
        form: { // 接受父组件传递过来的值渲染表单
          type: Object,
          default() {
            return {
              title: '',
              order_contents: '',
              result_desc: ''
            }
          }
        }
      },
    
      data() {
        return {
          rules: {
            result_desc: [
              { required: true, message: '请输入处理结果', trigger: 'blur' }
            ]
          }
        }
      },
    
      methods: {
        submitForm() {
          this.$refs.form.validate(valid => {
            if (!valid) {
              return
            }
            this.$emit('submit', this.form)
          })
        },
        cancel() {
          this.$emit('cancel')
        }
      }
    }
    </script>
    
    <style lang='scss' scoped>
    .workorder-form {
      position: relative;
      display: block;
      .btn-wrapper{
        text-align: right;
      }
    }
    </style>

    (2)workorder/list/index.vue

    ...
    import OrderForm from './form'
    ....
      export default {
        name: 'Workorder',
        components: {
          OrderList,
          OrderForm
        },

    效果如图:

    点击工单处理时如下报错:[Vue warn]: Invalid prop: type check failed for prop "rows". Expected Number, got String.

     解决办法:

    form.vue:中改成如下
            <el-input :rows="8" v-model="form.order_contents" type="textarea"  readonly/>

    最终效果如下图:

     

     4.工单申请

    (1)workorder/apply/index.vue

    <template>
      <div class="apply">
        <el-form ref="form" :model="form" :rules="rules" label-width="180px">
          <el-form-item label="工单类型:" prop="type">
            <el-select v-model="form.type" placeholder="请选择工单类型" style=" 60%;">
              <el-option
                v-for="item in type_list"
                :key="item.index"
                :label="item.name"
                :value="item.id"/>
            </el-select>
          </el-form-item>
    
          <el-form-item label="工单标题:" prop="title">
            <el-input v-model="form.title" style=" 60%;"/>
          </el-form-item>
    
          <el-form-item label="工单内容:" prop="order_contents">
            <el-input :rows="8" v-model="form.order_contents" type="textarea"  style=" 60%;"/>
          </el-form-item>
    
          <el-form-item label="指派给:" prop="assign_to">
            <el-select v-model="form.assign_to" filterable placeholder="请选择工单处理人" style=" 60%;">
              <el-option
                v-for="item in sa_list"
                :key="item.index"
                :label="item.name"
                :value="item.id"/>
            </el-select>
          </el-form-item>
    
          <el-form-item>
            <el-button type="primary" @click="onSubmit">Create</el-button>
            <el-button @click="onCancel">Cancel</el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>
    
    <script>
    
    import { getGroupMemberList } from '@/api/group'
    import { createWorkOrder } from '@/api/workorder/workorder'
    export default {
      data() {
        return {
          form: {
            type: '',
            title: '',
            order_contents: '',
            assign_to: ''
          },
          rules: {
            type: [
              { required: true, message: '请输入工单类型', trigger: 'blur' }
            ],
            title: [
              { required: true, message: '请输人工单标题', trigger: 'blur' }
            ],
            order_contents: [
              { required: true, message: '请输人工单内容', trigger: 'blur' }
            ],
            assign_to: [
              { required: true, message: '请输人工单指派人', trigger: 'blur' }
            ]
    
          },
          sa_list: [],
          type_list: [{ 'id': 0, 'name': '数据库' }, { 'id': 1, 'name': '计划任务' }, { 'id': 2, 'name': '配置文件' }, { 'id': 3, 'name': '其他' }],
          state: 0
        }
      },
    
      watch: {
        state() {
          getGroupMemberList(6).then(res => {
            this.sa_list = res.members
            console.log(this.sa_list)
          })
        }
      },
    
      created() {
        this.state = 1
      },
    
      methods: {
        onSubmit() {
          this.$message('submit!')
          this.$refs.form.validate((valid) => {
            if (!valid) {
              return
            }
            const params = Object.assign({}, this.form)
            console.log(params)
            createWorkOrder(params).then(res => {
              this.$message({
                message: '创建成功',
                type: 'success'
              })
              this.$router.push({ path: '/workorder/list' })
            })
          })
        },
        onCancel() {
          this.$message({
            message: 'cancel!',
            type: 'warning'
          })
        }
      }
    
    }
    </script>
    
    <style scoped>
    .apply{
        margin-top:2cm;
    }
    </style>

    (2)src/router/index.js

    import Vue from 'vue'
    import Router from 'vue-router'
    
    // in development-env not use lazy-loading, because lazy-loading too many pages will cause webpack hot update too slow. so only in production use lazy-loading;
    // detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
    
    Vue.use(Router)
    
    /* Layout */
    import Layout from '../views/layout/Layout'
    
    /**
     * hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
     * alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
     *                                if not set alwaysShow, only more than one route under the children
     *                                it will becomes nested mode, otherwise not show the root menu
     * redirect: noredirect           if `redirect:noredirect` will no redirect in the breadcrumb
     * name:'router-name'             the name is used by <keep-alive> (must set!!!)
     * meta : {
        title: 'title'               the name show in submenu and breadcrumb (recommend set)
        icon: 'svg-name'             the icon show in the sidebar,
      }
     **/
    export const constantRouterMap = [
      { path: '/login', component: () => import('@/views/login/index'), hidden: true },
      { path: '/404', component: () => import('@/views/404'), hidden: true },
      {
        path: '/',
        component: Layout,
        redirect: '/dashboard',
        name: 'Dashboard',
        children: [{
          path: 'dashboard',
          component: () => import('@/views/dashboard/index'),
          meta: { title: 'dashboard', icon: 'example' }
        }]
      },
      {
        path: '/users',
        component: Layout,
        name: 'users',
        meta: { title: '用户管理', icon: 'example' },
        children: [
          {
            path: 'user',
            name: 'user',
            component: () => import('@/views/users/user'),
            meta: { title: '用户' }
          },
          {
            path: 'groups',
            name: 'groups',
            permission: 'resources.add_ip',
            component: () => import('@/views/groups'),
            meta: { title: '用户组' }
          }
        ]
      },
      {
        path: '/workorder',
        component: Layout,
        name: 'workorder',
        meta: { title: '工单系统', icon: 'form' },
        children: [
          {
            path: 'apply',
            name: '工单申请',
            component: () => import('@/views/workorder/apply/index'),
            meta: { title: '工单申请', icon: 'form' }
          },
          {
            path: 'list',
            name: '申请列表',
            component: () => import('@/views/workorder/list/index'),
            meta: { title: '申请列表', icon: 'table' }
          },
          {
            path: 'history',
            name: '工单历史',
            component: () => import('@/views/workorder/history/index'),
            meta: { title: '工单历史', icon: 'table' }
          }
        ]
      },
      { path: '*', redirect: '/404', hidden: true }
    ]
    
    export default new Router({
      mode: 'history',
      scrollBehavior: () => ({ y: 0 }),
      routes: constantRouterMap
    })

    效果如下图:但是却获取不到用户列表---no data

     

    1

  • 相关阅读:
    VB.NET 操作Json 包括嵌套的
    c#和VB混用出现的错误
    System.ArgumentException: 另一个SqlParameterCollection中已包含SqlParameter。
    centos vsftpd 安装配置
    linux centos apache+php+mysql 安装( 用包安装 非yum 安装)
    迟到的一笔 php 5 apache 2.2 webservice 创建与配置
    linux centos apache+php+mysql 安装
    php 不能连接数据库 php error Can't connect to local MySQL server through socket '/tmp/mysql.sock'
    内置过渡动画
    Input 输入框
  • 原文地址:https://www.cnblogs.com/dbslinux/p/13352932.html
Copyright © 2020-2023  润新知