防止电信诈骗。

This commit is contained in:
Kunagisa 2025-06-19 22:10:20 +08:00
parent 73ceb5f9a4
commit d798392bab
6 changed files with 657 additions and 51 deletions

View File

@ -50,12 +50,8 @@ export const addDemand = async (demandData) => {
export const updateDemand = async (id, dataToUpdate) => {
try {
const payload = {
sendcontent: dataToUpdate.sendcontent,
requester: dataToUpdate.requester || '',
qq_code: dataToUpdate.qq_code || '',
content: dataToUpdate.content || '', // 直接使用传入的 content如果为空则使用空字符串
reward: dataToUpdate.reward || '',
date: dataToUpdate.date || new Date().toISOString().slice(0, 19).replace('T', ' ')
...dataToUpdate,
content: dataToUpdate.content // 直接使用传入的 content
};
console.log('更新需求的数据:', payload);
const response = await axiosInstance.put(`/demands/update/${id}`, payload);

View File

@ -108,12 +108,15 @@
</div>
</div>
<ErrorDialog :visible="showErrorDialog" :message="errorDialogMsg" @close="showErrorDialog = false" />
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { getDemandsList, updateDemand, deleteDemand, addDemand } from '../../api/demands'; //
import ErrorDialog from '@/components/ErrorDialog.vue'
const demands = ref([]);
const loading = ref(false);
@ -135,6 +138,9 @@ const initialAddFormState = {
const addForm = ref({ ...initialAddFormState });
const addError = ref('');
const showErrorDialog = ref(false)
const errorDialogMsg = ref('')
const formatDate = (dateString) => {
if (!dateString) return 'N/A';
try {
@ -185,22 +191,20 @@ const submitEditForm = async () => {
if (!currentDemand.value || !currentDemand.value.id) return;
editError.value = '';
try {
// updateDemand API payload
const payload = {
requester: editForm.value.requester,
qq_code: editForm.value.qq_code,
sendcontent: editForm.value.sendcontent,
reward: editForm.value.reward,
date: editForm.value.date // 使
// content API sendcontent
date: editForm.value.date
};
await updateDemand(currentDemand.value.id, payload);
alert('需求更新成功!');
closeEditModal();
fetchDemandsAdmin();
} catch (error) {
console.error('更新需求失败:', error);
editError.value = error.response?.data?.detail || error.message || '更新失败,请重试。';
errorDialogMsg.value = error.response?.data?.detail || error.message || '更新失败,请重试。';
showErrorDialog.value = true;
}
};
@ -211,8 +215,8 @@ const confirmDeleteDemand = async (id) => {
alert('需求删除成功!');
fetchDemandsAdmin();
} catch (error) {
console.error('删除需求失败:', error);
alert('删除需求失败: ' + (error.message || '请稍后重试'));
errorDialogMsg.value = error.response?.data?.detail || error.message || '删除失败,请稍后重试';
showErrorDialog.value = true;
}
}
};

View File

@ -84,7 +84,7 @@
<td>{{ competition.format === 'single' ? '单败淘汰' :
competition.format === 'double' ? '双败淘汰' : '积分赛' }}</td>
<td class="action-cell">
<button class="action-btn view" @click.stop="handleSignUp(competition)">
<button class="action-btn view" @click.stop="handleSignUp(competition)" :disabled="competition.status === 'finish'">
报名
</button>
</td>
@ -440,6 +440,14 @@ refreshCompetitions()
cursor: not-allowed;
}
.action-btn:disabled {
background: #e0e0e0 !important;
color: #b0b0b0 !important;
cursor: not-allowed;
border: none;
opacity: 1;
}
@media (max-width: 768px) {
.competition-page {
padding: 12px;

View File

@ -6,7 +6,7 @@
<div v-else class="detail-card">
<div class="nav-back">
<button class="back-btn" @click="handleBack"> 返回列表</button>
<div class="action-buttons">
<div class="action-buttons" v-if="isOrganizer">
<button class="status-btn" @click="openStatusDialog">修改状态</button>
<button class="edit-btn" @click="openEditDialog">编辑赛事</button>
<button class="delete-btn" @click="confirmDelete">删除赛事</button>
@ -60,7 +60,7 @@
<td>{{ player.lose }}</td>
<td>{{ player.status }}</td>
<td class="action-buttons">
<button class="edit-player-btn" @click="handleEditPlayer(player)">修改</button>
<button class="edit-player-btn" @click="handleEditPlayer(player)" >修改</button>
<button class="remove-btn" @click="handleRemovePlayer(player.id)">移除</button>
</td>
</tr>
@ -225,6 +225,7 @@ import {
updateSignUpResult,
deleteSignUpResult
} from '@/api/tournament'
import { getStoredUser } from '@/utils/jwt'
const router = useRouter()
const route = useRoute()
@ -263,7 +264,7 @@ const competition = ref({
})
const finalResults = ref([])
const isEditMode = ref(false)
const isOrganizer = ref(false) // TODO:
const isOrganizer = ref(false)
const isSaving = ref(false)
const showEditForm = ref(false)
const isUpdating = ref(false)
@ -421,6 +422,14 @@ const fetchTournamentDetail = async () => {
format: formatType(tournament.format)
}
//
const user = getStoredUser()
if (user && user.qq_code && tournament.qq_code) {
isOrganizer.value = String(user.qq_code) === String(tournament.qq_code)
} else {
isOrganizer.value = false
}
//
if (tournament.status === 'prepare') {
await fetchRegisteredPlayers()

View File

@ -2,10 +2,12 @@
<div class="demand-hall">
<div class="page-header">
<h1>需求列表</h1>
<h3>该功能仅做预约联系使用不设计现实中的货币账户一般等价物请用户分辨明细防止电信诈骗</h3>
<h3 class="warning-tip">
免责声明该功能仅做预约联系使用不设计现实中的货币账户一般等价物请用户分辨明细防止电信诈骗如出现任何问题与该平台无关
</h3>
</div>
<button class="btn-common btn-gradient btn-margin-right" @click="openAddModal">添加需求</button>
<button class="btn-common btn-light" @click="fetchDemands">刷新</button>
<button class="btn-common btn-light" @click="onRefresh">刷新</button>
<div class="table-container">
<table class="maps-table">
<thead>
@ -53,6 +55,13 @@
</div>
<div class="modal-body">
<form class="add-modal-form" @submit.prevent="submitReply">
<div class="form-row">
<span class="label">回复消息</span>
<select v-model="addForm.replyTo" class="input">
<option value=""></option>
<option v-for="msg in replyOptions" :key="msg.id" :value="msg.id">{{ msg.text }}</option>
</select>
</div>
<div class="form-row">
<span class="label">昵称</span>
<input
@ -72,7 +81,7 @@
/>
</div>
<div class="form-row">
<span class="label">相关建议</span>
<span class="label">内容</span>
<textarea
v-model="addForm.sendcontent"
class="input"
@ -98,7 +107,13 @@
<div class="modal-content" @click.stop>
<div class="modal-header">
<h2>需求详情</h2>
<button class="close-btn" @click="closeModal">&times;</button>
<div style="display:flex;align-items:center;gap:16px;">
<template v-if="isOwner">
<button class="edit-btn big-action-btn" @click="openEditModal">修改</button>
<button class="delete-btn big-action-btn" @click="handleDeleteDemand">删除</button>
</template>
<button class="close-btn" @click="closeModal">&times;</button>
</div>
</div>
<div class="modal-body">
<div class="detail-item">
@ -141,9 +156,9 @@
<div v-if="selectedDemand?.sendcontent">
<div v-for="(reply, index) in selectedDemand.sendcontent.split('|')" :key="index" class="reply-content">
<div class="reply-with-avatar">
<img :src="`https://q1.qlogo.cn/g?b=qq&nk=${reply.match(/\((\d+)\)/)?.[1] || ''}&s=40`" alt="User Avatar" class="reply-avatar" />
<img :src="`https://q1.qlogo.cn/g?b=qq&nk=${extractQQ(reply)}&s=40`" alt="User Avatar" class="reply-avatar" />
<div class="reply-text">
<b>{{ reply.split(')')[0] + '' }}</b>{{ reply.split(')')[1] }}
<b>{{ parseReplyText(reply).user }}</b> {{ parseReplyText(reply).content }}
</div>
</div>
</div>
@ -165,8 +180,8 @@
<h2>添加需求</h2>
<button class="close-btn" @click="closeAddModal">&times;</button>
</div>
<div class="modal-body">
需求一经发布不许修改
<div class="modal-body" style="background:linear-gradient(90deg,#fffbe6 0%,#fff1b8 100%);color:#ad8b00;font-weight:bold;text-align:center;border-radius:8px;padding:12px 10px;margin:18px 0 18px 0;font-size:16px;box-shadow:0 2px 8px rgba(173,139,0,0.08);display:flex;align-items:center;gap:8px;justify-content:center;">
<span style="font-size:20px;color:#faad14;margin-right:8px;">&#9888;</span>需求一经发布不许修改
</div>
<div class="modal-body">
<form class="add-modal-form" @submit.prevent="submitAddForm">
@ -180,10 +195,10 @@
v-model="addForm.qq_code"
class="input"
placeholder="可选"
@input="validateQQ"
type="text"
pattern="[0-9]*"
inputmode="numeric"
readonly
/>
</div>
<div class="form-row">
@ -209,12 +224,59 @@
</div>
</div>
</div>
<!-- 修改需求弹窗 -->
<div v-if="showEditModal" class="modal-overlay" @click="showEditModal=false">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h2>修改需求</h2>
<button class="close-btn" @click="showEditModal=false">&times;</button>
</div>
<div class="modal-body">
<form class="add-modal-form" @submit.prevent="handleEditSubmit">
<div class="form-row">
<span class="label">请求者</span>
<input v-model="editForm.requester" class="input" required />
</div>
<div class="form-row">
<span class="label">QQ号</span>
<input v-model="editForm.qq_code" class="input" required readonly />
</div>
<div class="form-row">
<span class="label">需求内容</span>
<textarea v-model="editForm.content" class="input" rows="3" required></textarea>
</div>
<div class="form-row">
<span class="label">赏金</span>
<input v-model="editForm.reward" class="input" />
</div>
<button class="btn-common btn-gradient submit-btn" type="submit">保存</button>
</form>
</div>
</div>
</div>
<div v-if="showDeleteConfirm" class="modal-overlay" style="z-index:2000;">
<div class="modal-content" style="max-width:350px;text-align:center;">
<div class="modal-header">
<h2 style="color:#F56C6C;">删除确认</h2>
</div>
<div class="modal-body" style="font-size:16px;">确定要删除该需求吗此操作不可恢复</div>
<div class="delete-dialog-footer" style="display:flex;justify-content:center;gap:18px;margin:18px 0 8px 0;">
<button class="confirm-button" @click="confirmDelete">确认删除</button>
<button class="cancel-button" @click="cancelDelete">取消</button>
</div>
</div>
</div>
<ErrorDialog :visible="showErrorDialog" :message="errorDialogMsg" @close="showErrorDialog = false" />
</div>
</template>
<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { getDemandsList, addDemand, updateDemand } from '../../api/demands'
import { ref, onMounted, nextTick, computed } from 'vue'
import { getDemandsList, addDemand, updateDemand, deleteDemand } from '../../api/demands'
import { getStoredUser } from '@/utils/jwt'
import ErrorDialog from '@/components/ErrorDialog.vue'
//
const demands = ref([])
@ -233,10 +295,24 @@ const addForm = ref({
qq_code: '',
sendcontent: '',
author: '',
author_contact: ''
author_contact: '',
replyTo: ''
})
const addLoading = ref(false)
const autoTextarea = ref(null)
const replyOptions = ref([])
const showEditModal = ref(false)
const editForm = ref({
requester: '',
qq_code: '',
content: '',
reward: '',
id: null
})
const showErrorDialog = ref(false)
const errorDialogMsg = ref('')
const showDeleteConfirm = ref(false)
const pendingDeleteId = ref(null)
//
const isNoReward = (reward) => {
@ -266,6 +342,11 @@ const fetchDemands = async () => {
try {
const data = await getDemandsList()
demands.value = data
replyOptions.value = data.map(demand => ({
id: demand.id,
author: demand.requester,
content: demand.content
}))
} catch (err) {
error.value = `加载失败: ${err.message}`
console.error('加载需求列表失败:', err)
@ -278,6 +359,24 @@ const fetchDemands = async () => {
const showReply = (demand) => {
reply.value = demand
replyModal.value = true
// sendcontent
if (demand.sendcontent) {
replyOptions.value = demand.sendcontent.split('|').map((msg, idx) => {
// qq
// qq (qq)
let match = msg.match(/^(.+?)[(](\d+)[)]/)
let nickname = match ? match[1] : ''
let qq = match ? match[2] : ''
return {
id: idx,
text: msg,
nickname,
qq
}
})
} else {
replyOptions.value = []
}
resetReplyForm();
}
@ -292,7 +391,8 @@ const resetReplyForm = () => {
addForm.value = {
sendcontent: '',
author: '',
author_contact: ''
author_contact: '',
replyTo: ''
};
addError.value = '';
//
@ -316,14 +416,16 @@ const closeModal = () => {
//
const openAddModal = () => {
//
const user = getStoredUser()
addForm.value = {
requester: '',
content: '',
reward: '',
qq_code: '',
qq_code: user && user.qq_code ? user.qq_code : '',
sendcontent: '',
author: '',
author_contact: ''
author_contact: '',
replyTo: ''
};
addError.value = '';
showAddModal.value = true;
@ -407,7 +509,15 @@ const submitReply = async () => {
const dateStr = `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2,'0')}-${now.getDate().toString().padStart(2,'0')} ${now.getHours().toString().padStart(2,'0')}:${now.getMinutes().toString().padStart(2,'0')}:${now.getSeconds().toString().padStart(2,'0')}`;
//
const newReply = `${addForm.value.author}(${addForm.value.author_contact})${addForm.value.sendcontent}`;
let newReply = '';
if (addForm.value.replyTo !== '' && replyOptions.value.length > 0) {
const targetMsg = replyOptions.value.find(msg => String(msg.id) === String(addForm.value.replyTo));
let targetName = targetMsg && targetMsg.nickname ? targetMsg.nickname : '';
newReply = `${addForm.value.author}${addForm.value.author_contact})回复${targetName ? ' ' + targetName : ''}${addForm.value.sendcontent}`;
} else {
newReply = `${addForm.value.author}${addForm.value.author_contact}${addForm.value.sendcontent}`;
}
const formattedContent = reply.value.sendcontent
? `${reply.value.sendcontent}|${newReply}`
: newReply;
@ -450,6 +560,99 @@ function autoResize() {
}
})
}
function extractQQ(str) {
const match = str.match(/[(]([1-9][0-9]{4,})[)]/)
return match ? match[1] : ''
}
function parseReplyText(str) {
// /
const match = str.match(/^(.+?[(][1-9][0-9]{4,}[)])(.*)$/)
if (match) {
// match[1] QQmatch[2] " xxx "
return {
user: match[1].trim(),
content: match[2].replace(/^|^:/, '').trim()
}
}
// fallback
return {
user: '',
content: str
}
}
const isOwner = computed(() => {
const user = getStoredUser()
return user && selectedDemand.value && user.qq_code && selectedDemand.value.qq_code && String(user.qq_code) === String(selectedDemand.value.qq_code)
})
function openEditModal() {
if (!selectedDemand.value) return
const user = getStoredUser()
editForm.value = {
requester: selectedDemand.value.requester || '',
qq_code: user && user.qq_code ? user.qq_code : selectedDemand.value.qq_code || '',
content: selectedDemand.value.content || '',
reward: selectedDemand.value.reward || '',
id: selectedDemand.value.id
}
showEditModal.value = true
}
async function handleEditSubmit() {
if (!editForm.value.content?.trim()) {
errorDialogMsg.value = '需求内容不能为空'
showErrorDialog.value = true
return
}
try {
await updateDemand(editForm.value.id, {
requester: editForm.value.requester,
qq_code: editForm.value.qq_code,
content: editForm.value.content,
reward: editForm.value.reward,
date: selectedDemand.value.date,
sendcontent: selectedDemand.value.sendcontent
})
showEditModal.value = false
fetchDemands()
closeModal()
} catch (e) {
errorDialogMsg.value = '修改失败: ' + (e.response?.data?.detail || e.message)
showErrorDialog.value = true
}
}
function handleDeleteDemand() {
if (!selectedDemand.value) return
pendingDeleteId.value = selectedDemand.value.id
showDeleteConfirm.value = true
}
async function confirmDelete() {
try {
await deleteDemand(pendingDeleteId.value)
fetchDemands()
closeModal()
} catch (e) {
errorDialogMsg.value = '删除失败: ' + (e.response?.data?.detail || e.message)
showErrorDialog.value = true
} finally {
showDeleteConfirm.value = false
pendingDeleteId.value = null
}
}
function cancelDelete() {
showDeleteConfirm.value = false
pendingDeleteId.value = null
}
const onRefresh = () => {
fetchDemands()
}
</script>
<style scoped>
@ -828,4 +1031,98 @@ function autoResize() {
color: #2563eb;
font-size: 15px;
}
.warning-tip {
background: linear-gradient(90deg, #ffeaea 0%, #ffd6d6 100%);
color: #d32f2f;
font-weight: bold;
text-align: center;
border-radius: 8px;
padding: 14px 18px;
margin: 18px 0 24px 0;
font-size: 18px;
box-shadow: 0 2px 8px rgba(211,47,47,0.08);
display: flex;
align-items: center;
gap: 10px;
}
.warning-tip::before {
content: '\26A0'; /* 警告符号 */
font-size: 22px;
color: #d32f2f;
margin-right: 8px;
}
.big-action-btn {
padding: 10px 28px;
font-size: 18px;
border-radius: 8px;
font-weight: 600;
box-shadow: 0 2px 8px rgba(65, 107, 223, 0.10);
transition: background 0.2s, box-shadow 0.2s, color 0.2s;
}
.big-action-btn.btn-gradient:hover {
background: linear-gradient(90deg, #416bdf 0%, #71eaeb 100%);
color: #fff;
}
.big-action-btn.btn-light:hover {
background: #f5f7fa;
color: #2563eb;
border-color: #2563eb;
}
.edit-btn.big-action-btn {
background: #409EFF;
color: #fff;
border: none;
padding: 7px 18px;
font-size: 15px;
border-radius: 8px;
font-weight: 600;
box-shadow: 0 2px 8px rgba(64,158,255,0.10);
transition: background 0.2s, box-shadow 0.2s, color 0.2s;
}
.edit-btn.big-action-btn:hover {
background: #66b1ff;
}
.delete-btn.big-action-btn {
background: #F56C6C;
color: #fff;
border: none;
padding: 7px 18px;
font-size: 15px;
border-radius: 8px;
font-weight: 600;
box-shadow: 0 2px 8px rgba(245,108,108,0.10);
transition: background 0.2s, box-shadow 0.2s, color 0.2s;
}
.delete-btn.big-action-btn:hover {
background: #f78989;
}
.confirm-button {
background-color: #f56c6c;
color: white;
border: none;
padding: 8px 24px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s;
}
.confirm-button:hover {
background-color: #f78989;
}
.cancel-button {
background-color: #f0f0f0;
color: #333;
border: none;
padding: 8px 24px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.cancel-button:hover {
background-color: #e0e0e0;
}
</style>

View File

@ -725,24 +725,316 @@ const allAttributes = computed(() => {
const attrs = new Set();
//
//
const attributeTranslations = {
'id': '单位ID',
'weapon': '武器',
'name': '名称',
'type': '类型',
'damage': '伤害值',
'range': '射程',
'speed': '速度',
'accuracy': '精准度',
'ammo': '弹药量',
'reload': '装弹时间',
'level': '等级',
'cost': '消耗',
'cooldown': '冷却时间',
'effect': '效果',
'target': '目标类型',
'radius': '作用半径',
'duration': '持续时间'
// ================= =================
'id': '武器ID',
'inheritFrom': '继承自',
'AttackRange': '射程',
'MinimumAttackRange': '最小射程',
'RangeBonusMinHeight': '射程加成最小高度',//
'RangeBonus': '射程加成值',//
'RangeBonusPerFoot': '每英尺射程加成',//
'RequestAssistRange': '请求援助范围',//
'AcceptableAimDelta': '允许瞄准偏差角',
'AimDirection': '基准瞄准方向', //
'ScatterRadius': '散射半径',
'ScatterLength': '散射长度',
'ScatterIndependently': '多抛射物独立散射', //V4
'WeaponSpeed': '武器/抛射物速度',
'MinWeaponSpeed': '最小抛射物速度',
'MaxWeaponSpeed': '最大抛射物速度',
'ScaleWeaponSpeed': '缩放抛射物速度',//
'IgnoresContactPoints': '忽略碰撞体积(将武器瞄准目标几何中心)',
'ScaleAttackRangeByAmmoRemaining': '射程随弹药剩余量缩放',//
'CanBeDodged': '可被躲避',//
'IdleAfterFiringDelaySeconds': '开火后待机延迟',//
'HoldAfterFiringDelaySeconds': '开火后保持延迟',//
'HoldDuringReload': '保持先前姿态时即可装填',
'CanFireWhileMoving': '移动射击能力',
'WeaponRecoil': '启用后坐力',
'MinTargetPitch': '最小俯仰角',
'MaxTargetPitch': '最大俯仰角',
'PreferredTargetBone': '首选目标骨骼',
'FireSound': '开火音效',
'FireSoundPerClip': '整弹匣开火音效',
'FiringLoopSound': '持续开火音效',
'FiringLoopSoundContinuesDuringReload': '装填时保持开火音效',
'FireFX': '开火特效',
'FireVeteranFX': '升级后开火特效', //
'FireFlankFX': '侧翼开火特效',
'PreAttackFX': '预攻击特效',
'ClipSize': '弹匣容量',
'ContinuousFireOne': '第一阶段连续射击次数',
'ContinuousFireTwo': '第二阶段连续射击次数',
'ContinuousFireCoastSeconds': '连续射击间隔', //
'AutoReloadWhenIdleSeconds': '空闲时自动装弹时间',//
'ShotsPerBarrel': '每炮管射弹数',
'DamageDealtAtSelfPosition': '伤害作用于自身位置', //
'RequiredFiringObjectStatus': '开火所需状态标志',
'ForbiddenFiringObjectStatus': '禁止开火的状态标志',
'CheckStatusFlagsInRangeChecks': '射程检查时包含状态标志',
'ProjectileSelf': '发射自身作为抛射物', //
'MeleeWeapon': '近战武器',
'ChaseWeapon': '追击武器', //
'LeechRangeWeapon': '吸血射程武器',
'HitStoredTarget': '会攻击预设目标',
'CapableOfFollowingWaypoints': '能否跟随路径点',
'ShowsAmmoPips': '是否显示弹药指示器',
'AllowAttackGarrisonedBldgs': '能否攻击驻军建筑',
'PlayFXWhenStealthed': '隐身时是否播放特效',//
'ContinueAttackRange': '持续攻击范围', //
'SuspendFXDelaySeconds': '特效暂停延迟',//
'IsAimingWeapon': '是否为瞄准武器',
'NoVictimNeeded': '是否需要攻击目标',
'HitPercentage': '命中率', //
'HitPassengerPercentage': '乘客命中概率',
'PassengerProportionalAttack': '是否按乘客比例攻击',
'HealthProportionalResolution': '生命值比例分辨率', //
'MaxAttackPassengers': '最大攻击乘客数',
'FinishAttackOnceStarted': '强制完成已开始攻击',//
'RestrictedHeightRange': '高度限制范围',
'CannotTargetCastleVictims': '能否攻击城堡保护目标',
'RequireFollowThru': '攻击动作必须完整执行', //
'ShareTimers': '共享计时器',//
'ShouldPlayUnderAttackEvaEvent': '是否播放受袭语音',
'InstantLoadClipOnActivate': '激活武器时才开始装填(无法立刻发射)',
'Flags': '行为控制标志集',
'LockWhenUsing': '使用时锁定',//
'BombardType': '轰炸类型武器',//
'UseInnateAttributes': '使用先天属性',//
'PreAttackType': '攻击前准备类型',
'ReAcquireDetailType': '目标重锁定模式',
'AutoReloadsClip': '自动装填机制 (AUTO-自动再装填/NONE-无法再装填/RETURN_TO_BASE-只能在基地再装填)',
'SingleAmmoReloadedNotFullSound': '单发装填音效', // CC3
'ClipReloadedSound': '弹匣重装音效', // CC3
'RadiusDamageAffects': '范围伤害影响对象',
'FXTrigger': '特效触发类型',
'ProjectileCollidesWith': '抛射物碰撞对象类型',
'RequiredAntiMask': '可攻击的目标类型',
'ForbiddenAntiMask': '禁止攻击的目标类型',
'StopFiringOnCanBeInvisible': '隐身时停止开火',//
'ProjectileStreamName': '投射物流名称',
'ContactWeapon': '接触式武器',
'UseCenterForRangeCheck': '使用几何中心点计算射程',
'VirtualDamage': '自动分弹模式/虚拟伤害类型(NONE-不进行自动分弹/SOLO-自动分弹时只计算自己/SHARED-自动分弹时计算所有单位的总火力)',
'PreAttackWeapon': '预攻击武器',
'RevealShroudOnFire': '开火时揭露战争迷雾',
'ShouldPlayTargetDeadEvaEvent': '目标死亡时播放语音',
// ================= =================
'MinSeconds': '最小持续时间(秒)',
'MaxSeconds': '最大持续时间(秒)',
// ================= AI =================
'IsAntiGarrisonWeapon': '反驻军武器',
'MaxSpeedOfTarget': '可命中的目标最大速度',
'UseLongLockOnTimeCode': '使用长锁定时间逻辑', //
'UseAsWarheadForDamageCalculations': 'AI伤害计算弹头',
// ================= =================
'Radius': '作用半径',
'PartitionFilterTestType': '属性过滤器作用区域形状',
'ForbiddenTargetObjectStatus': '瘫痪/冲击波失效的目标对象状态',
'ForbiddenTargetModelCondition': '瘫痪/冲击波失效的目标模型状态',
'RequiredUpgrade': '所需升级',
'ForbiddenUpgrade': '禁止升级',
// ================= =================
'Damage': '基础伤害值',
'DamageTaperOff': '伤害衰减系数', //
'MinRadius': '最小作用半径', //
'DamageArc': '扇形伤害范围角度', //
'DamageArcInverted': '反转伤害扇形', //
'DamageMaxHeight': '伤害最大高度', // F使
'DamageMaxHeightAboveTerrain': '伤害最大离地高度',//
'FlankingBonus': '侧翼攻击加成', //
'FlankedScalar': '被侧翼攻击倍率', //
'DelayTimeSeconds': '伤害延迟时间(秒)', //
'DamageType': '伤害类型', // 穿/
'DeathType': '死亡效果类型', // /
'DamageFXType': '伤害特效类型',
'DamageSubType': '伤害子类型', //
'OnlyKillOwnerWhenTriggered': '仅在被触发时杀死拥有者',
'DrainLifeMultiplier': '生命吸取倍率', // RAAALeech
'DrainLife': '生命吸取', // RAAALeech
'DamageSpeed': '伤害传播速度', // F
'UnderAttackOverrideEvaEvent': '覆盖受袭语音事件',
'VictimShroudRevealer': '目标战争迷雾揭示者', //
'NotifyOwnerOnVictimDeath': '目标死亡通知拥有者', //Leech稿BUG
'NotifyObserversOnPreDamageEffectPosition': '伤害位置预报', //
'ForceFXPositionToVictim': '特效绑定目标位置', //
'RadiusAffectsBridges': '影响桥梁',
'InvalidTargetStatus': '无效目标状态标志',
'DamageScalarDetails': '伤害比例详情',
'Scalar': '伤害比例',
'Filter': '对象过滤器',
// ================= =================
'DamageInterval': '伤害间隔(秒)', // 使
'DamageDuration': '伤害总时长(秒)', // 使
'RemoveIfHealed': '治疗时移除效果', // 使
// ================= =================
'PercentDamageToHeal': '伤害转化为治疗百分比',//
'PercentMaxHealthToTake': '最大生命值吸取比例', //
// ================= =================
'ProjectileTemplate': '抛射物模板',
'WarheadTemplate': '弹头模板',
'WeaponLaunchBoneSlotOverride': '武器发射骨骼槽', //
'AttackOffset': '攻击位置偏移',
'VeterancyLevel': '老兵等级',
'SpecificBarrelOverride': '特定炮管覆盖',
'x': 'X轴偏移',
'y': 'Y轴偏移',
'z': 'Z轴偏移',
// ================= =================
'Suppression': '压制强度', //
'DurationSeconds': '效果持续时间(秒)',
'SuppressionTaperOff': '压制衰减系数', //
'SuppressionArc': '压制扇形角度', //
'SuppressionArcInverted': '反转压制扇形', //
// ================= =================
'Lifetime': '激光持续时间',
'LaserId': '激光ID', //
'HitGroundFX': '命中地面特效',
'OverShootDistance': '激光延长线距离',
// ================= =================
'WeaponOCL': '武器对象创建列表', // OCL
'TargetAsPrimaryObject': '设目标为主要对象', //
// ================= =================
'EffectArc': '麻痹效果扇形角度',//
'DurationSeconds': '麻痹持续时间(秒)',
'ParalyzeType': '麻痹类型', // EMP/
'RemoveParalyzeType': '解除麻痹类型', // 使
'ParalyzeFX': '麻痹特效',
// ================= =================
'InfoWarType': '信息战类型', //
'RadarJamRadius': '雷达干扰半径',//
'RadarJamDuration': '雷达干扰持续时间',//
// ================= =================
'AmountToSpend': '消耗泰矿数量',
// ================= =================
'ShockWaveAmount': '冲击波强度',
'ShockWaveRadius': '冲击波半径',
'ShockWaveArc': '扇形冲击波范围角度',
'ShockWaveTaperOff': '冲击波衰减',
'ShockWaveSpeed': '冲击波速度',//
'ShockWaveZMult': '垂直方向冲击波系数', //
'CyclonicFactor': '气旋因子', //
'ShockwaveDelaySeconds': '冲击波延迟时间(秒)',
'InvertShockWave': '反转冲击波方向', //
'FlipDirection': '翻转方向',
'OnlyWhenJustDied': '仅在目标刚死亡时触发',
'ShockWaveClearRadius': '冲击波清除半径', //
'ShockWaveClearWaveMult': '清除冲击波倍数',
'ShockWaveClearFlingHeight': '清除抛射高度',
'KillObjectFilter': '击杀对象过滤器',
// ================= =================
'SpecialPowerTemplate': '特殊能力模板',
// ================= =================
'AttributeModifierName': '属性修改器名称',
'AttributeModifierOwnerName': '属性修改器所有者', //
'DamageFXType': '伤害特效类型',
'DamageArc': '伤害作用弧度',
'AntiCategories': '反制类别', //
'AntiFX': '反制特效', //
// ================= 线 =================
//线
'OffsetAngle': '线性伤害偏移角度', //
'LineWidth': '线性伤害宽度', //
'LineLengthLeadIn': '起始线长',//
'LineLengthLeadOut': '结束线长',//
'UseDynamicLineLength': '线性伤害使用动态线长',
'OverShootDistance': '线性伤害延长距离',
// ================= =================
//Tint/
'PreColorTime': '着色淡入时间',
'SustainedColorTime': '持续着色时间',
'PostColorTime': '着色淡出时间',
'Frequency': '脉冲频率', //
'Amplitude': '脉冲幅度', //
'Color': '着色颜色',
'r': '红色分量',
'g': '绿色分量',
'b': '蓝色分量',
// ================= =================
'Depth': '弹坑深度',//
'Lift': '地形隆起比例', //
// ================= =================
'FieldAmount': '矿场数量',//
'SpawnedInFieldBonus': '矿场内生成加成',//
// ================= =================
'ScatterMin': '最小散射角度',//
'ScatterMax': '最大散射角度',//
// ================= =================
'AttachModuleId': 'ATTR模块ID',
// ================= =================
'AmountToStrip': '生命值剥离百分比', //
// ================= =================
'Weapon': '使用的武器',
'FireOnVictimObject': '对目标使用武器', // 使
'VictimMustBeAlive': '目标必须存活',//
'Filter': '对象过滤器',
// ================= =================
'MinTimeToImpactFudgeFactor': '最小命中时间容差', //
'MaxTimeToImpactFudgeFactor': '最大命中时间容差', //
// ================= =================
'Rule': '生效规则(ALL/ANY/NONE)',
'Include': '包含对象类型',
'Exclude': '排除对象类型',
'Relationship': '阵营关系(敌/友/中等)',
'StatusBitFlags': '目标需要的状态标志', //
'StatusBitFlagsExclude': '排除目标的状态标志',
'RequiredModelConditions': '所需模型状态',
// ================= =================
'SpecialObjectFilter': '特殊对象过滤器',
'OverrideVoiceAttackSound': '覆盖攻击语音',//
'OverrideVoiceEnterStateAttackSound': '覆盖状态切换攻击语音',//
'SurpriseAttackObjectFilter': '突袭攻击对象过滤器',
'CombinedAttackObjectFilter': '联合攻击对象过滤器',
'HitStoredObjectFilter': '命中存储对象过滤器',
'ScatterRadiusVsType': '散射类型设置',
'IncompatibleAttributeModifier': '不兼容属性修改器',
// ================= =================
'SpawnTemplate': '生成模板',
'SpawnProbability': '生成概率',
'SpawnedModelConditionFlags': '生成模型状态标志',
'Amount': '伤害量',
'PercentDamageToContained': '对包含单位的伤害比例',
'DamageObjectFilter': '伤害对象过滤器',
'MaxUnitsToDamage': '最大伤害单位数',
'WindowBlastFX': '窗口爆炸特效',
'EventName': '事件名称',
'SendToEnemies': '发送给敌人',
'SendToAllies': '发送给盟友',
'SendToNeutral': '发送给中立单位',
// ================= =================
'ScatterRadiusVsType.Radius': '散射半径',
'ScatterRadiusVsType.RequiredModelConditions': '散射所需模型状态'
//
};