antd使用Transfer穿梭框(8)

https://www.bookstack.cn/read/vue.ant.design-v1.3.8/e5baab041f53bdf6.md#%E5%B8%A6%E6%90%9C%E7%B4%A2%E6%A1%86

一、transfer组件

targetKeys使用v-model的话,无法实现穿梭

<template>
  <a-transfer
    :dataSource="mockData"
    showSearch
    :filterOption="filterOption"
    :targetKeys="targetKeys"
    @change="handleChange"
    @search="handleSearch"
    :render="item=>item.title"
  >
  </a-transfer>
</template>
<script>
export default {
  data () {
    return {
      mockData: [],
      targetKeys: [],
    }
  },
  mounted() {
    this.getMock()
  },
  methods: {
    getMock() {
      const targetKeys = [];
      const mockData = [];
      for (let i = 0; i < 20; i++) {
        const data = {
          key: i.toString(),
          title: `content${i + 1}`,
          description: `description of content${i + 1}`,
          chosen: Math.random() * 2 > 1,
        };
        if (data.chosen) {
          targetKeys.push(data.key);
        }
        mockData.push(data);
      }
      this.mockData = mockData
      this.targetKeys = targetKeys
    },
    filterOption(inputValue, option) {
      return option.description.indexOf(inputValue) > -1;
    },
    handleChange(targetKeys, direction, moveKeys) {
      console.log(targetKeys, direction, moveKeys);
      this.targetKeys = targetKeys
    },
    handleSearch (dir, value) {
      console.log('search:', dir, value);
    },
  },
}
</script>

二、完整代码

