Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd6c308996 | |||
| ebf02eb58f | |||
| 5baa91e3e7 | |||
| 08c47cfa03 | |||
| cb5440c8d9 | |||
| 05eaa4741a | |||
| c0d5b4697f | |||
| d742425cac | |||
| 5729e88687 | |||
| 0681aad27d |
@@ -6,7 +6,7 @@ on: [release]
|
||||
|
||||
env:
|
||||
REPO: sugarbecomer/tianshen-web
|
||||
REGISTRY: git.likedream.xyz
|
||||
REGISTRY: mycoder.cc.cd
|
||||
|
||||
jobs:
|
||||
Build-And-Upload:
|
||||
|
||||
@@ -19,9 +19,17 @@ http:// {
|
||||
reverse_proxy ${BACKEND_URL}
|
||||
}
|
||||
|
||||
@assets path /assets/* /favicon.svg
|
||||
handle @assets {
|
||||
root * /www
|
||||
header Cache-Control "public, max-age=31536000, immutable"
|
||||
file_server
|
||||
}
|
||||
|
||||
handle {
|
||||
root * /www
|
||||
try_files {path} /index.html
|
||||
header Cache-Control "no-store, no-cache, must-revalidate"
|
||||
file_server
|
||||
}
|
||||
|
||||
|
||||
Generated
+1094
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,7 @@
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^8.0.1",
|
||||
"vite-plugin-bundle-obfuscator": "^1.11.0",
|
||||
"vue-tsc": "^3.2.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@ export const cpTaskApi = {
|
||||
request.post<any, ApiResponse>(`/v1/cpdaily/task/execute/${id}`, data),
|
||||
executeNow: (id: number) =>
|
||||
request.post<any, ApiResponse>(`/v1/cpdaily/task/executeNow/${id}`),
|
||||
updateTitle: (id: number, title: string) =>
|
||||
request.put<any, ApiResponse>(`/v1/cpdaily/task/title/${id}`, { title }),
|
||||
pause: (id: number) =>
|
||||
request.post<any, ApiResponse>(`/v1/cpdaily/task/pause/${id}`),
|
||||
findLocation: (address: string) =>
|
||||
|
||||
+1
-1
@@ -34,5 +34,5 @@ export const userApi = {
|
||||
|
||||
/** 生成邀请码 */
|
||||
generateInviteCode: () =>
|
||||
request.post<any, ApiResponse>('/v1/user/generate-invite-code'),
|
||||
request.post<any, ApiResponse>('/v1/user/generateInviteCode'),
|
||||
}
|
||||
|
||||
+10
-3
@@ -88,9 +88,16 @@ export interface CpLeave {
|
||||
|
||||
export interface CpTaskLog {
|
||||
id: number
|
||||
taskId: number
|
||||
result: string
|
||||
created_at: string
|
||||
cp_task_id?: number
|
||||
system_user_id?: number
|
||||
cp_user_id?: number
|
||||
is_success?: boolean
|
||||
real_name?: string
|
||||
real_title?: string
|
||||
error_message?: string
|
||||
createTime?: string
|
||||
created_at?: string
|
||||
updateTime?: string
|
||||
}
|
||||
|
||||
export interface CpSchool {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { message as toast } from '@/composables/useMessage'
|
||||
import { ArrowLeft, Save, Upload, X, Eye, HelpCircle } from 'lucide-vue-next'
|
||||
import { ArrowLeft, Save, Upload, X, Eye, HelpCircle, Play } from 'lucide-vue-next'
|
||||
import PageLoading from '@/components/common/PageLoading.vue'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -32,6 +32,10 @@ const formItems = ref<CpTaskFormItem[]>([])
|
||||
const savingForm = ref(false)
|
||||
const logicShowMap = ref<Record<string, boolean>>({})
|
||||
|
||||
// ---- 任务标题 ----
|
||||
const taskTitle = ref('')
|
||||
const savingTitle = ref(false)
|
||||
const executingNow = ref(false)
|
||||
// ---- 执行参数 ----
|
||||
const executeParams = ref<CpTaskExecute>({
|
||||
id: 0, frequency: 1, notification_type: 'none',
|
||||
@@ -275,6 +279,7 @@ async function loadExecute() {
|
||||
// getExecute 返回整个 cpTask 对象
|
||||
cpUserId.value = data.edges?.cp_user?.id || data.cp_user_id || 0
|
||||
taskType.value = data.task_type || ''
|
||||
taskTitle.value = data.title || ''
|
||||
executeParams.value = {
|
||||
id: data.id || 0, frequency: data.frequency ?? 1,
|
||||
notification_type: data.notification_type || 'none',
|
||||
@@ -319,6 +324,27 @@ async function saveExecute() {
|
||||
} finally { savingExecute.value = false }
|
||||
}
|
||||
|
||||
async function saveTitle() {
|
||||
if (!taskTitle.value.trim()) { toast.error('标题不能为空'); return }
|
||||
savingTitle.value = true
|
||||
try {
|
||||
await cpTaskApi.updateTitle(taskId.value, taskTitle.value.trim())
|
||||
toast.success('标题修改成功')
|
||||
} catch {
|
||||
// 全局拦截器已处理错误提示
|
||||
} finally { savingTitle.value = false }
|
||||
}
|
||||
|
||||
async function handleExecuteNow() {
|
||||
executingNow.value = true
|
||||
try {
|
||||
await cpTaskApi.executeNow(taskId.value)
|
||||
toast.success('任务已开始执行')
|
||||
} catch {
|
||||
// 全局拦截器已处理错误提示
|
||||
} finally { executingNow.value = false }
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadForm(), loadExecute()])
|
||||
loading.value = false
|
||||
@@ -332,6 +358,12 @@ onMounted(async () => {
|
||||
<ArrowLeft class="h-4 w-4" />
|
||||
</Button>
|
||||
<h2 class="text-2xl font-bold tracking-tight">任务配置</h2>
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<Button variant="default" size="sm" :disabled="executingNow" @click="handleExecuteNow">
|
||||
<Play class="mr-1 h-4 w-4" />
|
||||
{{ executingNow ? '执行中...' : '立即执行' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PageLoading v-if="loading" text="加载中..." />
|
||||
@@ -447,6 +479,18 @@ onMounted(async () => {
|
||||
<CardContent>
|
||||
<div v-if="executeLoading" class="text-sm text-muted-foreground py-4">加载中...</div>
|
||||
<div v-else class="space-y-5">
|
||||
<div class="space-y-2">
|
||||
<Label for="taskTitle">任务标题</Label>
|
||||
<div class="flex items-center gap-2">
|
||||
<Input id="taskTitle" v-model="taskTitle" placeholder="请输入任务标题" class="flex-1" />
|
||||
<Button size="sm" variant="outline" :disabled="savingTitle" @click="saveTitle">
|
||||
{{ savingTitle ? '保存中' : '保存' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="frequency">执行次数</Label>
|
||||
<Input id="frequency" type="number" v-model.number="executeParams.frequency" placeholder="请输入执行次数" :min="1" />
|
||||
|
||||
@@ -18,18 +18,44 @@ const taskId = computed(() => Number(route.params.id))
|
||||
const columns: ColumnDef<CpTaskLog, any>[] = [
|
||||
{ accessorKey: 'id', header: 'ID' },
|
||||
{
|
||||
accessorKey: 'result',
|
||||
accessorKey: 'is_success',
|
||||
header: '执行结果',
|
||||
cell: ({ row }) => {
|
||||
const result = row.getValue<string>('result')
|
||||
return h('span', { class: 'whitespace-pre-wrap break-all' }, result || '-')
|
||||
const isSuccess = row.original.is_success
|
||||
const errorMessage = row.original.error_message
|
||||
if (typeof isSuccess === 'boolean') {
|
||||
return h(
|
||||
'span',
|
||||
{ class: isSuccess ? 'text-green-600' : 'text-red-600' },
|
||||
isSuccess ? '成功' : '失败',
|
||||
)
|
||||
}
|
||||
if (errorMessage) {
|
||||
return h('span', { class: 'text-red-600' }, '失败')
|
||||
}
|
||||
return h('span', '-')
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'created_at',
|
||||
accessorKey: 'real_name',
|
||||
header: '成功标题',
|
||||
cell: ({ row }) => {
|
||||
const realTitle = row.original.real_name || row.original.real_title
|
||||
return h('span', { class: 'whitespace-pre-wrap break-all' }, realTitle || '-')
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'error_message',
|
||||
header: '失败原因',
|
||||
cell: ({ row }) => {
|
||||
return h('span', { class: 'whitespace-pre-wrap break-all' }, row.original.error_message || '-')
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'createTime',
|
||||
header: '执行时间',
|
||||
cell: ({ row }) => {
|
||||
const val = row.getValue<string>('created_at')
|
||||
const val = row.original.createTime || row.original.created_at
|
||||
return val ? val.replace('T', ' ').slice(0, 19) : '-'
|
||||
},
|
||||
},
|
||||
|
||||
+42
-1
@@ -2,9 +2,50 @@ import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import vitePluginBundleObfuscator from 'vite-plugin-bundle-obfuscator'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue(), tailwindcss()],
|
||||
plugins: [
|
||||
vue(),
|
||||
tailwindcss(),
|
||||
vitePluginBundleObfuscator({
|
||||
apply: 'build',
|
||||
log: true,
|
||||
autoExcludeNodeModules: true,
|
||||
threadPool: true,
|
||||
excludes: [
|
||||
/assets\/rolldown-runtime-.*\.js$/,
|
||||
],
|
||||
options: {
|
||||
compact: true,
|
||||
controlFlowFlattening: false,
|
||||
deadCodeInjection: false,
|
||||
debugProtection: false,
|
||||
debugProtectionInterval: 0,
|
||||
disableConsoleOutput: true,
|
||||
identifierNamesGenerator: 'hexadecimal',
|
||||
ignoreImports: true,
|
||||
numbersToExpressions: false,
|
||||
renameGlobals: false,
|
||||
selfDefending: false,
|
||||
simplify: true,
|
||||
splitStrings: false,
|
||||
stringArray: true,
|
||||
stringArrayCallsTransform: false,
|
||||
stringArrayEncoding: [],
|
||||
stringArrayIndexShift: true,
|
||||
stringArrayRotate: true,
|
||||
stringArrayShuffle: true,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersCount: 1,
|
||||
stringArrayWrappersParametersMaxCount: 2,
|
||||
stringArrayWrappersType: 'variable',
|
||||
stringArrayThreshold: 0.75,
|
||||
transformObjectKeys: false,
|
||||
unicodeEscapeSequence: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
|
||||
Reference in New Issue
Block a user