function newSprt02030Control(pageName, doctx="[data-doctx='sprt02030']", mainPageName="sprt02010") {
    let ctrlOpnn = new DatasetControl({
          doctx: doctx
        , prefix: "opnn"
        , prefixName: "의견제출"
        , dataGetter: obj => obj["opnnInfo"]
        , keys: ["OPNN_ID"]
        , infoSize: "lg"
        , urls: {
              load: "/list.do"
            , getInfo: "/info.do"
        }
    });

    /**************************************************************************
     * DatasetControl Events
     **************************************************************************/
    // 현재 선택 자료 변경 이벤트
    ctrlOpnn.onCurrentChange = (item) => {
        if (!item) return;

        // 화면에 단속 Dataset 셋팅
        let formFields = new FimsFormFields(ctrlOpnn.selector("[name='frmOpnn']"));
        formFields.set(ctrlOpnn, item);

        // 첨부파일 조회
        let key = item.data.OPNN_ID;
        if (key != null) {
            pageObject[pageName].fnSearchFileList(key);
        }
    };

    // 상세 정보 dialog
    ctrlOpnn.getInfo = (params) => {
        if (!params) return;

        ajax.get({
              url: wctx.url("/excl/excl02/020/info.do")
            , data: params || {}
            , success: (resp) => {
                let dialogName = ctrlOpnn.prefixed("Dialog");
                let dialogId = dialogName + "-" + uuid();

                dialog.open({
                      id: dialogId
                    , title: params.btnTitle
                    , size: ctrlOpnn.infoSize
                    , content: resp
                    , init: () => {
                        $("#" + dialogId).attr("name", dialogName);
                        $("#" + dialogId).attr("data-ref-doctx", pageName);

                        AppSupport.setDialogZindex();
                    }
                    , onClose: () => { pageObject[pageName].fnRefresh(); }      // 정보 새로고침
                });
            }
        });
    }

    // 삭제 callback
    ctrlOpnn.onRemove = (params, resp) => {
        let showMessage = resp.rtnMsg.replace(/[S]|[F]/g, params.btnTitle);

        dialog.alert({
              content: showMessage
            , init: () => { AppSupport.setDialogZindex(); }
            , onOK: resp.saved ? undefined : () => { }
            , onClose: () => {
                if (resp.saved) { pageObject[pageName].fnRefresh(); }           // 정보 새로고침
            }
        });
    }

    // 삭제
    ctrlOpnn.remove = (params) => {
        if (!params) return;

        ajax.post({
              url: wctx.url("/excl/excl02/010/remove.do")
            , data: params || {}
            , success: (resp) => { ctrlOpnn.onRemove(params, resp); }
        });
    }

    return ctrlOpnn;
}
