Add CJ OnStyle inspired login intro

This commit is contained in:
2026-06-09 00:11:47 +09:00
parent b056f711a4
commit 67904dcc56
6 changed files with 430 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -29,6 +29,7 @@
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\LoginBroadcastControlRoom.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />

View File

@@ -1,5 +1,6 @@
using Microsoft.UI;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using System.Collections.ObjectModel;
using TornadoAce_CJOnStyle.Services;
@@ -23,6 +24,8 @@ namespace TornadoAce_CJOnStyle.ViewModels
InspectionSummary = "1차 diff 실패 2건 / LLM 검토 대기 1건";
SceneSnapshotLabel = $"{workspace.ActiveScene.SceneName} / visible text objects";
SceneSnapshotText = workspace.ActiveScene.ToPreviewJson();
LoginOperatorName = "producer";
LaunchMessage = "큐시트, Scene 템플릿, 검수 큐 상태를 확인하고 있습니다.";
LlmPolicyText = "사내 LLM 우선, 외부 서비스는 정책 승인 후";
LlmPolicyDetail = "1차 Text Diffing 실패 건만 2차 LLM 판정으로 이동하고, 가격·구성·방송시간 변경은 높은 중요도로 표시합니다.";
@@ -42,6 +45,11 @@ namespace TornadoAce_CJOnStyle.ViewModels
private string sceneSnapshotText = string.Empty;
private string llmPolicyText = string.Empty;
private string llmPolicyDetail = string.Empty;
private string loginOperatorName = string.Empty;
private string launchMessage = string.Empty;
private Visibility loginScreenVisibility = Visibility.Visible;
private Visibility launchScreenVisibility = Visibility.Collapsed;
private Visibility mainShellVisibility = Visibility.Collapsed;
public string BuildPhase
{
@@ -107,6 +115,53 @@ namespace TornadoAce_CJOnStyle.ViewModels
public ObservableCollection<InspectionQueueItemViewModel> InspectionQueue { get; } = [];
public string LoginOperatorName
{
get => loginOperatorName;
set => SetProperty(ref loginOperatorName, value);
}
public string LaunchMessage
{
get => launchMessage;
set => SetProperty(ref launchMessage, value);
}
public Visibility LoginScreenVisibility
{
get => loginScreenVisibility;
set => SetProperty(ref loginScreenVisibility, value);
}
public Visibility LaunchScreenVisibility
{
get => launchScreenVisibility;
set => SetProperty(ref launchScreenVisibility, value);
}
public Visibility MainShellVisibility
{
get => mainShellVisibility;
set => SetProperty(ref mainShellVisibility, value);
}
public void BeginLogin(string operatorName, string accessCode)
{
LoginOperatorName = string.IsNullOrWhiteSpace(operatorName) ? "producer" : operatorName.Trim();
LaunchMessage = string.IsNullOrWhiteSpace(accessCode)
? "데모 접속으로 제작 콘솔을 준비하고 있습니다."
: "접속 코드 확인 후 제작 콘솔을 준비하고 있습니다.";
LoginScreenVisibility = Visibility.Collapsed;
LaunchScreenVisibility = Visibility.Visible;
}
public void CompleteLogin()
{
LaunchScreenVisibility = Visibility.Collapsed;
MainShellVisibility = Visibility.Visible;
OperatorMessage = $"{LoginOperatorName} 제작자가 접속했습니다. 큐시트와 Scene 매핑 상태를 확인하세요.";
}
[RelayCommand]
private void RefreshCueSheet()
{

View File

@@ -7,14 +7,69 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:TornadoAce_CJOnStyle.ViewModels"
mc:Ignorable="d">
<Page.Resources>
<Storyboard x:Name="LoginIntroStoryboard">
<DoubleAnimation
Storyboard.TargetName="LoginBackgroundScale"
Storyboard.TargetProperty="ScaleX"
From="1.07"
To="1.015"
Duration="0:0:8"
EnableDependentAnimation="True" />
<DoubleAnimation
Storyboard.TargetName="LoginBackgroundScale"
Storyboard.TargetProperty="ScaleY"
From="1.07"
To="1.015"
Duration="0:0:8"
EnableDependentAnimation="True" />
</Storyboard>
<Storyboard x:Name="LoginLineStoryboard" RepeatBehavior="Forever">
<DoubleAnimation
Storyboard.TargetName="RouteLineATransform"
Storyboard.TargetProperty="TranslateX"
From="-36"
To="68"
Duration="0:0:3.8"
AutoReverse="True"
EnableDependentAnimation="True" />
<DoubleAnimation
Storyboard.TargetName="RouteLineA"
Storyboard.TargetProperty="Opacity"
From="0.16"
To="0.76"
Duration="0:0:1.9"
AutoReverse="True" />
<DoubleAnimation
Storyboard.TargetName="RouteLineBTransform"
Storyboard.TargetProperty="TranslateX"
From="52"
To="-44"
BeginTime="0:0:1.1"
Duration="0:0:4.1"
AutoReverse="True"
EnableDependentAnimation="True" />
<DoubleAnimation
Storyboard.TargetName="RouteLineB"
Storyboard.TargetProperty="Opacity"
From="0.12"
To="0.64"
BeginTime="0:0:1.1"
Duration="0:0:2.1"
AutoReverse="True" />
</Storyboard>
</Page.Resources>
<Page.Content>
<Grid Background="{StaticResource AppBackgroundBrush}">
<NavigationView
x:Name="MainShell"
AlwaysShowHeader="False"
Background="{StaticResource AppChromeBrush}"
IsBackButtonVisible="Collapsed"
IsSettingsVisible="False"
PaneDisplayMode="LeftCompact"
RequestedTheme="Dark">
RequestedTheme="Dark"
Visibility="{x:Bind ViewModel.MainShellVisibility, Mode=OneWay}">
<NavigationView.PaneHeader>
<StackPanel Margin="12,18,12,12" Spacing="4">
<TextBlock Style="{StaticResource LabelTextStyle}" Text="TORNADOACE" />
@@ -495,5 +550,302 @@
</Grid>
</ScrollViewer>
</NavigationView>
<Grid
x:Name="LoginScreen"
Canvas.ZIndex="20"
Visibility="{x:Bind ViewModel.LoginScreenVisibility, Mode=OneWay}">
<Border RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<ScaleTransform x:Name="LoginBackgroundScale" ScaleX="1.07" ScaleY="1.07" />
</Border.RenderTransform>
<Border.Background>
<ImageBrush
ImageSource="ms-appx:///Assets/LoginBroadcastControlRoom.png"
Stretch="UniformToFill" />
</Border.Background>
</Border>
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#E6090B11" Offset="0" />
<GradientStop Color="#B3141020" Offset="0.48" />
<GradientStop Color="#D70F1014" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#33000000" Offset="0" />
<GradientStop Color="#66000000" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Border
x:Name="RouteLineA"
Width="460"
Height="2"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="92,198,0,0"
Background="#C8C8FF17"
Opacity="0.28"
RenderTransformOrigin="0,0.5">
<Border.RenderTransform>
<CompositeTransform x:Name="RouteLineATransform" Rotation="-11" />
</Border.RenderTransform>
</Border>
<Ellipse
Width="8"
Height="8"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="548,157,0,0"
Fill="#C8C8FF17" />
<Border
x:Name="RouteLineB"
Width="380"
Height="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,86,166"
Background="#B97632FF"
Opacity="0.22"
RenderTransformOrigin="1,0.5">
<Border.RenderTransform>
<CompositeTransform x:Name="RouteLineBTransform" Rotation="15" />
</Border.RenderTransform>
</Border>
<Grid
Width="1120"
MaxWidth="1120"
Margin="42"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ColumnSpacing="64">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="386" />
</Grid.ColumnDefinitions>
<StackPanel
MaxWidth="620"
Spacing="16"
VerticalAlignment="Bottom">
<Border
Width="54"
Height="54"
HorizontalAlignment="Left"
Background="#7A341069"
BorderBrush="#66C8FF17"
BorderThickness="1"
CornerRadius="8">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Bahnschrift SemiBold"
FontSize="18"
Foreground="#C8FF17"
Text="TA" />
</Border>
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="13"
Foreground="#D7D0B7FF"
Text="CJ ONSTYLE CG AUTOMATION" />
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="48"
Foreground="White"
LineHeight="56"
Text="방송 자막 제작을 ON 상태로 준비합니다"
TextWrapping="WrapWholeWords" />
<TextBlock
MaxWidth="540"
FontFamily="Bahnschrift"
FontSize="17"
Foreground="#DDE7EAEE"
LineHeight="28"
Text="큐시트 데이터, Tornado Scene, 자동 검수 흐름을 하나의 제작 데스크에서 확인합니다."
TextWrapping="WrapWholeWords" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Border
MinHeight="30"
Padding="10,6"
Background="#55341069"
BorderBrush="#66FFFFFF"
BorderThickness="1"
CornerRadius="4">
<TextBlock Foreground="#E8FFFFFF" Text="Cue Sheet" />
</Border>
<Border
MinHeight="30"
Padding="10,6"
Background="#55341069"
BorderBrush="#66FFFFFF"
BorderThickness="1"
CornerRadius="4">
<TextBlock Foreground="#E8FFFFFF" Text="Tornado Scene" />
</Border>
<Border
MinHeight="30"
Padding="10,6"
Background="#66341069"
BorderBrush="#99C8FF17"
BorderThickness="1"
CornerRadius="4">
<TextBlock Foreground="#C8FF17" Text="Auto Verify" />
</Border>
</StackPanel>
</StackPanel>
<Border
Grid.Column="1"
Padding="24"
Background="#F5FFFFFF"
BorderBrush="#33FFFFFF"
BorderThickness="1"
CornerRadius="8">
<StackPanel Spacing="14">
<TextBlock
FontFamily="Bahnschrift"
FontSize="12"
Foreground="#7B2CBF"
Text="접속" />
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="24"
Foreground="#15101A"
Text="제작 데스크 로그인" />
<TextBlock
FontFamily="Bahnschrift"
FontSize="13"
Foreground="#62606A"
Text="초기 빌드에서는 화면 전환 확인용 로그인입니다." />
<StackPanel Spacing="6">
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="12"
Foreground="#62606A"
Text="아이디" />
<TextBox
x:Name="OperatorNameTextBox"
MinHeight="42"
PlaceholderText="operator"
Text="{x:Bind ViewModel.LoginOperatorName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel Spacing="6">
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="12"
Foreground="#62606A"
Text="패스워드" />
<PasswordBox
x:Name="OperatorPasswordBox"
MinHeight="42"
PlaceholderText="access code" />
</StackPanel>
<Button
MinHeight="44"
Margin="0,4,0,0"
HorizontalAlignment="Stretch"
Background="#341069"
Click="LoginButton_Click"
CornerRadius="5"
Foreground="White">
<StackPanel
HorizontalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<SymbolIcon Symbol="Play" />
<TextBlock Text="콘솔 시작" />
</StackPanel>
</Button>
<TextBlock
FontFamily="Bahnschrift"
FontSize="12"
Foreground="#7D7688"
Text="CJ ONSTYLE Inspiring Purple / Vibrant Lime tone"
TextWrapping="WrapWholeWords" />
</StackPanel>
</Border>
</Grid>
</Grid>
<Grid
Canvas.ZIndex="30"
Background="#99090B11"
Visibility="{x:Bind ViewModel.LaunchScreenVisibility, Mode=OneWay}">
<Border
Width="420"
Padding="22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#F7FFFFFF"
BorderBrush="#E5FFFFFF"
BorderThickness="1"
CornerRadius="8">
<StackPanel Spacing="12">
<TextBlock
FontFamily="Bahnschrift"
FontSize="12"
Foreground="#7B2CBF"
Text="연결 확인" />
<TextBlock
FontFamily="Bahnschrift SemiBold"
FontSize="22"
Foreground="#15101A"
Text="제작 콘솔을 준비하는 중" />
<TextBlock
FontFamily="Bahnschrift"
FontSize="14"
Foreground="#62606A"
Text="{x:Bind ViewModel.LaunchMessage, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<ProgressBar
Height="5"
IsIndeterminate="True"
Foreground="#C8FF17" />
<Grid ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Padding="8" Background="#F3EEF9" CornerRadius="5">
<TextBlock
HorizontalAlignment="Center"
FontSize="12"
Foreground="#341069"
Text="큐시트" />
</Border>
<Border Grid.Column="1" Padding="8" Background="#F3EEF9" CornerRadius="5">
<TextBlock
HorizontalAlignment="Center"
FontSize="12"
Foreground="#341069"
Text="Scene" />
</Border>
<Border Grid.Column="2" Padding="8" Background="#F3EEF9" CornerRadius="5">
<TextBlock
HorizontalAlignment="Center"
FontSize="12"
Foreground="#341069"
Text="검수" />
</Border>
</Grid>
</StackPanel>
</Border>
</Grid>
</Grid>
</Page.Content>
</Page>

View File

@@ -10,8 +10,23 @@ namespace TornadoAce_CJOnStyle.Views
public MainPage()
{
this.InitializeComponent();
Loaded += MainPage_Loaded;
}
public MainViewModel ViewModel => viewModel;
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
LoginIntroStoryboard.Begin();
LoginLineStoryboard.Begin();
OperatorNameTextBox.Focus(FocusState.Programmatic);
}
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
ViewModel.BeginLogin(OperatorNameTextBox.Text, OperatorPasswordBox.Password);
await Task.Delay(1050);
ViewModel.CompleteLogin();
}
}
}

View File

@@ -21,6 +21,12 @@
- 솔루션 구성에서 Deploy 대상이 아니므로 `*.appxrecipe` 산출물을 요구하지 않는다.
- VS에서는 `x64` 구성으로 빌드/디버그 실행한다.
## 도입 화면 방향
- CargoRadar의 전체 화면 사진형 로그인 도입부를 참고하되, TornadoAce는 방송 CG 제작실/송출 콘솔 분위기로 전환한다.
- CJ ONSTYLE 공식 소개의 `Inspiring Purple` / `Vibrant Lime` 조합을 로그인 카드, 신호 라인, 강조 텍스트의 기준 톤으로 사용한다.
- 현재 로그인은 실제 인증이 아니라 초기 빌드용 진입 게이트이며, 추후 사내 계정/권한 정책이 정해지면 인증 서비스로 교체한다.
## 다음 설계 결정 지점
- Tornado2와 Tornado3의 어댑터 경계를 같은 인터페이스로 유지할지 여부.