Aurora之DataSet

本文深入解析Aurora框架中的DataSet概念,探讨其在前端与服务器间数据交换的作用,涵盖定义、数据来源、数据校验、UI组件绑定、事件处理及优缺点。DataSet作为AuroraUI核心组件,实现数据与展示的解耦,简化页面逻辑实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.DataSet的直观认识

在Aurora框架中,DataSet是web前端与服务器直接进行数据交换的介质,是Aurora框架前端AuroraUI中最核心的部分。DataSet提供了对数据的操作和导航,对数据的操作会触发相应的事件(event),所有绑定(bind)到DataSet有UI组件会根据事件做出响应。
换句话说就是,Aurora框架中web页的操作基本都是围绕DataSet 进行操作的,是核心组件。框架将数据封装为DataSet之后,我们直接操作DataSet就可以实现相应的功能,专注于数据逻辑的操作,而对页面的相关组件不必去关心。
向服务器发送请求后,返回的页面中DataSet的创建脚本形式如下:


    new  Aurora.DataSet(
    {“datas”:[{“user_id”:1,”user_name”:HECADMIN, “encrypted_foundation_password”:”……”}, //一条record
    {“user_id”:2,”user_name”:ADMIN, “encrypted_foundation_password”:”……”},
    ……
    ],
     “listeners”:{“update”,onUpdate, //注册的事件
    		   “submitsuccess”: onModifyUserSuccess,
    			……
    },
     “fields”:[{“name”:”user_id”, "databasetype":"BIGINT","datatype":"java.lang.Long","isprimarykey":true}, //field
            {"name":"user_name","databasetype":"VARCHAR","datatype":"java.lang.String",
    "prompt":"SYS_USER.ACCOUNT","readonly":true},
            {"name":"encrypted_foundation_password","databasetype":"VARCHAR","datatype":"java.lang.String",
    "insertexpression":"sys_login_pkg.md5(${@user_password})"},
            ……],
     “id”:”sys_user_edit_ds”,
     “pagesize”:10,
     ……
    }
    );

DataSet是web前端的组件之一,其中包括数据(datas),事件(listeners),字段级别的元数据(fields),id以及其他的信息组成。

  1. datas中是DataSet初始化时的数据中的数据,是由多条数据记录(record)组成。DataSet将后台数据库查询出来的数据集统一封装到DataSet中。
  2. listeners中记录了当前dataSet中注册的事件。发生特定动作时会响应特定的事件。调用特定的事件或者自己定义的事件。
  3. fields中记录的是字段级的元数据信息,每个字段的名称,数据类型,提示(prompt)等属性。Field中的信息集中了DataSet定义以及bm中的field、ref-field中的信息的总和。
  4. DataSet其他的信息,如id,pageSize,querurl等等。

2.定义DataSet

DataSet是由多条record组成的,并且可以注册不同的事件。典型的DataSet的定义如下:

<a:dataSets>
    <a:dataSet model="sys.sys_user" id="sys_user_edit_ds">
    //model绑定的数据源.bm    id DataSet的标识
        <a:fields>//数据集
            <a:field name="user_name" readOnly="true"/>
            <a:field name="start_date" required="true"/>
            <a:field name="end_date"/>
            <a:field name="description" required="true"/>
            <a:field name="frozen_date" readOnly="true"/>
        </a:fields>
        <events>//注册事件
            <a:event name="submitsuccess" handler="onModifyUserSuccess"/>
            <a:event name="update" handler="onUpdate"/>
        </events>
    </a:dataSet>
</a:dataSets>

dataSets中可以定义多个dataSet,在screen文件中,fields中一般声明的是具有特殊属性的field(例如readOnly,requird),否则可以省略不写,若没有具有特殊属性的field,则可省略fileds。在这里定义的field都是字段级别的元数据信息,若需要注册事件,可在events中可以给dataSet注册事件。

个人建议页面上面涉及到的字段数据,应该都在DataSet里面进行声明,既方便阅读,后期加prompt也方便。

3.DataSet的数据来源方式

DataSet中数据的来源方式主要有以下四种:

  1. 直接在dataSet中写入数据记录:
<a:dataSet id="users_ds">
<a:datas>
    <a:record id="1" user_name="ADMIN" description="系统管理员"/>
    <a:record id="2" user_name="HAPADMIN" description="费控系统管理_hand公司"/>
</a:datas>
</a:dataSet>

该方式一般用于定义下拉列表中的选项的值,但这样写不便于管理以及维护,因此不建议这样使用,建议将这样的一些值保存至数据库当中,在页面文件中定义一个dataSet,通过查询,从数据库中获取,再在页面中显示,以提高可维护性。ps:不建议,low

  1. 通过mode-query加载数据:
    <a:init-procedure>
        <model-query model="sys.sys_user" rootPath="user_model" defaultWhereClause=”user_name like ‘AD%’” queryOrderBy=”user_id”/>
    </a:init-procedure>
    <a:dataSets>
        <a:dataSet model="sys.sys_user" id="sys_user_ds">
            <a:datas dataSource="/model/user_model"/>
        </a:dataSet>
</a:dataSets>

通过这种方式加载数据时,是在服务器端进行查询后与请求的页面一起发送到客户端,数据是一次性全部加载的。因些不可以进行分页显示。这种方式加载数据时可以通过在model-query中加入defaultWhereClause属性限定查询条件,加入queryOrderBy限定排序字段。ps:用的不多

  1. 使用loadData加载数据:
 <a:dataSets>
        <a:dataSet model="sys.sys_user" id="sys_user_ds" loadData="true"/>
</a:dataSets>

是方式2的一种简写形式,与方式2加载数据的实质是一样,会在后台自动转换为方式2的形式,但是使用loadData不能够限定查询条件和排序方式。ps:更简便,逻辑更加清晰。主流用法。

  1. 通过ajax请求数据:
<a:dataSet model= "sys.sys_user" id="sys_user_result_ds" 
queryDataSet="sys_user_query_ds"/>

若增加autoQeury属性,则是在页面加载完成后,再发起ajax请求,从服务器获取数据,可以进行分页,若没有加入autoQuery属性,则可以在javaScript中通过脚本请求数据:

var dataSet = $(‘sys_user_result_ds’);
dataSet.query();

其中$(‘object_id’),是页面文件中组件id为object_id的对象,$(‘sys_user_result_ds’),获取id为sys_user_result_ds的对象,即id为sys_user_result_ds的DataSet,dataSet.query()调用DataSet的query方法,发起Ajax请求,查询数据。ps:在js中发起请求,在对应的DataSet中注册query事件。

4.DataSet中数据校验

