feat: TTLock — add Учетная запись + Пароль fields for OAuth
Per Sciener docs: OAuth requires TTHotel account credentials (Учетная запись + Пароль) separate from developer app client_id/client_secret. - Migration 055: add ttlock_username, ttlock_password columns - Backend: store and pass new fields to agent - UI: add input fields matching TTHotel PMS integration page - Agent: getAccessToken() uses ttlockUsername/ttlockPassword when provided Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1094,18 +1094,21 @@ export interface Workstation {
|
||||
}
|
||||
|
||||
export interface TTLockConfig {
|
||||
isEnabled: boolean
|
||||
clientId: string
|
||||
cardSectors: string
|
||||
apiServer: string
|
||||
isEnabled: boolean
|
||||
clientId: string
|
||||
cardSectors: string
|
||||
apiServer: string
|
||||
ttlockUsername: string
|
||||
}
|
||||
|
||||
export interface TTLockConfigUpdate {
|
||||
isEnabled?: boolean
|
||||
clientId?: string
|
||||
clientSecret?: string
|
||||
cardSectors?: string
|
||||
apiServer?: string
|
||||
isEnabled?: boolean
|
||||
clientId?: string
|
||||
clientSecret?: string
|
||||
ttlock_username?: string
|
||||
ttlock_password?: string
|
||||
cardSectors?: string
|
||||
apiServer?: string
|
||||
}
|
||||
|
||||
export interface RoomLockMapping {
|
||||
|
||||
@@ -139,11 +139,13 @@ export function TTLockPage() {
|
||||
const [success, setSuccess] = useState<string | null>(null)
|
||||
|
||||
// Форма настроек
|
||||
const [isEnabled, setIsEnabled] = useState(false)
|
||||
const [clientId, setClientId] = useState('')
|
||||
const [clientSecret, setClientSecret] = useState('')
|
||||
const [cardSectors, setCardSectors] = useState('1,2,3,4,5,6,7,8,9,10')
|
||||
const [apiServer, setApiServer] = useState('https://euapi.ttlock.com')
|
||||
const [isEnabled, setIsEnabled] = useState(false)
|
||||
const [clientId, setClientId] = useState('')
|
||||
const [clientSecret, setClientSecret] = useState('')
|
||||
const [ttlockUsername, setTtlockUsername] = useState('')
|
||||
const [ttlockPassword, setTtlockPassword] = useState('')
|
||||
const [cardSectors, setCardSectors] = useState('1,2,3,4,5,6,7,8,9,10')
|
||||
const [apiServer, setApiServer] = useState('https://euapi.ttlock.com')
|
||||
|
||||
// Per-workstation COM port state
|
||||
const [wsComPorts, setWsComPorts] = useState<Record<string, string>>({})
|
||||
@@ -242,6 +244,7 @@ export function TTLockPage() {
|
||||
setConfig(cfg)
|
||||
setIsEnabled(cfg.isEnabled)
|
||||
setClientId(cfg.clientId)
|
||||
setTtlockUsername(cfg.ttlockUsername || '')
|
||||
setCardSectors(cfg.cardSectors || '1,2,3,4,5,6,7,8,9,10')
|
||||
setApiServer(cfg.apiServer || 'https://euapi.ttlock.com')
|
||||
setMappings(maps)
|
||||
@@ -263,13 +266,16 @@ export function TTLockPage() {
|
||||
try {
|
||||
await api.ttlock.updateConfig(slug, {
|
||||
isEnabled,
|
||||
clientId: clientId.trim(),
|
||||
clientSecret: clientSecret.trim() || undefined,
|
||||
cardSectors: cardSectors.trim(),
|
||||
apiServer: apiServer,
|
||||
clientId: clientId.trim(),
|
||||
clientSecret: clientSecret.trim() || undefined,
|
||||
ttlock_username: ttlockUsername.trim() || undefined,
|
||||
ttlock_password: ttlockPassword.trim() || undefined,
|
||||
cardSectors: cardSectors.trim(),
|
||||
apiServer: apiServer,
|
||||
})
|
||||
showSuccess('Настройки сохранены')
|
||||
setClientSecret('')
|
||||
setTtlockPassword('')
|
||||
await load()
|
||||
} catch {
|
||||
setError('Ошибка сохранения')
|
||||
@@ -410,6 +416,27 @@ export function TTLockPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="form-label">Учетная запись <span className="font-normal text-slate-400">(поле «Учетная запись» в TTHotel)</span></label>
|
||||
<input
|
||||
type="text"
|
||||
value={ttlockUsername}
|
||||
onChange={e => setTtlockUsername(e.target.value)}
|
||||
placeholder="h_1754382851163"
|
||||
className="input w-full font-mono text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="form-label">Пароль <span className="font-normal text-slate-400">(поле «Пароль» в TTHotel)</span></label>
|
||||
<PasswordInput
|
||||
value={ttlockPassword}
|
||||
onChange={setTtlockPassword}
|
||||
placeholder={ttlockUsername && !ttlockPassword ? '••••••• (не изменится)' : 'Пароль от учетной записи TTHotel'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Сервер TTLock API */}
|
||||
<div>
|
||||
<label className="form-label">Сервер TTLock API</label>
|
||||
|
||||
Reference in New Issue
Block a user