| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- $ErrorActionPreference = "Stop"
- function Read-DotEnv {
- param([string]$Path)
- $map = @{}
- Get-Content -Encoding UTF8 $Path | ForEach-Object {
- $line = $_.Trim()
- if ($line.Length -eq 0 -or $line.StartsWith("#")) {
- return
- }
- if ($line -match "^([^=]+)=(.*)$") {
- $map[$Matches[1].Trim()] = $Matches[2].Trim()
- }
- }
- return $map
- }
- function Field {
- param(
- [string]$Type,
- [string]$TargetClass = ""
- )
- if ($Type -eq "Pointer") {
- return @{ type = $Type; targetClass = $TargetClass }
- }
- return @{ type = $Type }
- }
- $envPath = Join-Path $PSScriptRoot "..\.env"
- $envMap = Read-DotEnv -Path $envPath
- $required = @("PARSE_APP_ID", "PARSE_REST_API_KEY", "PARSE_MASTER_KEY", "PARSE_SERVER_URL")
- $missing = $required | Where-Object { -not $envMap.ContainsKey($_) -or [string]::IsNullOrWhiteSpace($envMap[$_]) }
- if ($missing.Count -gt 0) {
- throw "Missing Parse env: $($missing -join ', ')"
- }
- $baseUrl = $envMap["PARSE_SERVER_URL"].TrimEnd("/")
- $headers = @{
- "X-Parse-Application-Id" = $envMap["PARSE_APP_ID"]
- "X-Parse-REST-API-Key" = $envMap["PARSE_REST_API_KEY"]
- "X-Parse-Master-Key" = $envMap["PARSE_MASTER_KEY"]
- }
- $authenticatedClp = @{
- find = @{ requiresAuthentication = $true }
- get = @{ requiresAuthentication = $true }
- count = @{ requiresAuthentication = $true }
- create = @{ requiresAuthentication = $true }
- update = @{ requiresAuthentication = $true }
- delete = @{}
- addField = @{}
- }
- $schemas = @(
- @{
- className = "_User"
- description = "用户表"
- fields = @{
- name = (Field "String")
- role = (Field "String")
- phone = (Field "String")
- avatarUrl = (Field "String")
- status = (Field "String")
- company = (Field "Pointer" "Company")
- }
- },
- @{
- className = "Company"
- description = "客户企业表"
- fields = @{
- name = (Field "String")
- creditCode = (Field "String")
- contactName = (Field "String")
- contactPhone = (Field "String")
- email = (Field "String")
- serviceLevel = (Field "String")
- address = (Field "String")
- remark = (Field "String")
- status = (Field "String")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "Ticket"
- description = "工单表"
- fields = @{
- ticketNo = (Field "String")
- title = (Field "String")
- description = (Field "String")
- category = (Field "String")
- priority = (Field "String")
- impactScope = (Field "String")
- status = (Field "String")
- company = (Field "Pointer" "Company")
- creator = (Field "Pointer" "_User")
- assignee = (Field "Pointer" "_User")
- firstRespondedAt = (Field "Date")
- resolvedAt = (Field "Date")
- closedAt = (Field "Date")
- isOverdue = (Field "Boolean")
- slaDeadline = (Field "Date")
- companyName = (Field "String")
- ownerName = (Field "String")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "TicketComment"
- description = "工单沟通记录"
- fields = @{
- ticket = (Field "Pointer" "Ticket")
- author = (Field "Pointer" "_User")
- content = (Field "String")
- visibility = (Field "String")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "TicketAttachment"
- description = "工单附件"
- fields = @{
- ticket = (Field "Pointer" "Ticket")
- uploader = (Field "Pointer" "_User")
- fileName = (Field "String")
- fileUrl = (Field "String")
- fileType = (Field "String")
- fileSize = (Field "Number")
- businessType = (Field "String")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "TicketStatusLog"
- description = "工单状态流转日志"
- fields = @{
- ticket = (Field "Pointer" "Ticket")
- operator = (Field "Pointer" "_User")
- fromStatus = (Field "String")
- toStatus = (Field "String")
- remark = (Field "String")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "SlaRule"
- description = "SLA 规则"
- fields = @{
- priority = (Field "String")
- responseMinutes = (Field "Number")
- resolveHours = (Field "Number")
- alertBeforeMinutes = (Field "Number")
- enabled = (Field "Boolean")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "KnowledgeCategory"
- description = "知识库分类"
- fields = @{
- name = (Field "String")
- sortOrder = (Field "Number")
- enabled = (Field "Boolean")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "KnowledgeArticle"
- description = "知识库文章"
- fields = @{
- title = (Field "String")
- category = (Field "Pointer" "KnowledgeCategory")
- summary = (Field "String")
- content = (Field "String")
- tags = (Field "Array")
- visibility = (Field "String")
- status = (Field "String")
- author = (Field "Pointer" "_User")
- viewCount = (Field "Number")
- referenceCount = (Field "Number")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "SatisfactionReview"
- description = "满意度评价"
- fields = @{
- ticket = (Field "Pointer" "Ticket")
- customer = (Field "Pointer" "_User")
- serviceScore = (Field "Number")
- speedScore = (Field "Number")
- solutionScore = (Field "Number")
- averageScore = (Field "Number")
- content = (Field "String")
- followedUp = (Field "Boolean")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "Notification"
- description = "站内通知"
- fields = @{
- receiver = (Field "Pointer" "_User")
- title = (Field "String")
- content = (Field "String")
- type = (Field "String")
- read = (Field "Boolean")
- relatedTicket = (Field "Pointer" "Ticket")
- mockBatch = (Field "String")
- }
- },
- @{
- className = "AuditLog"
- description = "操作日志"
- fields = @{
- operator = (Field "Pointer" "_User")
- module = (Field "String")
- action = (Field "String")
- targetClass = (Field "String")
- targetId = (Field "String")
- ip = (Field "String")
- success = (Field "Boolean")
- detail = (Field "Object")
- mockBatch = (Field "String")
- }
- }
- )
- function Test-SchemaExists {
- param([string]$ClassName)
- try {
- Invoke-RestMethod -Method Get -Uri "$baseUrl/schemas/$ClassName" -Headers $headers | Out-Null
- return $true
- }
- catch {
- if ($_.Exception.Response -and [int]$_.Exception.Response.StatusCode -eq 404) {
- return $false
- }
- if ($_.ErrorDetails -and $_.ErrorDetails.Message -match '"code"\s*:\s*103') {
- return $false
- }
- if ($_.Exception.Message -match 'does not exist') {
- return $false
- }
- throw
- }
- }
- foreach ($schema in $schemas) {
- $exists = Test-SchemaExists -ClassName $schema.className
- $body = @{
- fields = $schema.fields
- }
- if ($schema.className -ne "_User") {
- $body.classLevelPermissions = $authenticatedClp
- }
- $json = $body | ConvertTo-Json -Depth 12
- $method = if ($exists) { "Put" } else { "Post" }
- Invoke-RestMethod -Method $method -Uri "$baseUrl/schemas/$($schema.className)" -Headers $headers -ContentType "application/json" -Body $json | Out-Null
- $verb = if ($exists) { "Updated" } else { "Created" }
- Write-Host "$verb $($schema.className) - $($schema.description)"
- }
- Write-Host "Parse schema initialization finished. Class count: $($schemas.Count)"
|