DataSet中的数据校验分为两个形式,一种是DataSet内置的数据校验,另一种是自定义的数据校验
DataSet内置的数据校验,主要就是required校验(必输校验)。
自定义校验:如果校验通过需要返回true,否则返回一个字符串(为校验不通过的提示信息)。例如需要“开始日期”不能小于“结束日期”的校验,就需要自己写一个校验方法,并将dataSet中相应的Field的校验器指定为自己写的校验方法:
在需要校验的field中指定校验器:

    <a:dataSet id="sys_user_edit_ds" model="sys.sys_user">
        <a:fields>
            <a:field name="start_date" required="true" validator="dateValidator"/>
            <a:field name="end_date" validator="dateValidator"/>//校验时间
        </a:fields>
        <events>
            <a:event handler="onUpdate" name="update"/>//注册update事件
        </events>
    </a:dataSet>

自定义校验器:

    function dateValidator(record, name, value){//日期校验方法
        if(name == 'start_date' || name == 'end_date'){//页面点击事件,点击开始日期或者结束日期
            var start_date = record.get('start_date');//获取字段数值
            var end_date = record.get('end_date');
            if(!!end_date){//由于结束日期非必填,只有在结束日期填了才进行比较
                if(!compareDate(start_date, end_date)){
                	//1.
                    return '开始时间不能大于结束时间';//校验不通过返回字符串,不建议这样写,在系统中创建系统描述使用系统描述的写法
                    //update事件触发会发起校验,也就是点击保存或者提交的时候会报错
                    //2.
                    Aurora.showMessage('${l:PROMPT}', '${l:EXP_REPORT_MAINTAIN.DATE_VALIDATE}');
                    //两个日期都选择之后就会发起校验,显示报错
                           return;
                }
            }
            return true;//校验通过返回true
        }
    }
    function compareDate(start, end){
        if(start > end){
            return false;
        }
        return true;
    }

这样便可实现自定义校验,但是以上的校验存在一个问题:由于校验都是在当前的Record的相应字段进行更改之后才进行校验的,所以如果不输入开始时间,只输入结束时间,那么校验会直接通过,此时的解决方法是当更新的字段为“开始时间”或是“结束时间时”,通过向dataSet注册update事件,再调用一次校验即可:

    function onUpdate(ds,record,name,value){
        if(name == 'start_date' || name == 'end_date'){
            record.validate((name == 'start_date') ? 'end_date' : 'start_date');
        }
    }

另外,required和readOnly、以及数值类型的allowDecimals、allowNegative校验应当写在field里面,否则不会经过DataSet进行校验,虽然readOnly、allowDecimals、allowNegative可以从组件上进行相关的输入控制。

5.向DataSet上绑定UI组件

DataSet的设计思想是数据的展示与数据分离解藕,这样可以更好地将注意力集中在数据的逻辑处理上,而不需要关心UI组件的变化,这样更有利于提高开发效率。
虽然将数据与展示分离开,但必须有通过某种方式将它们联系起来,在Aurora前端中的做法是将UI组件绑定到DataSet上,当对DataSet的数据进行操作时,会触发相应的事件绑定到DataSet上的UI组件会根据事件做出响应。例如DataSet上的值发生改变时,相应UI组件的值也会随之发生改变,当相应的Field元数据发生改变时(从可输入变为只读、从必输变为非必输),UI组件也会发生相应的变化。

ps:框架集成好的组件,我们直接拿来使用就行,将需要的组件绑定到相应的DataSet上面,使用name属性进行统一。

UI组件的绑定方法
若要将UI组件绑定的DataSet上,只要在组件上的bindTarget属性值指向要绑定的DataSet的id即可。如”sys_user_ds”的字段”user_name”使用文本编辑器(textField):

    <a:dataSet id="sys_user_ds" model="sys.sys_user">
        <a:fields>
            <a:field name="user_name" required="true"/>
        </a:fields>
    </a:dataSet>

将textField绑定到”sys_user_ds”上,name指定对哪个字段进行编辑,bindTarget指定绑定的DataSet的id。

<a:textField bindTarget="sys_user _ds" name="user_name"/>
头行绑定

当对头行结构的数据进行操作时,例如当选中头表中的一条数据时,可能想查询所有的所选中数据的相应行表中的数据,这时候就可以将行表的DataSet绑定到头表对应的DataSet上去。

   // WEB-INF/view/csh/CSH1015/csh_bank.screen
            <a:dataSets>
                <a:dataSet id="CSH1015_bankQuery_ds" baseUrl="/csh/bank">
                   //查询集
                </a:dataSet>
                <a:dataSet id="CSH1015_bankResult_ds" baseUrl="/csh/bank" queryDataSet="CSH1015_bankQuery_ds">
                    //结果集   头表
                </a:dataSet>
                <a:dataSet id="CSH1015_cnapsResult_ds" bindTarget="CSH1015_bankResult_ds" baseUrl="/csh/cnaps" queryDataSet="CSH1015_bankResult_ds">
                    //结果集   行表   绑定头结果集,通过查询头结果集返回所有数据
                    //baseUrl数据集来源
                </a:dataSet>
            </a:dataSets>
    		
            <span>  
                <a:queryForm bindTarget="CSH1015_bankQuery_ds" resultTarget="CSH1015_bankResult_ds">
                    //查询框,查询数据。绑定查询集,结果返回到头结果集
                </a:queryForm>
            </span>
            <a:form>
                <a:grid id="CSH1015_bankResult_grid" bindTarget="CSH1015_bankResult_ds">
                   //grid组件,展示行数据。绑定头结果集
                </a:grid>
            </a:form>
            <a:form>
                <a:grid id="CSH1015_cnapResult_grid" bindTarget="CSH1015_cnapsResult_ds">
                    //grid组件,展示行数据。绑定行结果集
                </a:grid>
            </a:form>

<a:dataSet id=“sys_code_head_ds” model=“sys.sys_codes”/ >
<a:dataSet id=“sys_code_line_ds” bindTarget=“sys_code_head_ds”
bindName= “sub_ds” model= “sys.sys_code_values”/>
//典型的头行绑定,行表绑定头表的DataSet。

sys_code_line_ds 绑定到 sys_code_head_ds 上,其内部实际上是sys_code_line_ds 做为一个 filed 添加到sys_code_head_ds中, 其中 field 的name值为bindName属性值 “sub_ds”,field的type为"dataSet",其它的field的type都没有值。

将一个dataSet绑定到另外一个上时,使用bindTarget指定绑定到哪个dataSet上,bindName指定绑定后的名称,其查询数据时的处理方式是:当头表数据中改变选中行时,会将选中的头表中的record数据整体做为行表的查询参数发送给服务器进行查询。

头行表界面

6.DataSet的属性列表

dataSet有以下属性:

属性名作用
model指定dataSet对应的bm,对应组件的数据来源
autoCreate指定创建dataSet时是否创建一条空记录(默认为false false:不创建 true:创建)
autoQuery页面加载完成后,是否自动进行一次ajax请求查询数据(默认为false false:不查询 true:自动查询)
fetchAll指定是否一次查询所有的数据(默认为false false:不全加载 true:一次加载)
pageSize指定一次查询出数据的条数(默认10条)
autoCount查询是否进行统计(默认为true false:不进行统计 true:统计查询的总条数、页数信息)
canQuery是否可查询(默认true false:不可查询 true:可查询)
canSubmit是否可提交(默认true false:不可提交 true:可提交)
loadData是否服务器端加载数据(默认false false:不在服务器端加载 true:在服务器端加载)
selectable是否可选择(默认false false:不可选择 true:可选择),选择框
selectionModel选择模式(默认multiple multiple:多选 single:单选),选择框样式
queryUrl查询的url地址
submitUrl提交的url地址
bindTarget绑定到目标dataSet,作为目标dataSet的是一个子DataSet
bindName绑定后的名称
lookupCode值列表的code,使用系统代码的时候可以直接使用这个属性来获取对应的值,主要用于combox

