Merge remote-tracking branch 'origin/dev' into dev

dev
UIJIN_KIM 3 months ago
commit a978e946d9

2
.gitignore vendored

@ -30,3 +30,5 @@ replay_pid*
/.idea/
/.gradle/
/.idea/
/src/main/UbiService/logs/
/src/main/UbiService/results/UBIHTML/

@ -136,6 +136,11 @@ dependencies {
// SQL datasource-proxy
implementation 'net.ttddyy:datasource-proxy:1.10.1'
// ===== UBI =====
// UbiServer.jar - UBI ( , WAR WEB-INF/lib )
providedCompile files('src/main/webapp/WEB-INF/lib/UbiServer.jar')
implementation 'xerces:xercesImpl:2.12.2'
// ===== =====
// Lombok - (Getter, Setter, Builder )
compileOnly 'org.projectlombok:lombok'

Binary file not shown.

@ -0,0 +1,26 @@
JAVA_DIR=/usr/local/jdk1.6.0
UBISERVICE_DIR=/webapp/myapp/UbiService
PROPERTY_DIR=$UBISERVICE_DIR
FONT_DIR=$UBISERVICE_DIR/fonts/
CLASSPATH=$UBISERVICE_DIR/lib/UbiServer.jar
XMS=1024M
XMX=2048M
GREP_STR=$UBISERVICE_DIR/lib/UbiServer.jar
#For SunOS
#if [ `/usr/ucb/ps -auxwww | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
# kill -9 `/usr/ucb/ps -auxwww | grep $GREP_STR | grep -v grep | awk '{print $2}'`
if [ `ps -ef | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
kill -9 `ps -ef | grep $GREP_STR | grep -v grep | awk '{print $2}'`
echo ""
echo ">>> UbiService has shutdown."
$JAVA_DIR/bin/java -Xms$XMS -Xmx$XMX -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dsun.java2d.fontpath=$FONT_DIR -classpath $CLASSPATH:. com.ubireport.service.UbiService4 $PROPERTY_DIR &
echo ">>> UbiService has started."
echo ""
else
echo ""
echo ">>> UbiService is not running."
echo ""
fi

@ -0,0 +1,18 @@
UBISERVICE_DIR=/webapp/myapp/UbiService
GREP_STR=$UBISERVICE_DIR/lib/UbiServer.jar
#For SunOS
#if [ `/usr/ucb/ps -auxwww | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
# kill -9 `/usr/ucb/ps -auxwww | grep $GREP_STR | grep -v grep | awk '{print $2}'`
if [ `ps -ef | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
kill -9 `ps -ef | grep $GREP_STR | grep -v grep | awk '{print $2}'`
echo ""
echo ">>> UbiService has shutdown."
echo ""
else
echo ""
echo ">>> UbiService is not running."
echo ""
fi

@ -0,0 +1,31 @@
JAVA_DIR=/usr/local/jdk1.6.0
UBISERVICE_DIR=/webapp/myapp/UbiService
PROPERTY_DIR=$UBISERVICE_DIR
FONT_DIR=$UBISERVICE_DIR/fonts/
CLASSPATH=$UBISERVICE_DIR/lib/UbiServer.jar
#For Redbc
#CLASSPATH=$UBISERVICE_DIR/lib/UbiServer.jar:$UBISERVICE_DIR/lib/EzIssuerJava.jar
#For Voiceye
#CLASSPATH=$UBISERVICE_DIR/lib/UbiServer.jar:$UBISERVICE_DIR/lib/VERVMakerJNI.jar
#CLASSPATH=$UBISERVICE_DIR/lib/UbiServer.jar:$UBISERVICE_DIR/lib/VERVMakerJNI64.jar
XMS=1024M
XMX=2048M
GREP_STR=$UBISERVICE_DIR/lib/UbiServer.jar
#For SunOS
#if [ `/usr/ucb/ps -auxwww | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
if [ `ps -ef | grep $GREP_STR | grep -v grep | awk '{print $2}'` ];then
echo ""
echo ">>> UbiService is running."
echo ""
else
$JAVA_DIR/bin/java -Xms$XMS -Xmx$XMX -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dsun.java2d.fontpath=$FONT_DIR -classpath $CLASSPATH:. com.ubireport.service.UbiService4 $PROPERTY_DIR &
echo ""
echo ">>> UbiService has started."
echo ""
fi

@ -0,0 +1,68 @@
echo off
set INPUT=%1
set UBISERVICE_DIR=C:\webapps\myapp\UbiService
set BATPATH=%UBISERVICE_DIR%\bin\ubiservice.bat
set NSSM=%UBISERVICE_DIR%\bin\nssm64.exe
if "%INPUT%" == "" (
echo ----------------------------------------
echo ex : svcregist.bat [install] [uninstall]
echo ----------------------------------------
echo.
) else (
if "%INPUT%" == "install" (
echo ----------------------------------------
echo UbiService Registration Job
echo ----------------------------------------
echo.
echo [UbiService Regist]
%NSSM% install UbiService %BATPATH%
echo.
echo [UbiService Set Description]
%NSSM% set UbiService Description "UbiService for UbiReport4.0"
echo.
echo [UbiService Start]
%NSSM% start UbiService
echo.
echo ----------------------------------------
echo Install Completed
echo ----------------------------------------
echo.
) else (
if "%INPUT%" == "uninstall" (
echo ----------------------------------------
echo UbiService UnRegistration Job
echo ----------------------------------------
echo.
echo [UbiService Stop]
%NSSM% stop UbiService
echo.
echo [UbiService Unregist]
%NSSM% remove UbiService confirm
echo.
echo ----------------------------------------
echo Uninstall Completed
echo ----------------------------------------
echo.
) else (
echo ----------------------------------------
echo ex : svcregist.bat [install] [uninstall]
echo ----------------------------------------
echo.
)
)
)

@ -0,0 +1,34 @@
echo off
echo ----------------------------------------
echo UbiService.bat
echo ----------------------------------------
echo.
set JAVA_DIR=D:\DEV\.jdks\jdk1.8.0_271
set UBISERVICE_DIR=D:\workspace\git\IBMS_NEW\src\main\UbiService
set PROPERTY_DIR=%UBISERVICE_DIR%
set FONT_DIR=%UBISERVICE_DIR%\fonts\
set XMS=512M
set XMX=1024M
set CLASSPATH=%UBISERVICE_DIR%\lib\UbiServer.jar
REM For Redbc
REM set CLASSPATH=%UBISERVICE_DIR%\lib\UbiServer.jar;%UBISERVICE_DIR%\lib\EzIssuerJava.jar
REM For Voiceye
REM set CLASSPATH=%UBISERVICE_DIR%\lib\UbiServer.jar;%UBISERVICE_DIR%\lib\VERVMakerJNI.jar
REM set CLASSPATH=%UBISERVICE_DIR%\lib\UbiServer.jar;%UBISERVICE_DIR%\lib\VERVMakerJNI64.jar
echo.
echo [Directory Information]
echo - Java : %JAVA_DIR%
echo - UbiService : %UBISERVICE_DIR%
echo.
echo [Java Information]
%JAVA_DIR%\bin\java -version
echo.
echo [UbiService Start]
%JAVA_DIR%\bin\java -Xms%XMS% -Xmx%XMX% -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dsun.java2d.fontpath=%FONT_DIR% -classpath %CLASSPATH%;. com.ubireport.service.UbiService4 %PROPERTY_DIR%

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:40:22</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:47:33</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:47:37</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:47:38</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:47:39</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4/work/images/LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4workimagesLOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4workimagesLOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2025/09/04 04:48:27</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,297 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE HWPML>
<HWPML Version="2.1" Style="embed" SubVersion="7.0.0.0">
<HEAD SecCnt="1">
<DOCSETTING>
<BEGINNUMBER Page="1" Footnote="1" Endnote="1" Picture="1" Table="1" Equation="1" />
<CARETPOS List="0" Para="0" Pos="16" />
</DOCSETTING>
<MAPPINGTABLE>
<FACENAMELIST>
<FONTFACE Lang="Hangul" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="Latin" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="Hanja" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="Japanese" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="Other" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="Symbol" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
<FONTFACE Lang="User" Count="3">
<FONT Id="0" Type="ttf" Name="바탕" />
<FONT Id="1" Type="ttf" Name="Arial" />
<FONT Id="2" Type="ttf" Name="맑은 고딕" />
</FONTFACE>
</FACENAMELIST>
<BORDERFILLLIST Count="5">
<BORDERFILL Id="1" ThreeD="false" Shadow="false" BackSlash="0" Slash="0" CrookedSlash="0">
<LEFTBORDER Type="None" Width="0mm" Color="-1" />
<RIGHTBORDER Type="None" Width="0mm" Color="-1" />
<TOPBORDER Type="None" Width="0mm" Color="-1" />
<BOTTOMBORDER Type="None" Width="0mm" Color="-1" />
<FILLBRUSH>
<WINDOWBRUSH FaceColor="16777215" HatchColor="0" />
</FILLBRUSH>
</BORDERFILL>
<BORDERFILL Id="2" ThreeD="false" Shadow="false" BackSlash="0" Slash="0" CrookedSlash="0">
<LEFTBORDER Type="None" Width="0.1mm" Color="0" />
<RIGHTBORDER Type="None" Width="0.1mm" Color="0" />
<TOPBORDER Type="None" Width="0.1mm" Color="0" />
<BOTTOMBORDER Type="None" Width="0.1mm" Color="0" />
<FILLBRUSH>
<WINDOWBRUSH FaceColor="-1" HatchColor="0" />
</FILLBRUSH>
</BORDERFILL>
<BORDERFILL Id="3" ThreeD="false" Shadow="false" BackSlash="0" Slash="0" CrookedSlash="0">
<LEFTBORDER Type="None" Width="0.1mm" Color="0" />
<RIGHTBORDER Type="None" Width="0.1mm" Color="0" />
<TOPBORDER Type="None" Width="0.1mm" Color="0" />
<BOTTOMBORDER Type="None" Width="0.1mm" Color="0" />
<FILLBRUSH>
<WINDOWBRUSH FaceColor="-1" HatchColor="0" />
</FILLBRUSH>
</BORDERFILL>
<BORDERFILL Id="4" ThreeD="false" Shadow="false" BackSlash="0" Slash="0" CrookedSlash="0">
<LEFTBORDER Type="None" Width="0.1mm" Color="0" />
<RIGHTBORDER Type="None" Width="0.1mm" Color="0" />
<TOPBORDER Type="None" Width="0.1mm" Color="0" />
<BOTTOMBORDER Type="None" Width="0.1mm" Color="0" />
<FILLBRUSH>
<WINDOWBRUSH FaceColor="-1" HatchColor="0" />
</FILLBRUSH>
</BORDERFILL>
<BORDERFILL Id="5" ThreeD="false" Shadow="false" BackSlash="0" Slash="0" CrookedSlash="0">
<LEFTBORDER Type="None" Width="0.1mm" Color="0" />
<RIGHTBORDER Type="None" Width="0.1mm" Color="0" />
<TOPBORDER Type="None" Width="0.1mm" Color="0" />
<BOTTOMBORDER Type="None" Width="0.1mm" Color="0" />
<FILLBRUSH>
<WINDOWBRUSH FaceColor="-1" HatchColor="0" />
</FILLBRUSH>
</BORDERFILL>
</BORDERFILLLIST>
<CHARSHAPELIST Count="6">
<CHARSHAPE Id="0" Height="1000" TextColor="0" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
</CHARSHAPE>
<CHARSHAPE Id="1" Height="4000" TextColor="0" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="1" Latin="1" Hanja="1" Japanese="1" Other="1" Symbol="1" User="1" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
</CHARSHAPE>
<CHARSHAPE Id="2" Height="1600" TextColor="3342540" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="2" Latin="2" Hanja="2" Japanese="2" Other="2" Symbol="2" User="2" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<BOLD />
</CHARSHAPE>
<CHARSHAPE Id="3" Height="1000" TextColor="0" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="2" Latin="2" Hanja="2" Japanese="2" Other="2" Symbol="2" User="2" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<BOLD />
</CHARSHAPE>
<CHARSHAPE Id="4" Height="1600" TextColor="16737843" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="2" Latin="2" Hanja="2" Japanese="2" Other="2" Symbol="2" User="2" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<BOLD />
</CHARSHAPE>
<CHARSHAPE Id="5" Height="1600" TextColor="13056" ShadeColor="4294967295" UseFontSpace="false" UseKerning="false" SymMark="0">
<FONTID Hangul="2" Latin="2" Hanja="2" Japanese="2" Other="2" Symbol="2" User="2" />
<RATIO Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHARSPACING Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<RELSIZE Hangul="100" Latin="100" Hanja="100" Japanese="100" Other="100" Symbol="100" User="100" />
<CHAROFFSET Hangul="0" Latin="0" Hanja="0" Japanese="0" Other="0" Symbol="0" User="0" />
<BOLD />
</CHARSHAPE>
</CHARSHAPELIST>
<TABDEFLIST Count="3">
<TABDEF Id="0" AutoTabLeft="false" AutoTabRight="false" />
<TABDEF Id="1" AutoTabLeft="true" AutoTabRight="false" />
<TABDEF Id="2" AutoTabLeft="false" AutoTabRight="true" />
</TABDEFLIST>
<PARASHAPELIST Count="5">
<PARASHAPE Id="0" Align="Justify" VerAlign="Baseline" TabDef="0" BreakLatinWord="BreakWord" BreakNonLatinWord="true">
<PARAMARGIN Left="0" Right="0" Indent="0" LineSpacing="160" LineSpacingType="Percent" />
<PARASPACING />
</PARASHAPE>
<PARASHAPE Id="1" Align="Center" VerAlign="Baseline" TabDef="0" BreakLatinWord="BreakWord" BreakNonLatinWord="true">
<PARAMARGIN Left="0" Right="0" Indent="0" LineSpacing="100" LineSpacingType="Percent" />
<PARASPACING />
</PARASHAPE>
<PARASHAPE Id="2" Align="Right" VerAlign="Baseline" TabDef="0" BreakLatinWord="BreakWord" BreakNonLatinWord="true">
<PARAMARGIN Left="200" Right="1000" Indent="0" LineSpacing="100" LineSpacingType="Percent" />
<PARASPACING />
</PARASHAPE>
<PARASHAPE Id="3" Align="Left" VerAlign="Baseline" TabDef="0" BreakLatinWord="BreakWord" BreakNonLatinWord="true">
<PARAMARGIN Left="1000" Right="200" Indent="0" LineSpacing="100" LineSpacingType="Percent" />
<PARASPACING />
</PARASHAPE>
<PARASHAPE Id="4" Align="Center" VerAlign="Baseline" TabDef="0" BreakLatinWord="BreakWord" BreakNonLatinWord="true">
<PARAMARGIN Left="1000" Right="200" Indent="0" LineSpacing="100" LineSpacingType="Percent" />
<PARASPACING />
</PARASHAPE>
</PARASHAPELIST>
</MAPPINGTABLE>
</HEAD>
<BODY>
<SECTION Id="0">
<P>
<TEXT CharShape="0">
<SECDEF TabStop="8000">
<PAGEDEF Landscape="0" Width="59528" Height="84189" GutterType="0">
<PAGEMARGIN Left="5700" Right="5700" Top="5700" Bottom="5600" Header="0" Footer="0" Gutter="0" />
</PAGEDEF>
</SECDEF>
<COLDEF Type="Newspaper" Count="1" Layout="Left" SameSize="true" SameGap="0" />
<TABLE RowCount="4" ColCount="1" PageBreak="Cell" RepeatHeader="true" CellSpacing="0" borderFill="0">
<SHAPEOBJECT Id="1" NumberingType="Table" TextWrap="InFrontOfText">
<POSITION TreatAsChar="false" VertRelTo="Para" HorzRelTo="Column" FlowWithText="true" AllowOverlap="false" VertOffset="0" HorzOffset="0" VertAlign="Top" HorzAlign="Top" />
<SIZE Width="48000" Height="62100" WidthRelTo="Absolute" HeightRelTo="Absolute" Protect="false" />
<OUTSIDEMARGIN Left="0" Right="0" Top="0" Bottom="0" />
</SHAPEOBJECT>
<INSIDEMARGIN Left="141" Right="141" Top="141" Bottom="141" />
<ROW>
<CELL ColAddr="0" RowAddr="0" ColSpan="1" RowSpan="1" Width="48000" Height="8400" BorderFill="2" HasMargin="true">
<CELLMARGIN Left="0" Right="0" Top="0" Bottom="0" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="1">
<TEXT CharShape="1">
<CHAR>UbiReport 4.0</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
</ROW>
<ROW>
<CELL ColAddr="0" RowAddr="1" ColSpan="1" RowSpan="1" Width="48000" Height="23700" BorderFill="5" HasMargin="true">
<CELLMARGIN Left="500" Right="100" Top="100" Bottom="100" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="4">
<TEXT CharShape="5">
<CHAR>UbiReport 4.0 설치 테스트 화면 입니다.</CHAR>
</TEXT>
</P>
<P ParaShape="4" />
<P ParaShape="4">
<TEXT CharShape="5">
<CHAR>웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄 </CHAR>
</TEXT>
</P>
<P ParaShape="4" />
<P ParaShape="4">
<TEXT CharShape="5">
<CHAR>테스트를 진행하시기 바랍니다.</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
</ROW>
<ROW>
<CELL ColAddr="0" RowAddr="2" ColSpan="1" RowSpan="1" Width="48000" Height="26700" BorderFill="4" HasMargin="true">
<CELLMARGIN Left="500" Right="100" Top="100" Bottom="100" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="4">
<TEXT CharShape="4">
<CHAR>This page is the UbiReport 4.0 installation test page.</CHAR>
</TEXT>
</P>
<P ParaShape="4" />
<P ParaShape="4">
<TEXT CharShape="4">
<CHAR>If preview is normal in web browser, please save and </CHAR>
</TEXT>
</P>
<P ParaShape="4" />
<P ParaShape="4">
<TEXT CharShape="4">
<CHAR>print test.</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
</ROW>
<ROW>
<CELL ColAddr="0" RowAddr="3" ColSpan="1" RowSpan="1" Width="48000" Height="3300" BorderFill="3" HasMargin="true">
<CELLMARGIN Left="0" Right="0" Top="0" Bottom="0" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="1">
<TEXT CharShape="2">
<CHAR>UbiReport Homepage ( http://www.ubireport.com )</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
</ROW>
</TABLE>
<TABLE RowCount="1" ColCount="2" PageBreak="Cell" RepeatHeader="true" CellSpacing="0" borderFill="0">
<SHAPEOBJECT Id="2" NumberingType="Table" TextWrap="InFrontOfText">
<POSITION TreatAsChar="false" VertRelTo="Para" HorzRelTo="Column" FlowWithText="true" AllowOverlap="false" VertOffset="70700" HorzOffset="0" VertAlign="Top" HorzAlign="Top" />
<SIZE Width="48000" Height="2000" WidthRelTo="Absolute" HeightRelTo="Absolute" Protect="false" />
<OUTSIDEMARGIN Left="0" Right="0" Top="0" Bottom="0" />
</SHAPEOBJECT>
<INSIDEMARGIN Left="141" Right="141" Top="141" Bottom="141" />
<ROW>
<CELL ColAddr="0" RowAddr="0" ColSpan="1" RowSpan="1" Width="24000" Height="2000" BorderFill="2" HasMargin="true">
<CELLMARGIN Left="500" Right="100" Top="100" Bottom="100" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="3">
<TEXT CharShape="3">
<CHAR>출력자 : 홍길동</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
<CELL ColAddr="1" RowAddr="0" ColSpan="1" RowSpan="1" Width="24000" Height="2000" BorderFill="2" HasMargin="true">
<CELLMARGIN Left="100" Right="500" Top="100" Bottom="100" />
<PARALIST Count="1" TextDirection="0" LineWrap="0" VertAlign="Center">
<P ParaShape="2">
<TEXT CharShape="3">
<CHAR>출력일시 : 2021/04/01 11:03:23</CHAR>
</TEXT>
</P>
</PARALIST>
</CELL>
</ROW>
</TABLE>
<CHAR />
</TEXT>
</P>
</SECTION>
</BODY>
</HWPML>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080ubi4LOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/ubi4//LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080ubi4LOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080ubi4LOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2021/04/01 11:03:23</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/xit-ibms/ubi4//LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2021/03/31 05:03:15</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/xit-ibms/ubi4//LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2021/03/31 05:06:24</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Doc version="1.0" pagecount="1" docname="" fontRevision="1" serviceid="48B5F134F77599425FC9AA878FCF78" enableNoPage="true" isconverthtml="false">
<DocProperty width="595" height="841" dwidth="595.2755905511812" dheight="841.8897637795277" margintop="58" marginbottom="56" marginleft="58" marginright="57" marginheader="0" marginfooter="0" pagesize="A4" orientation="Portrait" language="Korean" />
<Fontobj id="0_0" name="Arial" style="0" size="40" />
<Fontobj id="1_0" name="맑은 고딕" style="1" size="16" />
<Fontobj id="2_0" name="맑은 고딕" style="1" size="10" />
<Lineobj id="0_0" type="-1" thickness="1" colorid="0_0" />
<Colorobj id="0_0" color="000000" />
<Colorobj id="1_0" color="ffffff" />
<Colorobj id="2_0" color="cc0033" />
<Colorobj id="3_0" color="3366ff" />
<Colorobj id="4_0" color="003300" />
<Borderobj id="0_0" top="0_0" bottom="0_0" left="0_0" right="0_0" diagonaldown="0_0" diagonalup="0_0" />
<Imageobj id="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" width="0" height="0" originalsize="false" fixedrate="1" brightness="0" loadtype="2" loadsrc="http://localhost:8080/xit-ibms/ubi4//LOGO.jpg" />
<Page pagenum="1" masterflag="0" mastertitle="" width="595" height="841" iwidth="480" iheight="727" x="58" y="58" pagesize="A4" orientation="Portrait">
<Fontid>0_0</Fontid>
<Fontid>1_0</Fontid>
<Fontid>2_0</Fontid>
<Lineid>0_0</Lineid>
<Colorid>0_0</Colorid>
<Colorid>1_0</Colorid>
<Colorid>2_0</Colorid>
<Colorid>3_0</Colorid>
<Colorid>4_0</Colorid>
<Borderid>0_0</Borderid>
<Objectid>IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg</Objectid>
<Item classname="UbiImageItem" id="IMAGE5" x="0" y="218" width="480" height="267" compid="COMP1" forecolorid="" backcolorid="" transparent="0" >
<Image imageid="IMAGE5httplocalhost8080xit-ibmsubi4LOGOjpg" halign="1" valign="1" borderid="0_0" />
</Item>
<Item classname="UbiTextItem" id="TEXT5" x="0" y="0" width="480" height="84" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="0_0" halign="1" border="0_0" >UbiReport 4.0</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT4" x="0" y="588" width="480" height="33" compid="COMP1" forecolorid="2_0" backcolorid="1_0" linked="1" linkfilename="www.ubireport.com" linkstyle="WEBPAGE" >
<Text fontid="1_0" halign="1" border="0_0" >UbiReport Homepage ( http://www.ubireport.com )</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN1" x="240" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" halign="2" border="0_0" marginleft="1" marginright="5" margintop="1" marginbottom="1" >출력일시 : 2021/03/31 05:14:05</Text>
</Item>
<Item classname="UbiTextItem" id="USERCOLUMN2" x="0" y="707" width="240" height="20" compid="COMP1" forecolorid="0_0" backcolorid="1_0" >
<Text fontid="2_0" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >출력자 : 홍길동</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT9" x="0" y="321" width="480" height="267" compid="COMP1" forecolorid="3_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >This page is the UbiReport 4.0 installation test page.
If preview is normal in web browser, please save and
print test.</Text>
</Item>
<Item classname="UbiTextItem" id="TEXT7" x="0" y="84" width="480" height="237" compid="COMP1" forecolorid="4_0" backcolorid="1_0" >
<Text fontid="1_0" halign="1" border="0_0" marginleft="5" marginright="1" margintop="1" marginbottom="1" >UbiReport 4.0 설치 테스트 화면 입니다.
웹브라우저에서 미리보기가 정상적이라면, 파일저장, 인쇄
테스트를 진행하시기 바랍니다.</Text>
</Item>
</Page>
<DocInfo startindex="1" pagecount="1" docname="" />
</Doc>

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<UbiService port="16996">
<!-- Executor urfThreads="6" exportThreads="3" pageThreads="3" /-->
<!-- TaskInfo property value : MINUTE,HOUR,DAY,WEEK,MONTH,YEAR -->
<TaskInfo taskResId="UBIHTML" taskPeriod="1" taskPeriodType="DAY" delPeriod="1" delPeriodType="DAY" />
<LogInfo logPath=""
backupStyle="date"
backupPattern="yyyy-MM-dd"
backupSize="180" />
<S3Info useS3="false"
bucketName=""
accessKey=""
secretKey="" />
<!-- For Redbc
<Redbc configXml=""
drmCopyProtectFileName=""
drmBarcodeType="HTML"
drmBarcodeCount="3" /> -->
<!-- Resources 설정 관련
- jrfDir : 리포트 파일의 경로.
- resultDir : UbiService에서 생성되는 결과 파일(xml, pdf, image)등이 위치하는 경로.
- ubiserverUrl : 리포트 파일의 결과 데이터를 전송하는 Servlet URL.
* Resources 설정 관련 문서 : UbiReport_매뉴얼 > UbiService Operation Guide.pdf 11페이지 참고 *
-->
<Resources>
<Resource id="UBIHTML"
isLocalFile="true"
jrfDir="D:/workspace/git/IBMS_NEW/src/main/webapp/ubi4/work/"
resultDir="D:/workspace/git/IBMS_NEW/src/main/UbiService/results/"
ubiserverUrl="http://localhost:8080/UbiServer"
servletRoot="http://localhost:8080"
fileUrl="http://localhost:8080/ubi4"
resource="false"
dataSource="DEV_DB"
useLog="true"
useDebug="true"
useDetail="true"
httpConnectionClassName=""
voiceyeClassName="" />
<!--<Resource id="UBIHTML"
isLocalFile="true"
jrfDir="C:/Program Files/Apache Software Foundation/Tomcat 9.0/webapps/IBMS/ubi4/work/"
resultDir="C:/Program Files/Apache Software Foundation/UbiService/results/"
ubiserverUrl="http://localhost:8998/IBMS/UbiServer"
servletRoot="http://localhost:8998/IBMS"
fileUrl="http://localhost:8998/IBMS/ubi4"
resource="false"
dataSource="DEV_DB"
useLog="true"
useDebug="true"
useDetail="true"
httpConnectionClassName=""
voiceyeClassName="" />-->
</Resources>
<!-- <Resources>
<Resource id="UBIHTML"
isLocalFile="true"
jrfDir="D:/IUP-eGovFrameDev-3.9.0-64bit/workspace/IBMS/src/main/webapp/ubi4/work/"
resultDir="D:/IUP-eGovFrameDev-3.9.0-64bit/workspace/UbiService/results/"
ubiserverUrl="http://localhost:8080/xit-ibms/UbiServer.do"
servletRoot="http://localhost:8080/xit-ibms"
fileUrl="http://localhost:8080/xit-ibms/ubi4/"
resource="false"
dataSource="DEV_DB"
useLog="true"
httpConnectionClassName=""
voiceyeClassName="" />
</Resources> -->
<!-- <Resources>
<Resource id="UBIHTML"
isLocalFile="true"
jrfDir="D:/IUP-eGovFrameDev-3.9.0-64bit/workspace/IBMS/src/main/webapp/ubi4/work/"
resultDir="D:/IUP-eGovFrameDev-3.9.0-64bit/workspace/UbiService/results/"
ubiserverUrl="http://localhost:8080/xit-ibms/UbiServer.do"
servletRoot="http://localhost:8080/xit-ibms"
fileUrl="http://localhost:8080/xit-ibms/ubi4/"
resource="false"
dataSource="Tutorial"
useLog="true"
httpConnectionClassName=""
voiceyeClassName="" />
</Resources> -->
</UbiService>

@ -256,6 +256,7 @@ public class DataSourceProxyConfig {
/**
* ParameterSetOperation
* (Integer, String, Date ) null
*/
private List<Object> extractParameterValues(List<List<ParameterSetOperation>> parametersList) {
java.util.Map<Integer, Object> parameterMap = new java.util.TreeMap<>();
@ -267,10 +268,39 @@ public class DataSourceProxyConfig {
if (operations != null) {
for (ParameterSetOperation operation : operations) {
Object[] args = operation.getArgs();
if (args != null && args.length >= 2) {
// [0]은 파라미터 인덱스 (1-based), [1]은 실제 값
if (args != null && args.length >= 1) {
Integer paramIndex = (Integer) args[0];
Object paramValue = args[1];
Object paramValue = null;
// 리플렉션을 사용하여 실제 메서드명 추출
String methodName = extractMethodName(operation);
//logger.debug("[METHOD_INFO] 파라미터 {}번 - 메서드명: {}, args 길이: {}",
// paramIndex, methodName, args.length);
// 메서드명을 통한 정확한 null 처리
if ("setNull".equals(methodName)) {
// setNull 메서드 호출 - 확실하게 null 값으로 설정
paramValue = null;
//logger.debug("[NULL_SET] setNull 메서드 호출됨 - 파라미터 {}번을 null로 설정", paramIndex);
} else {
// 다른 모든 set 메서드들 (setString, setInt, setObject 등)
if (args.length >= 2) {
paramValue = args[1];
// args[1]이 null인 경우에도 null로 처리
if (paramValue == null) {
//logger.debug("[NULL_VALUE] 파라미터 {}번 값이 null임", paramIndex);
} else {
//logger.debug("[VALUE_SET] 파라미터 {}번 - 메서드: {}, 값: {} (타입: {})",
// paramIndex, methodName, paramValue, paramValue.getClass().getSimpleName());
}
} else {
logger.warn("[WARN] 파라미터 {}번 - 메서드: {}, args 길이 부족: {}",
paramIndex, methodName, args.length);
}
}
parameterMap.put(paramIndex, paramValue);
}
}
@ -280,6 +310,39 @@ public class DataSourceProxyConfig {
// TreeMap을 사용했으므로 자동으로 인덱스 순서대로 정렬됨
return new java.util.ArrayList<>(parameterMap.values());
}
/**
* ParameterSetOperation
*
*/
private String extractMethodName(ParameterSetOperation operation) {
try {
// ParameterSetOperation의 getMethod() 메서드 호출을 시도
java.lang.reflect.Method getMethodMethod = operation.getClass().getMethod("getMethod");
Object method = getMethodMethod.invoke(operation);
if (method instanceof java.lang.reflect.Method) {
return ((java.lang.reflect.Method) method).getName();
}
// getMethod가 없거나 실패한 경우 toString()에서 메서드명 추출 시도
String operationStr = operation.toString();
if (operationStr != null) {
// "MethodName(args...)" 형태에서 메서드명 추출
int openParen = operationStr.indexOf('(');
if (openParen > 0) {
String methodPart = operationStr.substring(0, openParen);
int lastDot = methodPart.lastIndexOf('.');
return lastDot >= 0 ? methodPart.substring(lastDot + 1) : methodPart;
}
}
} catch (Exception e) {
logger.debug("[METHOD_EXTRACT_ERROR] 메서드명 추출 실패: {}", e.getMessage());
}
return "unknown";
}
/**
* jsqlparser SQL .

@ -0,0 +1,50 @@
package egovframework.config;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* UbiServer servlet
* UBI servlet mapping
*/
@Configuration
public class UbiServerConfig {
/**
* UbiServer servlet
* URL : /UbiServer
*
* @return ServletRegistrationBean UbiServer servlet
*/
@Bean
public ServletRegistrationBean<com.ubireport.server.UbiServer4> ubiServerServlet() {
ServletRegistrationBean<com.ubireport.server.UbiServer4> registrationBean =
new ServletRegistrationBean<>(new com.ubireport.server.UbiServer4(), "/UbiServer");
registrationBean.setName("UbiServer");
registrationBean.setLoadOnStartup(1); // 서버 시작 시 로드
return registrationBean;
}
/**
* default servlet URL
* default servlet
* URL : /asset/*, /files/*, /ubi4/*
*
* @return ServletRegistrationBean default servlet
*/
/* 추후 리포트 테스트 완료 후 재설정할 수 있음!! */
/*@Bean
public ServletRegistrationBean<org.apache.catalina.servlets.DefaultServlet> defaultServlet() {
ServletRegistrationBean<org.apache.catalina.servlets.DefaultServlet> registrationBean =
new ServletRegistrationBean<>(new org.apache.catalina.servlets.DefaultServlet(),
"/asset/*", "/files/*", "/ubi4/*");
registrationBean.setName("default");
registrationBean.setLoadOnStartup(1); // 서버 시작 시 로드
return registrationBean;
}*/
}

@ -3,6 +3,7 @@ package go.kr.project.crdn.crndRegistAndView.crdnActInfo.controller;
import egovframework.constant.MessageConstants;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import egovframework.util.FileUtil;
import egovframework.util.SessionUtil;
import go.kr.project.common.model.CmmnCodeSearchVO;
import go.kr.project.common.service.CommonCodeService;
@ -10,8 +11,10 @@ import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnActInfoVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnStrctIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnVltnLwrgVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnUsgIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPhotoVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPstnIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnActInfoService;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnPhotoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@ -23,7 +26,12 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import go.kr.project.common.model.FileVO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@ -51,6 +59,8 @@ public class CrdnActInfoController {
private final CrdnActInfoService service;
private final CommonCodeService commonCodeService;
private final CrdnPhotoService photoService;
private final FileUtil fileUtil;
/**
* (AJAX)
@ -99,14 +109,19 @@ public class CrdnActInfoController {
log.debug("불법위반행위정보 팝업 요청 - crdnYr: {}, crdnNo: {}, mode: {}, actInfoId: {}", crdnYr, crdnNo, mode, actInfoId);
CrdnActInfoVO data = null;
List<CrdnPhotoVO> photoList = null;
// 수정 모드인 경우 기존 데이터 조회
// 수정 모드인 경우 기존 데이터 및 사진 목록 조회
if ("U".equals(mode) && actInfoId != null) {
data = service.selectActInfoByPk(actInfoId);
// 중요한 로직 주석: 수정 모드에서 기존 등록된 사진 목록을 조회하여 화면에 표시한다.
photoList = photoService.selectPhotoListByActInfoIdAndPhotoSeCd(
CrdnPhotoVO.builder().actInfoId(actInfoId).crdnPhotoSeCd("1").build());
}
ModelAndView mav = new ModelAndView("crdn/crndRegistAndView/crdnActInfo/crdnActInfoRegistPopup" + TilesConstants.POPUP);
mav.addObject("data", data);
mav.addObject("photoList", photoList);
mav.addObject("mode", mode);
mav.addObject("crdnYr", crdnYr);
mav.addObject("crdnNo", crdnNo);
@ -114,6 +129,7 @@ public class CrdnActInfoController {
// 필요한 공통코드 조회
model.addAttribute("actTypeCdList", commonCodeService.selectCodeDetailList(CmmnCodeSearchVO.builder().searchCdGroupId("ACT_TYPE_CD").build()));
model.addAttribute("crdnPhotoCdList", commonCodeService.selectCodeDetailList(CmmnCodeSearchVO.builder().searchCdGroupId("CRDN_PHOTO_CD").build()));
return mav;
}
@ -183,23 +199,33 @@ public class CrdnActInfoController {
}
/**
* (AJAX)
* ( , AJAX)
* : . service .
* @param vo
* @param photoFiles ()
* @param crdnPhotoSeCd
* @return
*/
@Operation(summary = "불법위반행위정보 등록", description = "불법위반행위정보를 등록합니다.")
@Operation(summary = "불법위반행위정보 등록", description = "불법위반행위정보를 등록합니다. 사진 파일도 함께 처리 가능합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "등록 성공"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@PostMapping("/insert.ajax")
public ResponseEntity<?> insertAjax(@ModelAttribute CrdnActInfoVO vo) {
log.debug("불법위반행위정보 등록 요청: {}", vo);
public ResponseEntity<?> insertAjax(
@ModelAttribute CrdnActInfoVO vo,
@RequestParam(value = "photoFiles", required = false) List<MultipartFile> photoFiles,
@RequestParam(value = "crdnPhotoSeCd", required = false) String crdnPhotoSeCd) {
log.debug("불법위반행위정보 등록 요청: {}, 파일 개수: {}", vo,
photoFiles != null ? photoFiles.size() : 0);
vo.setSggCd(SessionUtil.getSessionVO().getUser().getOrgCd());
vo.setRgtr(SessionUtil.getUserId());
vo.setMdfr(SessionUtil.getUserId());
int result = service.insertActInfo(vo);
// 중요한 로직 주석: service 단에서 행위정보 등록과 사진 파일 처리를 한 트랜잭션으로 처리
int result = service.insertActInfoWithFiles(vo, photoFiles, crdnPhotoSeCd);
if (result > 0) {
return ApiResponseUtil.success(MessageConstants.Common.SAVE_SUCCESS);
@ -208,21 +234,34 @@ public class CrdnActInfoController {
}
}
/**
* (AJAX)
* ( , AJAX)
* : . service .
* @param vo
* @param photoFiles ()
* @param crdnPhotoSeCd
* @return
*/
@Operation(summary = "불법위반행위정보 수정", description = "불법위반행위정보를 수정합니다.")
@Operation(summary = "불법위반행위정보 수정", description = "불법위반행위정보를 수정합니다. 사진 파일도 함께 처리 가능합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "수정 성공"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@PostMapping("/update.ajax")
public ResponseEntity<?> updateAjax(@ModelAttribute CrdnActInfoVO vo) {
log.debug("불법위반행위정보 수정 요청: {}", vo);
public ResponseEntity<?> updateAjax(
@ModelAttribute CrdnActInfoVO vo,
@RequestParam(value = "photoFiles", required = false) List<MultipartFile> photoFiles,
@RequestParam(value = "crdnPhotoSeCd", required = false) String crdnPhotoSeCd) {
log.debug("불법위반행위정보 수정 요청: {}, 파일 개수: {}", vo,
photoFiles != null ? photoFiles.size() : 0);
vo.setMdfr(SessionUtil.getUserId());
vo.setSggCd(SessionUtil.getSessionVO().getUser().getOrgCd()); // 업데이트 화면에서 신규파일 등록 시 필요
int result = service.updateActInfo(vo);
// 중요한 로직 주석: service 단에서 행위정보 수정과 사진 파일 처리를 한 트랜잭션으로 처리
int result = service.updateActInfoWithFiles(vo, photoFiles, crdnPhotoSeCd);
if (result > 0) {
return ApiResponseUtil.success(MessageConstants.Common.SAVE_SUCCESS);
@ -231,6 +270,7 @@ public class CrdnActInfoController {
}
}
/**
* (AJAX)
* @param actInfoIds ID
@ -252,4 +292,123 @@ public class CrdnActInfoController {
return ApiResponseUtil.error("삭제에 실패했습니다.");
}
}
/**
*
* : . photoView.jsp , / .
* @param actInfoId ID
* @param crdnPhotoSn
* @return photoView
*/
@Operation(summary = "단속 사진 보기", description = "단속 사진을 화면에 표시합니다.")
@GetMapping("/photoView.do")
public String photoView(
@Parameter(description = "행위정보ID") @RequestParam String actInfoId,
@Parameter(description = "사진순번") @RequestParam String crdnPhotoSn,
Model model) {
log.debug("단속 사진 보기 요청 - actInfoId: {}, crdnPhotoSn: {}", actInfoId, crdnPhotoSn);
// 중요한 로직 주석: 해당 행위정보의 모든 사진 목록 조회
CrdnPhotoVO searchVO = CrdnPhotoVO.builder()
.actInfoId(actInfoId)
.crdnPhotoSeCd("1") // 단속 사진
.build();
List<CrdnPhotoVO> photoList = photoService.selectPhotoListByActInfoIdAndPhotoSeCd(searchVO);
// 중요한 로직 주석: 현재 사진의 인덱스 찾기
int currentIndex = 0;
for (int i = 0; i < photoList.size(); i++) {
if (photoList.get(i).getCrdnPhotoSn().equals(crdnPhotoSn)) {
currentIndex = i;
break;
}
}
// 중요한 로직 주석: JSP에서 사용할 데이터 전달
model.addAttribute("actInfoId", actInfoId);
model.addAttribute("crdnPhotoSn", crdnPhotoSn);
model.addAttribute("photoList", photoList);
model.addAttribute("currentIndex", currentIndex);
model.addAttribute("totalCount", photoList.size());
return "crdn/crndRegistAndView/crdnActInfo/photoView";
}
/**
* ( )
* :
* @param actInfoId ID
* @param crdnPhotoSn
* @param request HTTP
* @param response HTTP
*/
@Operation(summary = "단속 사진 다운로드", description = "단속 사진을 다운로드합니다.")
@GetMapping("/downloadPhoto.do")
public void downloadPhoto(
@Parameter(description = "행위정보ID") @RequestParam String actInfoId,
@Parameter(description = "사진순번") @RequestParam String crdnPhotoSn,
HttpServletRequest request, HttpServletResponse response) {
log.debug("단속 사진 다운로드 요청 - actInfoId: {}, crdnPhotoSn: {}", actInfoId, crdnPhotoSn);
try {
// 중요한 로직 주석: 사진 정보 생성 및 조회
CrdnPhotoVO photoVO = CrdnPhotoVO.builder()
.actInfoId(actInfoId)
.crdnPhotoSn(crdnPhotoSn)
.build();
FileVO fileVO = photoService.getPhotoFileForDownload(photoVO);
if (fileVO == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 중요한 로직 주석: FileUtil을 통한 파일 다운로드 처리
fileUtil.downloadFile(fileVO, request, response);
} catch (Exception e) {
log.error("사진 다운로드 중 오류 발생: actInfoId={}, crdnPhotoSn={}", actInfoId, crdnPhotoSn, e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/**
* (AJAX)
* : Ajax , DB .
* @param actInfoId ID
* @param crdnPhotoSn
* @return
*/
@Operation(summary = "단속 사진 개별 삭제", description = "단속 사진을 개별적으로 삭제합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "삭제 성공"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@PostMapping("/deletePhoto.ajax")
public ResponseEntity<?> deletePhotoAjax(
@Parameter(description = "행위정보ID") @RequestParam String actInfoId,
@Parameter(description = "사진순번") @RequestParam String crdnPhotoSn) {
log.debug("단속 사진 개별 삭제 요청 - actInfoId: {}, crdnPhotoSn: {}", actInfoId, crdnPhotoSn);
// 중요한 로직 주석: 삭제할 사진 정보 생성
CrdnPhotoVO photoVO = CrdnPhotoVO.builder()
.actInfoId(actInfoId)
.crdnPhotoSn(crdnPhotoSn)
.dltr(SessionUtil.getUserId())
.build();
// 중요한 로직 주석: 사진 삭제 (논리삭제 + 파일삭제)
int result = photoService.deletePhotoWithFile(photoVO);
if (result > 0) {
return ApiResponseUtil.success("사진이 성공적으로 삭제되었습니다.");
} else {
return ApiResponseUtil.error("사진 삭제에 실패했습니다.");
}
}
}

@ -0,0 +1,80 @@
package go.kr.project.crdn.crndRegistAndView.crdnActInfo.mapper;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPhotoVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
*
* : tb_crdn_photo CRUD .
* ID , / .
*/
@Mapper
public interface CrdnPhotoMapper {
/**
*
* @param photoVO ID
* @return ( )
*/
List<CrdnPhotoVO> selectPhotoListByActInfoIdAndPhotoSeCd(CrdnPhotoVO photoVO);
/**
* (PK )
* @param photoVO ID +
* @return
*/
CrdnPhotoVO selectPhotoByPk(CrdnPhotoVO photoVO);
/**
*
* : .
* @param actInfoId ID
* @return (01, 02, 03 )
*/
String selectNextPhotoSn(String actInfoId);
/**
*
* @param photoVO
* @return
*/
int insertPhoto(CrdnPhotoVO photoVO);
/**
* (, )
* @param photoVO
* @return
*/
int updatePhoto(CrdnPhotoVO photoVO);
/**
* ()
* @param photoVO (delYn, delDt, dltr )
* @return
*/
int deletePhoto(CrdnPhotoVO photoVO);
/**
* ()
* : .
* @param photoVO (actInfoId, delYn, delDt, dltr )
* @return
*/
int deletePhotosByActInfoId(CrdnPhotoVO photoVO);
/**
*
* @param actInfoId ID
* @return ( )
*/
int selectPhotoCountByActInfoId(String actInfoId);
/**
*
* @param photoVO (actInfoId + crdnPhotoSn)
* @return (1: , 0: )
*/
int existsPhoto(CrdnPhotoVO photoVO);
}

@ -0,0 +1,51 @@
package go.kr.project.crdn.crndRegistAndView.crdnActInfo.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* VO
* : tb_crdn_photo , // .
* 01, 02, 03 .
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CrdnPhotoVO {
// ============ 테이블 컬럼 ============
private String actInfoId; // 행위 정보 ID (FK)
private String crdnPhotoSn; // 단속 사진 순번 (PK)
private String sggCd; // 시군구 코드
private String crdnYr; // 단속 연도
private String crdnNo; // 단속 번호
private String crdnPhotoPath; // 단속 사진 경로
private String crdnPhotoNm; // 단속 사진 명
private String crdnPhotoSeCd; // 단속 사진 구분 코드 (01:단속, 02:조치)
private String orgnlPhotoNm; // 원본 사진 명
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime regDt; // 등록 일시
private String rgtr; // 등록자
private String delYn; // 삭제 여부
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime delDt; // 삭제 일시
private String dltr; // 삭제자
// ============ 조인 컬럼(코드명) ============
private String crdnPhotoSeCdNm; // 단속 사진 구분 코드명
// ============ 파일 처리용 추가 필드 ============
private String fileSize; // 파일 크기 (표시용)
private String fileExt; // 파일 확장자
private String fullFilePath; // 전체 파일 경로 (서버 내부용)
private boolean isNewFile; // 신규 파일 여부 (등록/수정 구분용)
}

@ -5,6 +5,7 @@ import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnStrctIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnVltnLwrgVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnUsgIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPstnIdxVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -27,13 +28,16 @@ public interface CrdnActInfoService {
* @return
*/
int selectActInfoListTotalCount(CrdnActInfoVO vo);
/**
*
* ( )
* : . .
* @param vo
* @param photoFiles ()
* @param crdnPhotoSeCd
* @return
*/
int insertActInfo(CrdnActInfoVO vo);
int insertActInfoWithFiles(CrdnActInfoVO vo, List<MultipartFile> photoFiles, String crdnPhotoSeCd);
/**
* (PK )
@ -43,11 +47,14 @@ public interface CrdnActInfoService {
CrdnActInfoVO selectActInfoByPk(String actInfoId);
/**
*
* ( )
* : . .
* @param vo
* @param photoFiles ()
* @param crdnPhotoSeCd
* @return
*/
int updateActInfo(CrdnActInfoVO vo);
int updateActInfoWithFiles(CrdnActInfoVO vo, List<MultipartFile> photoFiles, String crdnPhotoSeCd);
/**
* ()

@ -0,0 +1,96 @@
package go.kr.project.crdn.crndRegistAndView.crdnActInfo.service;
import go.kr.project.common.model.FileVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPhotoVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
*
* : tb_crdn_photo CRUD / .
* FileUtil .
*/
public interface CrdnPhotoService {
/**
*
* @param photoVO ID
* @return ( )
*/
List<CrdnPhotoVO> selectPhotoListByActInfoIdAndPhotoSeCd(CrdnPhotoVO photoVO);
/**
* (PK )
* @param photoVO ID +
* @return
*/
CrdnPhotoVO selectPhotoByPk(CrdnPhotoVO photoVO);
/**
*
* : MultipartFile FileUtil DB .
* , DB .
* @param files
* @param actInfoId ID
* @param crdnPhotoSeCd (01:, 02:)
* @param actInfoVO (, , )
* @return
*/
int insertPhotosWithFiles(List<MultipartFile> files, String actInfoId, String crdnPhotoSeCd, Object actInfoVO);
/**
* ( )
* : , .
* @param file (null )
* @param photoVO
* @return
*/
int updatePhotoWithFile(MultipartFile file, CrdnPhotoVO photoVO);
/**
* ( + )
* : DB .
* @param photoVO
* @return
*/
int deletePhotoWithFile(CrdnPhotoVO photoVO);
/**
* ( + )
* : .
* @param actInfoId ID
* @param crdnPhotoSeCd [, ]
* @param dltr ID
* @return
*/
int deletePhotosByActInfoIdAndCrdnPhotoSecd(String actInfoId, String crdnPhotoSeCd, String dltr);
/**
*
* @param photoVO
* @return FileVO
*/
FileVO getPhotoFileForDownload(CrdnPhotoVO photoVO);
/**
*
* @param actInfoId ID
* @return ( )
*/
int selectPhotoCountByActInfoId(String actInfoId);
/**
*
* @param photoVO
* @return
*/
boolean existsPhoto(CrdnPhotoVO photoVO);
/**
*
* @param actInfoId ID
* @return (01, 02, 03 )
*/
String getNextPhotoSn(String actInfoId);
}

@ -9,12 +9,14 @@ import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnVltnLwrgVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnUsgIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPstnIdxVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnActInfoService;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnPhotoService;
import go.kr.project.crdn.crndRegistAndView.crdnActrInfo.mapper.CrdnActrInfoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -40,6 +42,7 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C
private final CrdnActInfoMapper mapper;
private final CrdnActrInfoMapper actrInfoMapper;
private final CrdnPhotoService photoService;
@Override
public List<CrdnActInfoVO> selectActInfoList(CrdnActInfoVO vo) {
@ -54,10 +57,34 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C
}
@Override
public int insertActInfo(CrdnActInfoVO vo) {
log.debug("불법위반행위정보 등록: {}", vo);
return mapper.insertActInfo(vo);
@Transactional
public int insertActInfoWithFiles(CrdnActInfoVO vo, List<MultipartFile> photoFiles, String crdnPhotoSeCd) {
log.debug("불법위반행위정보 등록 (파일 포함): {}, 파일 개수: {}", vo,
photoFiles != null ? photoFiles.size() : 0);
try {
// 중요한 로직 주석: 먼저 행위정보를 등록한다 (insertActInfo 메서드에서 actInfoId가 자동 설정됨)
int result = mapper.insertActInfo(vo);
if (result > 0) {
log.debug("행위정보 등록 완료: actInfoId={}", vo.getActInfoId());
// 중요한 로직 주석: 파일이 있는 경우에만 사진 처리를 진행한다
if (photoFiles != null && !photoFiles.isEmpty()) {
int photoResult = photoService.insertPhotosWithFiles(photoFiles, vo.getActInfoId(), crdnPhotoSeCd, vo);
log.debug("사진 파일 처리 완료: actInfoId={}, 등록된 사진 수={}", vo.getActInfoId(), photoResult);
}
} else {
log.error("행위정보 등록 실패: {}", vo);
throw new MessageException("행위정보 등록에 실패했습니다.");
}
return result;
} catch (Exception e) {
log.error("행위정보 등록 (파일 포함) 중 오류 발생: {}", vo, e);
throw new MessageException("행위정보 등록 중 오류가 발생했습니다: " + e.getMessage());
}
}
@Override
@ -67,14 +94,53 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C
}
@Override
public int updateActInfo(CrdnActInfoVO vo) {
log.debug("불법위반행위정보 수정: {}", vo);
return mapper.updateActInfo(vo);
@Transactional
public int updateActInfoWithFiles(CrdnActInfoVO vo, List<MultipartFile> photoFiles, String crdnPhotoSeCd) {
log.debug("불법위반행위정보 수정 (파일 포함): {}, 파일 개수: {}", vo,
photoFiles != null ? photoFiles.size() : 0);
try {
// 중요한 로직 주석: 먼저 행위정보를 수정한다
int result = mapper.updateActInfo(vo);
if (result > 0) {
log.debug("행위정보 수정 완료: actInfoId={}", vo.getActInfoId());
// 중요한 로직 주석: 새로운 파일이 있는 경우에만 사진 추가 처리를 진행한다
// 기존 사진의 개별 삭제는 별도의 Ajax 호출로 처리되므로 여기서는 신규 추가만 한다
if (photoFiles != null && !photoFiles.isEmpty()) {
int photoResult = photoService.insertPhotosWithFiles(photoFiles, vo.getActInfoId(), crdnPhotoSeCd, vo);
log.debug("사진 파일 추가 완료: actInfoId={}, 추가된 사진 수={}", vo.getActInfoId(), photoResult);
}
} else {
log.error("행위정보 수정 실패: {}", vo);
throw new MessageException("행위정보 수정에 실패했습니다.");
}
return result;
} catch (Exception e) {
log.error("행위정보 수정 (파일 포함) 중 오류 발생: {}", vo, e);
throw new MessageException("행위정보 수정 중 오류가 발생했습니다: " + e.getMessage());
}
}
@Override
@Transactional
public int deleteActInfo(CrdnActInfoVO vo) {
log.debug("불법위반행위정보 삭제: {}", vo);
// 중요한 로직 주석: 행위정보 삭제 시 관련된 모든 사진도 함께 삭제한다.
if (vo.getActInfoId() != null) {
try {
photoService.deletePhotosByActInfoIdAndCrdnPhotoSecd(vo.getActInfoId(), "1", vo.getDltr());
log.debug("행위정보 관련 사진 삭제 완료: actInfoId={}", vo.getActInfoId());
} catch (Exception e) {
log.warn("행위정보 관련 사진 삭제 중 오류 발생: actInfoId={}", vo.getActInfoId(), e);
// 사진 삭제 실패해도 행위정보 삭제는 진행
}
}
return mapper.deleteActInfo(vo);
}
@ -143,6 +209,15 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C
continue;
}
// 중요한 로직 주석: 해당 행위정보의 관련 사진들을 먼저 삭제한다.
try {
photoService.deletePhotosByActInfoIdAndCrdnPhotoSecd(actInfoId, "1", userId);
log.debug("행위정보 관련 사진 삭제 완료: actInfoId={}", actInfoId);
} catch (Exception e) {
log.warn("행위정보 관련 사진 삭제 중 오류 발생: actInfoId={}", actInfoId, e);
// 사진 삭제 실패해도 행위정보 삭제는 진행
}
// 중요한 로직 주석: 삭제 VO 생성 및 삭제자 정보 설정
CrdnActInfoVO deleteVO = CrdnActInfoVO.builder()
.actInfoId(actInfoId)

@ -0,0 +1,294 @@
package go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.impl;
import egovframework.exception.MessageException;
import egovframework.util.FileUtil;
import egovframework.util.SessionUtil;
import go.kr.project.common.model.FileVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.mapper.CrdnPhotoMapper;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnActInfoVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnPhotoVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnPhotoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
*
* <pre>
* packageName : go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.impl
* fileName : CrdnPhotoServiceImpl
* author :
* date : 2025-09-03
* description :
* : tb_crdn_photo CRUD FileUtil .
* .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-09-03
* </pre>
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class CrdnPhotoServiceImpl extends EgovAbstractServiceImpl implements CrdnPhotoService {
private final CrdnPhotoMapper mapper;
private final FileUtil fileUtil;
public List<CrdnPhotoVO> selectPhotoListByActInfoIdAndPhotoSeCd(CrdnPhotoVO photoVO) {
log.debug("단속 사진 목록 조회: actInfoId={}, CrdnPhotoSeCd={}", photoVO.getActInfoId(), photoVO.getCrdnPhotoSeCd());
return mapper.selectPhotoListByActInfoIdAndPhotoSeCd(photoVO);
}
@Override
public CrdnPhotoVO selectPhotoByPk(CrdnPhotoVO photoVO) {
log.debug("단속 사진 상세 조회: {}", photoVO);
return mapper.selectPhotoByPk(photoVO);
}
/**
*
* : MultipartFile DB .
* DB , .
*/
@Override
@Transactional
public int insertPhotosWithFiles(List<MultipartFile> files, String actInfoId, String crdnPhotoSeCd, Object actInfoVO) {
log.debug("사진 파일 업로드 및 등록: actInfoId={}, files.size={}", actInfoId, files != null ? files.size() : 0);
// 중요한 로직 주석: 파일 목록 유효성 검증
if (files == null || files.isEmpty()) {
log.warn("업로드할 파일이 없습니다.");
return 0;
}
// 중요한 로직 주석: 현재 사용자 정보 가져오기
String userId = SessionUtil.getUserId();
if (userId == null || userId.trim().isEmpty()) {
log.error("등록자 정보를 가져올 수 없습니다.");
throw new MessageException("사용자 정보를 확인할 수 없습니다.");
}
// 중요한 로직 주석: 행위정보에서 필요한 정보 추출
CrdnActInfoVO actInfo = (CrdnActInfoVO) actInfoVO;
int insertedCount = 0;
try {
// 중요한 로직 주석: FileUtil을 통해 파일 업로드 처리
List<FileVO> uploadedFiles = fileUtil.uploadFiles(files, "crdn-act-photo");
for (FileVO fileVO : uploadedFiles) {
// 중요한 로직 주석: 다음 사진 순번 생성
String nextPhotoSn = mapper.selectNextPhotoSn(actInfoId);
// 중요한 로직 주석: 사진 정보 VO 생성
CrdnPhotoVO photoVO = CrdnPhotoVO.builder()
.actInfoId(actInfoId)
.crdnPhotoSn(nextPhotoSn)
.sggCd(actInfo.getSggCd())
.crdnYr(actInfo.getCrdnYr())
.crdnNo(actInfo.getCrdnNo())
.crdnPhotoPath(fileVO.getFilePath())
.crdnPhotoNm(fileVO.getStoredFileNm())
.crdnPhotoSeCd(crdnPhotoSeCd)
.orgnlPhotoNm(fileVO.getOriginalFileNm())
.regDt(LocalDateTime.now())
.rgtr(userId)
.delYn("N")
.build();
// 중요한 로직 주석: DB에 사진 정보 등록
int result = mapper.insertPhoto(photoVO);
if (result > 0) {
insertedCount++;
log.debug("사진 등록 완료: actInfoId={}, photoSn={}, fileName={}",
actInfoId, nextPhotoSn, fileVO.getOriginalFileNm());
} else {
log.error("사진 DB 등록 실패: actInfoId={}, photoSn={}", actInfoId, nextPhotoSn);
throw new MessageException("사진 정보 등록에 실패했습니다.");
}
}
} catch (Exception e) {
log.error("사진 업로드 중 오류 발생: actInfoId={}", actInfoId, e);
throw new MessageException("사진 업로드에 실패했습니다: " + e.getMessage());
}
log.info("사진 파일 업로드 완료: actInfoId={}, 등록된 사진 수={}", actInfoId, insertedCount);
return insertedCount;
}
/**
* ( )
* : .
*/
@Override
@Transactional
public int updatePhotoWithFile(MultipartFile file, CrdnPhotoVO photoVO) {
log.debug("사진 정보 수정: {}", photoVO);
try {
// 중요한 로직 주석: 새로운 파일이 있는 경우 파일 교체 처리
if (file != null && !file.isEmpty()) {
// 중요한 로직 주석: 기존 사진 정보 조회
CrdnPhotoVO existingPhoto = mapper.selectPhotoByPk(photoVO);
if (existingPhoto != null) {
// 중요한 로직 주석: 기존 파일 삭제
FileVO existingFileVO = new FileVO();
existingFileVO.setFilePath(existingPhoto.getCrdnPhotoPath());
existingFileVO.setStoredFileNm(existingPhoto.getCrdnPhotoNm());
existingFileVO.setOriginalFileNm(existingPhoto.getOrgnlPhotoNm());
fileUtil.deleteFile(existingFileVO);
}
// 중요한 로직 주석: 새 파일 업로드
List<MultipartFile> fileList = Arrays.asList(file);
List<FileVO> uploadedFiles = fileUtil.uploadFiles(fileList, "crdn-act-photo");
if (!uploadedFiles.isEmpty()) {
FileVO newFileVO = uploadedFiles.get(0);
photoVO.setCrdnPhotoPath(newFileVO.getFilePath());
photoVO.setCrdnPhotoNm(newFileVO.getStoredFileNm());
photoVO.setOrgnlPhotoNm(newFileVO.getOriginalFileNm());
}
}
// 중요한 로직 주석: DB 정보 수정
int result = mapper.updatePhoto(photoVO);
log.debug("사진 정보 수정 완료: {}", photoVO);
return result;
} catch (Exception e) {
log.error("사진 수정 중 오류 발생: {}", photoVO, e);
throw new MessageException("사진 수정에 실패했습니다: " + e.getMessage());
}
}
/**
* ( + )
* : DB .
*/
@Override
@Transactional
public int deletePhotoWithFile(CrdnPhotoVO photoVO) {
log.debug("사진 삭제: {}", photoVO);
try {
// 중요한 로직 주석: 삭제할 사진 정보 조회
CrdnPhotoVO existingPhoto = mapper.selectPhotoByPk(photoVO);
if (existingPhoto == null) {
log.warn("삭제할 사진을 찾을 수 없습니다: {}", photoVO);
return 0;
}
// 중요한 로직 주석: 삭제자 정보 설정
String userId = SessionUtil.getUserId();
photoVO.setDltr(userId);
photoVO.setDelDt(LocalDateTime.now());
// 중요한 로직 주석: DB에서 논리삭제
int result = mapper.deletePhoto(photoVO);
if (result > 0) {
// 중요한 로직 주석: 실제 파일 삭제
FileVO fileVO = new FileVO();
fileVO.setFilePath(existingPhoto.getCrdnPhotoPath());
fileVO.setStoredFileNm(existingPhoto.getCrdnPhotoNm());
fileVO.setOriginalFileNm(existingPhoto.getOrgnlPhotoNm());
fileUtil.deleteFile(fileVO);
log.debug("사진 삭제 완료: {}", photoVO);
}
return result;
} catch (Exception e) {
log.error("사진 삭제 중 오류 발생: {}", photoVO, e);
throw new MessageException("사진 삭제에 실패했습니다: " + e.getMessage());
}
}
@Transactional
public int deletePhotosByActInfoIdAndCrdnPhotoSecd(String actInfoId, String crdnPhotoSeCd, String dltr) {
log.debug("행위정보 관련 모든 사진 삭제: actInfoId={}", actInfoId);
try {
// 중요한 로직 주석: 삭제할 사진 목록 조회
List<CrdnPhotoVO> photoList = mapper.selectPhotoListByActInfoIdAndPhotoSeCd(
CrdnPhotoVO.builder().actInfoId(actInfoId).crdnPhotoSeCd(crdnPhotoSeCd).build());
if (photoList.isEmpty()) {
log.debug("삭제할 사진이 없습니다: actInfoId={}", actInfoId);
return 0;
}
// 중요한 로직 주석: DB에서 모든 사진 논리삭제
CrdnPhotoVO deleteVO = CrdnPhotoVO.builder()
.actInfoId(actInfoId)
.dltr(dltr)
.delDt(LocalDateTime.now())
.build();
int deletedCount = mapper.deletePhotosByActInfoId(deleteVO);
// 중요한 로직 주석: 실제 파일들 삭제
for (CrdnPhotoVO photo : photoList) {
FileVO fileVO = new FileVO();
fileVO.setFilePath(photo.getCrdnPhotoPath());
fileVO.setStoredFileNm(photo.getCrdnPhotoNm());
fileVO.setOriginalFileNm(photo.getOrgnlPhotoNm());
fileUtil.deleteFile(fileVO);
}
log.info("행위정보 관련 모든 사진 삭제 완료: actInfoId={}, 삭제된 사진 수={}", actInfoId, deletedCount);
return deletedCount;
} catch (Exception e) {
log.error("사진 일괄 삭제 중 오류 발생: actInfoId={}", actInfoId, e);
throw new MessageException("사진 삭제에 실패했습니다: " + e.getMessage());
}
}
@Override
public FileVO getPhotoFileForDownload(CrdnPhotoVO photoVO) {
log.debug("사진 파일 다운로드 정보 조회: {}", photoVO);
CrdnPhotoVO photo = mapper.selectPhotoByPk(photoVO);
if (photo == null) {
log.warn("다운로드할 사진을 찾을 수 없습니다: {}", photoVO);
return null;
}
FileVO fileVO = new FileVO();
fileVO.setFilePath(photo.getCrdnPhotoPath());
fileVO.setStoredFileNm(photo.getCrdnPhotoNm());
fileVO.setOriginalFileNm(photo.getOrgnlPhotoNm());
return fileVO;
}
@Override
public int selectPhotoCountByActInfoId(String actInfoId) {
log.debug("사진 개수 조회: actInfoId={}", actInfoId);
return mapper.selectPhotoCountByActInfoId(actInfoId);
}
@Override
public boolean existsPhoto(CrdnPhotoVO photoVO) {
log.debug("사진 존재 여부 확인: {}", photoVO);
return mapper.existsPhoto(photoVO) > 0;
}
@Override
public String getNextPhotoSn(String actInfoId) {
log.debug("다음 사진 순번 조회: actInfoId={}", actInfoId);
return mapper.selectNextPhotoSn(actInfoId);
}
}

@ -190,7 +190,7 @@ public class CrdnRegistAndViewController {
.build();
model.addAttribute("dsclMthdCdList", commonCodeService.selectCodeDetailList(dsclMthdCdSearchVO));
return "crdn/crndRegistAndView/main/detailView" + TilesConstants.BASE;
return "crdn/crndRegistAndView/main/detailView-main" + TilesConstants.BASE;
}
/**

@ -93,7 +93,7 @@ file:
upload:
path: d:/data/@projectName@/file
max-size: 10 # 단일 파일 최대 크기 (MB)
max-total-size: 50 # 총 파일 최대 크기 (MB)
max-total-size: 100 # 총 파일 최대 크기 (MB)
max-files: 10 # 최대 파일 개수
allowed-extensions: hwp,jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt,zip
real-file-delete: true # 실제 파일 삭제 여부

@ -93,7 +93,7 @@ file:
upload:
path: d:/data/@projectName@/file
max-size: 10 # 단일 파일 최대 크기 (MB)
max-total-size: 50 # 총 파일 최대 크기 (MB)
max-total-size: 100 # 총 파일 최대 크기 (MB)
max-files: 10 # 최대 파일 개수
allowed-extensions: hwp,jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt,zip
real-file-delete: true # 실제 파일 삭제 여부

@ -100,7 +100,7 @@ file:
upload:
path: /data/@projectName@/file
max-size: 10 # 단일 파일 최대 크기 (MB)
max-total-size: 50 # 총 파일 최대 크기 (MB)
max-total-size: 100 # 총 파일 최대 크기 (MB)
max-files: 10 # 최대 파일 개수
allowed-extensions: hwp,jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt,zip
real-file-delete: true # 실제 파일 삭제 여부

@ -76,6 +76,7 @@ query-executor:
# Interceptor configuration
interceptor:
interceptorExclude:
- /** #ubi report test
- /login/** #로그인
- / #루트 페이지
- /.well-known/** #개발 툴

@ -74,6 +74,9 @@
<!-- 불법위반행위정보 등록 (시컨스 사용) -->
<insert id="insertActInfo" parameterType="CrdnActInfoVO">
/* ActInfoMapper.insertActInfo : 불법위반행위정보 등록 */
<selectKey keyProperty="actInfoId" resultType="String" order="BEFORE">
SELECT LPAD(NEXTVAL(seq_act_info_id), 10, '0') AS actInfoId
</selectKey>
INSERT INTO tb_act_info (
ACT_INFO_ID,
SGG_CD,
@ -97,7 +100,7 @@
MDFR,
DEL_YN
) VALUES (
LPAD(NEXTVAL(seq_act_info_id), 10, '0'),
#{actInfoId},
#{sggCd},
#{crdnYr},
#{crdnNo},

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="go.kr.project.crdn.crndRegistAndView.crdnActInfo.mapper.CrdnPhotoMapper">
<!-- 특정 행위정보의 사진 목록 조회 -->
<select id="selectPhotoListByActInfoIdAndPhotoSeCd" parameterType="CrdnPhotoVO" resultType="CrdnPhotoVO">
/* CrdnPhotoMapper.selectPhotoListByActInfoId : 특정 행위정보의 사진 목록 조회 */
SELECT
p.ACT_INFO_ID,
p.CRDN_PHOTO_SN,
p.SGG_CD,
p.CRDN_YR,
p.CRDN_NO,
p.CRDN_PHOTO_PATH,
p.CRDN_PHOTO_NM,
p.CRDN_PHOTO_SE_CD,
cd.CD_NM AS CRDN_PHOTO_SE_CD_NM,
p.ORGNL_PHOTO_NM,
p.REG_DT,
p.RGTR,
p.DEL_YN,
p.DEL_DT,
p.DLTR
FROM tb_crdn_photo p
LEFT JOIN tb_cd_detail cd ON cd.CD_GROUP_ID = 'CRDN_PHOTO_CD' AND cd.CD_ID = p.CRDN_PHOTO_SE_CD
WHERE p.ACT_INFO_ID = #{actInfoId}
AND p.CRDN_PHOTO_SE_CD = #{crdnPhotoSeCd}
AND p.DEL_YN = 'N'
ORDER BY p.CRDN_PHOTO_SN ASC
</select>
<!-- 사진 상세 조회 (PK 기준) -->
<select id="selectPhotoByPk" parameterType="CrdnPhotoVO" resultType="CrdnPhotoVO">
/* CrdnPhotoMapper.selectPhotoByPk : 사진 상세 조회 */
SELECT
p.ACT_INFO_ID,
p.CRDN_PHOTO_SN,
p.SGG_CD,
p.CRDN_YR,
p.CRDN_NO,
p.CRDN_PHOTO_PATH,
p.CRDN_PHOTO_NM,
p.CRDN_PHOTO_SE_CD,
cd.CD_NM AS CRDN_PHOTO_SE_CD_NM,
p.ORGNL_PHOTO_NM,
p.REG_DT,
p.RGTR,
p.DEL_YN,
p.DEL_DT,
p.DLTR
FROM tb_crdn_photo p
LEFT JOIN tb_cd_detail cd ON cd.CD_GROUP_ID = 'CRDN_PHOTO_CD' AND cd.CD_ID = p.CRDN_PHOTO_SE_CD
WHERE p.ACT_INFO_ID = #{actInfoId}
AND p.CRDN_PHOTO_SN = #{crdnPhotoSn}
</select>
<!-- 다음 사진 순번 조회 -->
<select id="selectNextPhotoSn" parameterType="string" resultType="string">
/* CrdnPhotoMapper.selectNextPhotoSn : 다음 사진 순번 조회 */
SELECT IFNULL(
LPAD(
CAST(MAX(CAST(CRDN_PHOTO_SN AS UNSIGNED)) + 1 AS CHAR),
2,
'0'
),
'01'
) AS NEXT_SN
FROM tb_crdn_photo
WHERE ACT_INFO_ID = #{actInfoId}
</select>
<!-- 사진 등록 -->
<insert id="insertPhoto" parameterType="CrdnPhotoVO">
/* CrdnPhotoMapper.insertPhoto : 사진 등록 */
INSERT INTO tb_crdn_photo (
ACT_INFO_ID,
CRDN_PHOTO_SN,
SGG_CD,
CRDN_YR,
CRDN_NO,
CRDN_PHOTO_PATH,
CRDN_PHOTO_NM,
CRDN_PHOTO_SE_CD,
ORGNL_PHOTO_NM,
REG_DT,
RGTR,
DEL_YN
) VALUES (
#{actInfoId},
#{crdnPhotoSn},
#{sggCd},
#{crdnYr},
#{crdnNo},
#{crdnPhotoPath},
#{crdnPhotoNm},
#{crdnPhotoSeCd},
#{orgnlPhotoNm},
NOW(),
#{rgtr},
'N'
)
</insert>
<!-- 사진 정보 수정 -->
<update id="updatePhoto" parameterType="CrdnPhotoVO">
/* CrdnPhotoMapper.updatePhoto : 사진 정보 수정 */
UPDATE tb_crdn_photo SET
CRDN_PHOTO_PATH = #{crdnPhotoPath},
CRDN_PHOTO_NM = #{crdnPhotoNm},
ORGNL_PHOTO_NM = #{orgnlPhotoNm}
WHERE ACT_INFO_ID = #{actInfoId}
AND CRDN_PHOTO_SN = #{crdnPhotoSn}
</update>
<!-- 사진 삭제 (논리삭제) -->
<update id="deletePhoto" parameterType="CrdnPhotoVO">
/* CrdnPhotoMapper.deletePhoto : 사진 삭제 */
UPDATE tb_crdn_photo SET
DEL_YN = 'Y',
DEL_DT = NOW(),
DLTR = #{dltr}
WHERE ACT_INFO_ID = #{actInfoId}
AND CRDN_PHOTO_SN = #{crdnPhotoSn}
AND DEL_YN = 'N'
</update>
<!-- 특정 행위정보의 모든 사진 삭제 (논리삭제) -->
<update id="deletePhotosByActInfoId" parameterType="CrdnPhotoVO">
/* CrdnPhotoMapper.deletePhotosByActInfoId : 특정 행위정보의 모든 사진 삭제 */
UPDATE tb_crdn_photo SET
DEL_YN = 'Y',
DEL_DT = NOW(),
DLTR = #{dltr}
WHERE ACT_INFO_ID = #{actInfoId}
AND DEL_YN = 'N'
</update>
<!-- 특정 행위정보의 사진 개수 조회 -->
<select id="selectPhotoCountByActInfoId" parameterType="string" resultType="int">
/* CrdnPhotoMapper.selectPhotoCountByActInfoId : 특정 행위정보의 사진 개수 조회 */
SELECT COUNT(*)
FROM tb_crdn_photo
WHERE ACT_INFO_ID = #{actInfoId}
AND DEL_YN = 'N'
</select>
<!-- 사진 존재 여부 확인 -->
<select id="existsPhoto" parameterType="CrdnPhotoVO" resultType="int">
/* CrdnPhotoMapper.existsPhoto : 사진 존재 여부 확인 */
SELECT COUNT(*)
FROM tb_crdn_photo
WHERE ACT_INFO_ID = #{actInfoId}
AND CRDN_PHOTO_SN = #{crdnPhotoSn}
AND DEL_YN = 'N'
</select>
</mapper>

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<UbiServer version="4.0.0000.0000">
<Environment licensePath="{APP_ROOT}/ubi4/license"
admin="YWRtcEBzc3dkIQ=="
adminImgUri="./ubi4/js/images"
xslPath=""
osCharset="KSC5601" />
<LogInfo logPath="{APP_ROOT}/ubi4/logs"
timeZone="GMT+9"
rowSize="5"
backupStyle="date"
backupSize="30"
serverBackupSize="180"
backupPattern="yyyy-MM-dd"
useLog="true"
info="true" />
<Resources>
<!-- <DataSource id="SAMPLE_DB1" type="auto" dataSourceName="jdbc/tutorial" charset="KSC5601" />
<DataSource id="SAMPLE_DB2"
type="direct"
vendor="Access"
driverClassName="sun.jdbc.odbc.JdbcOdbcDriver"
url="jdbc:odbc:UbiReport40"
charset="KSC5601"
username=""
password="" />
</Resources> -->
<!-- 로컬환경 및 개발서버 설정정보 url="jdbc:mariadb://115.21.123.117:53306/ibmsdb" [2021.10] IP변경됨 -->
<DataSource id="DEV_DB"
type="direct"
vendor="MariaDB"
driverClassName="org.mariadb.jdbc.Driver"
url="jdbc:mariadb://211.119.124.117:53306/ibmsdb"
charset="KSC5601"
username="root"
password="xit5811807" />
<!-- 운영 -->
<DataSource id="REAL_DB"
type="direct"
vendor="MariaDB"
driverClassName="org.mariadb.jdbc.Driver"
url="jdbc:mariadb://localhost:53306/ibmsdb"
charset="KSC5601"
username="root"
password="xit5811807" />
</Resources>
<UbiServiceInfo urftype="normal" connectionTime="1800000" >
<UbiService ip="localhost" port="16996" path=""/>
</UbiServiceInfo>
</UbiServer>

@ -4,6 +4,9 @@
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<!-- 파일 업로드 관련 CSS -->
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/xit/xit-fileupload.css'/>" />
<!-- 불법행위정보 등록 팝업 -->
<div class="popup_wrap">
<div class="popup_inner">
@ -49,7 +52,7 @@
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 위반법규1</th>
<th class="th"><span class="required">*</span> 위반법규</th>
<td colspan="3">
<input type="text" id="vltnLaw1" name="vltnLaw1" class="input" style="width: 250px;" placeholder="위반법규를 입력하거나 선택하세요" autocomplete="off" value="${data.vltnLaw1}" validation-check="required"/>
<input type="hidden" id="vltnLwrgCd1" name="vltnLwrgCd1" value="${data.vltnLwrgCd1}"/>
@ -98,6 +101,40 @@
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" maxlength="1000" style="height: 80px;">${data.rmrk}</textarea>
</td>
</tr>
<tr>
<th class="th">행위 사진</th>
<td colspan="3">
<!-- 중요한 로직 주석: 파일 업로드와 미리보기 기능을 제공한다 -->
<div class="file-upload-section">
<div class="file-upload-controls">
<label for="photoFiles" class="file-upload-btn smallb-2">
<span>사진 선택</span>
<input type="file" id="photoFiles" name="photoFiles" accept="image/*" multiple style="display: none;">
</label>
<input type="hidden" id="crdnPhotoSeCd" name="crdnPhotoSeCd" value="1"/>
<span class="file-info">최대 10개, 각 10MB 이하의 이미지 파일만 업로드 가능합니다.</span>
</div>
<div class="photo-preview-container" id="photoPreviewContainer">
<!-- 중요한 로직 주석: 수정 모드에서 기존 등록된 사진들을 표시한다 -->
<c:if test="${mode eq 'U' && not empty photoList}">
<c:forEach var="photo" items="${photoList}">
<div class="photo-preview-item existing-photo" data-act-info-id="${photo.actInfoId}" data-photo-sn="${photo.crdnPhotoSn}">
<div class="photo-thumbnail">
<img src="<c:url value='/crdn/crndRegistAndView/crdnActInfo/downloadPhoto.do'/>?actInfoId=${photo.actInfoId}&crdnPhotoSn=${photo.crdnPhotoSn}"
alt="${photo.orgnlPhotoNm}" onclick="viewOriginalPhoto('${photo.actInfoId}', '${photo.crdnPhotoSn}')">
</div>
<div class="photo-info">
<div class="photo-name" title="${photo.orgnlPhotoNm}">${photo.orgnlPhotoNm}</div>
<div class="photo-type">[${photo.crdnPhotoSeCdNm}]</div>
<button type="button" class="delete-photo-btn" onclick="deleteExistingPhoto('${photo.actInfoId}', '${photo.crdnPhotoSn}')">삭제</button>
</div>
</div>
</c:forEach>
</c:if>
</div>
</div>
</td>
</tr>
</table>
</form>
</div>
@ -146,6 +183,9 @@
initVltnLwrgDropdowns();
initUsgIdxDropdown();
// 파일 업로드 이벤트 초기화
initFileUpload();
console.log('불법행위정보 팝업이 초기화되었습니다. 모드:', mode);
});
@ -373,6 +413,7 @@
/**
* 불법행위정보 저장 함수
* 중요한 로직 주석: validation 체크 후 mode에 따라 등록/수정 API를 호출한다.
* 새로 선택한 사진 파일이 있으면 FormData를 사용하여 파일과 함께 전송한다.
*/
function saveActInfo() {
// 중요로직: validateFormByAttributes를 사용하여 모든 validation-check 속성 검증
@ -391,33 +432,228 @@
}
var mode = $('#mode').val();
var formData = $('#actInfoForm').serialize();
var actionText = (mode === 'U') ? '수정' : '등록';
// 중요한 로직 주석: FormData를 사용하여 모든 데이터 전송 (파일 유무에 상관없이)
var formData = new FormData();
// 폼의 모든 입력값을 FormData에 추가
$('#actInfoForm').find('input, select, textarea').each(function() {
var $this = $(this);
var name = $this.attr('name');
var value = $this.val();
if (name && value && $this.attr('type') !== 'file') {
formData.append(name, value);
}
});
// 중요한 로직 주석: 선택된 파일들을 FormData에 추가 (있는 경우에만)
if (selectedFiles && selectedFiles.length > 0) {
for (var i = 0; i < selectedFiles.length; i++) {
formData.append('photoFiles', selectedFiles[i]);
}
}
var url = (mode === 'U') ?
'<c:url value="/crdn/crndRegistAndView/crdnActInfo/update.ajax"/>' :
'<c:url value="/crdn/crndRegistAndView/crdnActInfo/insert.ajax"/>';
var actionText = (mode === 'U') ? '수정' : '등록';
$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
handleSaveResponse(response, actionText);
}
});
}
/**
* 저장 응답 처리
* 중요한 로직 주석: 성공/실패에 따른 공통 처리 로직
*/
function handleSaveResponse(response, actionText) {
if (response && response.success) {
alert('불법행위정보가 성공적으로 ' + actionText + '되었습니다.');
// 부모창의 그리드 새로고침
if (window.opener && window.opener.CrdnDetailView && window.opener.CrdnDetailView.grids.actInfo) {
window.opener.CrdnDetailView.grids.actInfo.search();
}
window.close();
} else {
alert(response.message || actionText + ' 중 오류가 발생했습니다.');
}
}
// 전역 변수: 선택된 파일들을 보관
var selectedFiles = [];
/**
* 파일 업로드 초기화
* 중요한 로직 주석: 파일 선택 이벤트와 파일 유효성 검증을 초기화한다.
*/
function initFileUpload() {
// 파일 선택 이벤트
$('#photoFiles').on('change', function(e) {
handleFileSelect(e.target.files);
});
}
/**
* 파일 선택 처리
* 중요한 로직 주석: 선택된 파일들을 검증하고 파일명만 표시한다. 미리보기는 하지 않는다.
*/
function handleFileSelect(files) {
if (!files || files.length === 0) {
return;
}
// 파일 개수 제한 체크
var existingPhotos = $('.photo-preview-item.existing-photo').length;
var newFiles = selectedFiles.length + files.length;
if (existingPhotos + newFiles > 10) {
alert('최대 10개의 사진만 업로드할 수 있습니다.');
return;
}
// 각 파일에 대해 검증 및 파일명만 표시
for (var i = 0; i < files.length; i++) {
var file = files[i];
// 파일 유효성 검증
if (!validateFile(file)) {
continue;
}
// 선택된 파일 목록에 추가
selectedFiles.push(file);
// 미리보기 생성 (클릭 이벤트 없음)
createPhotoPreview(file);
}
}
/**
* 파일 유효성 검증
* 중요한 로직 주석: 파일 크기, 확장자, 타입을 검증한다.
*/
function validateFile(file) {
// 파일 크기 체크 (10MB)
var maxSize = 10 * 1024 * 1024;
if (file.size > maxSize) {
alert(file.name + ' 파일이 10MB를 초과합니다.');
return false;
}
// 이미지 파일인지 체크
if (!file.type.startsWith('image/')) {
alert(file.name + ' 은(는) 이미지 파일이 아닙니다.');
return false;
}
// 허용된 확장자 체크
var allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];
var fileName = file.name.toLowerCase();
var fileExtension = fileName.split('.').pop();
if (allowedExtensions.indexOf(fileExtension) === -1) {
alert('지원되지 않는 파일 형식입니다. (jpg, jpeg, png, gif만 가능)');
return false;
}
return true;
}
/**
* 사진 미리보기 생성 (클릭 이벤트 없음)
* 중요한 로직 주석: 선택된 파일을 읽어서 미리보기 이미지를 생성한다. 클릭 시 원본 이미지 팝업은 제공하지 않는다.
*/
function createPhotoPreview(file) {
var reader = new FileReader();
reader.onload = function(e) {
var photoSeCd = $('#crdnPhotoSeCd').val();
var photoSeCdNm = photoSeCd === '1' ? '단속' : '조치';
var previewHtml =
'<div class="photo-preview-item new-photo" data-file-name="' + file.name + '">' +
' <div class="photo-thumbnail">' +
' <img src="' + e.target.result + '" alt="' + file.name + '">' +
' </div>' +
' <div class="photo-info">' +
' <div class="photo-name" title="' + file.name + '">' + file.name + '</div>' +
' <div class="photo-type">[' + photoSeCdNm + ']</div>' +
' <button type="button" class="delete-photo-btn" onclick="deleteNewPhoto(this)">삭제</button>' +
' </div>' +
'</div>';
$('#photoPreviewContainer').append(previewHtml);
};
reader.readAsDataURL(file);
}
/**
* 기존 사진 삭제
* 중요한 로직 주석: DB에 등록된 사진을 논리삭제하고 화면에서 제거한다.
*/
function deleteExistingPhoto(actInfoId, crdnPhotoSn) {
if (!confirm('선택한 사진을 삭제하시겠습니까?')) {
return;
}
$.ajax({
url: '<c:url value="/crdn/crndRegistAndView/crdnActInfo/deletePhoto.ajax"/>',
type: 'POST',
data: {
actInfoId: actInfoId,
crdnPhotoSn: crdnPhotoSn
},
success: function(response) {
if (response && response.success) {
alert('불법행위정보가 성공적으로 ' + actionText + '되었습니다.');
// 부모창의 그리드 새로고침
if (window.opener && window.opener.CrdnDetailView && window.opener.CrdnDetailView.grids.actInfo) {
window.opener.CrdnDetailView.grids.actInfo.search();
}
window.close();
// 화면에서 해당 사진 제거
$('[data-act-info-id="' + actInfoId + '"][data-photo-sn="' + crdnPhotoSn + '"]').remove();
} else {
alert(response.message || actionText + ' 중 오류가 발생했습니다.');
alert(response.message || '사진 삭제에 실패했습니다.');
}
}
});
}
/**
* 새로 선택한 파일 삭제
* 중요한 로직 주석: 아직 저장되지 않은 파일을 목록에서 제거하고 selectedFiles 배열에서도 제거한다.
*/
function deleteNewPhoto(button) {
var $item = $(button).closest('.photo-preview-item');
var fileName = $item.data('file-name');
// selectedFiles 배열에서 해당 파일 제거
for (var i = 0; i < selectedFiles.length; i++) {
if (selectedFiles[i].name === fileName) {
selectedFiles.splice(i, 1);
break;
}
}
// 화면에서 제거
$item.remove();
}
/**
* 원본 사진 보기 (기존 DB 사진)
* 중요한 로직 주석: 등록된 사진을 photoView 페이지에서 원본 크기로 표시하고 다운로드 버튼을 제공한다.
*/
function viewOriginalPhoto(actInfoId, crdnPhotoSn) {
var url = '<c:url value="/crdn/crndRegistAndView/crdnActInfo/photoView.do"/>?actInfoId=' + actInfoId + '&crdnPhotoSn=' + crdnPhotoSn;
window.open(url, '_blank', 'width=1000,height=700,scrollbars=yes,resizable=yes');
}
</script>

@ -0,0 +1,553 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>사진 보기</title>
<link rel="stylesheet" type="text/css" href="<c:url value='/resources/xit/xit-common.css'/>" />
<style>
body {
margin: 0;
padding: 0;
background-color: #000;
color: #fff;
font-family: Arial, sans-serif;
overflow: hidden;
}
.photo-viewer {
position: relative;
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.photo-header {
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.8);
padding: 15px 20px;
z-index: 1000;
display: flex;
justify-content: space-between;
align-items: center;
backdrop-filter: blur(5px);
}
.photo-info {
display: flex;
flex-direction: column;
gap: 5px;
}
.photo-title {
font-size: 16px;
font-weight: bold;
color: #fff;
}
.photo-details {
font-size: 12px;
color: #ccc;
}
.photo-counter {
font-size: 14px;
color: #fff;
margin-right: 15px;
}
.photo-actions {
display: flex;
gap: 10px;
align-items: center;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 5px;
transition: all 0.3s ease;
}
.btn-download {
background-color: #007bff;
color: white;
}
.btn-download:hover {
background-color: #0056b3;
}
.btn-close {
background-color: #6c757d;
color: white;
}
.btn-close:hover {
background-color: #545b62;
}
.photo-container {
position: relative;
max-width: 90vw;
max-height: 80vh;
display: flex;
justify-content: center;
align-items: center;
margin-top: 80px;
}
.photo-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
cursor: zoom-in;
transition: transform 0.3s ease;
}
.photo-image.zoomed {
cursor: zoom-out;
transform: scale(1.5);
}
.loading {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid rgba(255, 255, 255, 0.3);
border-left: 4px solid #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error-message {
text-align: center;
padding: 40px;
}
.error-title {
font-size: 24px;
margin-bottom: 10px;
}
.error-text {
font-size: 16px;
color: #ccc;
}
/* 네비게이션 화살표 스타일 */
.nav-button {
position: fixed;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.8);
color: #333;
border: none;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
z-index: 1000;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.nav-button:hover {
background: rgba(255, 255, 255, 0.95);
color: #000;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.nav-button:disabled {
background: rgba(128, 128, 128, 0.5);
cursor: not-allowed;
color: #666;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}
.prev-button {
left: 20px;
}
.next-button {
right: 20px;
}
/* 반응형 디자인 */
@media (max-width: 768px) {
.photo-header {
flex-direction: column;
gap: 10px;
padding: 10px;
}
.photo-actions {
justify-content: center;
width: 100%;
}
.photo-container {
margin-top: 120px;
max-height: 70vh;
}
.btn {
padding: 6px 12px;
font-size: 12px;
}
}
</style>
</head>
<body>
<div class="photo-viewer">
<!-- 헤더 -->
<div class="photo-header">
<div class="photo-info">
<div class="photo-title" id="photoTitle">사진을 불러오는 중...</div>
<div class="photo-details" id="photoDetails">-</div>
</div>
<div class="photo-actions">
<div class="photo-counter" id="photoCounter">1 / 1</div>
<a href="#" class="btn btn-download" id="downloadBtn" onclick="downloadPhoto()">
<i class="fas fa-download"></i> 다운로드
</a>
<button type="button" class="btn btn-close" onclick="closeWindow()">
<i class="fas fa-times"></i> 닫기
</button>
</div>
</div>
<!-- 사진 컨테이너 -->
<div class="photo-container">
<div class="loading" id="loadingArea">
<div class="loading-spinner"></div>
<div>사진을 불러오는 중입니다...</div>
</div>
<!-- 이전 버튼 -->
<button type="button" class="nav-button prev-button" id="prevBtn" onclick="prevPhoto()" style="display: none;">
&#8249;
</button>
<img id="photoImage" class="photo-image" style="display: none;" alt="사진" onclick="toggleZoom(this)">
<!-- 다음 버튼 -->
<button type="button" class="nav-button next-button" id="nextBtn" onclick="nextPhoto()" style="display: none;">
&#8250;
</button>
<div class="error-message" id="errorArea" style="display: none;">
<div class="error-title">사진을 불러올 수 없습니다</div>
<div class="error-text">파일이 존재하지 않거나 접근할 수 없습니다.</div>
</div>
</div>
</div>
<script>
// URL 파라미터 가져오기
const urlParams = new URLSearchParams(window.location.search);
const actInfoId = urlParams.get('actInfoId');
const crdnPhotoSn = urlParams.get('crdnPhotoSn');
// 중요한 로직 주석: 서버에서 전달된 사진 목록 데이터
let photoList = [];
let currentIndex = 0;
let totalCount = 0;
// 중요한 로직 주석: JSP에서 JavaScript 변수로 데이터 전달
<c:if test="${not empty photoList}">
photoList = [
<c:forEach items="${photoList}" var="photo" varStatus="status">
{
actInfoId: '${photo.actInfoId}',
crdnPhotoSn: '${photo.crdnPhotoSn}',
crdnPhotoNm: '${photo.crdnPhotoNm}'
}<c:if test="${not status.last}">,</c:if>
</c:forEach>
];
currentIndex = ${currentIndex};
totalCount = ${totalCount};
</c:if>
// 페이지 로드 시 사진 정보 가져오기
document.addEventListener('DOMContentLoaded', function() {
if (!actInfoId || !crdnPhotoSn) {
showError('필수 파라미터가 누락되었습니다.');
return;
}
loadPhotoInfo();
updateNavigationButtons();
updatePhotoCounter();
});
/**
* 사진 정보 로드
* 중요한 로직 주석: 서버에서 사진 정보를 가져와서 화면에 표시한다.
*/
function loadPhotoInfo() {
// 사진 이미지 로드
const photoImage = document.getElementById('photoImage');
const downloadUrl = '<c:url value="/crdn/crndRegistAndView/crdnActInfo/downloadPhoto.do"/>?actInfoId=' + actInfoId + '&crdnPhotoSn=' + crdnPhotoSn;
photoImage.onload = function() {
document.getElementById('loadingArea').style.display = 'none';
photoImage.style.display = 'block';
// 사진 정보 업데이트
updatePhotoInfo();
};
photoImage.onerror = function() {
showError('사진을 불러올 수 없습니다.');
};
// 다운로드 버튼 준비 (href는 설정하지 않음 - onclick으로만 처리)
// 이미지 소스 설정
photoImage.src = downloadUrl;
}
/**
* 사진 정보 업데이트
* 중요한 로직 주석: URL 파라미터를 기반으로 사진 제목과 상세정보를 설정한다.
*/
function updatePhotoInfo() {
const photoTitle = document.getElementById('photoTitle');
const photoDetails = document.getElementById('photoDetails');
//photoTitle.textContent = '단속 사진 (순번: ' + crdnPhotoSn + ')';
photoTitle.textContent = '단속 사진';
photoDetails.textContent = '행위정보ID: ' + actInfoId + ' | 사진순번: ' + crdnPhotoSn;
}
/**
* 오류 표시
* 중요한 로직 주석: 사진 로드 실패 시 오류 메시지를 표시한다.
*/
function showError(message) {
document.getElementById('loadingArea').style.display = 'none';
document.getElementById('photoImage').style.display = 'none';
const errorArea = document.getElementById('errorArea');
const errorText = errorArea.querySelector('.error-text');
errorText.textContent = message;
errorArea.style.display = 'block';
// 헤더 정보 업데이트
document.getElementById('photoTitle').textContent = '오류 발생';
document.getElementById('photoDetails').textContent = message;
// 다운로드 버튼 비활성화
const downloadBtn = document.getElementById('downloadBtn');
downloadBtn.style.opacity = '0.5';
downloadBtn.style.pointerEvents = 'none';
}
/**
* 줌 토글
* 중요한 로직 주석: 이미지 클릭 시 확대/축소 기능을 제공한다.
*/
function toggleZoom(img) {
img.classList.toggle('zoomed');
}
/**
* 사진 다운로드
* 중요한 로직 주석: 다운로드 버튼 클릭 시 현재 보고 있는 사진의 파일 다운로드를 시작한다.
*/
function downloadPhoto() {
// 중요한 로직 주석: 현재 인덱스의 사진 정보를 가져온다
let currentActInfoId = actInfoId;
let currentCrdnPhotoSn = crdnPhotoSn;
// 중요한 로직 주석: 사진 목록이 있고 현재 인덱스가 유효한 경우 현재 사진 정보 사용
if (photoList.length > 0 && currentIndex >= 0 && currentIndex < photoList.length) {
const currentPhoto = photoList[currentIndex];
currentActInfoId = currentPhoto.actInfoId;
currentCrdnPhotoSn = currentPhoto.crdnPhotoSn;
}
if (!currentActInfoId || !currentCrdnPhotoSn) {
alert('다운로드할 사진 정보가 없습니다.');
return;
}
const downloadUrl = '<c:url value="/crdn/crndRegistAndView/crdnActInfo/downloadPhoto.do"/>?actInfoId=' + currentActInfoId + '&crdnPhotoSn=' + currentCrdnPhotoSn;
// 중요한 로직 주석: 현재 창에서 다운로드 URL로 이동하여 파일 다운로드 실행
window.location.href = downloadUrl;
}
/**
* 이전 사진 보기
* 중요한 로직 주석: 이전 사진으로 이동하여 화면을 업데이트한다.
*/
function prevPhoto() {
if (currentIndex > 0) {
currentIndex--;
loadCurrentPhoto();
}
}
/**
* 다음 사진 보기
* 중요한 로직 주석: 다음 사진으로 이동하여 화면을 업데이트한다.
*/
function nextPhoto() {
if (currentIndex < photoList.length - 1) {
currentIndex++;
loadCurrentPhoto();
}
}
/**
* 현재 인덱스의 사진 로드
* 중요한 로직 주석: 현재 인덱스에 해당하는 사진을 로드하고 UI를 업데이트한다.
*/
function loadCurrentPhoto() {
if (photoList.length === 0 || currentIndex < 0 || currentIndex >= photoList.length) {
return;
}
const currentPhoto = photoList[currentIndex];
const photoImage = document.getElementById('photoImage');
const downloadUrl = '<c:url value="/crdn/crndRegistAndView/crdnActInfo/downloadPhoto.do"/>?actInfoId=' +
currentPhoto.actInfoId + '&crdnPhotoSn=' + currentPhoto.crdnPhotoSn;
// 로딩 표시
document.getElementById('loadingArea').style.display = 'flex';
photoImage.style.display = 'none';
photoImage.onload = function() {
document.getElementById('loadingArea').style.display = 'none';
photoImage.style.display = 'block';
// UI 업데이트
updatePhotoInfo(currentPhoto);
updateNavigationButtons();
updatePhotoCounter();
};
photoImage.onerror = function() {
showError('사진을 불러올 수 없습니다.');
};
photoImage.src = downloadUrl;
}
/**
* 네비게이션 버튼 상태 업데이트
* 중요한 로직 주석: 현재 인덱스에 따라 이전/다음 버튼의 활성화 상태를 조정한다.
*/
function updateNavigationButtons() {
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
if (totalCount <= 1) {
// 사진이 1개 이하면 네비게이션 버튼 숨김
prevBtn.style.display = 'none';
nextBtn.style.display = 'none';
} else {
// 사진이 2개 이상이면 네비게이션 버튼 표시
prevBtn.style.display = 'flex';
nextBtn.style.display = 'flex';
// 이전 버튼 상태
prevBtn.disabled = (currentIndex <= 0);
// 다음 버튼 상태
nextBtn.disabled = (currentIndex >= photoList.length - 1);
}
}
/**
* 사진 카운터 업데이트
* 중요한 로직 주석: 현재 사진 번호와 전체 개수를 표시한다.
*/
function updatePhotoCounter() {
const photoCounter = document.getElementById('photoCounter');
if (totalCount > 0) {
photoCounter.textContent = (currentIndex + 1) + ' / ' + totalCount;
} else {
photoCounter.textContent = '1 / 1';
}
}
/**
* 사진 정보 업데이트 (오버로드)
* 중요한 로직 주석: 특정 사진 객체 정보로 제목과 상세정보를 설정한다.
*/
function updatePhotoInfo(photo) {
const photoTitle = document.getElementById('photoTitle');
const photoDetails = document.getElementById('photoDetails');
photoTitle.textContent = '단속 사진';
photoDetails.textContent = '행위정보ID: ' + photo.actInfoId + ' | 사진순번: ' + photo.crdnPhotoSn;
}
/**
* 창 닫기
* 중요한 로직 주석: 닫기 버튼 클릭 시 현재 창을 닫는다.
*/
function closeWindow() {
if (window.opener) {
window.close();
} else {
// 팝업이 아닌 경우 이전 페이지로 이동
history.back();
}
}
// 키보드 단축키 지원
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
closeWindow();
} else if (event.key === 'ArrowLeft') {
// 중요한 로직 주석: 왼쪽 화살표키로 이전 사진 보기
event.preventDefault();
prevPhoto();
} else if (event.key === 'ArrowRight') {
// 중요한 로직 주석: 오른쪽 화살표키로 다음 사진 보기
event.preventDefault();
nextPhoto();
}
});
</script>
</body>
</html>

@ -13,11 +13,14 @@
<ul class="lef">
<li>
<input type="text" id="schExmnr" name="schExmnr" class="input" placeholder="조사원ID 또는 조사원명을 입력하세요." style="width: 300px;">
<button type="button" id="search_btn" class="newbtnss bg1 smallb-2">검색</button>
</li>
<li><button type="button" id="search_btn" class="newbtnss bg1 smallb-2">검색</button></li>
</ul>
<ul class="rig">
<li style="border-right: 0px;"></li>
<li style="border-right: 0px;">
<button type="button" id="newExmnrPopupBtn" class="newbtnss bg1">조사원 등록</button>
</li>
</ul>
</div>
@ -216,7 +219,6 @@
var totalCount = responseObj.data.contents.length;
$("#totalCount").text('총 ' + totalCount.toLocaleString() + '건');
}
});
// 체크 이벤트
@ -224,6 +226,15 @@
// 기존 선택된 행들의 체크박스 상태 복원
ExmnrPopPopup.restoreCheckboxStates();
});
// 행 더블클릭 시 선택
this.instance.on('dblclick', function(ev) {
var rowData = self.instance.getRow(ev.rowKey);
if (rowData) {
ExmnrPopPopup.onRowCheck(ev);
ExmnrPopPopup.selectExmnr();
}
});
// 체크 이벤트
this.instance.on('check', function(ev) {
@ -265,6 +276,14 @@
self.search();
});
//신규 조사원 등록
$('#newExmnrPopupBtn').on('click', function() {
var w = 450, h = 280;
var left = Math.max(0, (window.screen.availLeft + (window.screen.availWidth - w) / 2));
var top = Math.max(0, (window.screen.availTop + (window.screen.availHeight - h) / 2));
window.open('<c:url value="/crdn/exmnr/popup.do"/>?mode=C', 'exmnrReg', 'width=' + w + ',height=' + h + ',left=' + left + ',top=' + top + ',resizable=yes,scrollbars=yes');
});
// 엔터키 검색
$('#schExmnr').on('keypress', function(e) {
if (e.which === 13) {

@ -47,7 +47,9 @@
<td>
<input type="text" id="searchTelno" name="searchTelno" class="input" maxlength="11" placeholder="전화번호를 입력하세요"/>
</td>
<td style="text-align: right; border: 0px;"></td>
<td style="text-align: right; border: 0px;">
<button type="button" id="newOwnrPopupBtn" class="newbtn bg1">${popupGubunName} 등록</button>
</td>
</tr>
</table>
</form>
@ -261,6 +263,11 @@
}
self.selectOwners(checkedRows);
});
$('#newOwnrPopupBtn').on('click', function() {
window.open('<c:url value="/crdn/ownact/ownActRegistPopup.do"/>?mode=C', 'ownActRegistAndViewReg', 'width=600,height=600,scrollbars=yes');
});
// 닫기 버튼 클릭 이벤트
$('#closeBtn, #btnCloseTop').on('click', function(e) {

@ -203,7 +203,10 @@
totalCount = responseObj.data.contents.length;
}
if (totalCount >= 1) {
window.CrdnDetailView.actInfoId = responseObj.data.contents[0].actInfoId;
// 그리드 로딩 최초에만 첫번째 row 선택, 이 후에는 선택된 다른 row 유지
if( !window.CrdnDetailView.actInfoId ){
window.CrdnDetailView.actInfoId = responseObj.data.contents[0].actInfoId;
}
// 불법행위 정보가 있을때 행위자정보 버튼 활성화
$('#actrSelectBtn').prop('disabled', false);
@ -309,7 +312,7 @@
+ '&pstnInfoId=' + encodeURIComponent(pstnInfoId)
+ '&crdnNo=' + encodeURIComponent(crdnNo)
+ '&mode=C';
var w = 1200, h = 480;
var w = 1200, h = 700;
var left = Math.max(0, (screen.width - w) / 2);
var top = Math.max(0, (screen.height - h) / 2);
window.open(url, 'actInfoPopup', 'width=' + w + ',height=' + h + ',left=' + left + ',top=' + top + ',resizable=yes,scrollbars=yes');
@ -344,7 +347,7 @@
+ '&actInfoId=' + encodeURIComponent(actInfoId)
+ '&mode=U';
var w = 1200, h = 480;
var w = 1200, h = 700;
var left = Math.max(0, (screen.width - w) / 2);
var top = Math.max(0, (screen.height - h) / 2);

@ -168,10 +168,10 @@
<!-- /Main body -->
<!-- 각 그리드별 개별 JSP 포함 -->
<%@ include file="detailView-pstn.jsp" %>
<%@ include file="detailView-ownrInfo.jsp" %>
<%@ include file="detailView-actInfo.jsp" %>
<%@ include file="detailView-actrInfo.jsp" %>
<%@ include file="detailView-pstnGrid.jsp" %> <%-- 위치 정보 --%>
<%@ include file="detailView-ownrInfoGrid.jsp" %> <%-- 소유자 정보 --%>
<%@ include file="detailView-actInfoGrid.jsp" %> <%-- 불법행위 정보 --%>
<%@ include file="detailView-actrInfoGrid.jsp" %> <%-- 행위자 정보 --%>
<script type="text/javascript">
/**

@ -117,6 +117,8 @@
alert(response.message || '처리되었습니다.');
if (window.opener && window.opener.refreshCrdnList) {
window.opener.refreshCrdnList();
}else if (window.opener && window.opener.ExmnrPopPopup) {
window.opener.ExmnrPopPopup.search();
}
window.close();
} else {
@ -140,7 +142,10 @@
alert(response.message || '삭제되었습니다.');
if (window.opener && window.opener.refreshCrdnList) {
window.opener.refreshCrdnList();
}else if (window.opener && window.opener.ExmnrPopPopup) {
window.opener.ExmnrPopPopup.search();
}
window.close();
} else {
alert(response.message || '삭제 중 오류가 발생했습니다.');

@ -91,7 +91,7 @@
<tr style="display: none;">
<th class="th"><span class="required">*</span> 지번 주소</th>
<td colspan="3">
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.lotnoAddr}"/>
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" readonly value="${data.lotnoAddr}"/>
<input type="text" id="lotnoMno" name="lotnoMno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.lotnoMno}"/>
<input type="text" id="lotnoSno" name="lotnoSno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.lotnoSno}"/>
</td>
@ -99,7 +99,7 @@
<tr style="display: none;">
<th class="th"><span class="required">*</span> 도로명 주소</th>
<td colspan="3">
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.roadNmAddr}"/>
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" readonly value="${data.roadNmAddr}"/>
<input type="text" id="bldgMno" name="bldgMno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgMno}"/>
<input type="text" id="bldgSno" name="bldgSno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgSno}"/>
</td>
@ -226,6 +226,8 @@
alert(response.message || '처리되었습니다.');
if (window.opener && window.opener.refreshOwnActList) {
window.opener.refreshOwnActList();
}else if (window.opener && window.opener.CrdnOwnrSelectPopup) {
window.opener.CrdnOwnrSelectPopup.search();
}
window.close();
} else {
@ -249,6 +251,8 @@
alert(response.message || '삭제되었습니다.');
if (window.opener && window.opener.refreshOwnActList) {
window.opener.refreshOwnActList();
}else if (window.opener && window.opener.CrdnOwnrSelectPopup) {
window.opener.CrdnOwnrSelectPopup.search();
}
window.close();
} else {
@ -303,6 +307,7 @@
}
}
}
console.log(isValid, extraValid);
return isValid && extraValid;
}
};

@ -0,0 +1,288 @@
/**
* CSS
* : UI
*/
/* 파일 업로드 섹션 전체 컨테이너 */
.file-upload-section {
margin-top: 10px;
}
/* 파일 업로드 컨트롤 영역 */
.file-upload-controls {
display: flex;
align-items: center;
margin-bottom: 15px;
gap: 10px;
flex-wrap: wrap;
}
/* 파일 선택 버튼 */
.file-upload-btn {
background-color: #007bff;
color: white;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
border: none;
font-size: 13px;
transition: background-color 0.3s ease;
}
.file-upload-btn:hover {
background-color: #0056b3;
}
.file-upload-btn span {
pointer-events: none;
}
/* 파일 정보 텍스트 */
.file-info {
font-size: 12px;
color: #6c757d;
margin-left: 10px;
}
/* 사진 미리보기 컨테이너 */
.photo-preview-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 15px;
min-height: 80px;
padding: 10px 10px 10px 50px;
border: 1px dashed #ddd;
border-radius: 4px;
background-color: #fafafa;
}
.photo-preview-container:empty {
display: flex;
align-items: center;
justify-content: center;
}
.photo-preview-container:empty::before {
content: "선택된 사진이 없습니다.";
color: #999;
font-size: 14px;
}
/* 개별 사진 미리보기 아이템 */
.photo-preview-item {
display: flex;
flex-direction: column;
width: 150px;
background: white;
border: 1px solid #ddd;
border-radius: 4px;
padding: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: box-shadow 0.3s ease;
}
.photo-preview-item:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
/* 기존 사진 (DB에서 조회된) 스타일 */
.photo-preview-item.existing-photo {
border-color: #28a745;
}
.photo-preview-item.existing-photo::before {
content: "등록됨";
font-size: 10px;
color: #28a745;
text-align: center;
margin-bottom: 4px;
font-weight: bold;
}
/* 새로 선택한 사진 스타일 */
.photo-preview-item.new-photo {
border-color: #007bff;
}
.photo-preview-item.new-photo::before {
content: "신규";
font-size: 10px;
color: #007bff;
text-align: center;
margin-bottom: 4px;
font-weight: bold;
}
/* 사진 썸네일 영역 */
.photo-thumbnail {
width: 100%;
height: 80px;
overflow: hidden;
border-radius: 4px;
margin-bottom: 8px;
cursor: pointer;
position: relative;
background: #f8f9fa;
display: flex;
align-items: center;
justify-content: center;
}
.photo-thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.photo-thumbnail:hover img {
transform: scale(1.1);
}
/* 사진 정보 영역 */
.photo-info {
display: flex;
flex-direction: column;
gap: 4px;
}
/* 사진 파일명 */
.photo-name {
font-size: 12px;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
line-height: 1.2;
}
/* 사진 구분 타입 */
.photo-type {
font-size: 11px;
color: #666;
font-style: italic;
}
/* 사진 삭제 버튼 */
.delete-photo-btn {
background-color: #dc3545;
color: white;
border: none;
border-radius: 3px;
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 4px;
}
.delete-photo-btn:hover {
background-color: #c82333;
}
/* 반응형 디자인 */
@media (max-width: 768px) {
.photo-preview-container {
gap: 10px;
}
.photo-preview-item {
width: 100px;
}
.photo-thumbnail {
height: 70px;
}
.file-upload-controls {
flex-direction: column;
align-items: flex-start;
}
.file-info {
margin-left: 0;
margin-top: 5px;
}
}
/* 로딩 상태 */
.photo-preview-item.loading {
opacity: 0.7;
}
.photo-preview-item.loading::after {
content: "처리 중...";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
color: white;
padding: 4px 8px;
border-radius: 3px;
font-size: 11px;
}
/* 에러 상태 */
.photo-preview-item.error {
border-color: #dc3545;
background-color: #fff5f5;
}
.photo-preview-item.error .photo-name {
color: #dc3545;
}
/* 드래그 앤 드롭 효과 (향후 확장용) */
.photo-preview-container.drag-over {
border-color: #007bff;
background-color: #e7f3ff;
}
/* 애니메이션 */
.photo-preview-item {
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 팝업 창에서의 스타일 조정 */
.popup_wrap .file-upload-section {
max-width: 100%;
}
.popup_wrap .photo-preview-container {
max-height: 430px;
overflow-y: auto;
}
/* 스크롤바 스타일 (웹킷 기반 브라우저) */
.photo-preview-container::-webkit-scrollbar {
width: 6px;
}
.photo-preview-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.photo-preview-container::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.photo-preview-container::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}

@ -0,0 +1,293 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.sql.*, javax.sql.*, javax.naming.*" %>
<%
request.setCharacterEncoding("UTF-8"); //2020.09.25. 박민규- 캐릭터셋 설정
String uri = request.getRequestURI();
String type = request.getParameter("type");
String dsNm = request.getParameter("dsNm");
String driver = request.getParameter("driver");
String url = request.getParameter("url");
String user = request.getParameter("user");
String password = request.getParameter("password");
String sql = request.getParameter("sql");
if( type == null || type.equalsIgnoreCase("null") ) type = "";
if( dsNm == null || dsNm.equalsIgnoreCase("null") ) dsNm = "";
if( driver == null || driver.equalsIgnoreCase("null") ) driver = "";
if( url == null || url.equalsIgnoreCase("null") ) url = "";
if( user == null || user.equalsIgnoreCase("null") ) user = "";
if( password == null || password.equalsIgnoreCase("null") ) password = "";
if( sql == null || sql.equalsIgnoreCase("null") ) sql = "";
String msg = "";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>DataSource 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<script language="JavaScript">
<!--
function setField() {
var check = document.dbinfo.type.value;
if( check == "direct" ) {
document.all["nondirect"].style.visibility = "hidden";
document.all["direct1"].style.visibility = "visible";
document.all["direct2"].style.visibility = "visible";
document.all["direct3"].style.visibility = "visible";
document.all["direct4"].style.visibility = "visible";
}
else {
document.all["nondirect"].style.visibility = "visible";
document.all["direct1"].style.visibility = "hidden";
document.all["direct2"].style.visibility = "hidden";
document.all["direct3"].style.visibility = "hidden";
document.all["direct4"].style.visibility = "hidden";
}
}
function checkFiled() {
if( document.dbinfo.type.value == "direct" ) {
if(document.dbinfo.driver.value == "") {
alert("Plaese Input Driver Name.(ex : oracle.jdbc.driver.OracleDriver)");
document.dbinfo.driver.focus();
return false;
}
else if(document.dbinfo.url.value == "") {
alert("Please Input DB URL.(ex : jdbc:oracle:thin:@dbip:dbport:dbsid)");
document.dbinfo.url.focus();
return false;
}
else document.dbinfo.submit();
}
else {
if(document.dbinfo.dsNm.value == "") {
alert("Please Input DataSource Name.(ex : jdbc/demo)");
document.dbinfo.dsNm.focus();
return false;
}
else document.dbinfo.submit();
}
}
function checkFiled2() {
if( document.dbinfo.sql.value == "" ) {
alert("Plaese Input SQL statment.");
document.dbinfo.sql.focus();
return false;
}
else {
document.dbinfo.submit();
}
}
//-->
</script>
</head>
<body style="margin:10" onload="setField()">
<h2>Check DataSource<h2>
<form name="dbinfo" method="post" action="<%= uri %>">
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">WAS 유형</td>
<td align="center" width="192">
<select name="type" onchange="setField()">
<option value="lookup" <%= type.equals("lookup")?"selected":"" %>>lookup</option>
<option value="nonlookup" <%= type.equals("nonlookup")?"selected":"" %>>nonlookup</option>
<option value="direct" <%= type.equals("direct")?"selected":"" %>>direct</option>
</select>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">DataSource</td>
<td align="center" width="192">
<div id="nondirect" style="visibility:">
<input type="text" name="dsNm" size="20" value="<%= dsNm %>">
</div>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">Driver</td>
<td align="center">
<div id="direct1" style="visibility:hidden">
<input type="text" name="driver" size="20" value="<%= driver %>">
</div>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">URL</td>
<td align="center">
<div id="direct2" style="visibility:hidden">
<input type="text" name="url" size="20" value="<%= url %>">
</div>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">User</td>
<td align="center">
<div id="direct3" style="visibility:hidden">
<input type="text" name="user" size="20" value="<%= user %>">
</div>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">Password</td>
<td align="center">
<div id="direct4" style="visibility:hidden">
<input type="text" name="password" size="20" value="<%= password %>">
</div>
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="DB Connect Test" onclick="checkFiled()">
</td>
</tr>
</table>
<%
if( type.equals("lookup") || type.equals("nonlookup") || type.equals("direct") ) {
try {
if( type.equals("lookup") ) { //lookup type (Tomcat, resin, Jrun ...)
Context ctx = new InitialContext();
Context env = (Context)ctx.lookup("java:comp/env");
DataSource ds = (DataSource)env.lookup(dsNm);
conn = ds.getConnection();
}
else if( type.equals("nonlookup") ) { //nonlookup type (Jeus, WebLogic, WebSphere ...)
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(dsNm);
conn = ds.getConnection();
}
else { //direct
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
}
if( conn == null ) msg = "Connection Fail!!!";
else msg = "Connection Success!!!";
}
catch(Exception e) {
msg = e.getMessage();
}
finally {
%>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0">Result(<%= type %>)</td>
</tr>
<tr height="50">
<td align="center" valign="middle"><%= msg %></td>
</tr>
</table>
<%
if( conn != null ) {
%>
<br>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0">SQL</td>
</tr>
<tr height="50">
<td>
<textarea name="sql" rows="8" cols="80"><%= sql %></textarea>
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="Data View" onclick="checkFiled2()">
</td>
</tr>
</table>
<%
if( sql != null && !sql.equals("") ) {
%>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<%
try {
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int cnt = rsmd.getColumnCount();
out.println("<tr>");
for(int i = 0; i <= cnt; i++) {
if( i == 0 ) out.println("<td bgcolor=\"#C0C0C0\" align=\"center\">No</td>");
else out.println("<td bgcolor=\"#C0C0C0\" align=\"center\">" + rsmd.getColumnLabel(i) + "</td>");
}
int row_cnt = 0;
while( rs.next() ) {
out.println("<tr>");
for(int i = 0; i <= cnt; i++) {
if( i == 0 ) out.println("<td align=\"center\">" + ++row_cnt + "</td>");
else out.println("<td align=\"center\">" + rs.getString(i) + "</td>");
}
out.println("</tr>");
}
if( row_cnt == 0 ) {
out.println("<tr height=\"100\"><td align=\"center\" colspan=\"" + (cnt + 1) + "\">조회 내역이 없습니다.</td></tr>");
}
}
catch(Exception ee) {
out.println("<tr><td bgcolor=\"#C0C0C0\" align=\"center\">Error Message</td></tr>");
out.println("<tr height=\"100\"><td align=\"left\" valign=\"top\">" + ee.getMessage() + "</td></tr>");
}
%>
</table>
<%
}
if( rs != null ) try{ rs.close(); rs = null; } catch (Exception ex) {}
if( ps != null ) try{ ps.close(); ps = null; } catch (Exception ex) {}
if( conn != null ) try { conn.close(); conn = null; } catch(Exception e) {}
}
}
}
%>
</form>
</body>
</html>

@ -0,0 +1,24 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.awt.*" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Font 정보</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<body>
<%
//System.setProperty("sun.java2d.fontpath", "font_location_path");
// System.setProperty("java.awt.headless", "true");
String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (int i=0; i<fontNames.length; i++)
{
out.println(fontNames[i]+"<br>");
}
%>
</body>
</html>

@ -0,0 +1,19 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.net.*" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hostname 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
</style>
</head>
<body style="margin:10">
<h2>Hostname Check</h2>
Hostname : [<%= InetAddress.getLocalHost().getHostName() %>]<br>
AppPath : [<%= getServletContext().getRealPath("/") %>]
</body>
</html>

@ -0,0 +1,100 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.util.jar.*, java.io.File" %>
<%
String appPath = "";
try { appPath = request.getRealPath("/"); } catch(Exception e) {}
if( appPath == null || appPath.equals("") )
try { appPath = this.getClass().getResource("/").getPath(); } catch(Exception e) {}
boolean checkFlag = false;
String jar = request.getParameter("jar");
String version = "";
if( jar == null || jar.equalsIgnoreCase("null") || jar.equals("") ) {
checkFlag = false;
jar = appPath + "WEB-INF" + File.separator + "lib" + File.separator + "UbiServer.jar";
}
else {
try {
JarFile fJar = new JarFile(jar);
Manifest manifest = fJar.getManifest();
Attributes attrs = manifest.getMainAttributes();
version = attrs.getValue("version");
}
catch(Exception e) {
version = e.getMessage();
}
finally {
checkFlag = true;
}
}
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Jar 버전 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<script language="JavaScript">
<!--
function checkVersion() {
if(document.jarcheck.jar.value == "") {
// alert("Please Input URL(ex : /webapp/myapp/WEB-INF/lib/UbiServer.jar)");
alert("Please Input URL(ex : /webapp/WEB-INF/lib/UbiServer.jar)");
document.jarcheck.jar.focus();
return false;
}
else document.jarcheck.submit();
}
//-->
</script>
</head>
<body style="margin:10">
<h2>Jar Version Check</h2>
<form name='jarcheck' method='post' action='./jarcheck.jsp'>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center" bgcolor="#C0C0C0" width="120px" style='padding:3px'>App Home</td>
<td align="left" style='padding:3px'><%= appPath %></td>
</tr>
<tr height="30">
<td align="center" bgcolor="#C0C0C0" width="120px" style='padding:3px'>Jar File</td>
<td align="left" style='padding:3px'>
<input type="text" name="jar" size="55" value="<%= jar %>">
</td>
</tr>
<%
if( checkFlag ) {
%>
<tr height="30">
<td align="center" style='padding:3px' colspan='2'><%= version %></td>
</tr>
<%
}
%>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="Version CHECK" onclick="checkVersion()">
</td>
</tr>
</table>
</form>
</body>
</html>

@ -0,0 +1,26 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Java Environment 확인</title>
<style>
body {
font-size:10pt;
font-family: Arial;
color: #000000;
line-height:18px;
}
</style>
<body>
<%
java.util.Enumeration e = System.getProperties().propertyNames();
while(e.hasMoreElements()) {
String key = (String)e.nextElement();
if( key.indexOf("class.path") != -1 || key.indexOf("loader") != -1 ) out.print("<li><font color='red'>" + key + " : " + System.getProperty(key) + "</font></li>");
else out.print("<li>" + key + " : " + System.getProperty(key) + "<br>");
}
%>
</body>
</html>

@ -0,0 +1,134 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.net.*, java.io.*" %>
<%
String NL = System.getProperty("line.separator");
String sReqType = request.getParameter("req_type");
String sUrl = request.getParameter("url");
if( sReqType == null || sReqType.equalsIgnoreCase("null") ) {
sReqType = "GET";
}
if( sUrl == null || sUrl.equalsIgnoreCase("null") ) {
sUrl = "";
}
StringBuffer contents = new StringBuffer();
if( !sUrl.equals("") ) {
try {
URL url = new URL(sUrl);
contents.append(">> URL(" + sUrl + ") Connecting...").append(NL);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);
uc.setUseCaches(false);
uc.setRequestMethod(sReqType);
StringBuffer sb = new StringBuffer();
InputStream is = uc.getInputStream();
contents.append(">> Reading Contents...").append(NL);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int buffSize = 1024 * 8;
char[] buff;
int insize = 0;
while ((insize = in.read(buff = new char[buffSize], 0, buffSize)) != -1) {
sb.append((new String(buff, 0, insize)));
}
String receivestr = sb.toString().trim();
contents.append(">> Contents").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(sb.toString().trim()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
}
catch(FileNotFoundException fnfe){
contents.append(">> FileNotFoundException").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(fnfe.getMessage()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
fnfe.printStackTrace();
}
catch(Exception e){
contents.append(">> Exception").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(e.getMessage()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
e.printStackTrace();
}
}
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>URL 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<script language="JavaScript">
<!--
function checkURL() {
if(document.urlcheck.url.value == "") {
alert("Please Input URL(ex : http://localhost:8080/UbiData)");
document.urlcheck.url.focus();
return false;
}
else document.urlcheck.submit();
}
//-->
</script>
</head>
<body style="margin:10">
<h2>Check URL<h2>
<form name='urlcheck' method='post' action='./urlcheck.jsp'>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100" style='padding:3px'>REQ TYPE</td>
<td align="left" style='padding:3px; padding-left:6px;'' >
<select name="req_type">
<option value="GET" <%= sReqType.equals("GET")?"selected":"" %>>GET</option>
<option value="POST" <%= sReqType.equals("POST")?"selected":"" %>>POST</option>
</select>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100" style='padding:3px'>URL</td>
<td align="center" style='padding:3px'>
<input type="text" name="url" size="70" value="<%= sUrl %>">
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="URL CHECK" onclick="checkURL()">
</td>
</tr>
</table>
</form>
Result<br>
<textarea name="sql" rows="20" cols="84"><%= contents.toString() %></textarea>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save