<template>
  <div>
    <a-card :bordered="false">
      <div style="display: flex; flex-wrap: wrap">
        <head-info title="我的待办" content="8个任务" :bordered="true"/>
        <head-info title="本周任务平均处理时间" content="32分钟" :bordered="true"/>
        <head-info title="本周完成任务数" content="24个"/>
      </div>
    </a-card>
    <br />
    <a-form
        :model="formState"
        name="horizontal_login"
        layout="inline"
        autocomplete="off"
        @finish="onFinish"
        @finishFailed="onFinishFailed"
    >
      <a-form-item
          label="任务id"
          name="task_id"
          :rules="[{ required: true, message: 'Please input your task_id!' }]"
      >
        <a-input v-model="formState.task_id" />
      </a-form-item>

      <a-form-item
          label="创建人"
          name="creator"
          :rules="[{ required: true, message: 'Please input your creator!' }]"
      >
        <a-select v-model="UserType" style="width:150px" allowClear>
          <a-select-option :value="item.id" v-for="(item, i) in UserArr" :key="i">
            {{ item.name }}
          </a-select-option>
        </a-select>
      </a-form-item>

      <a-form-item>
        <a-button :style="{ marginLeft: '8px' }" @click="onSearchData">查询</a-button>
        <a-button :style="{ marginLeft: '8px' }" @click="reset">重置</a-button>
        <a-button :style="{ marginLeft: '8px' }" @click="showModal">+任务</a-button>
        <a-popconfirm
            title="task执行后不可修改,你确定要执行吗?"
            ok-text="确定"
            cancel-text="取消"
            @confirm="confirm"
            @cancel="cancel"
        >
          <a-button :style="{ marginLeft: '8px' }" :disabled="!hasSelected"  @click="start">批量执行</a-button>
          <a-button :style="{ marginLeft: '8px' }" :disabled="!hasSelected"  @click="start">关联需求</a-button>
        </a-popconfirm>

      </a-form-item>
      <a-modal v-model="visible" width="500px" title="添加用例" @ok="handleOk">
        <p>Some contents...</p>
      </a-modal>
    </a-form>
    <a-table :columns="columns" :data-source="data" class="components-table-demo-nested" @change="onChanged" rowKey="id"
             :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }">
      <template slot="operation" slot-scope="record">
        <a-tooltip  title="详情" >
            <a-icon style="color: #0080ff;margin:0 4px" type="eye" @click="onDetail(record)" />
        </a-tooltip>
        <a-drawer :title="myTitle" :visible="isEnable" :mask=false @close="onClose"  width="520" :bodyStyle="{ marginBottom: '30px' }">
          <a-form :model="contents" :rules="rules" layout="vertical">
            <a-row :gutter="16">
              <a-col :span="12">
                <a-form-item label="任务ID" name="id">
                  <a-input v-model="contents.id" :disabled="disabled" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="任务名称" name="task_name">
                  <a-input v-model="contents.task_name" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row :gutter="16">
              <a-col :span="12">
                <a-form-item label="关联需求" name="demand">
                  <a-input v-model="contents.demand" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
            </a-row>
            <a-row :gutter="16">
              <a-col :span="12">
                <a-form-item label="状态" name="status">
                  <a-input v-model="contents.status" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="创建人" name="creator">
                  <a-input v-model="contents.creator" style="width: 100%"  :disabled="disabled" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="创建时间" name="createdAt">
                  <a-input v-model="contents.createdAt" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="更新时间" name="updatedAt">
                  <a-input v-model="contents.updatedAt" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="关联case数" name="bind_case">
                  <a-transfer
                      :dataSource="mockData"
                      showSearch
                      v-if="flag"
                      :filterOption="filterOption"
                      :targetKeys="targetKeys"
                      @change="handleChange"
                      @search="handleSearch"
                      :render="item=>item.title"
                  />
                  <a-input v-model="contents.bind_case"  v-if="!flag" style="width: 100%" :disabled="disabled" />
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>

          <template #extra>
            <a-button style="margin-right: 8px" @click="onClose">Cancel</a-button>
            <a-button type="primary" @click="onClose">Submit</a-button>
          </template>
        </a-drawer>
        <a-tooltip  title="编辑" >
            <a-icon style="color: #0080ff;margin:0 4px" type="form" @click="onEdit(record)" />
        </a-tooltip>
        <!-- 运行 -->
        <a-tooltip title="运行">
          <a-icon type="play-circle" style="color: #0080ff;margin:0 4px"  @click="onRun(record)"/>
          <a-modal v-model="isshow" title="Task运行进度:" @ok="handleOk">
            <a-form
                :model="env"
                name="basic"
                autocomplete="off"
                @finish="onFinish"
                @finishFailed="onFinishFailed"
            >
              <a-form-item
                  label="运行环境"
                  name="env"
                  :rules="[{ required: true, message: 'Please input env!' }]"
              >
                <a-input v-model="env" />
              </a-form-item>
              </a-form>
          </a-modal>
        </a-tooltip>
        <a-tooltip  title="删除" >
          <a-popconfirm
              title="Are you sure delete this task?"
              ok-text="Yes"
              cancel-text="No"
              @confirm="confirm"
              @cancel="cancel"
          >
            <a-icon style="color: #0080ff;margin:0 4px" type="delete"  @click="onDelete(record)"/>
          </a-popconfirm>
        </a-tooltip>
      </template>

      <template #expandedRowRender>
        <a-table :columns="innerColumns" :data-source="innerData" :pagination="false">
          <template slot="operation" slot-scope="record">
            <a-tooltip  title="详情" >
              <a-icon style="color: #0080ff;margin:0 4px" type="eye" @click="onDetail(record)" />
            </a-tooltip>
            <a-tooltip  title="删除" >
              <a-popconfirm
                  title="Are you sure delete this case?"
                  ok-text="Yes"
                  cancel-text="No"
                  @confirm="confirm"
                  @cancel="cancel"
              >
                <a-icon style="color: #0080ff;margin:0 4px" type="delete"  @click="onDelete(record)"/>
              </a-popconfirm>
            </a-tooltip>
          </template>
        </a-table>
      </template>
    </a-table>
  </div>
</template>

<script>

import HeadInfo from "@/components/tool/HeadInfo";
import { get_task_detail, get_case_list, get_task_list} from "@/services/build_history";
import {getUserList} from "@/services/postman";
import {message} from "ant-design-vue";