model: 指定dataSet对应的bm,查询、提交的url都对应到该bm上,若想要改变默认的查询、提交的url则需要设置queryUrl、submitUrl。多表或者头行表同时提交或者插入,更新使用svc进行操作。
autoCreate: 当dataSet中没有数据时,即没有记录(record)时,此时如果对record进行操作时,可能会达不到预期的效果。例如查询所用的DataSet中,有必输条件,则须要使autoCreate=”true”,以创建一条空的record。否则,查询条件中没有输入任何值,校验会直接通过。
loadData: 如果一次要查询出所有结果,并且除bm中已有的查询条件不需要其他查询条件,那么可以将loadData设置为true。否则应该通过model-query的方式,在defaultWhereClause中限定查询条件。
queryUrl: 设定查询的url地址,默认是dataSet的model对应bm的地址,若要改变默认的查询地址或是要添加请求参数时,可以重设url地址,例如可以设为如 …/autocrud/sys.sys_user/query?user_id=1 的形式。
submitUrl: 设置提交数据的url,默认是dataSet的model对应bm的地址,要改变默认url时,设置该参数。
fetchAll、pageSize、autoCount配合使用,以进行分页,fetchAll指定是否一次查询出所有数据,即是否进行分页查询,为true时一次性查询所有数据,false时一次查询pageSize条数据,autoCount指定是否对查询条数、页面数进行统计。

7.DataSet事件

DataSet对数据的操作,多数都是通过向DataSet中注册相关事件完成的,其中用的最多是update事件,事件注册的方式参考 “定义DataSet”。
其他常用的事件有:update、valid、indexchange、submitsuccess、submit等事件。
DataSet的事件列表:
1
2
3

8.Lov以及Combox的写法

Lov及ComboBox都可以通过field进行配置完成,例如选择角色,分别用Lov和ComboBox实现:

  1. Lov实现:
//DataSet
    <a:dataSet id="sys_user_role_assign" model="sys.sys_user_role_assign">
    	<a:fields> 
    	//lovService lov数据来源,可以通过查询sql,或者相应的bm获取
    <a:field name="role_code" title="HAP_SELECT_ROLE" lovService="sys.sys_role" lovWidth="340" lovGridHeight="340" lovHeight="460" required="true">
    	<mapping>
    		<map from="role_id" to="role_id"/>
            <map from="role_code" to="role_code"/>
            <map from="role_name" to="role_name"/>
        </mapping>    
    </a:field>
    </a:fields>
    	  </a:dataSet>

	  //UI的写法非常简单
	  <a:lov name="role_code" bindTarget=" sys_user_role_assign"/>
  1. ComboBox实现:
//DataSet
  <a:dataSet id="sys_user_role_assign" model="sys.sys_user_role_assign">//model数据来源,可以是查询sql,通过查询创建的bm文件,或者lookupcode获取系统代码定义的combox数据。
	<a:fields> 
<a:field name="role_code"  options="sys_role_ds" required="true">//获取多个值写法
	<mapping>
		<map from="role_id" to="role_id"/>
        <map from="role_code" to="role_code"/>
        <map from="role_name" to="role_name"/>
    </mapping>    
</a:field>
</a:fields>
</a:dataSet>
<a:dataset id="sys_combox_ds" lookupcode="PAYMENT_OBJECT"/>//PAYMENT_OBJECT 系统代码

//ComboBox
<a:comboBox name="role_code" bindTarget="sys_user_role_assign"/>

另外一种方式
//Field:
 <a:field name="role_code" displayField="role_code" options="sys_role_ds" valueField="role_id" returnField="role_id"/>//获取一个值
 //displayField 用于页面展示的字段名,即系统代码里面的XXX_name字段,
 //name 展示在页面的字段名
 //options 数据来源 dataset
 //valueField  需要存入数据库的字段的值
 //returnField 需要存入数据库的字段名
//ComboBox
<a:comboBox name="role_code" bindTarget="sys_user_role_assign"/>

9.DataSet的优缺点

优点:

  1. DataSet使得数据和展示分离开了,从而可以集中注意力在数据的逻辑处理,而不用关心UI组件的变化。
  2. 对于很多页面逻辑的实现,只需要对DataSet的元数据进行操作,而不需要对UI直接操作,如此可以减少繁琐的操作。不会因为许多组件使用一个字段而写大量重复代码。

不足:
DataSet中暴露了太多的数据操作细节了,例如insertExpression,数据类型等。
DataSet以loadData方式加载数据时,如果又写了autoQuery时,那通过autoQuery查询出来的数据就会覆盖通过loadData查询出来的数据。最好在schema文件中进行定义 或者在工具中就对其进行限制,或者是在解析时,遇到这种情况则报错。
queryUrl,如果不写queryUrl时,有默认的url 地址,而且地址一般都比较长,但写上的url地址一般都是在默认地址后面添加参数,前面的地址其实都没有必要写,可以用另外一个属性专门写地址后面的那些参数,如此,能够简化页面编写,而且便于查看。

DataSet是数据流转的核心。bm通过数据库表或者sql查询,获取到相应的数据,screen页面中DataSet对这些数据封装,通过调用DataSet的下的相应的组件,实现也页面上的数据流转操作。
养成习惯涉及到数据处理或者逻辑处理的尽量在包里进行操作,页面直接调用相应的存储过程就行,减少在页面进行数据处理。

开始的懵懵懂懂,一段时间的练习回头来看,体悟更深。虽然有些还是不懂,但是都有了自己的理解。

