master
lion 4 months ago
parent fa1a6a814c
commit f36f6055d4

@ -108,6 +108,7 @@ class CrawlAddressController extends Controller
),
],
'university_id' => ['nullable', 'integer', 'exists:universities,id'],
'department' => ['nullable', 'string', 'max:128'],
'sort' => ['nullable', 'integer', 'min:0'],
'status' => ['required', 'integer', 'in:0,1'],
]);
@ -125,6 +126,12 @@ class CrawlAddressController extends Controller
}
if ($data['target_type'] !== 'teacher') {
$data['university_id'] = null;
$data['department'] = null;
} else {
$data['department'] = isset($data['department']) ? trim((string) $data['department']) : null;
if ($data['department'] === '') {
$data['department'] = null;
}
}
return $data;
@ -145,6 +152,7 @@ class CrawlAddressController extends Controller
'category_label' => $row->categoryDictItem?->label,
'university_id' => $row->university_id,
'university_name' => $row->university?->name,
'department' => $row->department,
'sort' => (int) $row->sort,
'status' => (int) $row->status,
'created_at' => $row->created_at?->toIso8601String(),

@ -109,6 +109,7 @@ class CrawlJobController extends Controller
'params' => ['nullable', 'array'],
'teacher_defaults' => ['nullable', 'array'],
'teacher_defaults.university_id' => ['nullable', 'integer', 'exists:universities,id'],
'teacher_defaults.department' => ['nullable', 'string', 'max:128'],
'teacher_defaults.city' => ['nullable', 'string', 'max:64'],
'teacher_defaults.research_direction_ids' => ['nullable', 'array'],
'teacher_defaults.research_direction_ids.*' => ['integer', 'exists:research_directions,id'],
@ -191,6 +192,7 @@ class CrawlJobController extends Controller
'select_all' => ['nullable', 'boolean'],
'teacher_defaults' => ['nullable', 'array'],
'teacher_defaults.university_id' => ['nullable', 'integer', 'exists:universities,id'],
'teacher_defaults.department' => ['nullable', 'string', 'max:128'],
'teacher_defaults.city' => ['nullable', 'string', 'max:64'],
'teacher_defaults.research_direction_ids' => ['nullable', 'array'],
'teacher_defaults.research_direction_ids.*' => ['integer', 'exists:research_directions,id'],
@ -479,7 +481,7 @@ class CrawlJobController extends Controller
/**
* @param array{source?:string, category_dict_item_id?:int} $newsDefaults
* @param array{university_id?:int,city?:string,research_direction_ids?:int[]} $teacherDefaults
* @param array{university_id?:int,department?:string,city?:string,research_direction_ids?:int[]} $teacherDefaults
*/
protected function applyCrawlDefaultsToPreviewItems(
CrawlJob $job,
@ -508,17 +510,24 @@ class CrawlJobController extends Controller
});
}
if ($job->target_type === 'teacher' && ! empty($teacherDefaults['university_id'])) {
$universityId = (int) $teacherDefaults['university_id'];
if ($job->target_type === 'teacher' && (! empty($teacherDefaults['university_id']) || ! empty($teacherDefaults['department']))) {
$universityId = ! empty($teacherDefaults['university_id']) ? (int) $teacherDefaults['university_id'] : 0;
$department = trim((string) ($teacherDefaults['department'] ?? ''));
CrawlJobItem::query()
->where('crawl_job_id', $job->id)
->where('target_type', 'teacher')
->where('status', 'preview')
->get()
->each(function (CrawlJobItem $item) use ($universityId) {
->each(function (CrawlJobItem $item) use ($universityId, $department) {
$payload = $item->payload ?? [];
$extra = $payload['extra'] ?? [];
$extra['default_university_id'] = $universityId;
if ($universityId > 0) {
$extra['default_university_id'] = $universityId;
}
if ($department !== '') {
$extra['default_department'] = $department;
$payload['college_name'] = $department;
}
$payload['extra'] = $extra;
$item->update(['payload' => $payload]);
});

@ -14,6 +14,7 @@ class CrawlAddress extends Model
'keyword',
'category_dict_item_id',
'university_id',
'department',
'sort',
'status',
];

@ -30,7 +30,11 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
$items = [];
$seen = [];
foreach (HtmlPagination::fetchPagesHtml($requestUrl, $maxPages) as $html) {
$pages = HtmlPagination::fetchPagesHtml($requestUrl, $maxPages);
$listHtml = $pages[0] ?? '';
$applyKeywordFilter = HtmlCrawlSupport::shouldApplyKeywordFilter($requestUrl, $listHtml, $keywords);
foreach ($pages as $html) {
foreach ($this->parseListHtml($html, $requestUrl, $pageHost) as $item) {
if (isset($seen[$item->externalId])) {
continue;
@ -41,7 +45,7 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
}
if (count($items) <= 1) {
$firstHtml = HtmlPagination::fetchPagesHtml($requestUrl, 1)[0] ?? '';
$firstHtml = $pages[0] ?? '';
if ($firstHtml !== '' && $this->looksLikeArticlePage($firstHtml)) {
$single = $this->parseArticleFromHtml($firstHtml, $requestUrl);
if ($single !== null) {
@ -50,11 +54,28 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
}
}
$items = array_values(array_filter(
$items,
fn (CrawlItemDto $item) => CrawlKeywordParser::matchesAny($item->title, $item->summary, $keywords)
));
if ($applyKeywordFilter) {
$items = array_values(array_filter(
$items,
fn (CrawlItemDto $item) => CrawlKeywordParser::matchesAny($item->title, $item->summary, $keywords)
));
}
return $this->enrichNewsItems($items, $keywords, $applyKeywordFilter, $maxResults);
}
/**
* @param list<CrawlItemDto> $items
* @param list<string> $keywords
* @return list<CrawlItemDto>
*/
protected function enrichNewsItems(
array $items,
array $keywords,
bool $applyKeywordFilter,
int $maxResults,
string $platform = 'generic_html',
): array {
$enriched = [];
foreach ($items as $item) {
if (count($enriched) >= $maxResults) {
@ -76,7 +97,7 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
$plainForMatch = $contentHtml ? trim(strip_tags($contentHtml)) : '';
$publishedAt = $detail['published_at'] ?? $item->publishedAt;
if (! CrawlKeywordParser::matchesAny($title, $plainForMatch !== '' ? $plainForMatch : null, $keywords)) {
if ($applyKeywordFilter && ! CrawlKeywordParser::matchesAny($title, $plainForMatch !== '' ? $plainForMatch : null, $keywords)) {
continue;
}
@ -94,7 +115,7 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
publishedAt: $publishedAt,
contentHtml: $contentHtml,
extra: [
'platform' => 'generic_html',
'platform' => $platform,
'keywords' => $keywords,
'category_dict_item_id' => $categoryId,
'category_label' => $this->categoryMatcher->labelForId($categoryId),
@ -164,7 +185,7 @@ class GenericNewsHtmlAdapter implements CrawlerAdapterInterface
return null;
}
$url = HtmlCrawlSupport::absoluteUrl($href, $baseUrl);
$url = HtmlCrawlSupport::normalizeNewsUrl(HtmlCrawlSupport::absoluteUrl($href, $baseUrl));
if (! $url || HtmlCrawlSupport::isAssetPath($url)) {
return null;
}

@ -0,0 +1,166 @@
<?php
namespace App\Services\Crawl\Adapters;
use App\Models\CrawlSource;
use App\Services\Crawl\CrawlItemDto;
use App\Services\Crawl\CrawlKeywordParser;
use App\Services\Crawl\HtmlCrawlSupport;
use Illuminate\Support\Facades\Http;
class HuxiuHtmlAdapter extends GenericNewsHtmlAdapter
{
protected const API_URL = 'https://api-web-article.huxiu.com/web/channel/articleListV1';
protected const PAGE_SIZE = 20;
public function fetch(string $requestUrl, CrawlSource $source, array $params): array
{
$channelId = $this->resolveChannelId($requestUrl);
if ($channelId === null) {
return parent::fetch($requestUrl, $source, $params);
}
return $this->fetchChannelViaApi($requestUrl, $params, $channelId);
}
/**
* @param array<string, mixed> $params
* @return list<CrawlItemDto>
*/
protected function fetchChannelViaApi(string $requestUrl, array $params, int $channelId): array
{
$keywords = CrawlKeywordParser::parse((string) ($params['keyword'] ?? ''));
$maxResults = min(50, max(1, (int) ($params['max_results'] ?? 30)));
$maxPages = min(50, max(1, (int) ($params['max_pages'] ?? 1)));
$listItems = [];
$seen = [];
$lastId = null;
for ($page = 1; $page <= $maxPages && count($listItems) < $maxResults; $page++) {
$payload = $this->requestChannelArticleList($channelId, self::PAGE_SIZE, $lastId);
$rows = $payload['datalist'] ?? [];
if ($rows === []) {
break;
}
foreach ($rows as $row) {
if (count($listItems) >= $maxResults) {
break 2;
}
$item = $this->mapApiRowToDto($row);
if ($item === null || isset($seen[$item->externalId])) {
continue;
}
$seen[$item->externalId] = true;
$listItems[] = $item;
}
$nextLastId = isset($payload['last_id']) ? (int) $payload['last_id'] : 0;
if ($nextLastId <= 0 || $nextLastId === $lastId) {
break;
}
$lastId = $nextLastId;
}
$applyKeywordFilter = HtmlCrawlSupport::shouldApplyKeywordFilter($requestUrl, '', $keywords);
return $this->enrichNewsItems($listItems, $keywords, $applyKeywordFilter, $maxResults, 'huxiu');
}
protected function resolveChannelId(string $url): ?int
{
$path = (string) parse_url($url, PHP_URL_PATH);
if (preg_match('#/channel/(\d+)\.(?:html?|shtml)$#i', $path, $match)) {
return (int) $match[1];
}
if (preg_match('#/article/?(?:\.html?|\.shtml)?$#i', $path)) {
return 0;
}
return null;
}
/**
* @return array{name?:string, datalist?:list<array<string, mixed>>, last_id?:int|string}
*/
protected function requestChannelArticleList(int $channelId, int $pageSize, ?int $lastId): array
{
$form = [
'platform' => 'www',
'channel_id' => (string) $channelId,
'pagesize' => (string) max(1, min(30, $pageSize)),
];
if ($lastId) {
$form['last_id'] = (string) $lastId;
}
$response = Http::timeout(30)
->withHeaders([
'User-Agent' => 'Mozilla/5.0 (compatible; SlakeCrawler/1.0)',
'Accept' => 'application/json',
'Origin' => 'https://www.huxiu.com',
'Referer' => 'https://www.huxiu.com/',
])
->asForm()
->post(self::API_URL, $form);
if (! $response->successful()) {
throw new \RuntimeException('虎嗅列表接口请求失败:HTTP '.$response->status());
}
$json = $response->json();
if (! is_array($json) || empty($json['success'])) {
$message = is_array($json) ? (string) ($json['message'] ?? '未知错误') : '响应格式异常';
throw new \RuntimeException('虎嗅列表接口返回失败:'.$message);
}
$data = $json['data'] ?? [];
return is_array($data) ? $data : [];
}
/**
* @param array<string, mixed> $row
*/
protected function mapApiRowToDto(array $row): ?CrawlItemDto
{
$title = trim((string) ($row['title'] ?? ''));
if ($title === '' || HtmlCrawlSupport::isSkippableLinkTitle($title) || HtmlCrawlSupport::isWeakLinkTitle($title)) {
return null;
}
$url = HtmlCrawlSupport::normalizeNewsUrl((string) ($row['url'] ?? ''));
if ($url === null || $url === '') {
$aid = trim((string) ($row['aid'] ?? ''));
if ($aid === '') {
return null;
}
$url = 'https://www.huxiu.com/article/'.$aid.'.html';
}
$publishedAt = null;
if (! empty($row['dateline'])) {
$timestamp = (int) $row['dateline'];
if ($timestamp > 0) {
$publishedAt = gmdate('Y-m-d', $timestamp);
}
}
$summary = trim((string) ($row['summary'] ?? $row['short_content'] ?? ''));
return new CrawlItemDto(
externalId: 'news:'.md5($url),
title: $title,
canonicalUrl: $url,
summary: $summary !== '' ? $summary : null,
publishedAt: $publishedAt,
extra: ['platform' => 'huxiu'],
);
}
}

@ -18,7 +18,7 @@ class CrawlImportService
{
/**
* @param array<int>|null $itemIds
* @param array{university_id?:int,city?:string,research_direction_ids?:int[]} $teacherDefaults
* @param array{university_id?:int,department?:string,city?:string,research_direction_ids?:int[]} $teacherDefaults
* @return array{
* imported:int,
* imported_primary:int,
@ -164,7 +164,7 @@ class CrawlImportService
}
/**
* @param array{university_id?:int,city?:string,research_direction_ids?:int[]} $defaults
* @param array{university_id?:int,department?:string,city?:string,research_direction_ids?:int[]} $defaults
*/
protected function importTeacher(CrawlJob $job, CrawlJobItem $item, array $defaults = []): ?int
{
@ -193,6 +193,10 @@ class CrawlImportService
$academicTitle = trim((string) ($lead['academic_title'] ?? $payload['academic_title'] ?? ''));
$collegeName = trim((string) ($lead['college'] ?? $lead['affiliation'] ?? $payload['college_name'] ?? ''));
$defaultDepartment = trim((string) ($defaults['department'] ?? ''));
if ($defaultDepartment !== '') {
$collegeName = $defaultDepartment;
}
$bio = trim((string) ($lead['bio'] ?? $payload['bio'] ?? ''));
$profileUrl = trim((string) ($payload['profile_url'] ?? $item->canonical_url ?? ''));

@ -7,6 +7,7 @@ use App\Services\Crawl\Adapters\ArxivApiAdapter;
use App\Services\Crawl\Adapters\FacultyListHtmlAdapter;
use App\Services\Crawl\Adapters\GenericNewsHtmlAdapter;
use App\Services\Crawl\Adapters\GenericPaperHtmlAdapter;
use App\Services\Crawl\Adapters\HuxiuHtmlAdapter;
use App\Services\Crawl\Adapters\PedailyHtmlAdapter;
use App\Services\Crawl\Contracts\CrawlerAdapterInterface;
@ -16,6 +17,7 @@ class CrawlJobDispatcher
protected ArxivApiAdapter $arxiv,
protected PedailyHtmlAdapter $pedaily,
protected GenericNewsHtmlAdapter $genericNews,
protected HuxiuHtmlAdapter $huxiu,
protected GenericPaperHtmlAdapter $genericPaper,
protected FacultyListHtmlAdapter $facultyList,
) {}
@ -34,6 +36,7 @@ class CrawlJobDispatcher
return match ($code) {
'arxiv_api' => $this->arxiv,
'pedaily_html' => $this->pedaily,
'huxiu_html' => $this->huxiu,
'generic_news_html' => $this->genericNews,
'generic_paper_html' => $this->genericPaper,
'faculty_list_html' => $this->facultyList,

@ -152,4 +152,70 @@ class HtmlCrawlSupport
{
return (bool) preg_match('#\.(css|js|png|jpe?g|gif|svg|ico|woff2?|pdf|zip)(\?|$)#i', $url);
}
public static function normalizeNewsUrl(?string $url): ?string
{
if ($url === null || trim($url) === '') {
return null;
}
$parts = parse_url($url);
if (! is_array($parts) || empty($parts['scheme']) || empty($parts['host'])) {
return $url;
}
$path = $parts['path'] ?? '/';
$normalized = $parts['scheme'].'://'.$parts['host'];
if (! empty($parts['port'])) {
$normalized .= ':'.$parts['port'];
}
return $normalized.$path;
}
/**
* 频道/栏目列表页上的关键词多为分类标签,不应再按标题二次过滤。
*
* @param list<string> $keywords
*/
public static function shouldApplyKeywordFilter(string $requestUrl, string $listHtml, array $keywords): bool
{
if ($keywords === []) {
return false;
}
$path = strtolower((string) parse_url($requestUrl, PHP_URL_PATH));
if (preg_match('#/(channel|column|tag|topic|special)/[^/]+\.(?:html?|shtml)$#i', $path)) {
return false;
}
$heading = self::extractListPageHeading($listHtml);
if ($heading !== null) {
foreach ($keywords as $keyword) {
if ($keyword !== '' && mb_stripos($heading, $keyword) !== false) {
return false;
}
}
}
return true;
}
public static function extractListPageHeading(string $html): ?string
{
if (preg_match('#<h3[^>]+class=["\'][^"\']*channel-name[^"\']*["\'][^>]*>(.*?)</h3>#is', $html, $m)) {
$title = trim(strip_tags(html_entity_decode($m[1])));
return $title !== '' ? $title : null;
}
if (preg_match('#<h1[^>]*>(.*?)</h1>#is', $html, $m)) {
$title = trim(strip_tags(html_entity_decode($m[1])));
if ($title !== '' && mb_strlen($title) <= 40) {
return $title;
}
}
return null;
}
}

@ -21,6 +21,7 @@ class NewsContentHtml
'#<article[^>]*>(.*?)</article>#is',
'#<div[^>]+id=["\'](?:news-content|article-body|article-content|main-content|post-content)["\'][^>]*>(.*?)</div>#is',
'#<div[^>]+class=["\'][^"\']*(?:article-body|article-content|news-content|post-content|entry-content|content-detail|detail-content)[^"\']*["\'][^>]*>(.*?)</div>#is',
'#<div[^>]+class=["\'][^"\']*article__content[^"\']*["\'][^>]*>(.*?)</div>#is',
];
foreach ($patterns as $pattern) {

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('crawl_addresses', function (Blueprint $table) {
$table->string('department', 128)->nullable()->after('university_id');
});
}
public function down(): void
{
Schema::table('crawl_addresses', function (Blueprint $table) {
$table->dropColumn('department');
});
}
};

@ -71,6 +71,25 @@ class CrawlSourcesSeeder extends Seeder
],
];
CrawlSource::query()->updateOrCreate(
['adapter_code' => 'huxiu_html', 'target_type' => 'industry_news'],
[
'name' => '虎嗅',
'entry_url' => 'https://www.huxiu.com/',
'match_domains' => ['huxiu.com', 'www.huxiu.com'],
'config' => [],
'param_schema' => $newsSchema,
'status' => 1,
'sort' => 15,
]
);
CrawlSource::query()
->where('target_type', 'industry_news')
->where('name', '虎嗅')
->where('adapter_code', '!=', 'huxiu_html')
->delete();
CrawlSource::query()->updateOrCreate(
['adapter_code' => 'pedaily_html', 'target_type' => 'industry_news'],
[
@ -152,6 +171,6 @@ class CrawlSourcesSeeder extends Seeder
]
);
$this->command?->info('采集源 arXiv / 投资界 / 通用 HTML / 师资列表 已写入。');
$this->command?->info('采集源 arXiv / 虎嗅 / 投资界 / 通用 HTML / 师资列表 已写入。');
}
}

@ -1 +1 @@
import{C as e,Ct as t,D as n,E as r,G as i,S as a,T as o,Y as s,Z as c,at as l,b as u,f as d,h as f,ht as p,m,q as h,tn as g,x as _,y as v}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as y,d as b,h as x,l as S,n as C,o as w,s as T,t as E,v as D}from"./index-BXVUywjg.js";var O={class:`user-link`},k=T(n({__name:`AdminLayout`,setup(n){let T=y(),k=w(),A=E(),j=v(()=>T.path),M=p(!1),N=p(!1),P=p({password:``,password_confirmation:``}),F=v(()=>A.user?.username||`—`);function I(e){return e&&x[e]||D}function L(e){e&&e!==T.path&&k.push(e)}async function R(e){e===`out`&&(await A.logout(),await k.replace({name:`login`})),e===`pwd`&&(P.value={password:``,password_confirmation:``},M.value=!0)}async function z(){N.value=!0;try{await C(P.value),S.success(`密码已更新`),M.value=!1}finally{N.value=!1}}return(n,p)=>{let v=s(`el-icon`),y=s(`el-dropdown-item`),x=s(`el-dropdown-menu`),S=s(`el-dropdown`),C=s(`el-header`),w=s(`el-menu-item`),E=s(`el-sub-menu`),D=s(`el-menu`),k=s(`el-aside`),B=s(`router-view`),V=s(`el-main`),H=s(`el-container`),U=s(`el-input`),W=s(`el-form-item`),G=s(`el-form`),K=s(`el-button`),q=s(`el-dialog`);return i(),e(m,null,[r(H,{class:`admin-layout`,direction:`vertical`},{default:l(()=>[r(C,{class:`layout-topbar`,height:`52px`},{default:l(()=>[p[7]||=u(`div`,{class:`brand`},`S-lake高校雷达网`,-1),p[8]||=u(`div`,{class:`spacer`},null,-1),r(S,{class:`topbar-user`,trigger:`click`,onCommand:R},{dropdown:l(()=>[r(x,null,{default:l(()=>[r(y,{command:`pwd`},{default:l(()=>[...p[5]||=[o(`修改密码`,-1)]]),_:1}),r(y,{command:`out`,divided:``,class:`dropdown-logout`},{default:l(()=>[...p[6]||=[o(` 退出登录 `,-1)]]),_:1})]),_:1})]),default:l(()=>[u(`span`,O,[o(g(t(A).user?.real_name||t(A).user?.username)+` `,1),r(v,{class:`el-icon--right`},{default:l(()=>[r(t(b))]),_:1})])]),_:1})]),_:1}),r(H,{class:`layout-body`},{default:l(()=>[r(k,{width:`260px`,class:`aside`},{default:l(()=>[r(D,{"default-active":j.value,class:`menu slake-menu`,"background-color":`#ffffff`,"text-color":`#495057`,"active-text-color":`#ffffff`},{default:l(()=>[(i(!0),e(m,null,h(t(A).menus,t=>(i(),e(m,{key:t.id},[t.children?.length?(i(),_(E,{key:0,index:String(t.id)},{title:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(t.icon))))]),_:2},1024),u(`span`,null,g(t.title),1)]),default:l(()=>[(i(!0),e(m,null,h(t.children,e=>(i(),_(w,{key:e.id,index:e.path,onClick:t=>L(e.path)},{default:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(e.icon))))]),_:2},1024),u(`span`,null,g(e.title),1)]),_:2},1032,[`index`,`onClick`]))),128))]),_:2},1032,[`index`])):(i(),_(w,{key:1,index:t.path,onClick:e=>L(t.path)},{default:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(t.icon))))]),_:2},1024),u(`span`,null,g(t.title),1)]),_:2},1032,[`index`,`onClick`]))],64))),128))]),_:1},8,[`default-active`])]),_:1}),r(V,{class:`main`},{default:l(()=>[r(B,null,{default:l(({Component:e})=>[(i(),_(f,null,[t(T).meta.keepAlive&&e?(i(),_(c(e),{key:t(T).fullPath})):a(``,!0)],1024)),!t(T).meta.keepAlive&&e?(i(),_(c(e),{key:t(T).fullPath})):a(``,!0)]),_:1})]),_:1})]),_:1})]),_:1}),r(q,{modelValue:M.value,"onUpdate:modelValue":p[3]||=e=>M.value=e,class:`pwd-dialog`,title:`修改密码`,width:`480px`,"append-to-body":``,"destroy-on-close":``,onClosed:p[4]||=e=>P.value={password:``,password_confirmation:``}},{footer:l(()=>[r(K,{onClick:p[2]||=e=>M.value=!1},{default:l(()=>[...p[9]||=[o(`取消`,-1)]]),_:1}),r(K,{type:`primary`,loading:N.value,onClick:z},{default:l(()=>[...p[10]||=[o(`保存`,-1)]]),_:1},8,[`loading`])]),default:l(()=>[r(G,{class:`pwd-dialog-form`,"label-width":`100px`,onSubmit:d(z,[`prevent`])},{default:l(()=>[r(W,{label:`账号`},{default:l(()=>[r(U,{"model-value":F.value,readonly:``},null,8,[`model-value`])]),_:1}),r(W,{label:`新密码`,required:``},{default:l(()=>[r(U,{modelValue:P.value.password,"onUpdate:modelValue":p[0]||=e=>P.value.password=e,type:`password`,"show-password":``,placeholder:`至少 6 位`,autocomplete:`new-password`},null,8,[`modelValue`])]),_:1}),r(W,{label:`确认新密码`,required:``},{default:l(()=>[r(U,{modelValue:P.value.password_confirmation,"onUpdate:modelValue":p[1]||=e=>P.value.password_confirmation=e,type:`password`,"show-password":``,placeholder:`再次输入新密码`,autocomplete:`new-password`},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`])],64)}}}),[[`__scopeId`,`data-v-54fb5ddb`]]);export{k as default};
import{C as e,Ct as t,D as n,E as r,G as i,S as a,T as o,Y as s,Z as c,at as l,b as u,f as d,h as f,ht as p,m,q as h,tn as g,x as _,y as v}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as y,d as b,h as x,l as S,n as C,o as w,s as T,t as E,v as D}from"./index-1sotE_gT.js";var O={class:`user-link`},k=T(n({__name:`AdminLayout`,setup(n){let T=y(),k=w(),A=E(),j=v(()=>T.path),M=p(!1),N=p(!1),P=p({password:``,password_confirmation:``}),F=v(()=>A.user?.username||`—`);function I(e){return e&&x[e]||D}function L(e){e&&e!==T.path&&k.push(e)}async function R(e){e===`out`&&(await A.logout(),await k.replace({name:`login`})),e===`pwd`&&(P.value={password:``,password_confirmation:``},M.value=!0)}async function z(){N.value=!0;try{await C(P.value),S.success(`密码已更新`),M.value=!1}finally{N.value=!1}}return(n,p)=>{let v=s(`el-icon`),y=s(`el-dropdown-item`),x=s(`el-dropdown-menu`),S=s(`el-dropdown`),C=s(`el-header`),w=s(`el-menu-item`),E=s(`el-sub-menu`),D=s(`el-menu`),k=s(`el-aside`),B=s(`router-view`),V=s(`el-main`),H=s(`el-container`),U=s(`el-input`),W=s(`el-form-item`),G=s(`el-form`),K=s(`el-button`),q=s(`el-dialog`);return i(),e(m,null,[r(H,{class:`admin-layout`,direction:`vertical`},{default:l(()=>[r(C,{class:`layout-topbar`,height:`52px`},{default:l(()=>[p[7]||=u(`div`,{class:`brand`},`S-lake高校雷达网`,-1),p[8]||=u(`div`,{class:`spacer`},null,-1),r(S,{class:`topbar-user`,trigger:`click`,onCommand:R},{dropdown:l(()=>[r(x,null,{default:l(()=>[r(y,{command:`pwd`},{default:l(()=>[...p[5]||=[o(`修改密码`,-1)]]),_:1}),r(y,{command:`out`,divided:``,class:`dropdown-logout`},{default:l(()=>[...p[6]||=[o(` 退出登录 `,-1)]]),_:1})]),_:1})]),default:l(()=>[u(`span`,O,[o(g(t(A).user?.real_name||t(A).user?.username)+` `,1),r(v,{class:`el-icon--right`},{default:l(()=>[r(t(b))]),_:1})])]),_:1})]),_:1}),r(H,{class:`layout-body`},{default:l(()=>[r(k,{width:`260px`,class:`aside`},{default:l(()=>[r(D,{"default-active":j.value,class:`menu slake-menu`,"background-color":`#ffffff`,"text-color":`#495057`,"active-text-color":`#ffffff`},{default:l(()=>[(i(!0),e(m,null,h(t(A).menus,t=>(i(),e(m,{key:t.id},[t.children?.length?(i(),_(E,{key:0,index:String(t.id)},{title:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(t.icon))))]),_:2},1024),u(`span`,null,g(t.title),1)]),default:l(()=>[(i(!0),e(m,null,h(t.children,e=>(i(),_(w,{key:e.id,index:e.path,onClick:t=>L(e.path)},{default:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(e.icon))))]),_:2},1024),u(`span`,null,g(e.title),1)]),_:2},1032,[`index`,`onClick`]))),128))]),_:2},1032,[`index`])):(i(),_(w,{key:1,index:t.path,onClick:e=>L(t.path)},{default:l(()=>[r(v,null,{default:l(()=>[(i(),_(c(I(t.icon))))]),_:2},1024),u(`span`,null,g(t.title),1)]),_:2},1032,[`index`,`onClick`]))],64))),128))]),_:1},8,[`default-active`])]),_:1}),r(V,{class:`main`},{default:l(()=>[r(B,null,{default:l(({Component:e})=>[(i(),_(f,null,[t(T).meta.keepAlive&&e?(i(),_(c(e),{key:t(T).fullPath})):a(``,!0)],1024)),!t(T).meta.keepAlive&&e?(i(),_(c(e),{key:t(T).fullPath})):a(``,!0)]),_:1})]),_:1})]),_:1})]),_:1}),r(q,{modelValue:M.value,"onUpdate:modelValue":p[3]||=e=>M.value=e,class:`pwd-dialog`,title:`修改密码`,width:`480px`,"append-to-body":``,"destroy-on-close":``,onClosed:p[4]||=e=>P.value={password:``,password_confirmation:``}},{footer:l(()=>[r(K,{onClick:p[2]||=e=>M.value=!1},{default:l(()=>[...p[9]||=[o(`取消`,-1)]]),_:1}),r(K,{type:`primary`,loading:N.value,onClick:z},{default:l(()=>[...p[10]||=[o(`保存`,-1)]]),_:1},8,[`loading`])]),default:l(()=>[r(G,{class:`pwd-dialog-form`,"label-width":`100px`,onSubmit:d(z,[`prevent`])},{default:l(()=>[r(W,{label:`账号`},{default:l(()=>[r(U,{"model-value":F.value,readonly:``},null,8,[`model-value`])]),_:1}),r(W,{label:`新密码`,required:``},{default:l(()=>[r(U,{modelValue:P.value.password,"onUpdate:modelValue":p[0]||=e=>P.value.password=e,type:`password`,"show-password":``,placeholder:`至少 6 位`,autocomplete:`new-password`},null,8,[`modelValue`])]),_:1}),r(W,{label:`确认新密码`,required:``},{default:l(()=>[r(U,{modelValue:P.value.password_confirmation,"onUpdate:modelValue":p[1]||=e=>P.value.password_confirmation=e,type:`password`,"show-password":``,placeholder:`再次输入新密码`,autocomplete:`new-password`},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`])],64)}}}),[[`__scopeId`,`data-v-54fb5ddb`]]);export{k as default};

@ -1 +1 @@
import{C as e,Ct as t,D as n,E as r,G as i,T as a,Y as o,at as s,b as c,tn as l,y as u}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{g as d,s as f}from"./index-BXVUywjg.js";var p={class:`page`},m={class:`card-head`},h=f(n({__name:`HomeView`,setup(n){let f=u(()=>`/api`);return(n,u)=>{let h=o(`el-icon`),g=o(`el-descriptions-item`),_=o(`el-descriptions`),v=o(`el-card`);return i(),e(`div`,p,[r(v,{class:`card`,shadow:`hover`},{header:s(()=>[c(`div`,m,[r(h,{size:22},{default:s(()=>[r(t(d))]),_:1}),u[0]||=c(`span`,null,`高校雷达网 · 管理后台`,-1)])]),default:s(()=>[u[2]||=c(`p`,{class:`desc`},[a(`技术栈:Vue 3、Vite、TypeScript、Element Plus。本地已配置对接 `),c(`code`,null,`slake-school-service`),a(` 的 API 代理。`)],-1),r(_,{column:1,border:``},{default:s(()=>[r(g,{label:`VITE_API_BASE_URL`},{default:s(()=>[c(`code`,null,l(f.value),1)]),_:1}),r(g,{label:`说明`},{default:s(()=>[...u[1]||=[a(` 开发时请求 `,-1),c(`code`,null,`/api/*`,-1),a(` 由 Vite 转发至 `,-1),c(`code`,null,`VITE_PROXY_TARGET`,-1),a(`(默认 `,-1),c(`code`,null,`http://127.0.0.1:8000`,-1),a(`),与 Laravel 的 `,-1),c(`code`,null,`/api`,-1),a(` 前缀一致。 `,-1)]]),_:1})]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-436e6398`]]);export{h as default};
import{C as e,Ct as t,D as n,E as r,G as i,T as a,Y as o,at as s,b as c,tn as l,y as u}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{g as d,s as f}from"./index-1sotE_gT.js";var p={class:`page`},m={class:`card-head`},h=f(n({__name:`HomeView`,setup(n){let f=u(()=>`/api`);return(n,u)=>{let h=o(`el-icon`),g=o(`el-descriptions-item`),_=o(`el-descriptions`),v=o(`el-card`);return i(),e(`div`,p,[r(v,{class:`card`,shadow:`hover`},{header:s(()=>[c(`div`,m,[r(h,{size:22},{default:s(()=>[r(t(d))]),_:1}),u[0]||=c(`span`,null,`高校雷达网 · 管理后台`,-1)])]),default:s(()=>[u[2]||=c(`p`,{class:`desc`},[a(`技术栈:Vue 3、Vite、TypeScript、Element Plus。本地已配置对接 `),c(`code`,null,`slake-school-service`),a(` 的 API 代理。`)],-1),r(_,{column:1,border:``},{default:s(()=>[r(g,{label:`VITE_API_BASE_URL`},{default:s(()=>[c(`code`,null,l(f.value),1)]),_:1}),r(g,{label:`说明`},{default:s(()=>[...u[1]||=[a(` 开发时请求 `,-1),c(`code`,null,`/api/*`,-1),a(` 由 Vite 转发至 `,-1),c(`code`,null,`VITE_PROXY_TARGET`,-1),a(`(默认 `,-1),c(`code`,null,`http://127.0.0.1:8000`,-1),a(`),与 Laravel 的 `,-1),c(`code`,null,`/api`,-1),a(` 前缀一致。 `,-1)]]),_:1})]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-436e6398`]]);export{h as default};

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/activities`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/activities/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/activities`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/activities/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/activities/${t}`);return n}async function o(t){let{data:n}=await e.get(`/admin/v1/activities/${t}/sessions`);return n.data.items}async function s(t,n){let{data:r}=await e.post(`/admin/v1/activities/${t}/sessions`,n);return r.data}async function c(t,n,r){let{data:i}=await e.put(`/admin/v1/activities/${t}/sessions/${n}`,r);return i}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/activities/${t}/sessions/${n}`);return r}async function u(t,n){let{data:r}=await e.get(`/admin/v1/activities/${t}/signups`,{params:n});return r.data}async function d(e,t={}){let n=1,r=[];for(;;){let i=await u(e,{...t,page:n,page_size:200});if(r.push(...i.items),n>=i.meta.last_page||i.items.length===0)break;n+=1}return r}async function f(t,n){let{data:r}=await e.delete(`/admin/v1/activities/${t}/signups/${n}`);return r}async function p(t,n,r){let{data:i}=await e.post(`/admin/v1/activities/${t}/signups/${n}/checkin`,r);return i}export{l as a,n as c,d,i as f,a as i,o as l,r as n,f as o,c as p,s as r,t as s,p as t,u};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/activities`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/activities/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/activities`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/activities/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/activities/${t}`);return n}async function o(t){let{data:n}=await e.get(`/admin/v1/activities/${t}/sessions`);return n.data.items}async function s(t,n){let{data:r}=await e.post(`/admin/v1/activities/${t}/sessions`,n);return r.data}async function c(t,n,r){let{data:i}=await e.put(`/admin/v1/activities/${t}/sessions/${n}`,r);return i}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/activities/${t}/sessions/${n}`);return r}async function u(t,n){let{data:r}=await e.get(`/admin/v1/activities/${t}/signups`,{params:n});return r.data}async function d(e,t={}){let n=1,r=[];for(;;){let i=await u(e,{...t,page:n,page_size:200});if(r.push(...i.items),n>=i.meta.last_page||i.items.length===0)break;n+=1}return r}async function f(t,n){let{data:r}=await e.delete(`/admin/v1/activities/${t}/signups/${n}`);return r}async function p(t,n,r){let{data:i}=await e.post(`/admin/v1/activities/${t}/signups/${n}/checkin`,r);return i}export{l as a,n as c,d,i as f,a as i,o as l,r as n,f as o,c as p,s as r,t as s,p as t,u};

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/universities`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/universities`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/universities/${t}`,n);return r.data}async function i(t){let{data:n}=await e.delete(`/admin/v1/universities/${t}`);return n}async function a(t){let{data:n}=await e.get(`/admin/v1/papers`,{params:t});return n.data}async function o(){let{data:t}=await e.get(`/admin/v1/papers/filter-options`);return t.data}async function s(t){let{data:n}=await e.get(`/admin/v1/papers/${t}`);return n.data}async function c(t){let{data:n}=await e.delete(`/admin/v1/papers/${t}`);return n}async function l(t,n){let{data:r}=await e.post(`/admin/v1/papers/${t}/teachers`,{teacher_ids:n});return r}async function u(t){let{data:n}=await e.post(`/admin/v1/crawl-jobs/resolve-url`,t);return n.data}async function d(t){let{data:n}=await e.post(`/admin/v1/crawl-jobs`,t,{timeout:3e5});return n.data}async function f(t,n){let{data:r}=await e.get(`/admin/v1/crawl-jobs/${t}/items`,{params:n});return r.data}async function p(e,t){let n=[],r=1;for(;;){let i=await f(e,{...t,page:r,page_size:200});if(n.push(...i.items),r>=i.meta.last_page||i.items.length===0)break;r+=1}return n}async function m(){let{data:t}=await e.get(`/admin/v1/radar-map`);return t.data}async function h(t){let{data:n}=await e.get(`/admin/v1/weekly-briefs`,{params:t});return n.data}async function g(t){let{data:n}=await e.get(`/admin/v1/weekly-briefs/${t}`);return n.data}async function _(t={}){let{data:n}=await e.post(`/admin/v1/weekly-briefs/generate`,t);return n.data}export{p as a,a as c,g as d,h as f,r as g,d as h,i,m as l,u as m,n,s as o,_ as p,c as r,o as s,l as t,t as u};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/universities`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/universities`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/universities/${t}`,n);return r.data}async function i(t){let{data:n}=await e.delete(`/admin/v1/universities/${t}`);return n}async function a(t){let{data:n}=await e.get(`/admin/v1/papers`,{params:t});return n.data}async function o(){let{data:t}=await e.get(`/admin/v1/papers/filter-options`);return t.data}async function s(t){let{data:n}=await e.get(`/admin/v1/papers/${t}`);return n.data}async function c(t){let{data:n}=await e.delete(`/admin/v1/papers/${t}`);return n}async function l(t,n){let{data:r}=await e.post(`/admin/v1/papers/${t}/teachers`,{teacher_ids:n});return r}async function u(t){let{data:n}=await e.post(`/admin/v1/crawl-jobs/resolve-url`,t);return n.data}async function d(t){let{data:n}=await e.post(`/admin/v1/crawl-jobs`,t,{timeout:3e5});return n.data}async function f(t,n){let{data:r}=await e.get(`/admin/v1/crawl-jobs/${t}/items`,{params:n});return r.data}async function p(e,t){let n=[],r=1;for(;;){let i=await f(e,{...t,page:r,page_size:200});if(n.push(...i.items),r>=i.meta.last_page||i.items.length===0)break;r+=1}return n}async function m(){let{data:t}=await e.get(`/admin/v1/radar-map`);return t.data}async function h(t){let{data:n}=await e.get(`/admin/v1/weekly-briefs`,{params:t});return n.data}async function g(t){let{data:n}=await e.get(`/admin/v1/weekly-briefs/${t}`);return n.data}async function _(t={}){let{data:n}=await e.post(`/admin/v1/weekly-briefs/generate`,t);return n.data}export{p as a,a as c,g as d,h as f,r as g,d as h,i,m as l,u as m,n,s as o,_ as p,c as r,o as s,l as t,t as u};

@ -1 +1 @@
import{C as e,D as t,E as n,G as r,T as i,X as a,Y as o,at as s,b as c,d as l,ht as u,ot as d,x as f}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{r as p}from"./index-BXVUywjg.js";import{n as m,t as h}from"./usePageLoad-I-Vfu6XZ.js";async function g(e){let{data:t}=await p.get(`/admin/v1/operation-logs`,{params:e});return t.data}var _={class:`list-page`},v={class:`page-header`},y={class:`list-filter-bar`},b={class:`list-pager`},x=t({__name:`index`,setup(t){let p=u(!1),x=u([]),S=u({current_page:1,per_page:20,total:0}),C=u(1),w=u(``),T=u(``),E=u(``);async function D(){p.value=!0;try{let e=await g({page:C.value,page_size:S.value.per_page,keyword:w.value||void 0,from:T.value||void 0,to:E.value||void 0});x.value=e.items,S.value=e.meta}finally{p.value=!1}}function O(){C.value=1,D()}function k(){w.value=``,T.value=``,E.value=``,C.value=1,D()}return h(D),(t,u)=>{let h=o(`el-input`),g=o(`el-date-picker`),A=o(`el-button`),j=o(`el-table-column`),M=o(`el-table`),N=o(`el-pagination`),P=o(`el-card`),F=a(`loading`);return r(),e(`div`,_,[c(`div`,v,[n(m)]),n(P,{shadow:`never`,class:`admin-list-card`},{default:s(()=>[c(`div`,y,[n(h,{modelValue:w.value,"onUpdate:modelValue":u[0]||=e=>w.value=e,placeholder:`接口路径/操作人`,clearable:``,class:`filter-search`,onKeyup:l(O,[`enter`])},null,8,[`modelValue`]),n(g,{modelValue:T.value,"onUpdate:modelValue":u[1]||=e=>T.value=e,type:`datetime`,placeholder:`开始时间`,"value-format":`YYYY-MM-DD HH:mm:ss`,style:{width:`190px`}},null,8,[`modelValue`]),n(g,{modelValue:E.value,"onUpdate:modelValue":u[2]||=e=>E.value=e,type:`datetime`,placeholder:`结束时间`,"value-format":`YYYY-MM-DD HH:mm:ss`,style:{width:`190px`}},null,8,[`modelValue`]),n(A,{type:`primary`,onClick:O},{default:s(()=>[...u[4]||=[i(`搜索`,-1)]]),_:1}),n(A,{onClick:k},{default:s(()=>[...u[5]||=[i(`重置`,-1)]]),_:1})]),d((r(),f(M,{data:x.value,"row-key":`id`},{default:s(()=>[n(j,{prop:`operated_at`,label:`操作时间`,width:`180`}),n(j,{prop:`operator_name`,label:`操作人`,width:`120`}),n(j,{prop:`http_method`,label:`方法`,width:`80`}),n(j,{prop:`api_path`,label:`接口`,"min-width":`220`,"show-overflow-tooltip":``}),n(j,{prop:`action_label`,label:`操作项`,"min-width":`160`,"show-overflow-tooltip":``}),n(j,{prop:`ip`,label:`IP`,width:`140`}),n(j,{prop:`response_code`,label:`状态码`,width:`90`,align:`center`}),n(j,{prop:`duration_ms`,label:`耗时ms`,width:`90`,align:`center`})]),_:1},8,[`data`])),[[F,p.value]]),c(`div`,b,[n(N,{"current-page":C.value,"onUpdate:currentPage":u[3]||=e=>C.value=e,layout:`total, prev, pager, next`,total:S.value.total,"page-size":S.value.per_page,onCurrentChange:D},null,8,[`current-page`,`total`,`page-size`])])]),_:1})])}}});export{x as default};
import{C as e,D as t,E as n,G as r,T as i,X as a,Y as o,at as s,b as c,d as l,ht as u,ot as d,x as f}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{r as p}from"./index-1sotE_gT.js";import{n as m,t as h}from"./usePageLoad-CcT5DJVR.js";async function g(e){let{data:t}=await p.get(`/admin/v1/operation-logs`,{params:e});return t.data}var _={class:`list-page`},v={class:`page-header`},y={class:`list-filter-bar`},b={class:`list-pager`},x=t({__name:`index`,setup(t){let p=u(!1),x=u([]),S=u({current_page:1,per_page:20,total:0}),C=u(1),w=u(``),T=u(``),E=u(``);async function D(){p.value=!0;try{let e=await g({page:C.value,page_size:S.value.per_page,keyword:w.value||void 0,from:T.value||void 0,to:E.value||void 0});x.value=e.items,S.value=e.meta}finally{p.value=!1}}function O(){C.value=1,D()}function k(){w.value=``,T.value=``,E.value=``,C.value=1,D()}return h(D),(t,u)=>{let h=o(`el-input`),g=o(`el-date-picker`),A=o(`el-button`),j=o(`el-table-column`),M=o(`el-table`),N=o(`el-pagination`),P=o(`el-card`),F=a(`loading`);return r(),e(`div`,_,[c(`div`,v,[n(m)]),n(P,{shadow:`never`,class:`admin-list-card`},{default:s(()=>[c(`div`,y,[n(h,{modelValue:w.value,"onUpdate:modelValue":u[0]||=e=>w.value=e,placeholder:`接口路径/操作人`,clearable:``,class:`filter-search`,onKeyup:l(O,[`enter`])},null,8,[`modelValue`]),n(g,{modelValue:T.value,"onUpdate:modelValue":u[1]||=e=>T.value=e,type:`datetime`,placeholder:`开始时间`,"value-format":`YYYY-MM-DD HH:mm:ss`,style:{width:`190px`}},null,8,[`modelValue`]),n(g,{modelValue:E.value,"onUpdate:modelValue":u[2]||=e=>E.value=e,type:`datetime`,placeholder:`结束时间`,"value-format":`YYYY-MM-DD HH:mm:ss`,style:{width:`190px`}},null,8,[`modelValue`]),n(A,{type:`primary`,onClick:O},{default:s(()=>[...u[4]||=[i(`搜索`,-1)]]),_:1}),n(A,{onClick:k},{default:s(()=>[...u[5]||=[i(`重置`,-1)]]),_:1})]),d((r(),f(M,{data:x.value,"row-key":`id`},{default:s(()=>[n(j,{prop:`operated_at`,label:`操作时间`,width:`180`}),n(j,{prop:`operator_name`,label:`操作人`,width:`120`}),n(j,{prop:`http_method`,label:`方法`,width:`80`}),n(j,{prop:`api_path`,label:`接口`,"min-width":`220`,"show-overflow-tooltip":``}),n(j,{prop:`action_label`,label:`操作项`,"min-width":`160`,"show-overflow-tooltip":``}),n(j,{prop:`ip`,label:`IP`,width:`140`}),n(j,{prop:`response_code`,label:`状态码`,width:`90`,align:`center`}),n(j,{prop:`duration_ms`,label:`耗时ms`,width:`90`,align:`center`})]),_:1},8,[`data`])),[[F,p.value]]),c(`div`,b,[n(N,{"current-page":C.value,"onUpdate:currentPage":u[3]||=e=>C.value=e,layout:`total, prev, pager, next`,total:S.value.total,"page-size":S.value.per_page,onCurrentChange:D},null,8,[`current-page`,`total`,`page-size`])])]),_:1})])}}});export{x as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/courses`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/courses/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/courses`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/courses/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/courses/${t}`);return n}async function o(t){let{data:n}=await e.get(`/admin/v1/courses/${t}/checkin-days`);return n.data.items}async function s(t,n){let{data:r}=await e.get(`/admin/v1/courses/${t}/signups`,{params:n});return r.data}async function c(e,t={}){let n=1,r=[];for(;;){let i=await s(e,{...t,page:n,page_size:200});if(r.push(...i.items),n>=i.meta.last_page||i.items.length===0)break;n+=1}return r}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/courses/${t}/signups/${n}`);return r}async function u(t,n,r){let{data:i}=await e.post(`/admin/v1/courses/${t}/signups/${n}/checkin`,r);return i}export{c as a,s as c,l as i,t as l,r as n,n as o,a as r,o as s,u as t,i as u};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/courses`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/courses/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/courses`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/courses/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/courses/${t}`);return n}async function o(t){let{data:n}=await e.get(`/admin/v1/courses/${t}/checkin-days`);return n.data.items}async function s(t,n){let{data:r}=await e.get(`/admin/v1/courses/${t}/signups`,{params:n});return r.data}async function c(e,t={}){let n=1,r=[];for(;;){let i=await s(e,{...t,page:n,page_size:200});if(r.push(...i.items),n>=i.meta.last_page||i.items.length===0)break;n+=1}return r}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/courses/${t}/signups/${n}`);return r}async function u(t,n,r){let{data:i}=await e.post(`/admin/v1/courses/${t}/signups/${n}/checkin`,r);return i}export{c as a,s as c,l as i,t as l,r as n,n as o,a as r,o as s,u as t,i as u};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/crawl-addresses`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/crawl-addresses/options`,{params:t?{target_type:t}:void 0});return n.data.items}async function r(t){let{data:n}=await e.post(`/admin/v1/crawl-addresses`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/crawl-addresses/${t}`,n);return r.data}async function a(t){let{data:n}=await e.delete(`/admin/v1/crawl-addresses/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/crawl-addresses`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/crawl-addresses/options`,{params:t?{target_type:t}:void 0});return n.data.items}async function r(t){let{data:n}=await e.post(`/admin/v1/crawl-addresses`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/crawl-addresses/${t}`,n);return r.data}async function a(t){let{data:n}=await e.delete(`/admin/v1/crawl-addresses/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.filter-select[data-v-ce20f0d3]{width:180px}

@ -1 +0,0 @@
.filter-select[data-v-6e264547]{width:180px}

@ -0,0 +1 @@
.crawl-url-select[data-v-ed7f8c92]{width:100%}.crawler-form[data-v-ed7f8c92]{max-width:640px}.crawl-resolve-hint[data-v-ed7f8c92]{color:var(--el-text-color-secondary);margin:6px 0 0;font-size:12px}.result-alert[data-v-ed7f8c92]{max-width:720px;margin-top:16px}.result-alert p[data-v-ed7f8c92]{margin:4px 0}.result-actions[data-v-ed7f8c92]{flex-wrap:wrap;gap:8px;margin-top:12px;display:flex}.preview-tabs[data-v-ed7f8c92]{margin-bottom:12px}.teacher-batch-bar[data-v-ed7f8c92]{background:var(--el-fill-color-light);border-radius:4px;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px;padding:10px 12px;display:flex}.batch-hint[data-v-ed7f8c92]{color:var(--el-text-color-secondary);font-size:12px}.brief-card[data-v-ed7f8c92]{margin-top:16px}.brief-card-head[data-v-ed7f8c92]{justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:16px;display:flex}.brief-card-title[data-v-ed7f8c92]{margin:0 0 6px;font-size:16px;font-weight:600}.brief-card-desc[data-v-ed7f8c92]{color:var(--el-text-color-secondary);margin:0;font-size:13px;line-height:1.5}.brief-pager[data-v-ed7f8c92]{justify-content:flex-end;margin-top:16px;display:flex}.brief-dialog-meta[data-v-ed7f8c92]{color:var(--el-text-color-secondary);flex-wrap:wrap;gap:16px;margin-bottom:12px;font-size:13px;display:flex}.brief-markdown[data-v-ed7f8c92]{white-space:pre-wrap;word-break:break-word;background:var(--el-fill-color-light);border:1px solid var(--el-border-color-lighter);border-radius:6px;max-height:62vh;margin:0;padding:16px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:13px;line-height:1.65;overflow:auto}.brief-loading[data-v-ed7f8c92]{min-height:240px}

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
.crawl-url-select[data-v-3ba1cd9d]{width:100%}.crawler-form[data-v-3ba1cd9d]{max-width:640px}.crawl-resolve-hint[data-v-3ba1cd9d]{color:var(--el-text-color-secondary);margin:6px 0 0;font-size:12px}.result-alert[data-v-3ba1cd9d]{max-width:720px;margin-top:16px}.result-alert p[data-v-3ba1cd9d]{margin:4px 0}.result-actions[data-v-3ba1cd9d]{flex-wrap:wrap;gap:8px;margin-top:12px;display:flex}.preview-tabs[data-v-3ba1cd9d]{margin-bottom:12px}.teacher-batch-bar[data-v-3ba1cd9d]{background:var(--el-fill-color-light);border-radius:4px;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px;padding:10px 12px;display:flex}.batch-hint[data-v-3ba1cd9d]{color:var(--el-text-color-secondary);font-size:12px}.brief-card[data-v-3ba1cd9d]{margin-top:16px}.brief-card-head[data-v-3ba1cd9d]{justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:16px;display:flex}.brief-card-title[data-v-3ba1cd9d]{margin:0 0 6px;font-size:16px;font-weight:600}.brief-card-desc[data-v-3ba1cd9d]{color:var(--el-text-color-secondary);margin:0;font-size:13px;line-height:1.5}.brief-pager[data-v-3ba1cd9d]{justify-content:flex-end;margin-top:16px;display:flex}.brief-dialog-meta[data-v-3ba1cd9d]{color:var(--el-text-color-secondary);flex-wrap:wrap;gap:16px;margin-bottom:12px;font-size:13px;display:flex}.brief-markdown[data-v-3ba1cd9d]{white-space:pre-wrap;word-break:break-word;background:var(--el-fill-color-light);border:1px solid var(--el-border-color-lighter);border-radius:6px;max-height:62vh;margin:0;padding:16px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:13px;line-height:1.65;overflow:auto}.brief-loading[data-v-3ba1cd9d]{min-height:240px}

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/demands`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/demands/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/demands`,t);return n.data}async function i(t){let{data:n}=await e.delete(`/admin/v1/demands/${t}`);return n}async function a(t){let{data:n}=await e.get(`/admin/v1/demands/${t}/handle-logs`);return n.data.items}async function o(t,n){let{data:r}=await e.post(`/admin/v1/demands/${t}/handle-logs`,n);return r.data}function s(e){return e===`done`?`success`:e===`terminated`?`info`:`warning`}export{n as a,s as i,o as n,a as o,i as r,t as s,r as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/demands`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/demands/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/demands`,t);return n.data}async function i(t){let{data:n}=await e.delete(`/admin/v1/demands/${t}`);return n}async function a(t){let{data:n}=await e.get(`/admin/v1/demands/${t}/handle-logs`);return n.data.items}async function o(t,n){let{data:r}=await e.post(`/admin/v1/demands/${t}/handle-logs`,n);return r.data}function s(e){return e===`done`?`success`:e===`terminated`?`info`:`warning`}export{n as a,s as i,o as n,a as o,i as r,t as s,r as t};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/dict-by-code/${encodeURIComponent(t)}/items`);return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/dict-types`,{params:t});return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/dict-types`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/dict-types/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/dict-types/${t}`);return n}async function o(t,n){let{data:r}=await e.get(`/admin/v1/dict-types/${t}/items`,{params:n});return r.data}async function s(t,n){let{data:r}=await e.post(`/admin/v1/dict-types/${t}/items`,n);return r.data}async function c(t,n,r){let{data:i}=await e.put(`/admin/v1/dict-types/${t}/items/${n}`,r);return i}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/dict-types/${t}/items/${n}`);return r}export{t as a,c,a as i,i as l,r as n,o,l as r,n as s,s as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/dict-by-code/${encodeURIComponent(t)}/items`);return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/dict-types`,{params:t});return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/dict-types`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/dict-types/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/dict-types/${t}`);return n}async function o(t,n){let{data:r}=await e.get(`/admin/v1/dict-types/${t}/items`,{params:n});return r.data}async function s(t,n){let{data:r}=await e.post(`/admin/v1/dict-types/${t}/items`,n);return r.data}async function c(t,n,r){let{data:i}=await e.put(`/admin/v1/dict-types/${t}/items/${n}`,r);return i}async function l(t,n){let{data:r}=await e.delete(`/admin/v1/dict-types/${t}/items/${n}`);return r}export{t as a,c,a as i,i as l,r as n,o,l as r,n as s,s as t};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/grid-members`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/grid-members`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/grid-members/${t}`,n);return r}async function i(t,n){let{data:r}=await e.post(`/admin/v1/grid-members/${t}/password`,{password:n});return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/grid-members/${t}`);return n}export{r as a,i,a as n,t as r,n as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/grid-members`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/grid-members`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/grid-members/${t}`,n);return r}async function i(t,n){let{data:r}=await e.post(`/admin/v1/grid-members/${t}/password`,{password:n});return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/grid-members/${t}`);return n}export{r as a,i,a as n,t as r,n as t};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{C as e,D as t,E as n,G as r,T as i,Y as a,at as o,b as s,f as c,ht as l}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as u,l as d,o as f,s as p,t as m}from"./index-BXVUywjg.js";var h={class:`login-split`},g={class:`login-main`},_={class:`login-container`},v={class:`login-panel-wrap`},y={class:`login-panel-card`},b=p(t({__name:`index`,setup(t){let p=f(),b=u(),x=m(),S=l(!1),C=l(!0),w=l({username:``,password:``});function T(){C.value=!1}async function E(){if(!w.value.username||!w.value.password){d.warning(`请输入账号和密码`);return}S.value=!0;try{await x.login(w.value.username,w.value.password);let e=b.query.redirect||`/dashboard`;await p.replace(e)}catch(e){let t=e?.response?.data?.message||`登录失败`;d.error(typeof t==`string`?t:`登录失败`)}finally{S.value=!1}}return(t,l)=>{let u=a(`el-input`),d=a(`el-form-item`),f=a(`el-button`),p=a(`el-form`);return r(),e(`div`,h,[s(`main`,g,[s(`div`,_,[l[4]||=s(`div`,{class:`login-hero`},[s(`h1`,{class:`login-hero-title`},`S-lake先进技术发展中心高校雷达网`),s(`p`,{class:`login-hero-desc`},`加强长三角高校顶尖科研人才的发现、跟踪与服务`)],-1),s(`div`,v,[s(`div`,y,[l[3]||=s(`h2`,{class:`login-panel-title`},`欢迎登录`,-1),n(p,{class:`login-form`,"label-position":`top`,size:`large`,autocomplete:`off`,onSubmit:c(E,[`prevent`])},{default:o(()=>[n(d,{label:`账号`},{default:o(()=>[n(u,{modelValue:w.value.username,"onUpdate:modelValue":l[0]||=e=>w.value.username=e,placeholder:`请输入账号`,autocomplete:`off`,name:`login-account`,readonly:C.value,onFocus:T},null,8,[`modelValue`,`readonly`])]),_:1}),n(d,{label:`密码`},{default:o(()=>[n(u,{modelValue:w.value.password,"onUpdate:modelValue":l[1]||=e=>w.value.password=e,type:`password`,placeholder:`请输入密码`,"show-password":``,autocomplete:`new-password`,name:`login-password`,readonly:C.value,onFocus:T},null,8,[`modelValue`,`readonly`])]),_:1}),n(d,null,{default:o(()=>[n(f,{type:`primary`,class:`login-btn`,loading:S.value,"native-type":`submit`,onClick:E},{default:o(()=>[...l[2]||=[i(` 登录 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])])])])])}}}),[[`__scopeId`,`data-v-bc69620b`]]);export{b as default};
import{C as e,D as t,E as n,G as r,T as i,Y as a,at as o,b as s,f as c,ht as l}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as u,l as d,o as f,s as p,t as m}from"./index-1sotE_gT.js";var h={class:`login-split`},g={class:`login-main`},_={class:`login-container`},v={class:`login-panel-wrap`},y={class:`login-panel-card`},b=p(t({__name:`index`,setup(t){let p=f(),b=u(),x=m(),S=l(!1),C=l(!0),w=l({username:``,password:``});function T(){C.value=!1}async function E(){if(!w.value.username||!w.value.password){d.warning(`请输入账号和密码`);return}S.value=!0;try{await x.login(w.value.username,w.value.password);let e=b.query.redirect||`/dashboard`;await p.replace(e)}catch(e){let t=e?.response?.data?.message||`登录失败`;d.error(typeof t==`string`?t:`登录失败`)}finally{S.value=!1}}return(t,l)=>{let u=a(`el-input`),d=a(`el-form-item`),f=a(`el-button`),p=a(`el-form`);return r(),e(`div`,h,[s(`main`,g,[s(`div`,_,[l[4]||=s(`div`,{class:`login-hero`},[s(`h1`,{class:`login-hero-title`},`S-lake先进技术发展中心高校雷达网`),s(`p`,{class:`login-hero-desc`},`加强长三角高校顶尖科研人才的发现、跟踪与服务`)],-1),s(`div`,v,[s(`div`,y,[l[3]||=s(`h2`,{class:`login-panel-title`},`欢迎登录`,-1),n(p,{class:`login-form`,"label-position":`top`,size:`large`,autocomplete:`off`,onSubmit:c(E,[`prevent`])},{default:o(()=>[n(d,{label:`账号`},{default:o(()=>[n(u,{modelValue:w.value.username,"onUpdate:modelValue":l[0]||=e=>w.value.username=e,placeholder:`请输入账号`,autocomplete:`off`,name:`login-account`,readonly:C.value,onFocus:T},null,8,[`modelValue`,`readonly`])]),_:1}),n(d,{label:`密码`},{default:o(()=>[n(u,{modelValue:w.value.password,"onUpdate:modelValue":l[1]||=e=>w.value.password=e,type:`password`,placeholder:`请输入密码`,"show-password":``,autocomplete:`new-password`,name:`login-password`,readonly:C.value,onFocus:T},null,8,[`modelValue`,`readonly`])]),_:1}),n(d,null,{default:o(()=>[n(f,{type:`primary`,class:`login-btn`,loading:S.value,"native-type":`submit`,onClick:E},{default:o(()=>[...l[2]||=[i(` 登录 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])])])])])}}}),[[`__scopeId`,`data-v-bc69620b`]]);export{b as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(){let{data:t}=await e.get(`/admin/v1/menus`);return t.data}async function n(t){let{data:n}=await e.post(`/admin/v1/menus`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/menus/${t}`,n);return r}async function i(t){let{data:n}=await e.delete(`/admin/v1/menus/${t}`);return n}export{r as i,i as n,t as r,n as t};
import{r as e}from"./index-1sotE_gT.js";async function t(){let{data:t}=await e.get(`/admin/v1/menus`);return t.data}async function n(t){let{data:n}=await e.post(`/admin/v1/menus`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/menus/${t}`,n);return r}async function i(t){let{data:n}=await e.delete(`/admin/v1/menus/${t}`);return n}export{r as i,i as n,t as r,n as t};

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/news`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/news/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/news`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/news/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/news/${t}`);return n}async function o(t,n){let{data:r}=await e.post(`/admin/v1/news/batch-publish`,{ids:t,published_at:n});return r.data}export{t as a,n as i,r as n,i as o,a as r,o as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/news`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/news/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/news`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/news/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/news/${t}`);return n}async function o(t,n){let{data:r}=await e.post(`/admin/v1/news/batch-publish`,{ids:t,published_at:n});return r.data}export{t as a,n as i,r as n,i as o,a as r,o as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/research-directions`,{params:t});return n.data}async function n(){let{data:t}=await e.get(`/admin/v1/research-directions/options`);return t.data.items}async function r(t){let{data:n}=await e.post(`/admin/v1/research-directions`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/research-directions/${t}`,n);return r.data}async function a(t){let{data:n}=await e.delete(`/admin/v1/research-directions/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/research-directions`,{params:t});return n.data}async function n(){let{data:t}=await e.get(`/admin/v1/research-directions/options`);return t.data.items}async function r(t){let{data:n}=await e.post(`/admin/v1/research-directions`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/research-directions/${t}`,n);return r.data}async function a(t){let{data:n}=await e.delete(`/admin/v1/research-directions/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};

@ -1 +1 @@
import{C as e,Ct as t,D as n,E as r,G as i,T as a,X as o,Xt as s,Y as c,at as l,b as u,d,ht as f,m as p,ot as m,tn as h,x as g}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{c as _,l as v}from"./index-BXVUywjg.js";import{n as y,t as b}from"./usePageLoad-I-Vfu6XZ.js";import{r as x}from"./admin-list-DjncsyJC.js";import{a as S,i as C,n as w,t as T}from"./research-directions-B33gDOhB.js";var E={class:`list-page`},D={class:`page-header`},O={class:`list-filter-bar`},k={class:`table-row-actions`},A={class:`list-pager`},j=n({__name:`index`,setup(n){let j=f(!1),M=f([]),N=f({current_page:1,per_page:20,total:0}),P=f(``),F=f(1),I=f(!1),L=f(null),R=f({name:``,sort:0,status:1,remark:``});async function z(){j.value=!0;try{let e=await C({page:F.value,page_size:N.value.per_page,keyword:P.value||void 0});M.value=e.items,N.value=e.meta}finally{j.value=!1}}function B(){L.value=null,R.value={name:``,sort:0,status:1,remark:``},I.value=!0}function V(e){L.value=e,R.value={name:e.name,sort:e.sort,status:e.status,remark:e.remark||``},I.value=!0}async function H(){if(!R.value.name.trim()){v.warning(`请填写研究方向名称`);return}let e={name:R.value.name.trim(),sort:R.value.sort,status:R.value.status,remark:R.value.remark||null};L.value?await S(L.value.id,e):await T(e),v.success(`已保存`),I.value=!1,await z()}async function U(e){await _.confirm(`确定删除研究方向「${e.name}」?`,`提示`,{type:`warning`}),await w(e.id),v.success(`已删除`),await z()}function W(){F.value=1,z()}function G(){P.value=``,F.value=1,z()}return b(z),(n,f)=>{let _=c(`el-button`),v=c(`el-input`),b=c(`el-table-column`),S=c(`el-table`),C=c(`el-pagination`),w=c(`el-card`),T=c(`el-form-item`),K=c(`el-input-number`),q=c(`el-switch`),J=c(`el-form`),Y=c(`el-dialog`),X=o(`loading`);return i(),e(p,null,[u(`div`,E,[u(`div`,D,[r(y),r(_,{type:`primary`,size:`small`,class:`btn-create`,onClick:B},{default:l(()=>[...f[8]||=[a(`新增`,-1)]]),_:1})]),r(w,{shadow:`never`,class:`admin-list-card`},{default:l(()=>[u(`div`,O,[r(v,{modelValue:P.value,"onUpdate:modelValue":f[0]||=e=>P.value=e,placeholder:`研究方向名称`,clearable:``,class:`filter-search`,onKeyup:d(W,[`enter`])},null,8,[`modelValue`]),r(_,{type:`primary`,onClick:W},{default:l(()=>[...f[9]||=[a(`搜索`,-1)]]),_:1}),r(_,{onClick:G},{default:l(()=>[...f[10]||=[a(`重置`,-1)]]),_:1})]),m((i(),g(S,{data:M.value,"row-key":`id`},{default:l(()=>[r(b,{prop:`name`,label:`名称`,"min-width":`180`}),r(b,{prop:`sort`,label:`排序`,width:`80`,align:`center`}),r(b,{prop:`teacher_count`,label:`关联老师数`,width:`110`,align:`center`}),r(b,{label:`状态`,width:`90`,align:`center`},{default:l(({row:e})=>[u(`span`,{class:s([`status-badge`,t(x)(e.status)])},h(e.status===1?`启用`:`停用`),3)]),_:1}),r(b,{prop:`remark`,label:`备注`,"min-width":`160`,"show-overflow-tooltip":``}),r(b,{label:`操作`,width:`160`,fixed:`right`},{default:l(({row:e})=>[u(`div`,k,[r(_,{class:`btn-action-primary`,onClick:t=>V(e)},{default:l(()=>[...f[11]||=[a(`编辑`,-1)]]),_:1},8,[`onClick`]),r(_,{class:`btn-action-brand`,onClick:t=>U(e)},{default:l(()=>[...f[12]||=[a(`删除`,-1)]]),_:1},8,[`onClick`])])]),_:1})]),_:1},8,[`data`])),[[X,j.value]]),u(`div`,A,[r(C,{"current-page":F.value,"onUpdate:currentPage":f[1]||=e=>F.value=e,layout:`total, prev, pager, next`,total:N.value.total,"page-size":N.value.per_page,onCurrentChange:z},null,8,[`current-page`,`total`,`page-size`])])]),_:1})]),r(Y,{modelValue:I.value,"onUpdate:modelValue":f[7]||=e=>I.value=e,title:L.value?`编辑研究方向`:`新增研究方向`,width:`480px`},{footer:l(()=>[r(_,{onClick:f[6]||=e=>I.value=!1},{default:l(()=>[...f[13]||=[a(`取消`,-1)]]),_:1}),r(_,{type:`primary`,onClick:H},{default:l(()=>[...f[14]||=[a(`保存`,-1)]]),_:1})]),default:l(()=>[r(J,{"label-width":`88px`},{default:l(()=>[r(T,{label:`名称`},{default:l(()=>[r(v,{modelValue:R.value.name,"onUpdate:modelValue":f[2]||=e=>R.value.name=e,maxlength:`255`},null,8,[`modelValue`])]),_:1}),r(T,{label:`排序`},{default:l(()=>[r(K,{modelValue:R.value.sort,"onUpdate:modelValue":f[3]||=e=>R.value.sort=e,min:0},null,8,[`modelValue`])]),_:1}),r(T,{label:`状态`},{default:l(()=>[r(q,{modelValue:R.value.status,"onUpdate:modelValue":f[4]||=e=>R.value.status=e,"active-value":1,"inactive-value":0},null,8,[`modelValue`])]),_:1}),r(T,{label:`备注`},{default:l(()=>[r(v,{modelValue:R.value.remark,"onUpdate:modelValue":f[5]||=e=>R.value.remark=e,type:`textarea`,rows:3},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`,`title`])],64)}}});export{j as default};
import{C as e,Ct as t,D as n,E as r,G as i,T as a,X as o,Xt as s,Y as c,at as l,b as u,d,ht as f,m as p,ot as m,tn as h,x as g}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{c as _,l as v}from"./index-1sotE_gT.js";import{n as y,t as b}from"./usePageLoad-CcT5DJVR.js";import{r as x}from"./admin-list-DjncsyJC.js";import{a as S,i as C,n as w,t as T}from"./research-directions-21NC92he.js";var E={class:`list-page`},D={class:`page-header`},O={class:`list-filter-bar`},k={class:`table-row-actions`},A={class:`list-pager`},j=n({__name:`index`,setup(n){let j=f(!1),M=f([]),N=f({current_page:1,per_page:20,total:0}),P=f(``),F=f(1),I=f(!1),L=f(null),R=f({name:``,sort:0,status:1,remark:``});async function z(){j.value=!0;try{let e=await C({page:F.value,page_size:N.value.per_page,keyword:P.value||void 0});M.value=e.items,N.value=e.meta}finally{j.value=!1}}function B(){L.value=null,R.value={name:``,sort:0,status:1,remark:``},I.value=!0}function V(e){L.value=e,R.value={name:e.name,sort:e.sort,status:e.status,remark:e.remark||``},I.value=!0}async function H(){if(!R.value.name.trim()){v.warning(`请填写研究方向名称`);return}let e={name:R.value.name.trim(),sort:R.value.sort,status:R.value.status,remark:R.value.remark||null};L.value?await S(L.value.id,e):await T(e),v.success(`已保存`),I.value=!1,await z()}async function U(e){await _.confirm(`确定删除研究方向「${e.name}」?`,`提示`,{type:`warning`}),await w(e.id),v.success(`已删除`),await z()}function W(){F.value=1,z()}function G(){P.value=``,F.value=1,z()}return b(z),(n,f)=>{let _=c(`el-button`),v=c(`el-input`),b=c(`el-table-column`),S=c(`el-table`),C=c(`el-pagination`),w=c(`el-card`),T=c(`el-form-item`),K=c(`el-input-number`),q=c(`el-switch`),J=c(`el-form`),Y=c(`el-dialog`),X=o(`loading`);return i(),e(p,null,[u(`div`,E,[u(`div`,D,[r(y),r(_,{type:`primary`,size:`small`,class:`btn-create`,onClick:B},{default:l(()=>[...f[8]||=[a(`新增`,-1)]]),_:1})]),r(w,{shadow:`never`,class:`admin-list-card`},{default:l(()=>[u(`div`,O,[r(v,{modelValue:P.value,"onUpdate:modelValue":f[0]||=e=>P.value=e,placeholder:`研究方向名称`,clearable:``,class:`filter-search`,onKeyup:d(W,[`enter`])},null,8,[`modelValue`]),r(_,{type:`primary`,onClick:W},{default:l(()=>[...f[9]||=[a(`搜索`,-1)]]),_:1}),r(_,{onClick:G},{default:l(()=>[...f[10]||=[a(`重置`,-1)]]),_:1})]),m((i(),g(S,{data:M.value,"row-key":`id`},{default:l(()=>[r(b,{prop:`name`,label:`名称`,"min-width":`180`}),r(b,{prop:`sort`,label:`排序`,width:`80`,align:`center`}),r(b,{prop:`teacher_count`,label:`关联老师数`,width:`110`,align:`center`}),r(b,{label:`状态`,width:`90`,align:`center`},{default:l(({row:e})=>[u(`span`,{class:s([`status-badge`,t(x)(e.status)])},h(e.status===1?`启用`:`停用`),3)]),_:1}),r(b,{prop:`remark`,label:`备注`,"min-width":`160`,"show-overflow-tooltip":``}),r(b,{label:`操作`,width:`160`,fixed:`right`},{default:l(({row:e})=>[u(`div`,k,[r(_,{class:`btn-action-primary`,onClick:t=>V(e)},{default:l(()=>[...f[11]||=[a(`编辑`,-1)]]),_:1},8,[`onClick`]),r(_,{class:`btn-action-brand`,onClick:t=>U(e)},{default:l(()=>[...f[12]||=[a(`删除`,-1)]]),_:1},8,[`onClick`])])]),_:1})]),_:1},8,[`data`])),[[X,j.value]]),u(`div`,A,[r(C,{"current-page":F.value,"onUpdate:currentPage":f[1]||=e=>F.value=e,layout:`total, prev, pager, next`,total:N.value.total,"page-size":N.value.per_page,onCurrentChange:z},null,8,[`current-page`,`total`,`page-size`])])]),_:1})]),r(Y,{modelValue:I.value,"onUpdate:modelValue":f[7]||=e=>I.value=e,title:L.value?`编辑研究方向`:`新增研究方向`,width:`480px`},{footer:l(()=>[r(_,{onClick:f[6]||=e=>I.value=!1},{default:l(()=>[...f[13]||=[a(`取消`,-1)]]),_:1}),r(_,{type:`primary`,onClick:H},{default:l(()=>[...f[14]||=[a(`保存`,-1)]]),_:1})]),default:l(()=>[r(J,{"label-width":`88px`},{default:l(()=>[r(T,{label:`名称`},{default:l(()=>[r(v,{modelValue:R.value.name,"onUpdate:modelValue":f[2]||=e=>R.value.name=e,maxlength:`255`},null,8,[`modelValue`])]),_:1}),r(T,{label:`排序`},{default:l(()=>[r(K,{modelValue:R.value.sort,"onUpdate:modelValue":f[3]||=e=>R.value.sort=e,min:0},null,8,[`modelValue`])]),_:1}),r(T,{label:`状态`},{default:l(()=>[r(q,{modelValue:R.value.status,"onUpdate:modelValue":f[4]||=e=>R.value.status=e,"active-value":1,"inactive-value":0},null,8,[`modelValue`])]),_:1}),r(T,{label:`备注`},{default:l(()=>[r(v,{modelValue:R.value.remark,"onUpdate:modelValue":f[5]||=e=>R.value.remark=e,type:`textarea`,rows:3},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`,`title`])],64)}}});export{j as default};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/roles`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/roles/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/roles`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/roles/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/roles/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/roles`,{params:t});return n.data}async function n(t){let{data:n}=await e.get(`/admin/v1/roles/${t}`);return n.data}async function r(t){let{data:n}=await e.post(`/admin/v1/roles`,t);return n.data}async function i(t,n){let{data:r}=await e.put(`/admin/v1/roles/${t}`,n);return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/roles/${t}`);return n}export{i as a,t as i,a as n,n as r,r as t};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(){let{data:t}=await e.get(`/admin/v1/teachers/filter-options`);return t.data}async function n(){let{data:t}=await e.get(`/admin/v1/teachers/stats`);return t.data}async function r(t){let{data:n}=await e.get(`/admin/v1/teachers`,{params:t});return n.data}async function i(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}`);return n.data}async function a(t){let{data:n}=await e.post(`/admin/v1/teachers`,t);return n.data}async function o(t,n){let{data:r}=await e.put(`/admin/v1/teachers/${t}`,n);return r}async function s(t){let{data:n}=await e.patch(`/admin/v1/teachers/batch-star`,t);return n.data}async function c(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}/follow-records`);return n.data.items}async function l(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/follow-records`,n);return r.data}async function u(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}/papers`);return n.data.items}async function d(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/papers`,n);return r.data}async function f(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/papers/link`,{paper_id:n});return r}async function p(t,n){let{data:r}=await e.delete(`/admin/v1/teachers/${t}/papers/${n}`);return r}async function m(t){let{data:n}=await e.get(`/admin/v1/universities`,{params:t});return n.data}async function h(t){let{data:n}=await e.post(`/admin/v1/universities`,t);return n.data}export{h as a,t as c,n as d,r as f,o as h,d as i,c as l,f as m,a as n,p as o,m as p,l as r,i as s,s as t,u};
import{r as e}from"./index-1sotE_gT.js";async function t(){let{data:t}=await e.get(`/admin/v1/teachers/filter-options`);return t.data}async function n(){let{data:t}=await e.get(`/admin/v1/teachers/stats`);return t.data}async function r(t){let{data:n}=await e.get(`/admin/v1/teachers`,{params:t});return n.data}async function i(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}`);return n.data}async function a(t){let{data:n}=await e.post(`/admin/v1/teachers`,t);return n.data}async function o(t,n){let{data:r}=await e.put(`/admin/v1/teachers/${t}`,n);return r}async function s(t){let{data:n}=await e.patch(`/admin/v1/teachers/batch-star`,t);return n.data}async function c(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}/follow-records`);return n.data.items}async function l(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/follow-records`,n);return r.data}async function u(t){let{data:n}=await e.get(`/admin/v1/teachers/${t}/papers`);return n.data.items}async function d(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/papers`,n);return r.data}async function f(t,n){let{data:r}=await e.post(`/admin/v1/teachers/${t}/papers/link`,{paper_id:n});return r}async function p(t,n){let{data:r}=await e.delete(`/admin/v1/teachers/${t}/papers/${n}`);return r}async function m(t){let{data:n}=await e.get(`/admin/v1/universities`,{params:t});return n.data}async function h(t){let{data:n}=await e.post(`/admin/v1/universities`,t);return n.data}export{h as a,t as c,n as d,r as f,o as h,d as i,c as l,f as m,a as n,p as o,m as p,l as r,i as s,s as t,u};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{C as e,D as t,G as n,H as r,L as i,Xt as a,tn as o,y as s}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as c}from"./index-BXVUywjg.js";var l=t({__name:`PageTitle`,props:{variant:{default:`default`}},setup(t){let r=t,i=c(),l=s(()=>String(i.meta.title||``)),u=s(()=>r.variant===`dashboard`?`dashboard-page-title`:r.variant===`radar`?`radar-page-title`:`page-title`);return(t,r)=>(n(),e(`h1`,{class:a(u.value)},o(l.value),3))}});function u(e){let t=()=>{Promise.resolve(e())};r(t),i(t)}export{l as n,u as t};
import{C as e,D as t,G as n,H as r,L as i,Xt as a,tn as o,y as s}from"./vue.runtime.esm-bundler-DUiYyeqQ.js";import{a as c}from"./index-1sotE_gT.js";var l=t({__name:`PageTitle`,props:{variant:{default:`default`}},setup(t){let r=t,i=c(),l=s(()=>String(i.meta.title||``)),u=s(()=>r.variant===`dashboard`?`dashboard-page-title`:r.variant===`radar`?`radar-page-title`:`page-title`);return(t,r)=>(n(),e(`h1`,{class:a(u.value)},o(l.value),3))}});function u(e){let t=()=>{Promise.resolve(e())};r(t),i(t)}export{l as n,u as t};

@ -1 +1 @@
import{r as e}from"./index-BXVUywjg.js";async function t(t){let{data:n}=await e.get(`/admin/v1/admin-users`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/admin-users`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/admin-users/${t}`,n);return r}async function i(t,n){let{data:r}=await e.post(`/admin/v1/admin-users/${t}/password`,{password:n});return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/admin-users/${t}`);return n}export{r as a,i,a as n,t as r,n as t};
import{r as e}from"./index-1sotE_gT.js";async function t(t){let{data:n}=await e.get(`/admin/v1/admin-users`,{params:t});return n.data}async function n(t){let{data:n}=await e.post(`/admin/v1/admin-users`,t);return n.data}async function r(t,n){let{data:r}=await e.put(`/admin/v1/admin-users/${t}`,n);return r}async function i(t,n){let{data:r}=await e.post(`/admin/v1/admin-users/${t}/password`,{password:n});return r}async function a(t){let{data:n}=await e.delete(`/admin/v1/admin-users/${t}`);return n}export{r as a,i,a as n,t as r,n as t};

File diff suppressed because one or more lines are too long

@ -11,7 +11,7 @@
rel="stylesheet"
/>
<title>S-lake高校雷达网</title>
<script type="module" crossorigin src="/admin/assets/index-BXVUywjg.js"></script>
<script type="module" crossorigin src="/admin/assets/index-1sotE_gT.js"></script>
<link rel="modulepreload" crossorigin href="/admin/assets/rolldown-runtime-BYbx6iT9.js">
<link rel="modulepreload" crossorigin href="/admin/assets/vue.runtime.esm-bundler-DUiYyeqQ.js">
<link rel="stylesheet" crossorigin href="/admin/assets/index-BoedZQk5.css">

Loading…
Cancel
Save