const columns = [
  { title: '任务ID', dataIndex: 'id', key: 'id' },
  { title: '任务名称', dataIndex: 'task_name', key: 'task_name' },
  { title: '关联case数', dataIndex: 'bind_case', key: 'bind_case',
    sorter: (a, b) => a.bind_case - b.bind_case,
    defaultSortOrder: 'descend',
    sortDirections: ['ascend', 'descend'] },
  { title: '关联需求', dataIndex: 'demand', key: 'demand'},
  { title: '状态', dataIndex: 'status', key: 'status' },
  { title: '创建人', dataIndex: 'creator', key: 'creator' },
  { title: '创建时间', dataIndex: 'createdAt', key: 'createdAt',
    sorter: (a, b) => Date.parse(a.createdAt) - Date.parse(b.createdAt),
    defaultSortOrder: 'descend',
    sortDirections: ['ascend', 'descend'] },
  { title: '更新时间', dataIndex: 'updatedAt', key: 'updatedAt',
    sorter: (a, b) => Date.parse(a.updatedAt) - Date.parse(b.updatedAt),
    defaultSortOrder: 'descend',
    sortDirections: ['ascend', 'descend'] },
  { title: '操作', key: 'operation',
    scopedSlots: { customRender: 'operation' }, //值跟dataIndex对应,支持操作列插槽
    width: 120,
  },
];

const rules = {
  id: [{ required: true, message: 'Please enter id' }],
  task_name: [{ required: true, message: 'please enter task_name' }],
  bind_case: [{ required: true, message: 'Please select bind_case' }],
  demand: [{ required: true, message: 'Please choose the demand' }],
  status: [{ required: true, message: 'Please choose the status' }],
  creator: [{ required: true, message: 'Please choose the creator', type: 'object' }],
  createdAt: [{ required: true, message: 'Please enter createdAt' }],
  updatedAt: [{ required: true, message: 'Please enter updatedAt' }],
};

const innerColumns = [
  {
    title : '用例名称',
    dataIndex: 'case_name',
    resizable: true,        //设置 resizable 开启拖动列
    width: 20,
  },
  {
    title : '优先级',
    dataIndex: 'priority',
    resizable: true,
    width: 20,
  },
  {
    title: '用例状态',
    dataIndex: 'status',
    resizable: true,
    width: 20,
  },
  {
    title: '创建人',
    dataIndex: 'creator',
    resizable: true,
    width: 20,
  },
  {
    title: '更新时间',
    dataIndex: 'update_time',
    resizable: true,
    width: 50,
  },
  {
    title: '操作',
    dataIndex: 'operation',
    resizable: true,
    scopedSlots: { customRender: 'operation' }, //值跟dataIndex对应,支持操作列插槽
    width: 50,
  },
];