<template> <div> <title>{{$route.name}}</title> <h1>{{$route.name}}</h1> <aui-form id="editForm"> <div class="first-field" :class="isShowMore?'showMore':'hideMore'"> <aui-form-item label="版本号" label-width="110px"> <aui-dropdown size="small" v-model="searchForm.planId" :op="planIdOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="厂区" label-width="110px"> <aui-dropdown size="small" v-model="searchForm.locationCodeStr" :op="siteCodeOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="部门" label-width="110px"> <aui-dropdown size="small" ref="deptCodeRef" v-model="searchForm.deptNameStr" :op="deptOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="工序" label-width="110px"> <aui-dropdown size="small" v-model="searchForm.workSerctionStr" :op="workSerctionOp"></aui-dropdown> </aui-form-item> <aui-form-item label="产品线" label-width="110px"> <aui-dropdown size="small" ref="prodLineCnNameRef" v-model="searchForm.prodLineCnNameStr" :op="prodLineOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="产品族" label-width="110px"> <aui-dropdown size="small" ref="prodFamilyEnNameRef" v-model="searchForm.prodFamilyEnNameStr" :op="prodFamilyOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="产品型号" label-width="110px"> <aui-dropdown size="small" ref="prodModelCodeRef" v-model="searchForm.prodModelCodeStr" :op="prodModelCodeOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item label="物料编码" label-width="110px"> <aui-input size="small" ref="itemCodeRef" v-model="searchForm.itemCodeStr" placeholder="连续首字母或者字符可模糊匹配"></aui-input> </aui-form-item> <aui-form-item label="类型" label-width="110px"> <aui-dropdown size="small" v-model="searchForm.dataTypeStr" :op="dataTypeOp" place-holder="请选择"></aui-dropdown> </aui-form-item> <aui-form-item class="first-field-btn" label-width="0px" style="width: 265px"> <i v-show="isTriangleIconShow" class="hae-icon" :class="isShowMore?'icon-down':'icon-left-o'" @click="isShowMore = !isShowMore "></i> <aui-button type="primary" size="mini" round @click="findClick">查询</aui-button> <aui-button type="primary" size="mini" round @click="reset" style="margin-right: 8px">重置</aui-button> <FormTempBtn style="width:100px;" :form-code="formId" :formData="searchForm" @templateChanged="setFormData"></FormTempBtn> </aui-form-item> </div> </aui-form> <div class="table-auto"> <aui-grid height="100%" auto-resize ref="grid" :auto-load="false" resizable :row-class-name="rowClassName" :pager="pagerConfig" border :span-method="colspanMethod" :fetch-data="fetchData"> <template #toolbar> <aui-grid-toolbar id="scheduleSupplyDemandGridId" :setting="{ showIndex: true, sortable: Sortable, }" ref="auiToolbar" @remote-setting="remoteSetting" @save-setting="saveSetting"> <template #buttons> <div style="width: 800px; display: inline-block"> <aui-button size="mini" @click="exportData">导出</aui-button> <aui-button size="mini" @click="showBaseLoggerInfo">版本日志</aui-button> </div> </template> </aui-grid-toolbar> </template> <aui-grid-column fixed="left" title="版本" field="planId" min-width="100" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="厂区" field="locationName" min-width="100" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="部门" field="deptName" min-width="120" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="产品线" field="prodLineCnName" min-width="80" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="产品族" field="prodFamilyEnName" min-width="80" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="产品型号" field="prodModelCode" min-width="80" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="工序" field="workSerction" min-width="80" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="物料编码" field="itemCode" min-width="90" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="类型" field="dataType" min-width="80" show-overflow header-align="center" align="center"></aui-grid-column> <aui-grid-column fixed="left" title="库存" field="invQty" min-width="80" show-overflow header-align="center" align="center"> <template #default="{ row }"> <div style="color: #189ff0 !important;cursor: pointer;text-decoration: underline;" @click="operateRow(row, 'invQty')">{{ row.invQty }}</div> </template> </aui-grid-column> <aui-grid-column fixed="left" title="历史" field="hisQty" min-width="100" show-overflow header-align="center" align="center"> <template #default="{ row }"> <div :class="{ 'row-link_click': ['预计供应', '过站供应', '排产需求'].includes(row.dataType), 'row-link-red': String(row.hisQty) && row.hisQty < 0 }" @click="operateRow(row, 'hisQty')">{{ row.hisQty }}</div> </template> </aui-grid-column> <aui-grid-column v-for="(item, i) in dateItem" :key="i" :field="item.field" :title="item.title" :renderer="renderFunction" min-width="50" align="center"> <template #default="{ row }"> <a v-if="row.dataType === '排产需求'" :style="{ textDecoration: 'underline', cursor: 'pointer' }" @click="handleDateCellClick(row, item.field)">{{ row[item.field] }} </a> </template> </aui-grid-column> </aui-grid> </div> <StockDialog v-if="showStock" :rowData="rowData" @changeDialog="changeDialog"></StockDialog> <InProcessWorkOrderSchedule v-if="showInProcess" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></InProcessWorkOrderSchedule> <WorkOrderScheduleHistory v-if="showHistory" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></WorkOrderScheduleHistory> <aui-dialog-box title="版本日志" class="history-Info" v-model="isShowBaseLoggerInfo" width="90%" top="8%" :dragable="true" :modal-closable="false"> <base-logger-info v-bind:apiUrl="getLoggerInfoUrl" v-if="isShowBaseLoggerInfo"></base-logger-info> </aui-dialog-box> </div> </template> <script> import { Form, FormItem, Dropdown, Hae, $, DialogBox } from '@aurora/ui3' import { Grid, GridColumn, Modal, Pager, Button, GridToolbar } from '@aurora/vue3' import { FormTempBtn } from '@mxdesign/ui' import Sortable from 'sortablejs' import { remoteSettingFn, saveSettingFn, getCustomConfigsFn } from '@/utils/personSettings' import StockDialog from '@/components/supplydemandmgt/StockDialog' import InProcessWorkOrderSchedule from '@/components/supplydemandmgt/InProcessWorkOrderSchedule' import WorkOrderScheduleHistory from '@/components/supplydemandmgt/WorkOrderScheduleHistory' import WorkOrderScheduleHistoryCopy from './WorkOrderScheduleHistory copy.vue' import BaseLoggerInfo from '../basedata/BaseLoggerInfo.vue' export default { components: { AuiDialogBox: DialogBox, AuiButton: Button, AuiForm: Form, AuiFormItem: FormItem, AuiDropdown: Dropdown, AuiGrid: Grid, AuiGridColumn: GridColumn, AuiGridToolbar: GridToolbar, FormTempBtn, StockDialog, InProcessWorkOrderSchedule, WorkOrderScheduleHistory, BaseLoggerInfo }, computed: { tableData() { return this.$refs.grid && this.$refs.grid.getTableData() ? this.$refs.grid.getTableData().tableData : [] } }, data() { return { Sortable, isShowBaseLoggerInfo: false, getLoggerInfoUrl: 'services/supplyRequireItemHeadService/getSupplyRequireLogList/page/{{pageSize}}/{{curPage}}', formId: 'scheduleSupplyDemandId', toolBoxShow: false, isShowMore: true, isTriangleIconShow: true, searchForm: { planId: '', // 版本号 locationCodeStr: '', // 厂区 deptNameStr: '', // 部门 prodLineCnNameStr: '', // 产品线 prodFamilyEnNameStr: '', // 产品族 prodModelCodeStr: '', // 产品型号 workSerctionStr: '', // 工序 itemCodeStr: '', // 编码 dataTypeStr: '' // 类型 }, // 版本号 planIdOp: { multi: false, showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, id: 'planId', validation: { required: true }, textField: 'planId', valueField: 'planId', placeHolder: '-----请选择-----', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getAllPlanIdList' } } }, // 厂区 siteCodeOp: { multi: true, id: 'locationCodeId', showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, textField: 'locationName', valueField: 'locationCode', placeHolder: '-----请选择-----', emptyDataMsg: '-----没有数据-----', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getAllLocationInfo' } } }, // 部门 deptOp: { multi: true, // 是否多选 id: 'deptCodeId', showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, textField: 'deptName', valueField: 'deptName', placeHolder: '-----请选择-----', emptyDataMsg: '-----请选择厂区-----', dataset: { source: { type: 'POST', url: 'services/apsSupplyRequireService/getDeptInfo' } }, cascade: [ { trigger: '#locationCodeId', allowEmpty: false, // 是否允许空值参加级联 name: 'locationCodeStr' } ] }, // 工序 workSerctionOp: { id: 'workSerctionId', multi: true, showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, placeHolder: '-----请选择-----', textField: 'valueInfo', valueField: 'valueInfo', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getAllWorkSerction' } } }, // 产品线 prodLineOp: { multi: true, id: 'prodLineId', showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, textField: 'prodLineCnName', valueField: 'prodLineCnName', placeHolder: '-----请选择-----', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getProdLineList' } } }, // 产品族(系列) prodFamilyOp: { multi: true, id: 'prodFamilyId', showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, textField: 'prodSeriesEnName', valueField: 'prodSeriesEnName', placeHolder: '-----请选择-----', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getProdSeriesList' } }, cascade: [ { trigger: '#prodLineId', allowEmpty: true, // 是否允许空值参加级联 name: 'prodLineCnNameStr' } ], emptyDataMsg: '-----请选择产品线-----' }, // 产品型号 prodModelCodeOp: { multi: true, id: 'prodModelId', showClearBtn: true, autoSelect: false, alwaysLoad: true, editable: true, textField: 'prodModelCode', valueField: 'prodModelCode', placeHolder: '-----请选择-----', dataset: { source: { type: 'post', url: 'services/apsSupplyRequireService/getAllProdModelList' } }, cascade: [ { trigger: '#prodFamilyId', allowEmpty: false, name: 'prodSeriesEnNameStr' } ], emptyDataMsg: '-----请选择产品族-----' }, // 类型 dataTypeOp: { multi: true, id: 'dataTypeId', showClearBtn: true, autoSelect: false, editable: true, textField: 'label', valueField: 'value', placeHolder: '-----请选择-----', dataset: { value: [ { value: '排产', label: '排产' }, { value: '预计供应', label: '预计供应' }, { value: '过站供应', label: '过站供应' }, { value: '排产需求', label: '排产需求' }, { value: '供需匹配', label: '供需匹配' } ] } }, pageFlag: false, pagerConfig: { component: Pager, attrs: { currentPage: 1, pageSize: 15, pageSizes: [15, 30, 50, 100], total: 0, layout: 'total, sizes, prev, pager, next, jumper' } }, dateItem: [], fetchData: { api: this.getData }, clickSearchForm: {}, rowData: {}, showStock: false, showInProcess: false, showHistory: false, settingType: 'scheduleSupplyDemand', setTableColumn: [] } }, methods: { showBaseLoggerInfo() { this.isShowBaseLoggerInfo = true }, // 导出 exportData() { let formData = this.searchForm Hae.ajax({ url: 'services/exportFileUtilService/exportApsSupplyRequire', data: formData, type: 'post', success: () => { Hae.confirm('导出任务已开始,你可以进入[我的导入导出>导出查询]中查看任务状态并下载导出文件!', (bool) => { if (bool) { window.open('#/ListExport') } }) } }) }, // 行合并 colspanMethod({ row, column, rowIndex, columnIndex }) { let fields = ['mergerKey', 'invQty'] // 获取当前行的 mergerKey const currentGroupKey = row.mergerKey // 获取当前列的 prop const columnProp = column.property // 计算相同 mergerKey 的行范围 const groupRows = this.tableData.filter((item) => item.mergerKey === currentGroupKey && currentGroupKey) const firstGroupRowIndex = this.tableData.findIndex( (item) => item.mergerKey === currentGroupKey && currentGroupKey ) const lastGroupRowIndex = firstGroupRowIndex + groupRows.length - 1 // 对于 fields 列,合并相同 mergerKey 的所有行 if (fields.includes(columnProp)) { if (rowIndex === firstGroupRowIndex) { return { rowspan: groupRows.length, colspan: 1 } } else { return { rowspan: 0, colspan: 0 } } } }, // 行渲染 renderFunction(h, { row, column }) { if (row.dataType === '排产需求'&& Number(row[column.property]) < 0) { return <span style={{ color: '#000', fontSize: '12px' }}>{row[column.property]}</span> } if (String(row[column.property]) && Number(row[column.property]) < 0) { return <span style={{ color: '#fe281f', fontSize: '12px' }}>{row[column.property]}</span> } else { return <span style={{ color: '#000', fontSize: '12px' }}>{row[column.property]}</span> } }, rowClassName({ seq, row, rowIndex, $rowIndex }) { if (row.dataType === '排产') { return 'row__word--remarked' } else { return '' } }, setFormData(data) { let tempArr = Object.keys(data) this.resData = data if (tempArr.length === 0) { return } this.searchForm.planId = data.planId // 版本号 this.searchForm.locationCodeStr = data.locationCodeStr // 厂区 this.searchForm.prodLineCnNameStr = data.prodLineCnNameStr // 产品线 this.searchForm.workSerctionStr = data.workSerctionStr // 工序 this.searchForm.dataTypeStr = data.dataTypeStr // 类型 // 级联关系接口先后执行 setTimeout(() => { this.$refs.deptCodeRef.widget.setValueByField(data.deptNameStr, 'deptName') // 注意: 第二个参数是下拉的value值,不是v-model的值 }, 500) setTimeout(() => { this.$refs.prodFamilyEnNameRef.widget.setValueByField(data.prodFamilyEnNameStr, 'prodSeriesEnName') }, 800) setTimeout(() => { this.$refs.prodModelCodeRef.widget.setValueByField(data.prodModelCodeStr, 'prodModelCode') }, 1500) setTimeout(() => { this.$refs.itemCodeRef.widget.setValueByField(data.itemCodeStr, 'prodItemCode') }, 2000) }, operateRow(row, flag) { this.rowData = row this.rowData.dialogFlag = flag if (flag === 'invQty') { this.showStock = true } else { if (['排产需求'].includes(row.dataType)) { this.showHistory = true } if (['预计供应', '过站供应'].includes(row.dataType)) { this.showInProcess = true } } }, handleDateCellClick(row, field) { this.rowData = { ...row, date: field, quantity: row[field] }; this.showHistory = true; }, changeDialog() { this.rowData = {} this.showStock = false this.showHistory = false this.showInProcess = false }, reset() { // 清空选择 this.searchForm = { planId: '', // 版本号 locationCodeStr: '', // 厂区 deptNameStr: '', // 部门 prodLineCnNameStr: '', // 产品线 prodFamilyEnNameStr: '', // 产品族 prodModelCodeStr: '', // 产品型号 workSerctionStr: '', // 工序 itemCodeStr: '', // 编码 dataTypeStr: '' // 类型 } this.clickSearchForm = JSON.parse(JSON.stringify(this.searchForm)) }, // 动态日期列 columnDate() { this.dateItem = [] let params = { ...this.searchForm } this.$service.network.post('services/apsSupplyRequireService/getHeadBucketList', params).then(({ data }) => { this.pageFlag = false if (data && data.length) { data.forEach((element) => { // 将完整日期转换为月日格式 MM/DD const dateParts = element.split('-') const monthDay = dateParts.length >= 3 ? `${dateParts[1]}/${dateParts[2]}` : element this.dateItem.push({ title: monthDay, field: element }) }) } }) }, findClick() { Hae.validForm($('#editForm'), (valid) => { if (valid) { this.pageFlag = true this.getCustomConfigs() this.clickSearchForm = JSON.parse(JSON.stringify(this.searchForm)) setTimeout(() => { this.$refs.grid.handleFetch() }, 500) } }) }, // 查询 getData({ page }) { let { pageSize } = page if (this.pageFlag) { page.currentPage = 1 } let curPage = page.currentPage return new Promise((resolve, reject) => { let params = { ...this.clickSearchForm } this.$service.network .post(`services/apsSupplyRequireService/getApsSupplyRequireList/page/${pageSize}/${curPage}`, params) .then(({ data }) => { this.pageFlag = false this.isShowMore = false this.columnDate() let totalRows = data.pageVO && data.pageVO.totalRows ? data.pageVO.totalRows : 0 let result = data.result && data.result.length ? data.result : [] resolve({ result, page: { total: totalRows } }) }) }) }, getCustomConfigs() { let config = { settingType: this.settingType, grid: 'grid', auiToolbar: 'auiToolbar', setTableColumn: 'setTableColumn', dragSort: true } getCustomConfigsFn.call(this, config) }, remoteSetting(settings) { remoteSettingFn.call(this, settings, 'grid') }, saveSetting() { let customConfigs = arguments[0].columns let config = { settingType: this.settingType, customConfigs } saveSettingFn.call(this, config) } }, mounted() { let that = this // 判断是否有更多条件显示隐藏小三角 let editFormHeight = $('.first-field').outerHeight() that.isTriangleIconShow = !(editFormHeight < 38) that.isShowMore = false this.getCustomConfigs() } } </script> <style scoped src="./../unit/css/newModelPublic.css"></style> <style scoped> .first-field { padding-right: 300px !important; } :deep(.table-auto .aui-grid .aui-grid-cell) { width: 100% !important; font-size: 12px; } .table-auto { height: calc(100vh - 140px) !important; } :deep(.table-auto .aui-grid__body-wrapper) { height: calc(100vh - 280px) !important; } :deep(.aui-grid__body-wrapper::-webkit-scrollbar) { height: 12px !important; width: 12px !important; } :deep(.aui-grid__body .aui-grid-body__column .aui-grid-cell .row-link) { color: #189ff0 !important; cursor: pointer; text-decoration: underline; } :deep(.aui-grid-toolbar) { padding: 5px 0; } :deep(.aui-grid-toolbar .aui-grid-custom__wrapper) { height: 24px !important; width: 24px !important; } :deep(.aui-grid__body .aui-grid-body__column .aui-grid-cell .row-link_click) { color: #189ff0 !important; cursor: pointer; text-decoration: underline; } :deep(.aui-grid__body .aui-grid-body__column .aui-grid-cell .row-link-red) { color: #fe281f !important; } :deep(.aui-grid.fixed__sticky .row__word--remarked) { --body-background-color: #ebf1de !important; } :deep(.row__word--remarked) { background-color: #ebf1de !important; } :deep(.aui-grid .aui-pager) { padding-top: 6px !important; } </style> <style> /* 隐藏aui3个性化重置按钮 */ .aui-grid-modal__box .aui-grid-custom .aui-grid-custom__footer .aui-button:nth-child(2) { display: none !important; } </style> 中在dataItem动态生成的日期列中对应的数值类型是排产需求的点击数值展示WorkOrderScheduleHistory页面,如果为排产则跳转为WorkOrderScheduleHistory2页面
最新发布
08-15
<think>我们注意到在模板中已经有一个`handleDateCellClick`方法,但是目前它只是设置了`rowData`并显示`WorkOrderScheduleHistory`组件。现在需要根据数据类型跳转不同的页面(组件)。 根据需求: - 当数据类型为“排产需求”时,点击日期列中的数值,显示`WorkOrderScheduleHistory`组件(即跳转到该页面)。 - 当数据类型为“排产”时,点击日期列中的数值,显示`WorkOrderScheduleHistory2`组件(即跳转到该页面)。 但是,在现有的模板中,只有“排产需求”类型的单元格被渲染为可点击的链接(使用`<a>`标签),而“排产”类型并没有被处理。因此,我们需要修改模板,使得“排产”类型的单元格也变成可点击的链接,并且调用同一个方法(或不同的方法)来跳转。 然而,观察模板,目前只有`row.dataType === '排产需求'`的单元格才被渲染为`<a>`标签。所以我们需要扩展条件,将“排产”类型也包含进来,或者使用不同的条件分别处理。 但是请注意,需求中要求: - 排产需求 -> WorkOrderScheduleHistory - 排产 -> WorkOrderScheduleHistory2 因此,我们可以修改模板,让两种类型的单元格都变成可点击,然后在点击事件中根据类型进行判断。 修改步骤: 1. 修改模板,将条件改为同时包含“排产需求”和“排产”类型,或者使用一个更通用的条件(比如根据类型判断是否可点击)。这里我们选择将两种类型都渲染为可点击链接。 将原来的: <a v-if="row.dataType === '排产需求'" ...></a> 改为: <a v-if="['排产需求', '排产'].includes(row.dataType)" ...></a> 2. 在`handleDateCellClick`方法中,根据数据类型进行不同的跳转。 但是,注意现有代码中已经有一个`operateRow`方法用于处理其他列的点击,而日期列的点击使用的是`handleDateCellClick`方法。因此,我们修改`handleDateCellClick`方法。 修改后的`handleDateCellClick`方法: handleDateCellClick(row, field) { // 根据数据类型跳转不同页面 if (row.dataType === '排产需求') { // 跳转到WorkOrderScheduleHistory this.rowData = { ...row, date: field, quantity: row[field] }; this.showHistory = true; // 显示WorkOrderScheduleHistory组件 } else if (row.dataType === '排产') { // 跳转到WorkOrderScheduleHistory2 this.rowData = { ...row, date: field, quantity: row[field] }; // 这里我们需要一个状态来控制显示WorkOrderScheduleHistory2组件 this.showHistory2 = true; } } 3. 在模板中,我们需要添加一个`WorkOrderScheduleHistory2`组件的显示条件,类似于其他组件的显示。 因此,在data中需要添加一个状态`showHistory2`,初始化为false。 4. 在`changeDialog`方法中,也要记得将`showHistory2`重置为false。 5. 在组件引入部分,需要引入`WorkOrderScheduleHistory2`组件,并在components中注册。 但是,注意原代码中已经有一个`WorkOrderScheduleHistoryCopy`的引入,但未使用。我们假设`WorkOrderScheduleHistory2`就是`WorkOrderScheduleHistoryCopy`,因为文件名是'./WorkOrderScheduleHistory copy.vue',所以我们可以将其注册为`WorkOrderScheduleHistory2`。 修改组件引入和注册: import WorkOrderScheduleHistory2 from './WorkOrderScheduleHistory copy.vue' components: { ..., WorkOrderScheduleHistory2 } 6. 在模板中添加`WorkOrderScheduleHistory2`组件的显示条件: <WorkOrderScheduleHistory2 v-if="showHistory2" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></WorkOrderScheduleHistory2> 7. 注意,原代码中已经有一个`WorkOrderScheduleHistory`组件(用于排产需求),我们保持原样。 但是,这里有一个问题:原代码中已经有一个`WorkOrderScheduleHistory`组件的显示,现在又添加了`WorkOrderScheduleHistory2`,所以需要分别控制。 8. 另外,注意原代码中`handleDateCellClick`方法已经存在,我们只需要修改它。 然而,观察现有代码,发现现有的`handleDateCellClick`方法已经做了一些事情,但并没有根据类型区分。所以我们按照上面的思路修改。 但是,在现有代码中,`handleDateCellClick`方法只设置了`rowData`和`showHistory`,并没有处理“排产”类型。所以我们修改该方法。 修改后的方法: handleDateCellClick(row, field) { this.rowData = { ...row, date: field, quantity: row[field] }; if (row.dataType === '排产需求') { this.showHistory = true; } else if (row.dataType === '排产') { this.showHistory2 = true; } } 9. 在data中添加showHistory2属性: data() { return { ..., showHistory2: false } } 10. 修改模板,将日期列中“排产”类型的单元格也渲染为可点击链接。 但是,原模板中已经有一个`renderFunction`用于渲染单元格内容(颜色等)。我们不需要修改这个渲染函数,因为链接的样式已经在`<a>`标签上定义了。我们只需要确保两种类型都使用`<a>`标签。 11. 注意,原模板中日期列已经使用了`renderFunction`,但是该函数只负责内容(颜色)的渲染,而模板结构(即使用`<a>`还是`<span>`)是由外层模板决定的。所以外层模板的修改不会影响`renderFunction`。 因此,我们只需要修改外层模板的条件即可。 修改后的日期列模板: <template #default="{ row }"> <!-- 将条件改为同时包含排产需求和排产 --> <a v-if="['排产需求', '排产'].includes(row.dataType)" :style="{ textDecoration: 'underline', cursor: 'pointer' }" @click="handleDateCellClick(row, item.field)">{{ row[item.field] }} </a> <!-- 其他类型不变,注意这里原代码没有显示其他类型的单元格,我们加上非排产需求和排产的情况 --> <span v-else>{{ row[item.field] }}</span> </template> 但是,原代码中并没有处理非排产需求的情况(即没有显示),所以我们可以保留原代码,只修改条件。 原代码中,只有排产需求才显示为链接,其他都是普通文本(由`renderFunction`渲染)。现在我们要将排产也显示为链接,所以修改条件即可。 12. 另外,注意原代码中`renderFunction`已经对负数的颜色做了处理,我们不需要修改。 13. 最后,在`changeDialog`方法中重置`showHistory2`: changeDialog() { this.rowData = {}; this.showStock = false; this.showHistory = false; this.showInProcess = false; this.showHistory2 = false; // 添加这一行 } 14. 在模板中添加`WorkOrderScheduleHistory2`组件的显示: 在现有对话框组件的后面添加: <WorkOrderScheduleHistory2 v-if="showHistory2" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></WorkOrderScheduleHistory2> 但是,注意原代码中已经引入了`WorkOrderScheduleHistoryCopy`并注册为`WorkOrderScheduleHistoryCopy`,我们需要将其改为`WorkOrderScheduleHistory2`。 修改引入和注册: import WorkOrderScheduleHistoryCopy from './WorkOrderScheduleHistory copy.vue' 然后在components中: components: { ..., WorkOrderScheduleHistory2: WorkOrderScheduleHistoryCopy } 或者直接修改引入名: import WorkOrderScheduleHistory2 from './WorkOrderScheduleHistory copy.vue' 然后注册: components: { ..., WorkOrderScheduleHistory2 } 15. 由于原文件名为'WorkOrderScheduleHistory copy.vue',我们建议在项目中重命名为'WorkOrderScheduleHistory2.vue',避免混淆。但这里不强制,因为只是引用。 16. 另外,注意原代码中已经有一个`WorkOrderScheduleHistory`组件(用于排产需求),我们保持原样。 总结修改点: - 修改日期列模板,将条件改为`['排产需求','排产'].includes(row.dataType)` - 在`handleDateCellClick`方法中根据类型设置不同的show变量 - 添加`showHistory2`状态 - 在`changeDialog`中重置`showHistory2` - 引入并注册`WorkOrderScheduleHistory2`组件(即原来的copy组件) - 在模板中添加`WorkOrderScheduleHistory2`组件的显示 注意:由于原代码中已经存在`WorkOrderScheduleHistoryCopy`的引入,但未使用,所以我们直接使用它。 但是,原代码中引入的是`WorkOrderScheduleHistoryCopy`,而注册时没有使用。我们将其注册为`WorkOrderScheduleHistory2`。 修改后的代码: import WorkOrderScheduleHistory2 from './WorkOrderScheduleHistory copy.vue' 并在components中注册:WorkOrderScheduleHistory2 最后,在模板中显示: <WorkOrderScheduleHistory2 v-if="showHistory2" ... /> 按照上述步骤修改。 但是,为了避免混淆,我们也可以将组件名保持为`WorkOrderScheduleHistoryCopy`,只要在模板中使用即可。不过为了清晰,我们使用`WorkOrderScheduleHistory2`。 由于原代码中已经有一个`WorkOrderScheduleHistory`组件(用于排产需求),所以我们将新组件命名为`WorkOrderScheduleHistory2`。 修改后的代码示例: <WorkOrderScheduleHistory2 v-if="showHistory2" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></WorkOrderScheduleHistory2> 注意:原代码中已经有一个`WorkOrderScheduleHistory`组件(用于排产需求)的显示,我们保留。 因此,在模板中会有两个对话框组件同时存在,但根据不同的条件显示。 由于对话框组件使用`v-if`控制,所以同一时间只会显示一个。 17. 另外,注意原代码中`handleDateCellClick`方法已经存在,我们只需要修改其内容。 修改后的`handleDateCellClick`方法: handleDateCellClick(row, field) { this.rowData = { ...row, date: field, quantity: row[field] }; if (row.dataType === '排产需求') { this.showHistory = true; } else if (row.dataType === '排产') { this.showHistory2 = true; } } 18. 在data中添加showHistory2: data() { return { ..., showHistory: false, showHistory2: false, // 新增 ... } } 19. 修改changeDialog方法: changeDialog() { this.rowData = {} this.showStock = false this.showHistory = false this.showInProcess = false this.showHistory2 = false // 新增 } 20. 修改日期列模板,将条件改为:`['排产需求','排产'].includes(row.dataType)` 修改后的日期列模板: <aui-grid-column v-for="(item, i) in dateItem" :key="i" :field="item.field" :title="item.title" :renderer="renderFunction" min-width="50" align="center"> <template #default="{ row }"> <a v-if="['排产需求','排产'].includes(row.dataType)" :style="{ textDecoration: 'underline', cursor: 'pointer' }" @click="handleDateCellClick(row, item.field)"> {{ row[item.field] }} </a> <span v-else>{{ row[item.field] }}</span> </template> </aui-grid-column> 注意:原代码中日期列没有`v-else`,现在添加了`v-else`用于显示其他情况。 21. 引入并注册新组件: import WorkOrderScheduleHistory2 from './WorkOrderScheduleHistory copy.vue' components: { ..., WorkOrderScheduleHistory2 } 22. 在模板中添加新组件的显示: 在现有对话框组件的后面添加: <WorkOrderScheduleHistory2 v-if="showHistory2" :rowData="rowData" @changeDialog="changeDialog" :dateItem="dateItem"></WorkOrderScheduleHistory2> 完成以上修改即可。 但是,注意原代码中已经有一个`WorkOrderScheduleHistory`组件的显示,我们保持不变。 最后,注意样式问题:由于两个对话框的样式可能相同,如果同时显示可能会有重叠,但因为我们使用`v-if`控制,所以不会同时显示。 按照以上步骤修改代码。</think>根据您的需求,我将修改代码以实现动态日期列中不同类型数据的跳转逻辑。关键修改在于`handleDateCellClick`方法,使其根据数据类型跳转到不同页面: ```vue <script> // ...其他代码保持不变... methods: { // ...其他方法保持不变... handleDateCellClick(row, field) { // 根据数据类型跳转不同页面 if (row.dataType === '排产需求') { this.$router.push({ name: 'WorkOrderScheduleHistory', query: { workOrderNo: row.workOrderNo, date: this.parseFieldToDate(field), productCode: row.productCode } }); } else if (row.dataType === '排产') { this.$router.push({ name: 'WorkOrderScheduleHistory2', query: { workOrderNo: row.workOrderNo, date: this.parseFieldToDate(field), lineId: row.productionLineId } }); } }, // 解析字段名为日期格式 parseFieldToDate(field) { // 假设字段格式为 "date_2023-08-01" if (field.startsWith('date_')) { return field.replace('date_', ''); } return field; } }, // ...其他代码保持不变... </script> ``` ### 完整修改说明: 1. **修改模板部分**: ```vue <aui-grid-column v-for="(item, i) in dateItem" :key="i" :field="item.field" :title="item.title" min-width="50" align="center"> <template #default="{ row }"> <!-- 修改条件判断,支持排产需求和排产类型 --> <a v-if="['排产需求', '排产'].includes(row.dataType)" :style="{ color: Number(row[item.field]) < 0 ? '#fe281f' : '#000', textDecoration: 'underline', cursor: 'pointer' }" @click="handleDateCellClick(row, item.field)"> {{ row[item.field] }} </a> <span v-else :style="{ color: Number(row[item.field]) < 0 ? '#fe281f' : '#000' }"> {{ row[item.field] }} </span> </template> </aui-grid-column> ``` 2. **添加路由配置**(在router/index.js中): ```javascript const routes = [ { path: '/work-order-history', name: 'WorkOrderScheduleHistory', component: () => import('@/views/WorkOrderScheduleHistory.vue') }, { path: '/work-order-history2', name: 'WorkOrderScheduleHistory2', component: () => import('@/views/WorkOrderScheduleHistory2.vue') } ]; ``` 3. **目标页面接收参数**(WorkOrderScheduleHistory.vue): ```vue <script> export default { mounted() { const { workOrderNo, date, productCode } = this.$route.query; console.log('接收参数:', workOrderNo, date, productCode); // 调用API获取详情数据 } } </script> ``` ### 关键优化点: 1. **动态路由跳转**: - 使用`$router.push`进行页面跳转 - 通过query参数传递工单号、日期和生产线ID 2. **字段解析优化**: ```javascript parseFieldToDate(field) { // 支持多种日期格式 if (field.includes('_')) { return field.split('_')[1]; } return field; } ``` 3. **错误处理增强**: ```javascript handleDateCellClick(row, field) { try { // ...跳转逻辑... } catch (error) { console.error('跳转失败:', error); this.$message.error('页面跳转失败,请检查参数'); } } ``` 4. **空值处理**: ```javascript handleDateCellClick(row, field) { if (!row.workOrderNo) { this.$message.warning('工单号不存在'); return; } // ...正常跳转逻辑... } ``` ### 完整修改后的组件代码: ```vue <template> <!-- 模板部分保持不变 --> </template> <script> import { /* 导入保持不变 */ } from '@aurora/ui3' import { /* 导入保持不变 */ } from '@aurora/vue3' import WorkOrderScheduleHistory2 from './WorkOrderScheduleHistory2.vue' // 确保导入新页面 export default { components: { // ...其他组件保持不变... WorkOrderScheduleHistory2 }, methods: { // ...其他方法保持不变... handleDateCellClick(row, field) { try { if (row.dataType === '排产需求') { this.$router.push({ name: 'WorkOrderScheduleHistory', query: { workOrderNo: row.workOrderNo || '', date: this.parseFieldToDate(field), productCode: row.productCode || '' } }); } else if (row.dataType === '排产') { this.$router.push({ name: 'WorkOrderScheduleHistory2', query: { workOrderNo: row.workOrderNo || '', date: this.parseFieldToDate(field), lineId: row.productionLineId || '' } }); } } catch (error) { console.error('页面跳转失败:', error); this.$message.error('系统错误,请联系管理员'); } }, parseFieldToDate(field) { // 支持更多日期格式 if (field.startsWith('date_')) { return field.substring(5); } else if (field.includes('_')) { return field.split('_')[1]; } return field; } } } </script> ``` ### 注意事项: 1. **确保路由配置正确**: - 在router/index.js中正确定义两个页面的路由 - 确保目标页面组件存在 2. **数据一致性**: - 确保行数据中包含`workOrderNo`、`productionLineId`等必要字段 - 在API返回数据时检查这些字段是否存在 3. **权限控制**: ```javascript handleDateCellClick(row, field) { // 检查用户是否有权限访问目标页面 if (!this.$store.getters.hasPermission('VIEW_SCHEDULE_HISTORY')) { this.$message.warning('您没有查看权限'); return; } // ...跳转逻辑... } ``` 4. **性能优化**: - 对于大量数据,使用路由懒加载 - 在目标页面添加加载状态和错误处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值