一.工单系统需求分析

 

 

 

 

 

 

二.工单系统后端

  1. (python36env) [vagrant@CentOS devops]$ django-admin startapp workorder
  2. (python36env) [vagrant@CentOS devops]$ mv workorder apps/
  3. settings.py:
  4. INSTALLED_APPS = [
  5. .....
  6. \'workorder\',
  7. .......
  8. ]

(1)apps/workorder/models.py:

  1. from django.db import models
  2. from users.models import User
  3. class WorkOrder(models.Model):
  4. TYPE = (
  5. (0, \'数据库\'),
  6. (1, \'WEB服务\'),
  7. (2, \'计划任务\'),
  8. (3, \'配置文件\'),
  9. (4, \'其它\'),
  10. )
  11. STATUS = (
  12. (0, \'申请\'),
  13. (1, \'处理中\'),
  14. (2, \'完成\'),
  15. (3, \'失败\'),
  16. )
  17. title = models.CharField(max_length=100, verbose_name=u\'工单标题\')
  18. type = models.IntegerField(choices=TYPE, default=0, verbose_name=u\'工单类型\')
  19. order_contents = models.TextField(verbose_name=\'工单内容\')
  20. applicant = models.ForeignKey(User, verbose_name=u\'申请人\', related_name=\'work_order_applicant\',on_delete=models.CASCADE)
  21. assign_to = models.ForeignKey(User, verbose_name=u\'指派给\',on_delete=models.CASCADE)
  22. final_processor = models.ForeignKey(User, null=True, blank=True, verbose_name=u\'最终处理人\', related_name=\'final_processor\',on_delete=models.CASCADE)
  23. status = models.IntegerField(choices=STATUS, default=0, verbose_name=u\'工单状态\')
  24. result_desc = models.TextField(verbose_name=u\'处理结果\', blank=True, null=True)
  25. apply_time = models.DateTimeField(auto_now_add=True, verbose_name=u\'申请时间\')
  26. complete_time = models.DateTimeField(auto_now=True, verbose_name=u\'处理完成时间\')
  27. def __str__(self):
  28. return self.title
  29. class Meta:
  30. verbose_name = \'工单\'
  31. verbose_name_plural = verbose_name
  32. 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:

  1. from rest_framework import serializers
  2. from django.contrib.auth import get_user_model
  3. from .models import WorkOrder
  4. from datetime import datetime
  5. User = get_user_model()
  6. class WorkOrderSerializer(serializers.ModelSerializer):
  7. """
  8. 工单序列化类
  9. """
  10. # 获取当前登陆用户,并将其赋值给数据库中对应的字段
  11. applicant = serializers.HiddenField(
  12. default=serializers.CurrentUserDefault())
  13. # 后端格式时间
  14. # apply_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
  15. # complete_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
  16.  
  17. class Meta:
  18. model = WorkOrder
  19. fields = "__all__"
  20.  
  21. def to_representation(self, instance):
  22. applicant_obj = instance.applicant
  23. assign_to_obj = instance.assign_to
  24. final_processor_obj = instance.final_processor
  25. type_value = instance.get_type_display()
  26. # print("new:", type_value)
  27. # print("old:", instance.type)
  28. status_value = instance.get_status_display()
  29. ret = super(WorkOrderSerializer, self).to_representation(instance)
  30. ret[\'type\'] = {
  31. "id": instance.type,
  32. "name": type_value
  33. }
  34. ret[\'status\'] = {
  35. "id": instance.status,
  36. "name": status_value
  37. }
  38. ret["applicant"] = {
  39. "id": applicant_obj.id,
  40. "name": applicant_obj.name
  41. },
  42. ret["assign_to"] = {
  43. "id": assign_to_obj.id,
  44. "name": assign_to_obj.name
  45. },
  46. if final_processor_obj:
  47. ret["final_processor"] = {
  48. "id": final_processor_obj.id,
  49. "name": final_processor_obj.name
  50. },
  51. # print(ret)
  52. return ret
  53. # def create(self, validated_data):
  54. # applicant = self.context[\'request\'].user #获取用户信息
  55. # validated_data[\'applicant\'] = applicant
  56. # print(validated_data)
  57. # instance = self.Meta.model.objects.create(**validated_data)
  58. # instance.save()
  59. # return instance
  60.  
  61. # def update(self, instance, validated_data):
  62. # final_processor = self.context[\'request\'].user
  63. # print(validated_data)
  64. # validated_data[\'final_processor\'] = final_processor
  65. # instance = self.Meta.model.objects.filter(id=instance.id).update(**validated_data)
  66. # return instance

(3)workorder/views.py:

  1. from django.contrib.auth import get_user_model
  2. from rest_framework import viewsets, mixins,permissions, status
  3. from rest_framework.response import Response
  4. from rest_framework.pagination import PageNumberPagination
  5. from rest_framework import filters
  6. from django_filters.rest_framework import DjangoFilterBackend
  7. from rest_framework.authentication import TokenAuthentication,BasicAuthentication,SessionAuthentication
  8. from rest_framework_jwt.authentication import JSONWebTokenAuthentication
  9. import time
  10. from .serializers import WorkOrderSerializer
  11. from .models import WorkOrder
  12. User = get_user_model()
  13. class Pagination(PageNumberPagination):
  14. page_size = 10
  15. page_size_query_param = \'page_size\'
  16. page_query_param = "page"
  17. max_page_size = 100
  18.  
  19.  
  20. class WorkOrderViewset(viewsets.ModelViewSet):
  21. """
  22. create:
  23. 创建工单
  24. list:
  25. 获取工单列表
  26. retrieve:
  27. 获取工单信息
  28. update:
  29. 更新更新信息
  30. delete:
  31. 删除用户
  32. """
  33. authentication_classes = (JSONWebTokenAuthentication, TokenAuthentication, SessionAuthentication, BasicAuthentication)
  34. permission_classes = (permissions.IsAuthenticated, permissions.DjangoModelPermissions)
  35. queryset = WorkOrder.objects.all()
  36. serializer_class = WorkOrderSerializer
  37. pagination_class = Pagination
  38. filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
  39. search_fields = (\'title\', \'order_contents\')
  40. ordering_fields = (\'id\',)
  41. def get_queryset(self):
  42. status = self.request.GET.get(\'status\', None)
  43. applicant = self.request.user
  44. # 获取当前登陆用户所有组的信息, RBAC 用户-->组-->权限
  45. role = applicant.groups.all().values(\'name\')
  46. # print(role)
  47. role_name = [r[\'name\'] for r in role]
  48. # print(role_name)
  49. queryset = super(WorkOrderViewset, self).get_queryset()
  50. # 判断传来的status值判断是申请列表还是历史列表
  51. if status and int(status) == 1:
  52. queryset = queryset.filter(status__lte=int(status))
  53. elif status and int(status) == 2:
  54. queryset = queryset.filter(status__gte=int(status))
  55. else:
  56. pass
  57.  
  58. # 判断登陆用户是否是管理员,是则显示所有工单,否则只显示自己的
  59. if "sa" not in role_name:
  60. queryset = queryset.filter(applicant=applicant)
  61. return queryset
  62. def partial_update(self, request, *args, **kwargs):
  63. pk = int(kwargs.get("pk"))
  64. print(pk)
  65. final_processor = self.request.user
  66. data = request.data
  67. data[\'final_processor\'] = final_processor
  68. data[\'complete_time\'] = time.strftime(\'%Y-%m-%d %H:%M:%S\', time.localtime(time.time()))
  69. print(data)
  70. WorkOrder.objects.filter(pk=pk).update(**data)
  71. return Response(status=status.HTTP_204_NO_CONTENT)

(4)workorder/filters.py

  1. import django_filters
  2. from django.contrib.auth import get_user_model
  3. from.models import WorkOrder
  4. User = get_user_model()
  5. class WorkOrderFilter(django_filters.rest_framework.FilterSet):
  6. """
  7. 工单过滤类
  8. """
  9. class Meta:
  10. model = WorkOrder
  11. fields = [\'title\']

(5)workorder/router.py:

  1. from rest_framework.routers import DefaultRouter
  2. from .views import WorkOrderViewset
  3. workorder_router = DefaultRouter()
  4. workorder_router.register(r\'workorder\', WorkOrderViewset, basename="workorder")

(6)devops/urls.py

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

效果如图:

 

 

三.工单前端处理

安装插件:

F:\devops\data\web\vueAdmin-template>npm install moment  –save

1.工单基础页面实现

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

  1. import request from \'@/utils/request\'
  2.  
  3. // 获取工单列表
  4. export function getWorkOrderList(params) {
  5. return request({
  6. url: \'/api/workorder/\',
  7. method: \'get\',
  8. params
  9. })
  10. }
  11. // 创建工单
  12. export function createWorkOrder(data) {
  13. return request({
  14. url: \'/api/workorder/\',
  15. method: \'post\',
  16. data
  17. })
  18. }
  19. // 修改工单
  20. export function updateWorkOrder(id, data) {
  21. return request({
  22. url: \'/api/workorder/\' + id + \'/\',
  23. method: \'patch\',
  24. data
  25. })
  26. }
  27. // 删除工单
  28. export function deleteWorkOrder(id) {
  29. return request({
  30. url: \'/api/workorder/\' + id + \'/\',
  31. method: \'delete\'
  32. })
  33. }

(2)src/router/index.js

  1. {
  2. path: \'/workorder\',
  3. component: Layout,
  4. name: \'workorder\',
  5. meta: { title: \'工单系统\', icon: \'form\' },
  6. children: [
  7. {
  8. path: \'apply\',
  9. name: \'工单申请\',
  10. meta: { title: \'工单申请\', icon: \'form\' }
  11. },
  12. {
  13. path: \'list\',
  14. name: \'申请列表\',
  15. component: () => import(\'@/views/workorder/list/index\'),
  16. meta: { title: \'申请列表\', icon: \'table\' }
  17. },
  18. {
  19. path: \'history\',
  20. name: \'工单历史\',
  21. meta: { title: \'工单历史\', icon: \'table\' }
  22. }
  23. ]
  24. },

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

  1. <template>
  2. <div class="workorder">
  3. <div>
  4. <!--搜索-->
  5. <el-col :span="8">
  6. <el-input v-model="params.search" placeholder="搜索" @keyup.enter.native="searchClick">
  7. <el-button slot="append" icon="el-icon-search" @click="searchClick"/>
  8. </el-input>
  9. </el-col>
  10. </div>
  11.  
  12. <!--表格-->
  13. <order-list :value="workorders" @rate="handleRate" @edit="handleEdit" @delete="handleDelete"/>
  14.  
  15. <!--模态窗任务进度-->
  16. <el-dialog
  17. :title="currentValue.title"
  18. :visible.sync="dialogVisibleForRate"
  19. width="30%">
  20. <div style="height: 300px;">
  21. <el-steps :active="active" direction="vertical" finish-status="success" >
  22. <el-step
  23. v-for="(item,index) in rate"
  24. :title="item.title"
  25. :description="item.description"
  26. :key="index" />
  27. </el-steps>
  28. </div>
  29. </el-dialog>
  30.  
  31. <!--模态窗工单处理-->
  32. <el-dialog
  33. :visible.sync="dialogVisibleForEdit"
  34. title="工单处理"
  35. width="50%">
  36. <order-form
  37. ref="workorderForm"
  38. :form="currentValue"
  39. @submit="handleSubmitEdit"
  40. @cancel="handleCancelEdit"/>
  41. </el-dialog>
  42.  
  43. <!--分页-->
  44. <center>
  45. <el-pagination
  46. :page-size="pagesize"
  47. :total="totalNum"
  48. background
  49. layout="total, prev, pager, next, jumper"
  50. @current-change="handleCurrentChange"/>
  51. </center>
  52. </div>
  53. </template>
  54.  
  55. <script>
  56. import { getWorkOrderList, updateWorkOrder } from \'@/api/workorder/workorder\'
  57. import OrderList from \'./table\'
  58. export default {
  59. name: \'Workorder\',
  60. components: {
  61. OrderList
  62. },
  63. data() {
  64. return {
  65. dialogVisibleForEdit: false,
  66. dialogVisibleForRate: false,
  67. currentValue: {},
  68. workorders: [],
  69. totalNum: 0,
  70. pagesize: 10,
  71. active: 1,
  72. apply: {},
  73. assign: {},
  74. final_processor: {},
  75. rate: [],
  76. params: {
  77. page: 1,
  78. search: \'\',
  79. status: 1
  80. }
  81. }
  82. },
  83. created() {
  84. this.fetchData()
  85. },
  86. methods: {
  87. fetchData() {
  88. getWorkOrderList(this.params).then(
  89. res => {
  90. this.workorders = res.results
  91. console.log(this.workorders)
  92. this.totalNum = res.count
  93. })
  94. },
  95. handleCurrentChange(val) {
  96. this.params.page = val
  97. this.fetchData()
  98. },
  99. searchClick() {
  100. this.fetchData()
  101. },
  102. /* 流程进度处理函数 */
  103. handleRate(value) {
  104. this.currentValue = { ...value }
  105. console.log(value)
  106. this.dialogVisibleForRate = true
  107. this.rate = []
  108. this.final_processor = {}
  109. this.apply[\'title\'] = \'任务申请: \' + value.applicant[0].name + \': \' + value.apply_time
  110. this.assign[\'title\'] = \'任务分配: \' + value.assign_to[0].name
  111. if (value.final_processor) {
  112. this.final_processor[\'title\'] = \'任务领取: \' + value.final_processor[0].name + \': \' + value.complete_time
  113. this.active = 3
  114. }
  115. this.rate.push(this.apply)
  116. this.rate.push(this.assign)
  117. this.rate.push(this.final_processor)
  118. },
  119. /* 处理工单,弹出模态窗、提交数据、取消 */
  120. handleEdit(value) {
  121. this.currentValue = { ...value }
  122. console.log(this.currentValue)
  123. const data = { \'status\': 1 }
  124. const id = this.currentValue.id
  125. updateWorkOrder(id, data).then(res => {
  126. this.$message({
  127. message: \'接受工单\',
  128. type: \'success\'
  129. })
  130. this.dialogVisibleForEdit = true
  131. this.fetchData()
  132. })
  133. },
  134. handleSubmitEdit(value) {
  135. const { id, ...params } = value // 很神奇,能把表单的值拆解成自己想要的样子
  136. console.log(params)
  137. const data = { \'status\': 2, \'result_desc\': params.result_desc }
  138. updateWorkOrder(id, data).then(res => {
  139. this.$message({
  140. message: \'更新成功\',
  141. type: \'success\'
  142. })
  143. this.handleCancelEdit()
  144. this.fetchData()
  145. })
  146. },
  147. handleCancelEdit() {
  148. this.dialogVisibleForEdit = false
  149. this.$refs.workorderForm.$refs.form.resetFields()
  150. },
  151. /* 取消 */
  152. handleDelete(id) {
  153. const data = { \'status\': 3 }
  154. updateWorkOrder(id, data).then(res => {
  155. this.$message({
  156. message: \'取消成功\',
  157. type: \'success\'
  158. })
  159. this.fetchData()
  160. },
  161. err => {
  162. console.log(err.message)
  163. })
  164. }
  165. }
  166. }
  167. </script>
  168.  
  169. <style lang=\'scss\' scoped>
  170. .workorder {
  171. padding: 10px;
  172. }
  173. </style>

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

  1. <template>
  2. <div class="workorder-list">
  3. <el-table
  4. :data="value"
  5. border
  6. stripe
  7. style="width: 100%">
  8.  
  9. <el-table-column type="expand">
  10. <template slot-scope="props">
  11. <span><pre>工单详情:{{ props.row.order_contents }}</pre></span>
  12. </template>
  13. </el-table-column>
  14.  
  15. <el-table-column
  16. label="工单类型"
  17. prop="type.name"/>
  18.  
  19. <el-table-column
  20. label="工单标题"
  21. prop="title"/>
  22.  
  23. <el-table-column
  24. label="申请人"
  25. prop="applicant[0].name"/>
  26.  
  27. <el-table-column
  28. label="工单状态"
  29. prop="status.name"/>
  30.  
  31. <el-table-column
  32. label="任务进度"
  33. align="center">
  34. <template slot-scope="scope">
  35. <el-button type="text" size="small" @click="handleRate(scope.row)">
  36. {{ \'任务进度\' }}
  37. </el-button>
  38. </template>
  39. </el-table-column>
  40.  
  41. <el-table-column
  42. :formatter="dateFormat"
  43. label="申请时间"
  44. prop="apply_time"
  45. />
  46.  
  47. <el-table-column label="操作">
  48. <template slot-scope="scope">
  49. <el-button
  50. size="mini"
  51. type="primary"
  52. @click="handleEdit(scope.row)">处理</el-button>
  53.  
  54. <el-button
  55. size="mini"
  56. type="danger"
  57. @click="handleDelete(scope.row)">取消</el-button>
  58. </template>
  59. </el-table-column>
  60.  
  61. </el-table>
  62. </div>
  63. </template>
  64.  
  65. <script>
  66. import moment from \'moment\'
  67. export default {
  68. name: \'OrderList\',
  69. props: {
  70. value: {
  71. type: Array,
  72. default: function() {
  73. return []
  74. }
  75. }
  76. },
  77. methods: {
  78. /* 点击编辑按钮,将子组件的事件传递给父组件 */
  79. handleEdit(value) {
  80. this.$emit(\'edit\', value)
  81. },
  82. /* 流程进度 */
  83. handleRate(value) {
  84. this.$emit(\'rate\', value)
  85. },
  86. /* 删除 */
  87. handleDelete(workorder) {
  88. const id = workorder.id
  89. const name = workorder.title
  90. this.$confirm(`此操作将删除: ${name}, 是否继续?`, \'提示\', {
  91. confirmButtonText: \'确定\',
  92. cancelButtonText: \'取消\',
  93. type: \'warning\'
  94. }).then(() => {
  95. this.$emit(\'delete\', id)
  96. }).catch(() => {
  97. this.$message({
  98. type: \'info\',
  99. message: \'已取消删除\'
  100. })
  101. })
  102. },
  103. dateFormat: function(row, column) {
  104. const date = row[column.property]
  105. if (date === undefined) {
  106. return \'\'
  107. }
  108. return moment(date).format(\'YYYY-MM-DD HH:mm:ss\')
  109. }
  110. }
  111. }
  112. </script>
  113.  
  114. <style lang=\'scss\'>
  115. </style>

效果如图:

 

 2.历史工单

(1)src/router/index.js

  1. {
  2. path: \'history\',
  3. name: \'工单历史\',
  4. component: () => import(\'@/views/workorder/history/index\'),
  5. meta: { title: \'工单历史\', icon: \'table\' }
  6. }

(1)workorder/history/index.vue

  1. <template>
  2. <div class="workorder">
  3. <div>
  4. <!--搜索-->
  5. <el-col :span="8">
  6. <el-input v-model="params.search" placeholder="搜索" @keyup.enter.native="searchClick">
  7. <el-button slot="append" icon="el-icon-search" @click="searchClick"/>
  8. </el-input>
  9. </el-col>
  10. </div>
  11.  
  12. <!--表格-->
  13. <order-list :value="workorders"/>
  14.  
  15. <!--分页-->
  16. <center>
  17. <el-pagination
  18. :page-size="pagesize"
  19. :total="totalNum"
  20. background
  21. layout="total, prev, pager, next, jumper"
  22. @current-change="handleCurrentChange"/>
  23. </center>
  24. </div>
  25. </template>
  26.  
  27. <script>
  28. import { getWorkOrderList } from \'@/api/workorder/workorder\'
  29. import OrderList from \'./table\'
  30. export default {
  31. name: \'Workorder\',
  32. components: {
  33. OrderList
  34. },
  35. data() {
  36. return {
  37. workorders: [],
  38. totalNum: 0,
  39. pagesize: 10,
  40. params: {
  41. page: 1,
  42. status: 2
  43. }
  44. }
  45. },
  46. created() {
  47. this.fetchData()
  48. },
  49. methods: {
  50. fetchData() {
  51. getWorkOrderList(this.params).then(
  52. res => {
  53. this.workorders = res.results
  54. console.log(this.workorders)
  55. this.totalNum = res.count
  56. })
  57. },
  58. handleCurrentChange(val) {
  59. this.params.page = val
  60. this.fetchData()
  61. },
  62. searchClick() {
  63. this.fetchData()
  64. }
  65. }
  66. }
  67. </script>
  68.  
  69. <style lang=\'scss\' scoped>
  70. .workorder {
  71. padding: 10px;
  72. }
  73. </style>

(3)workorder/table.vue

  1. <template>
  2. <div class="workorder-list">
  3. <el-table
  4. :data="value"
  5. border
  6. stripe
  7. style="width: 100%">
  8.  
  9. <el-table-column type="expand">
  10. <template slot-scope="props">
  11. <span>工单详情:{{ props.row.order_contents }}</span>
  12. <br>
  13. <span>处理结果:{{ props.row.result_desc }}</span>
  14. </template>
  15. </el-table-column>
  16.  
  17. <el-table-column
  18. label="工单类型"
  19. prop="type.name"/>
  20.  
  21. <el-table-column
  22. label="工单标题"
  23. prop="title"/>
  24.  
  25. <el-table-column
  26. label="申请人"
  27. prop="applicant[0].name"/>
  28.  
  29. <el-table-column
  30. label="指派人"
  31. prop="assign_to[0].name"/>
  32.  
  33. <el-table-column
  34. label="处理人"
  35. prop="final_processor[0].name"/>
  36.  
  37. <el-table-column
  38. label="状态"
  39. prop="status.name"/>
  40.  
  41. <el-table-column
  42. :formatter="dateFormat"
  43. label="申请时间"
  44. prop="apply_time"/>
  45.  
  46. <el-table-column
  47. :formatter="dateFormat"
  48. label="完成时间"
  49. prop="complete_time"/>
  50.  
  51. </el-table>
  52. </div>
  53. </template>
  54.  
  55. <script>
  56. import moment from \'moment\'
  57. export default {
  58. name: \'OrderList\',
  59. props: {
  60. value: {
  61. type: Array,
  62. default: function() {
  63. return []
  64. }
  65. }
  66. },
  67. methods: {
  68. dateFormat: function(row, column) {
  69. var date = row[column.property]
  70. if (date === undefined) {
  71. return \'\'
  72. }
  73. return moment(date).format(\'YYYY-MM-DD HH:mm:ss\')
  74. }
  75. }
  76. }
  77. </script>
  78.  
  79. <style lang=\'scss\'>
  80. .workorder-list {}
  81. </style>

效果图:

 

 

 

点击工单处理时报如错:

 

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

解决:

  1. 注掉workorder/views.py:
  2. # data[\'complete_time\'] = time.strftime(\'%Y-%m-%d %H:%M:%S\', time.localtime(time.time()))
    并打开workorder/serializers.py:
  1. 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

  1. <template>
  2. <div class="workorder-form">
  3. <el-form ref="form" :model="form" :rules="rules" label-width="100px" class="demo-form">
  4.  
  5. <el-form-item label="工单标题" prop="title">
  6. <el-input v-model="form.title" readonly/>
  7. </el-form-item>
  8.  
  9. <el-form-item label="工单内容" prop="order_contents">
  10. <el-input v-model="form.order_contents" type="textarea" rows="8" readonly/>
  11. </el-form-item>
  12.  
  13. <el-form-item label="处理结果" prop="result_desc">
  14. <el-input v-model="form.result_desc"/>
  15. </el-form-item>
  16.  
  17. <el-form-item>
  18. <div class="btn-wrapper">
  19. <el-button size="small" @click="cancel">取消</el-button>
  20. <el-button size="small" type="primary" @click="submitForm">保存</el-button>
  21. </div>
  22. </el-form-item>
  23.  
  24. </el-form>
  25. </div>
  26. </template>
  27.  
  28. <script>
  29. export default {
  30. name: \'OrderForm\',
  31. props: {
  32. form: { // 接受父组件传递过来的值渲染表单
  33. type: Object,
  34. default() {
  35. return {
  36. title: \'\',
  37. order_contents: \'\',
  38. result_desc: \'\'
  39. }
  40. }
  41. }
  42. },
  43. data() {
  44. return {
  45. rules: {
  46. result_desc: [
  47. { required: true, message: \'请输入处理结果\', trigger: \'blur\' }
  48. ]
  49. }
  50. }
  51. },
  52. methods: {
  53. submitForm() {
  54. this.$refs.form.validate(valid => {
  55. if (!valid) {
  56. return
  57. }
  58. this.$emit(\'submit\', this.form)
  59. })
  60. },
  61. cancel() {
  62. this.$emit(\'cancel\')
  63. }
  64. }
  65. }
  66. </script>
  67.  
  68. <style lang=\'scss\' scoped>
  69. .workorder-form {
  70. position: relative;
  71. display: block;
  72. .btn-wrapper{
  73. text-align: right;
  74. }
  75. }
  76. </style>

(2)workorder/list/index.vue

  1. ...
  2. import OrderForm from \'./form\'
  3. ....
  4. export default {
  5. name: \'Workorder\',
  6. components: {
  7. OrderList,
  8. OrderForm
  9. },

效果如图:

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

 

 解决办法:

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

最终效果如下图:

 

 

 4.工单申请

(1)workorder/apply/index.vue

  1. <template>
  2. <div class="apply">
  3. <el-form ref="form" :model="form" :rules="rules" label-width="180px">
  4. <el-form-item label="工单类型:" prop="type">
  5. <el-select v-model="form.type" placeholder="请选择工单类型" style="width: 60%;">
  6. <el-option
  7. v-for="item in type_list"
  8. :key="item.index"
  9. :label="item.name"
  10. :value="item.id"/>
  11. </el-select>
  12. </el-form-item>
  13.  
  14. <el-form-item label="工单标题:" prop="title">
  15. <el-input v-model="form.title" style="width: 60%;"/>
  16. </el-form-item>
  17.  
  18. <el-form-item label="工单内容:" prop="order_contents">
  19. <el-input :rows="8" v-model="form.order_contents" type="textarea" style="width: 60%;"/>
  20. </el-form-item>
  21.  
  22. <el-form-item label="指派给:" prop="assign_to">
  23. <el-select v-model="form.assign_to" filterable placeholder="请选择工单处理人" style="width: 60%;">
  24. <el-option
  25. v-for="item in sa_list"
  26. :key="item.index"
  27. :label="item.name"
  28. :value="item.id"/>
  29. </el-select>
  30. </el-form-item>
  31.  
  32. <el-form-item>
  33. <el-button type="primary" @click="onSubmit">Create</el-button>
  34. <el-button @click="onCancel">Cancel</el-button>
  35. </el-form-item>
  36. </el-form>
  37. </div>
  38. </template>
  39.  
  40. <script>
  41.  
  42. import { getGroupMemberList } from \'@/api/group\'
  43. import { createWorkOrder } from \'@/api/workorder/workorder\'
  44. export default {
  45. data() {
  46. return {
  47. form: {
  48. type: \'\',
  49. title: \'\',
  50. order_contents: \'\',
  51. assign_to: \'\'
  52. },
  53. rules: {
  54. type: [
  55. { required: true, message: \'请输入工单类型\', trigger: \'blur\' }
  56. ],
  57. title: [
  58. { required: true, message: \'请输人工单标题\', trigger: \'blur\' }
  59. ],
  60. order_contents: [
  61. { required: true, message: \'请输人工单内容\', trigger: \'blur\' }
  62. ],
  63. assign_to: [
  64. { required: true, message: \'请输人工单指派人\', trigger: \'blur\' }
  65. ]
  66. },
  67. sa_list: [],
  68. type_list: [{ \'id\': 0, \'name\': \'数据库\' }, { \'id\': 1, \'name\': \'计划任务\' }, { \'id\': 2, \'name\': \'配置文件\' }, { \'id\': 3, \'name\': \'其他\' }],
  69. state: 0
  70. }
  71. },
  72. watch: {
  73. state() {
  74. getGroupMemberList(6).then(res => {
  75. this.sa_list = res.members
  76. console.log(this.sa_list)
  77. })
  78. }
  79. },
  80. created() {
  81. this.state = 1
  82. },
  83. methods: {
  84. onSubmit() {
  85. this.$message(\'submit!\')
  86. this.$refs.form.validate((valid) => {
  87. if (!valid) {
  88. return
  89. }
  90. const params = Object.assign({}, this.form)
  91. console.log(params)
  92. createWorkOrder(params).then(res => {
  93. this.$message({
  94. message: \'创建成功\',
  95. type: \'success\'
  96. })
  97. this.$router.push({ path: \'/workorder/list\' })
  98. })
  99. })
  100. },
  101. onCancel() {
  102. this.$message({
  103. message: \'cancel!\',
  104. type: \'warning\'
  105. })
  106. }
  107. }
  108. }
  109. </script>
  110.  
  111. <style scoped>
  112. .apply{
  113. margin-top:2cm;
  114. }
  115. </style>

(2)src/router/index.js

  1. import Vue from \'vue\'
  2. import Router from \'vue-router\'
  3.  
  4. // 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;
  5. // detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
  6. Vue.use(Router)
  7. /* Layout */
  8. import Layout from \'../views/layout/Layout\'
  9.  
  10. /**
  11. * hidden: true if `hidden:true` will not show in the sidebar(default is false)
  12. * alwaysShow: true if set true, will always show the root menu, whatever its child routes length
  13. * if not set alwaysShow, only more than one route under the children
  14. * it will becomes nested mode, otherwise not show the root menu
  15. * redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
  16. * name:\'router-name\' the name is used by <keep-alive> (must set!!!)
  17. * meta : {
  18. title: \'title\' the name show in submenu and breadcrumb (recommend set)
  19. icon: \'svg-name\' the icon show in the sidebar,
  20. }
  21. **/
  22. export const constantRouterMap = [
  23. { path: \'/login\', component: () => import(\'@/views/login/index\'), hidden: true },
  24. { path: \'/404\', component: () => import(\'@/views/404\'), hidden: true },
  25. {
  26. path: \'/\',
  27. component: Layout,
  28. redirect: \'/dashboard\',
  29. name: \'Dashboard\',
  30. children: [{
  31. path: \'dashboard\',
  32. component: () => import(\'@/views/dashboard/index\'),
  33. meta: { title: \'dashboard\', icon: \'example\' }
  34. }]
  35. },
  36. {
  37. path: \'/users\',
  38. component: Layout,
  39. name: \'users\',
  40. meta: { title: \'用户管理\', icon: \'example\' },
  41. children: [
  42. {
  43. path: \'user\',
  44. name: \'user\',
  45. component: () => import(\'@/views/users/user\'),
  46. meta: { title: \'用户\' }
  47. },
  48. {
  49. path: \'groups\',
  50. name: \'groups\',
  51. permission: \'resources.add_ip\',
  52. component: () => import(\'@/views/groups\'),
  53. meta: { title: \'用户组\' }
  54. }
  55. ]
  56. },
  57. {
  58. path: \'/workorder\',
  59. component: Layout,
  60. name: \'workorder\',
  61. meta: { title: \'工单系统\', icon: \'form\' },
  62. children: [
  63. {
  64. path: \'apply\',
  65. name: \'工单申请\',
  66. component: () => import(\'@/views/workorder/apply/index\'),
  67. meta: { title: \'工单申请\', icon: \'form\' }
  68. },
  69. {
  70. path: \'list\',
  71. name: \'申请列表\',
  72. component: () => import(\'@/views/workorder/list/index\'),
  73. meta: { title: \'申请列表\', icon: \'table\' }
  74. },
  75. {
  76. path: \'history\',
  77. name: \'工单历史\',
  78. component: () => import(\'@/views/workorder/history/index\'),
  79. meta: { title: \'工单历史\', icon: \'table\' }
  80. }
  81. ]
  82. },
  83. { path: \'*\', redirect: \'/404\', hidden: true }
  84. ]
  85. export default new Router({
  86. mode: \'history\',
  87. scrollBehavior: () => ({ y: 0 }),
  88. routes: constantRouterMap
  89. })

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

 

 

 

 

 

 

 

 

1

 

版权声明:本文为dbslinux原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dbslinux/p/13352932.html