export default {
  name: "Task",
  data() {
    return {
      case_list: "http://localhost:7777/auth/case_list",
      task_list:"http://localhost:7777/auth/task_list",
      task_detail:"http://localhost:7777/auth/task_detail",
      data:[],
      columns,
      innerColumns,
      innerData:[],
      formState: {
        creator: '',
        task_id: '',
      },
      form: this.$form.createForm(this, {name: 'task'}),
      UserArr:[],
      UserType:'',
      visible:false,
      hasSelected:false,
      selectedRowKeys:[],
      contents:"",
      isEnable:false,
      myTitle:"Task详情页",
      disabled:false,
      flag:false,
      rules: rules,
      //Transfer
      mockData: [],
      targetKeys: [],
      isshow:false,
    }
  },
  components: {HeadInfo},
  methods: {
    onSearchData() {
      this.loading = true;
      const task_id = this.formState.task_id
      const creator = this.UserType
      console.log(task_id,creator);
      get_task_list(this.task_list, {task_id, creator})
          .then((result) => {
            this.loading = false;
            this.data = result.data.data;   //跟后端接口response对齐
          })
          .catch((err) => {
            this.data = err;
          });
    },
    onSelectChange(selectedRowKeys){
      this.selectedRowKeys = selectedRowKeys;
      if (this.selectedRowKeys.length > 0) {
        this.hasSelected = true
      }
    },
    onChanged(pagination, filters, sorter) {
      console.log('params', pagination, filters, sorter);
    },
    reset() {
      this.UserType = ''    //清空casename
      this.formState = []   //清空创建人
      this.data = []        //清空搜索结果
    },
    start(){
      this.loading = true;
      // ajax request after empty completing
      setTimeout(() => {
        this.loading = false;
        this.selectedRowKeys = [];
      }, 1000);
    },
    cancel(e) {
      console.log(e);
      message.error('Click on No');
    },
    confirm(e) {
      console.log(e);
      message.error('Click on Yes');
    },
    onFinish(val) {
      console.log('endValue', val);
    },
    onFinishFailed(val) {
      console.log('endValue', val);
    },
    showModal(){            //点击添加用例后展示弹窗
      this.visible = true;
    },
    handleOk(e){
      console.log(e);
      this.visible = false;
    },
    onEdit(record) {
      this.isEnable = true    //控制展示 Drawer抽屉
      this.disabled = false
      this.flag = true       //控制编辑页  展示Transfer 穿梭框
      this.myTitle = "更新Task"
      console.log('task edit:', this.flag);
      get_task_detail(this.task_detail, {record})
          .then((result) => {
            this.loading = false;
            this.contents = result.data.data;   //跟后端接口response对齐
            console.log('onedit ', this.contents);
          })
          .catch((err) => {
            this.contents = err;
          });
    },
    onDelete(e) {
      console.log(e);
    },
    onRun(record) {
      this.isEnable = false     //控制不展示 Drawer抽屉
      this.flag = false         //控制不展示 Transfer穿梭框
      this.isshow= true
      this.myTitle = "Task运行"
      console.log('task run:', record);  //TODO 调用后端运行接口
    },
    onDetail(record) {
      this.isEnable = true     //控制展示 Drawer抽屉
      this.disabled = true     //控制详情页输入框  不可编辑
      this.flag = false        //控制详情页       不展示Transfer穿梭框
      this.myTitle = "Task详情页"
      console.log('task detai:', this.flag);
      get_task_detail(this.task_detail, {record})
          .then((result) => {
            this.loading = false;
            this.contents = result.data.data;   //跟后端接口response对齐
            console.log('ondetail ', this.contents);
          })
          .catch((err) => {
            this.contents = err;
          });
    },
    onClose () {
      this.isEnable = false;
    },
    filterOption (inputValue, option) {
      return option.description.indexOf(inputValue) > -1;
    },
    handleChange (keys, direction, moveKeys) {
      console.log(keys, direction, moveKeys);
      this.targetKeys = keys
    },
    handleSearch (dir, value) {
      console.log('search:', dir, value);
    },
    getMock () {
      const keys = [];
      const mData = [];

      for (let i = 0; i < 20; i++) {
        const data = {
          key: i.toString(),
          title: `content${i + 1}`,
          description: `description of content${i + 1}`,
          chosen: Math.random() * 2 > 1,
        };

        if (data.chosen) {
          keys.push(data.key);
        }

        mData.push(data);
      }

      this.mockData = mData;
      this.targetKeys = keys;
    },
  },
  mounted() {
    this.getMock()     //TODO 改成后端获取真实数据
    const task_id = 1  //TODO 任务id
    getUserList().then(res => {
      this.UserArr = res.data.data         //跟后端接口response对齐
      console.log('搜索条件',this.UserArr);
    }),
    get_case_list(this.case_list,{task_id}).then(res => {
      this.loading = false;
      this.innerData = res.data.data         //跟后端接口response对齐
      if( this.innerData.length > 0) {
        console.log('res:--- ', this.innerData);
      }
    })
  },
}
</script>

<style scoped>

</style>

三、效果

详情页:
在这里插入图片描述
编辑页:
在这里插入图片描述
运行:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值