Compare commits
14 Commits
1.0
...
41795c7c77
| Author | SHA1 | Date | |
|---|---|---|---|
| 41795c7c77 | |||
| 1f243f977a | |||
| ed4780d6c2 | |||
| 5b3b55cf10 | |||
| c37cbe0054 | |||
| 80ddcc96d3 | |||
| 0304804057 | |||
| 9570745a94 | |||
| 241807325b | |||
| 7d62f3a9ed | |||
| 3b468e3177 | |||
| f6849b33c3 | |||
| 1335959881 | |||
| a5db05fba6 |
32
.gitignore
vendored
32
.gitignore
vendored
@@ -5,4 +5,34 @@ build_output
|
||||
docker/schoolNews/volumes/
|
||||
docker/schoolNews/crawler
|
||||
docker.zip
|
||||
docker/dify/volumes
|
||||
# docker/dify/volumes
|
||||
docker/dify/volumes/app/storage/*
|
||||
docker/dify/volumes/certbot/*
|
||||
docker/dify/volumes/db/data/*
|
||||
docker/dify/volumes/redis/data/*
|
||||
docker/dify/volumes/weaviate/*
|
||||
docker/dify/volumes/qdrant/*
|
||||
docker/dify/tidb/volumes/*
|
||||
docker/dify/volumes/etcd/*
|
||||
docker/dify/volumes/minio/*
|
||||
docker/dify/volumes/milvus/*
|
||||
docker/dify/volumes/chroma/*
|
||||
docker/dify/volumes/opensearch/data/*
|
||||
docker/dify/volumes/myscale/data/*
|
||||
docker/dify/volumes/myscale/log/*
|
||||
docker/dify/volumes/unstructured/*
|
||||
docker/dify/volumes/pgvector/data/*
|
||||
docker/dify/volumes/pgvecto_rs/data/*
|
||||
docker/dify/volumes/couchbase/*
|
||||
docker/dify/volumes/oceanbase/*
|
||||
docker/dify/volumes/plugin_daemon/*
|
||||
docker/dify/volumes/matrixone/*
|
||||
docker/dify/volumes/mysql/*
|
||||
docker/dify/volumes/seekdb/*
|
||||
!docker/dify/volumes/oceanbase/init.d
|
||||
|
||||
docker/dify/nginx/conf.d/default.conf
|
||||
docker/dify/nginx/ssl/*
|
||||
!docker/dify/nginx/ssl/.gitkeep
|
||||
docker/dify/middleware.env
|
||||
docker/dify/docker-compose.override.yaml
|
||||
@@ -1502,7 +1502,7 @@ networks:
|
||||
# create a network between sandbox, api and ssrf_proxy, and can not access outside.
|
||||
ssrf_proxy_network:
|
||||
driver: bridge
|
||||
internal: true # 修改为false以允许访问外部网络(如192.168.0.64)
|
||||
internal: true
|
||||
milvus:
|
||||
driver: bridge
|
||||
opensearch-net:
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
# Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration.
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
location /console/api {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /v1 {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /files {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /explore {
|
||||
proxy_pass http://web:3000;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /e/ {
|
||||
proxy_pass http://plugin_daemon:5002;
|
||||
proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://web:3000;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /mcp {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /triggers {
|
||||
proxy_pass http://api:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
# placeholder for acme challenge location
|
||||
|
||||
|
||||
# placeholder for https config defined in https.conf.template
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<clickhouse>
|
||||
<users>
|
||||
<default>
|
||||
<password></password>
|
||||
<networks>
|
||||
<ip>::1</ip> <!-- change to ::/0 to allow access from all addresses -->
|
||||
<ip>127.0.0.1</ip>
|
||||
<ip>10.0.0.0/8</ip>
|
||||
<ip>172.16.0.0/12</ip>
|
||||
<ip>192.168.0.0/16</ip>
|
||||
</networks>
|
||||
<profile>default</profile>
|
||||
<quota>default</quota>
|
||||
<access_management>1</access_management>
|
||||
</default>
|
||||
</users>
|
||||
</clickhouse>
|
||||
1
docker/dify/volumes/oceanbase/init.d/vec_memory.sql
Normal file
1
docker/dify/volumes/oceanbase/init.d/vec_memory.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
|
||||
222
docker/dify/volumes/opensearch/opensearch_dashboards.yml
Normal file
222
docker/dify/volumes/opensearch/opensearch_dashboards.yml
Normal file
@@ -0,0 +1,222 @@
|
||||
---
|
||||
# Copyright OpenSearch Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Description:
|
||||
# Default configuration for OpenSearch Dashboards
|
||||
|
||||
# OpenSearch Dashboards is served by a back end server. This setting specifies the port to use.
|
||||
# server.port: 5601
|
||||
|
||||
# Specifies the address to which the OpenSearch Dashboards server will bind. IP addresses and host names are both valid values.
|
||||
# The default is 'localhost', which usually means remote machines will not be able to connect.
|
||||
# To allow connections from remote users, set this parameter to a non-loopback address.
|
||||
# server.host: "localhost"
|
||||
|
||||
# Enables you to specify a path to mount OpenSearch Dashboards at if you are running behind a proxy.
|
||||
# Use the `server.rewriteBasePath` setting to tell OpenSearch Dashboards if it should remove the basePath
|
||||
# from requests it receives, and to prevent a deprecation warning at startup.
|
||||
# This setting cannot end in a slash.
|
||||
# server.basePath: ""
|
||||
|
||||
# Specifies whether OpenSearch Dashboards should rewrite requests that are prefixed with
|
||||
# `server.basePath` or require that they are rewritten by your reverse proxy.
|
||||
# server.rewriteBasePath: false
|
||||
|
||||
# The maximum payload size in bytes for incoming server requests.
|
||||
# server.maxPayloadBytes: 1048576
|
||||
|
||||
# The OpenSearch Dashboards server's name. This is used for display purposes.
|
||||
# server.name: "your-hostname"
|
||||
|
||||
# The URLs of the OpenSearch instances to use for all your queries.
|
||||
# opensearch.hosts: ["http://localhost:9200"]
|
||||
|
||||
# OpenSearch Dashboards uses an index in OpenSearch to store saved searches, visualizations and
|
||||
# dashboards. OpenSearch Dashboards creates a new index if the index doesn't already exist.
|
||||
# opensearchDashboards.index: ".opensearch_dashboards"
|
||||
|
||||
# The default application to load.
|
||||
# opensearchDashboards.defaultAppId: "home"
|
||||
|
||||
# Setting for an optimized healthcheck that only uses the local OpenSearch node to do Dashboards healthcheck.
|
||||
# This settings should be used for large clusters or for clusters with ingest heavy nodes.
|
||||
# It allows Dashboards to only healthcheck using the local OpenSearch node rather than fan out requests across all nodes.
|
||||
#
|
||||
# It requires the user to create an OpenSearch node attribute with the same name as the value used in the setting
|
||||
# This node attribute should assign all nodes of the same cluster an integer value that increments with each new cluster that is spun up
|
||||
# e.g. in opensearch.yml file you would set the value to a setting using node.attr.cluster_id:
|
||||
# Should only be enabled if there is a corresponding node attribute created in your OpenSearch config that matches the value here
|
||||
# opensearch.optimizedHealthcheckId: "cluster_id"
|
||||
|
||||
# If your OpenSearch is protected with basic authentication, these settings provide
|
||||
# the username and password that the OpenSearch Dashboards server uses to perform maintenance on the OpenSearch Dashboards
|
||||
# index at startup. Your OpenSearch Dashboards users still need to authenticate with OpenSearch, which
|
||||
# is proxied through the OpenSearch Dashboards server.
|
||||
# opensearch.username: "opensearch_dashboards_system"
|
||||
# opensearch.password: "pass"
|
||||
|
||||
# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.
|
||||
# These settings enable SSL for outgoing requests from the OpenSearch Dashboards server to the browser.
|
||||
# server.ssl.enabled: false
|
||||
# server.ssl.certificate: /path/to/your/server.crt
|
||||
# server.ssl.key: /path/to/your/server.key
|
||||
|
||||
# Optional settings that provide the paths to the PEM-format SSL certificate and key files.
|
||||
# These files are used to verify the identity of OpenSearch Dashboards to OpenSearch and are required when
|
||||
# xpack.security.http.ssl.client_authentication in OpenSearch is set to required.
|
||||
# opensearch.ssl.certificate: /path/to/your/client.crt
|
||||
# opensearch.ssl.key: /path/to/your/client.key
|
||||
|
||||
# Optional setting that enables you to specify a path to the PEM file for the certificate
|
||||
# authority for your OpenSearch instance.
|
||||
# opensearch.ssl.certificateAuthorities: [ "/path/to/your/CA.pem" ]
|
||||
|
||||
# To disregard the validity of SSL certificates, change this setting's value to 'none'.
|
||||
# opensearch.ssl.verificationMode: full
|
||||
|
||||
# Time in milliseconds to wait for OpenSearch to respond to pings. Defaults to the value of
|
||||
# the opensearch.requestTimeout setting.
|
||||
# opensearch.pingTimeout: 1500
|
||||
|
||||
# Time in milliseconds to wait for responses from the back end or OpenSearch. This value
|
||||
# must be a positive integer.
|
||||
# opensearch.requestTimeout: 30000
|
||||
|
||||
# List of OpenSearch Dashboards client-side headers to send to OpenSearch. To send *no* client-side
|
||||
# headers, set this value to [] (an empty list).
|
||||
# opensearch.requestHeadersWhitelist: [ authorization ]
|
||||
|
||||
# Header names and values that are sent to OpenSearch. Any custom headers cannot be overwritten
|
||||
# by client-side headers, regardless of the opensearch.requestHeadersWhitelist configuration.
|
||||
# opensearch.customHeaders: {}
|
||||
|
||||
# Time in milliseconds for OpenSearch to wait for responses from shards. Set to 0 to disable.
|
||||
# opensearch.shardTimeout: 30000
|
||||
|
||||
# Logs queries sent to OpenSearch. Requires logging.verbose set to true.
|
||||
# opensearch.logQueries: false
|
||||
|
||||
# Specifies the path where OpenSearch Dashboards creates the process ID file.
|
||||
# pid.file: /var/run/opensearchDashboards.pid
|
||||
|
||||
# Enables you to specify a file where OpenSearch Dashboards stores log output.
|
||||
# logging.dest: stdout
|
||||
|
||||
# Set the value of this setting to true to suppress all logging output.
|
||||
# logging.silent: false
|
||||
|
||||
# Set the value of this setting to true to suppress all logging output other than error messages.
|
||||
# logging.quiet: false
|
||||
|
||||
# Set the value of this setting to true to log all events, including system usage information
|
||||
# and all requests.
|
||||
# logging.verbose: false
|
||||
|
||||
# Set the interval in milliseconds to sample system and process performance
|
||||
# metrics. Minimum is 100ms. Defaults to 5000.
|
||||
# ops.interval: 5000
|
||||
|
||||
# Specifies locale to be used for all localizable strings, dates and number formats.
|
||||
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
|
||||
# i18n.locale: "en"
|
||||
|
||||
# Set the allowlist to check input graphite Url. Allowlist is the default check list.
|
||||
# vis_type_timeline.graphiteAllowedUrls: ['https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite']
|
||||
|
||||
# Set the blocklist to check input graphite Url. Blocklist is an IP list.
|
||||
# Below is an example for reference
|
||||
# vis_type_timeline.graphiteBlockedIPs: [
|
||||
# //Loopback
|
||||
# '127.0.0.0/8',
|
||||
# '::1/128',
|
||||
# //Link-local Address for IPv6
|
||||
# 'fe80::/10',
|
||||
# //Private IP address for IPv4
|
||||
# '10.0.0.0/8',
|
||||
# '172.16.0.0/12',
|
||||
# '192.168.0.0/16',
|
||||
# //Unique local address (ULA)
|
||||
# 'fc00::/7',
|
||||
# //Reserved IP address
|
||||
# '0.0.0.0/8',
|
||||
# '100.64.0.0/10',
|
||||
# '192.0.0.0/24',
|
||||
# '192.0.2.0/24',
|
||||
# '198.18.0.0/15',
|
||||
# '192.88.99.0/24',
|
||||
# '198.51.100.0/24',
|
||||
# '203.0.113.0/24',
|
||||
# '224.0.0.0/4',
|
||||
# '240.0.0.0/4',
|
||||
# '255.255.255.255/32',
|
||||
# '::/128',
|
||||
# '2001:db8::/32',
|
||||
# 'ff00::/8',
|
||||
# ]
|
||||
# vis_type_timeline.graphiteBlockedIPs: []
|
||||
|
||||
# opensearchDashboards.branding:
|
||||
# logo:
|
||||
# defaultUrl: ""
|
||||
# darkModeUrl: ""
|
||||
# mark:
|
||||
# defaultUrl: ""
|
||||
# darkModeUrl: ""
|
||||
# loadingLogo:
|
||||
# defaultUrl: ""
|
||||
# darkModeUrl: ""
|
||||
# faviconUrl: ""
|
||||
# applicationTitle: ""
|
||||
|
||||
# Set the value of this setting to true to capture region blocked warnings and errors
|
||||
# for your map rendering services.
|
||||
# map.showRegionBlockedWarning: false%
|
||||
|
||||
# Set the value of this setting to false to suppress search usage telemetry
|
||||
# for reducing the load of OpenSearch cluster.
|
||||
# data.search.usageTelemetry.enabled: false
|
||||
|
||||
# 2.4 renames 'wizard.enabled: false' to 'vis_builder.enabled: false'
|
||||
# Set the value of this setting to false to disable VisBuilder
|
||||
# functionality in Visualization.
|
||||
# vis_builder.enabled: false
|
||||
|
||||
# 2.4 New Experimental Feature
|
||||
# Set the value of this setting to true to enable the experimental multiple data source
|
||||
# support feature. Use with caution.
|
||||
# data_source.enabled: false
|
||||
# Set the value of these settings to customize crypto materials to encryption saved credentials
|
||||
# in data sources.
|
||||
# data_source.encryption.wrappingKeyName: 'changeme'
|
||||
# data_source.encryption.wrappingKeyNamespace: 'changeme'
|
||||
# data_source.encryption.wrappingKey: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
|
||||
# 2.6 New ML Commons Dashboards Feature
|
||||
# Set the value of this setting to true to enable the ml commons dashboards
|
||||
# ml_commons_dashboards.enabled: false
|
||||
|
||||
# 2.12 New experimental Assistant Dashboards Feature
|
||||
# Set the value of this setting to true to enable the assistant dashboards
|
||||
# assistant.chat.enabled: false
|
||||
|
||||
# 2.13 New Query Assistant Feature
|
||||
# Set the value of this setting to false to disable the query assistant
|
||||
# observability.query_assist.enabled: false
|
||||
|
||||
# 2.14 Enable Ui Metric Collectors in Usage Collector
|
||||
# Set the value of this setting to true to enable UI Metric collections
|
||||
# usageCollection.uiMetric.enabled: false
|
||||
|
||||
opensearch.hosts: [https://localhost:9200]
|
||||
opensearch.ssl.verificationMode: none
|
||||
opensearch.username: admin
|
||||
opensearch.password: 'Qazwsxedc!@#123'
|
||||
opensearch.requestHeadersWhitelist: [authorization, securitytenant]
|
||||
|
||||
opensearch_security.multitenancy.enabled: true
|
||||
opensearch_security.multitenancy.tenants.preferred: [Private, Global]
|
||||
opensearch_security.readonly_mode.roles: [kibana_read_only]
|
||||
# Use this setting if you are running opensearch-dashboards without https
|
||||
opensearch_security.cookie.secure: false
|
||||
server.host: '0.0.0.0'
|
||||
14
docker/dify/volumes/sandbox/conf/config.yaml
Normal file
14
docker/dify/volumes/sandbox/conf/config.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
app:
|
||||
port: 8194
|
||||
debug: True
|
||||
key: dify-sandbox
|
||||
max_workers: 4
|
||||
max_requests: 50
|
||||
worker_timeout: 5
|
||||
python_path: /usr/local/bin/python3
|
||||
enable_network: True # please make sure there is no network risk in your environment
|
||||
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
|
||||
proxy:
|
||||
socks5: ''
|
||||
http: ''
|
||||
https: ''
|
||||
35
docker/dify/volumes/sandbox/conf/config.yaml.example
Normal file
35
docker/dify/volumes/sandbox/conf/config.yaml.example
Normal file
@@ -0,0 +1,35 @@
|
||||
app:
|
||||
port: 8194
|
||||
debug: True
|
||||
key: dify-sandbox
|
||||
max_workers: 4
|
||||
max_requests: 50
|
||||
worker_timeout: 5
|
||||
python_path: /usr/local/bin/python3
|
||||
python_lib_path:
|
||||
- /usr/local/lib/python3.10
|
||||
- /usr/lib/python3.10
|
||||
- /usr/lib/python3
|
||||
- /usr/lib/x86_64-linux-gnu
|
||||
- /etc/ssl/certs/ca-certificates.crt
|
||||
- /etc/nsswitch.conf
|
||||
- /etc/hosts
|
||||
- /etc/resolv.conf
|
||||
- /run/systemd/resolve/stub-resolv.conf
|
||||
- /run/resolvconf/resolv.conf
|
||||
- /etc/localtime
|
||||
- /usr/share/zoneinfo
|
||||
- /etc/timezone
|
||||
# add more paths if needed
|
||||
python_pip_mirror_url: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
nodejs_path: /usr/local/bin/node
|
||||
enable_network: True
|
||||
allowed_syscalls:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
# add all the syscalls which you require
|
||||
proxy:
|
||||
socks5: ''
|
||||
http: ''
|
||||
https: ''
|
||||
@@ -7,7 +7,7 @@ app:
|
||||
use_icon_as_answer_icon: false
|
||||
dependencies: []
|
||||
kind: app
|
||||
version: 0.4.0
|
||||
version: 0.5.0
|
||||
workflow:
|
||||
conversation_variables: []
|
||||
environment_variables: []
|
||||
@@ -136,7 +136,16 @@ workflow:
|
||||
required: true
|
||||
type: text-input
|
||||
variable: query
|
||||
height: 114
|
||||
- default: ''
|
||||
hint: ''
|
||||
label: dataset_apikey
|
||||
max_length: 100
|
||||
options: []
|
||||
placeholder: ''
|
||||
required: true
|
||||
type: text-input
|
||||
variable: dataset_apikey
|
||||
height: 161
|
||||
id: '1747125462435'
|
||||
position:
|
||||
x: 80
|
||||
@@ -250,7 +259,7 @@ workflow:
|
||||
}'
|
||||
type: json
|
||||
desc: ''
|
||||
headers: 'Authorization:Bearer dataset-HeDK9gHBqPnI4rBZ2q2Hm7rV
|
||||
headers: 'Authorization:Bearer {{#1747125462435.dataset_apikey#}}
|
||||
|
||||
Content-Type:application/json'
|
||||
isInIteration: true
|
||||
@@ -260,7 +269,7 @@ workflow:
|
||||
params: ''
|
||||
retry_config:
|
||||
max_retries: 3
|
||||
retry_enabled: true
|
||||
retry_enabled: false
|
||||
retry_interval: 100
|
||||
selected: false
|
||||
ssl_verify: true
|
||||
@@ -270,9 +279,9 @@ workflow:
|
||||
max_write_timeout: 0
|
||||
title: HTTP 请求
|
||||
type: http-request
|
||||
url: http://192.168.0.64:7700/v1/datasets/{{#1747125586388.item#}}/retrieve
|
||||
url: http://nginx:80/v1/datasets/{{#1747125586388.item#}}/retrieve
|
||||
variables: []
|
||||
height: 157
|
||||
height: 111
|
||||
id: '1747125795256'
|
||||
parentId: '1747125586388'
|
||||
position:
|
||||
@@ -351,7 +360,7 @@ workflow:
|
||||
type: custom
|
||||
width: 242
|
||||
viewport:
|
||||
x: 116.27083894320822
|
||||
y: 126.27330841264018
|
||||
x: -967.224047730792
|
||||
y: 147.70051636546336
|
||||
zoom: 0.8705505632961247
|
||||
rag_pipeline_variables: []
|
||||
|
||||
@@ -9,17 +9,25 @@ dependencies:
|
||||
- current_identifier: null
|
||||
type: marketplace
|
||||
value:
|
||||
marketplace_plugin_unique_identifier: langgenius/siliconflow:0.0.34@1c203017d8ef49fd9152696a42e6dc71ecf272b115d8caf731c99ee0d2956dce
|
||||
marketplace_plugin_unique_identifier: anspire/anspire_search:0.0.9@a59824e9507c05c81d582cc5d8384197215d91bf5c787150d8aad723eb5d1a69
|
||||
version: null
|
||||
- current_identifier: null
|
||||
type: marketplace
|
||||
value:
|
||||
marketplace_plugin_unique_identifier: anspire/anspire_search:0.0.9@a59824e9507c05c81d582cc5d8384197215d91bf5c787150d8aad723eb5d1a69
|
||||
marketplace_plugin_unique_identifier: langgenius/ollama:0.1.0@7c18c74b94a855de83aa66f376939d47b96a49b6dbb6904b46b267cb0213396e
|
||||
version: null
|
||||
kind: app
|
||||
version: 0.4.0
|
||||
version: 0.5.0
|
||||
workflow:
|
||||
conversation_variables:
|
||||
- description: ''
|
||||
id: 71e3f805-8445-46b1-bd43-8af398234527
|
||||
name: dataset_apikey
|
||||
selector:
|
||||
- conversation
|
||||
- dataset_apikey
|
||||
value: ''
|
||||
value_type: string
|
||||
- description: ''
|
||||
id: e18aacca-16a2-4d93-80c4-5a85ead53ae4
|
||||
name: datasets
|
||||
@@ -225,19 +233,6 @@ workflow:
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInIteration: false
|
||||
isInLoop: false
|
||||
sourceType: start
|
||||
targetType: if-else
|
||||
id: 1762339910800-source-1762421892949-target
|
||||
selected: false
|
||||
source: '1762339910800'
|
||||
sourceHandle: source
|
||||
target: '1762421892949'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInIteration: false
|
||||
isInLoop: false
|
||||
@@ -257,6 +252,7 @@ workflow:
|
||||
sourceType: code
|
||||
targetType: iteration
|
||||
id: 1762510470105-source-1762339969303-target
|
||||
selected: false
|
||||
source: '1762510470105'
|
||||
sourceHandle: source
|
||||
target: '1762339969303'
|
||||
@@ -268,21 +264,11 @@ workflow:
|
||||
isInLoop: false
|
||||
sourceType: if-else
|
||||
targetType: tool
|
||||
id: 1762421892949-true-1762511001734-target
|
||||
id: 1762421892949-true-1764314675268-target
|
||||
selected: false
|
||||
source: '1762421892949'
|
||||
sourceHandle: 'true'
|
||||
target: '1762511001734'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInLoop: false
|
||||
sourceType: assigner
|
||||
targetType: tool
|
||||
id: 1762509024795-source-1762511001734-target
|
||||
source: '1762509024795'
|
||||
sourceHandle: source
|
||||
target: '1762511001734'
|
||||
target: '1764314675268'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
@@ -290,13 +276,76 @@ workflow:
|
||||
isInLoop: false
|
||||
sourceType: tool
|
||||
targetType: code
|
||||
id: 1762511001734-source-1762510470105-target
|
||||
source: '1762511001734'
|
||||
id: 1764314675268-source-1762510470105-target
|
||||
selected: false
|
||||
source: '1764314675268'
|
||||
sourceHandle: source
|
||||
target: '1762510470105'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInLoop: false
|
||||
sourceType: assigner
|
||||
targetType: tool
|
||||
id: 1762509024795-source-1764314675268-target
|
||||
selected: false
|
||||
source: '1762509024795'
|
||||
sourceHandle: source
|
||||
target: '1764314675268'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInIteration: false
|
||||
isInLoop: false
|
||||
sourceType: start
|
||||
targetType: if-else
|
||||
id: 1762339910800-source-1764314703864-target
|
||||
selected: false
|
||||
source: '1762339910800'
|
||||
sourceHandle: source
|
||||
target: '1764314703864'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInIteration: false
|
||||
isInLoop: false
|
||||
sourceType: if-else
|
||||
targetType: assigner
|
||||
id: 1764314703864-false-1764314714879-target
|
||||
selected: false
|
||||
source: '1764314703864'
|
||||
sourceHandle: 'false'
|
||||
target: '1764314714879'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInLoop: false
|
||||
sourceType: assigner
|
||||
targetType: if-else
|
||||
id: 1764314714879-source-1762421892949-target
|
||||
selected: false
|
||||
source: '1764314714879'
|
||||
sourceHandle: source
|
||||
target: '1762421892949'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
- data:
|
||||
isInLoop: false
|
||||
sourceType: if-else
|
||||
targetType: if-else
|
||||
id: 1764314703864-true-1762421892949-target
|
||||
selected: false
|
||||
source: '1764314703864'
|
||||
sourceHandle: 'true'
|
||||
target: '1762421892949'
|
||||
targetHandle: target
|
||||
type: custom
|
||||
zIndex: 0
|
||||
nodes:
|
||||
- data:
|
||||
selected: false
|
||||
@@ -321,14 +370,32 @@ workflow:
|
||||
required: true
|
||||
type: text-input
|
||||
variable: datasets
|
||||
height: 114
|
||||
- default: ''
|
||||
hint: ''
|
||||
label: dataset_apikey
|
||||
max_length: 100
|
||||
options: []
|
||||
placeholder: ''
|
||||
required: true
|
||||
type: text-input
|
||||
variable: dataset_apikey
|
||||
- default: ''
|
||||
hint: ''
|
||||
label: promt
|
||||
max_length: 2000
|
||||
options: []
|
||||
placeholder: ''
|
||||
required: true
|
||||
type: paragraph
|
||||
variable: promt
|
||||
height: 187
|
||||
id: '1762339910800'
|
||||
position:
|
||||
x: -1233.1402302396395
|
||||
y: 149.5782401176896
|
||||
x: -1704.106555788423
|
||||
y: 174.193204867626
|
||||
positionAbsolute:
|
||||
x: -1233.1402302396395
|
||||
y: 149.5782401176896
|
||||
x: -1704.106555788423
|
||||
y: 174.193204867626
|
||||
selected: false
|
||||
sourcePosition: right
|
||||
targetPosition: left
|
||||
@@ -354,8 +421,8 @@ workflow:
|
||||
model:
|
||||
completion_params: {}
|
||||
mode: chat
|
||||
name: deepseek-ai/DeepSeek-V3
|
||||
provider: langgenius/siliconflow/siliconflow
|
||||
name: qwen-14b
|
||||
provider: langgenius/ollama/ollama
|
||||
prompt_config:
|
||||
jinja2_variables:
|
||||
- value_selector:
|
||||
@@ -370,10 +437,14 @@ workflow:
|
||||
- '1762510470105'
|
||||
- result
|
||||
variable: result
|
||||
- value_selector:
|
||||
- '1762339910800'
|
||||
- promt
|
||||
variable: promt
|
||||
prompt_template:
|
||||
- edition_type: jinja2
|
||||
id: 5d50499d-b81d-43aa-a891-38fd349bd754
|
||||
jinja2_text: "你是一个专业的思政学习助手,致力于帮助用户学习思想政治理论知识。请基于提供的知识库内容{{ result }},为用户提供准确、简洁的回答。\r\
|
||||
jinja2_text: "{{ promt }}\r\n\r\n请基于提供的知识库内容{{ result }},为用户提供准确、简洁的回答。\r\
|
||||
\n\r\n{% if searchData %}\r\n结合 {{ searchData }} 回答用户\r\n{% endif %}\r\
|
||||
\n{% if fileData %}\r\n结合文件内容 {{ fileData }} 回答用户\r\n{% endif %}\r\n"
|
||||
role: system
|
||||
@@ -394,7 +465,7 @@ workflow:
|
||||
- id: 23264213-e421-4449-b666-a55a0e39e561
|
||||
role: user
|
||||
text: ''
|
||||
selected: false
|
||||
selected: true
|
||||
title: LLM
|
||||
type: llm
|
||||
vision:
|
||||
@@ -407,7 +478,7 @@ workflow:
|
||||
positionAbsolute:
|
||||
x: 2674.6343495125943
|
||||
y: 75.75635633814841
|
||||
selected: false
|
||||
selected: true
|
||||
sourcePosition: right
|
||||
targetPosition: left
|
||||
type: custom
|
||||
@@ -496,7 +567,7 @@ workflow:
|
||||
variable_selector:
|
||||
- '1762339969303'
|
||||
- item
|
||||
height: 92
|
||||
height: 104
|
||||
id: '1762339981310'
|
||||
parentId: '1762339969303'
|
||||
position:
|
||||
@@ -958,7 +1029,7 @@ workflow:
|
||||
type: code
|
||||
variables:
|
||||
- value_selector:
|
||||
- '1762511001734'
|
||||
- '1764314675268'
|
||||
- text
|
||||
value_type: string
|
||||
variable: text
|
||||
@@ -1034,10 +1105,44 @@ workflow:
|
||||
scope: null
|
||||
template: null
|
||||
type: string
|
||||
- auto_generate: null
|
||||
default: ''
|
||||
form: llm
|
||||
human_description:
|
||||
en_US: ''
|
||||
ja_JP: ''
|
||||
pt_BR: ''
|
||||
zh_Hans: ''
|
||||
label:
|
||||
en_US: dataset_apikey
|
||||
ja_JP: dataset_apikey
|
||||
pt_BR: dataset_apikey
|
||||
zh_Hans: dataset_apikey
|
||||
llm_description: ''
|
||||
max: null
|
||||
min: null
|
||||
name: dataset_apikey
|
||||
options: []
|
||||
placeholder:
|
||||
en_US: ''
|
||||
ja_JP: ''
|
||||
pt_BR: ''
|
||||
zh_Hans: ''
|
||||
precision: null
|
||||
required: true
|
||||
scope: null
|
||||
template: null
|
||||
type: string
|
||||
params:
|
||||
dataset_apikey: ''
|
||||
dataset_ids: ''
|
||||
query: ''
|
||||
provider_id: 019a5dd7-5f2b-7767-b2df-82bfda84c7ec
|
||||
plugin_id: null
|
||||
plugin_unique_identifier: null
|
||||
provider_icon:
|
||||
background: '#FFEAD5'
|
||||
content: 🤖
|
||||
provider_id: e7e4453f-0667-47fe-be4c-62accfbc7cc6
|
||||
provider_name: 动态知识库检索
|
||||
provider_type: workflow
|
||||
selected: false
|
||||
@@ -1048,6 +1153,9 @@ workflow:
|
||||
tool_name: dynamic_dataset
|
||||
tool_node_version: '2'
|
||||
tool_parameters:
|
||||
dataset_apikey:
|
||||
type: mixed
|
||||
value: '{{#conversation.dataset_apikey#}}'
|
||||
dataset_ids:
|
||||
type: mixed
|
||||
value: '{{#conversation.datasets#}}'
|
||||
@@ -1056,20 +1164,77 @@ workflow:
|
||||
value: '{{#sys.query#}}'
|
||||
type: tool
|
||||
height: 52
|
||||
id: '1762511001734'
|
||||
id: '1764314675268'
|
||||
position:
|
||||
x: -142.91348174874167
|
||||
y: -247.51043561574136
|
||||
x: -165.1249185156642
|
||||
y: -247.5444668446392
|
||||
positionAbsolute:
|
||||
x: -142.91348174874167
|
||||
y: -247.51043561574136
|
||||
selected: true
|
||||
x: -165.1249185156642
|
||||
y: -247.5444668446392
|
||||
selected: false
|
||||
sourcePosition: right
|
||||
targetPosition: left
|
||||
type: custom
|
||||
width: 242
|
||||
- data:
|
||||
cases:
|
||||
- case_id: 'true'
|
||||
conditions:
|
||||
- comparison_operator: not empty
|
||||
id: 3123b598-113d-453f-b3fc-d04b6e83a35e
|
||||
value: ''
|
||||
varType: string
|
||||
variable_selector:
|
||||
- conversation
|
||||
- dataset_apikey
|
||||
id: 'true'
|
||||
logical_operator: and
|
||||
selected: false
|
||||
title: 条件分支 3
|
||||
type: if-else
|
||||
height: 124
|
||||
id: '1764314703864'
|
||||
position:
|
||||
x: -1295.7675522246373
|
||||
y: -98.76989654474232
|
||||
positionAbsolute:
|
||||
x: -1295.7675522246373
|
||||
y: -98.76989654474232
|
||||
selected: false
|
||||
sourcePosition: right
|
||||
targetPosition: left
|
||||
type: custom
|
||||
width: 242
|
||||
- data:
|
||||
items:
|
||||
- input_type: variable
|
||||
operation: over-write
|
||||
value:
|
||||
- '1762339910800'
|
||||
- dataset_apikey
|
||||
variable_selector:
|
||||
- conversation
|
||||
- dataset_apikey
|
||||
write_mode: over-write
|
||||
selected: false
|
||||
title: 变量赋值 2
|
||||
type: assigner
|
||||
version: '2'
|
||||
height: 84
|
||||
id: '1764314714879'
|
||||
position:
|
||||
x: -988.84455927465
|
||||
y: -5.23303049498395
|
||||
positionAbsolute:
|
||||
x: -988.84455927465
|
||||
y: -5.23303049498395
|
||||
selected: false
|
||||
sourcePosition: right
|
||||
targetPosition: left
|
||||
type: custom
|
||||
width: 242
|
||||
viewport:
|
||||
x: 863.6452676587132
|
||||
y: 446.19950772630614
|
||||
zoom: 0.9236555375410279
|
||||
x: -1068.6187404167313
|
||||
y: 347.5222255720734
|
||||
zoom: 0.6093853943072881
|
||||
rag_pipeline_variables: []
|
||||
|
||||
@@ -303,6 +303,7 @@ INSERT INTO `tb_sys_menu` VALUES
|
||||
('402', 'menu_learning_records', '学习记录', 'menu_user_center', '/user-center/learning-records', 'user/user-center/LearningRecordsView', NULL, 1, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('403', 'menu_my_favorites', '我的收藏', 'menu_user_center', '/user-center/favorites', 'user/user-center/MyFavoritesView', NULL, 2, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('404', 'menu_my_achievements', '我的成就', 'menu_user_center', '/user-center/achievements', 'user/user-center/MyAchievementsView', NULL, 3, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('650', 'menu_user_message_center', '消息中心', 'menu_user_center', '/user-center/message', 'user/message/MyMessageListView', NULL, 4, 0, 'NavigationLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0),
|
||||
('500', 'menu_profile', '账号中心', 'menu_user_dropdown', '/profile', 'user/user-center/UserCenterLayout', NULL, 5, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('501', 'menu_personal_info', '个人信息', 'menu_profile', '/profile/personal-info', 'user/user-center/profile/PersonalInfoView', NULL, 1, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('502', 'menu_account_settings', '账号设置', 'menu_profile', '/profile/account-settings', 'user/user-center/profile/AccountSettingsView', NULL, 2, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
@@ -344,9 +345,8 @@ INSERT INTO `tb_sys_menu` VALUES
|
||||
('8004', 'menu_admin_system_task', '系统定时任务配置', 'menu_admin_crontab_manage', '/admin/manage/crontab/system-task', 'admin/manage/crontab/SystemTaskView', NULL, 4, 0, 'SidebarLayout', '1', NULL, '2025-11-25 13:45:00', '2025-11-25 13:45:00', NULL, 0),
|
||||
-- 消息通知模块菜单 (9000-9999)
|
||||
('9001', 'menu_admin_message_manage', '消息管理', NULL, '/admin/manage/message', 'admin/manage/message/MessageManageView', 'admin/notice.svg', 9, 0, 'SidebarLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0),
|
||||
-- 用户端消息中心菜单 (650-699)
|
||||
('650', 'menu_user_message_center', '消息中心', NULL, '/user/message', 'user/message/MyMessageListView', NULL, 7, 1, 'NavigationLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0),
|
||||
('651', 'menu_user_message_detail', '消息详情', 'menu_user_message_center', '/user/message/detail/:messageID', 'user/message/MyMessageDetailView', NULL, 1, 3, 'NavigationLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0);
|
||||
-- 用户端消息详情菜单 (651)
|
||||
('651', 'menu_user_message_detail', '消息详情', 'menu_user_message_center', '/user-center/message/detail/:messageID', 'user/message/MyMessageDetailView', NULL, 1, 3, 'NavigationLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0);
|
||||
|
||||
-- 插入菜单权限关联数据
|
||||
-- ============================================
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
condition_value, points, order_num, creator, updater, create_time, update_time,
|
||||
delete_time, deleted
|
||||
) VALUES (
|
||||
#{ID}, #{achievementID}, #{name}, #{description}, #{icon}, #{type}, #{level},
|
||||
#{id}, #{achievementID}, #{name}, #{description}, #{icon}, #{type}, #{level},
|
||||
#{conditionType}, #{conditionValue}, #{points}, #{orderNum}, #{creator}, #{updater},
|
||||
#{createTime}, #{updateTime}, #{deleteTime}, #{deleted}
|
||||
)
|
||||
@@ -236,13 +236,13 @@
|
||||
deleted = #{deleted},
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{ID}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 删除成就 -->
|
||||
<delete id="deleteAchievement" parameterType="org.xyzh.common.dto.usercenter.TbAchievement">
|
||||
DELETE FROM tb_achievement
|
||||
WHERE id = #{ID}
|
||||
WHERE id = #{id}
|
||||
</delete>
|
||||
|
||||
<!-- 批量插入成就 -->
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
INSERT INTO tb_user_achievement (
|
||||
id, user_id, achievement_id, obtain_time
|
||||
) VALUES (
|
||||
#{ID}, #{userID}, #{achievementID}, #{obtainTime}
|
||||
#{id}, #{userID}, #{achievementID}, #{obtainTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
obtain_time = #{obtainTime},
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{ID}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 删除用户成就 -->
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
id, user_id, achievement_id, current_value, target_value,
|
||||
progress_percentage, completed, last_update_time, create_time
|
||||
) VALUES (
|
||||
#{ID}, #{userID}, #{achievementID}, #{currentValue}, #{targetValue},
|
||||
#{id}, #{userID}, #{achievementID}, #{currentValue}, #{targetValue},
|
||||
#{progressPercentage}, #{completed}, #{lastUpdateTime}, #{createTime}
|
||||
)
|
||||
</insert>
|
||||
@@ -90,7 +90,7 @@
|
||||
last_update_time = #{lastUpdateTime},
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{ID}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 增加进度值 -->
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<if test="updater != null">updater = #{updater},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</set>
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 逻辑删除智能体配置 -->
|
||||
@@ -73,7 +73,7 @@
|
||||
SET deleted = 1,
|
||||
delete_time = NOW(),
|
||||
updater = #{updater}
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 根据ID查询智能体配置 -->
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
status, is_favorite, is_pinned, message_count, total_tokens,
|
||||
last_message_time, create_time, update_time, deleted
|
||||
) VALUES (
|
||||
#{ID}, #{userID}, #{agentID}, #{title}, #{summary}, #{difyConversationId},
|
||||
#{id}, #{userID}, #{agentID}, #{title}, #{summary}, #{difyConversationId},
|
||||
#{status}, #{isFavorite}, #{isPinned}, #{messageCount}, #{totalTokens},
|
||||
#{lastMessageTime}, #{createTime}, #{updateTime}, #{deleted}
|
||||
)
|
||||
@@ -82,12 +82,12 @@
|
||||
<if test="lastMessageTime != null">last_message_time = #{lastMessageTime},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</set>
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 逻辑删除会话 -->
|
||||
<update id="deleteConversation" parameterType="org.xyzh.common.dto.ai.TbAiConversation">
|
||||
DELETE FROM tb_ai_conversation WHERE id = #{ID}
|
||||
DELETE FROM tb_ai_conversation WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 根据ID查询会话 -->
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
vector_id, document_count, total_chunks, status, creator, creator_dept,
|
||||
updater, create_time, update_time, deleted
|
||||
) VALUES (
|
||||
#{ID}, #{title}, #{avatar}, #{description}, #{content}, #{sourceType}, #{sourceID}, #{fileName}, #{filePath},
|
||||
#{id}, #{title}, #{avatar}, #{description}, #{content}, #{sourceType}, #{sourceID}, #{fileName}, #{filePath},
|
||||
#{category}, #{tags}, #{difyDatasetId}, #{difyIndexingTechnique}, #{embeddingModel}, #{embeddingModelProvider},
|
||||
#{rerankModel}, #{rerankModelProvider}, #{rerankingEnable}, #{retrievalTopK}, #{retrievalScoreThreshold},
|
||||
#{vectorID}, #{documentCount}, #{totalChunks}, #{status}, #{creator}, #{creatorDept},
|
||||
@@ -235,7 +235,7 @@
|
||||
<if test="updater != null">updater = #{updater},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</set>
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- deleteKnowledge(逻辑删除知识库) -->
|
||||
@@ -244,7 +244,7 @@
|
||||
SET deleted = 1,
|
||||
delete_time = NOW(),
|
||||
updater = #{updater}
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- selectKnowledgeById(根据ID查询知识库,不带权限校验) -->
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
file_ids, knowledge_ids, knowledge_refs, token_count,
|
||||
dify_message_id, rating, feedback, create_time, update_time, deleted
|
||||
) VALUES (
|
||||
#{ID}, #{conversationID}, #{userID}, #{agentID}, #{role}, #{content},
|
||||
#{id}, #{conversationID}, #{userID}, #{agentID}, #{role}, #{content},
|
||||
#{fileIDs}, #{knowledgeIDs}, #{knowledgeRefs}, #{tokenCount},
|
||||
#{difyMessageId}, #{rating}, #{feedback}, #{createTime}, #{updateTime}, #{deleted}
|
||||
)
|
||||
@@ -70,7 +70,7 @@
|
||||
<if test="feedback != null">feedback = #{feedback},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</set>
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 逻辑删除消息 -->
|
||||
@@ -78,7 +78,7 @@
|
||||
UPDATE tb_ai_message
|
||||
SET deleted = 1,
|
||||
delete_time = NOW()
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 根据ID查询消息 -->
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
chunk_count, status, error_message, enabled, display_status,
|
||||
create_time, update_time, deleted
|
||||
) VALUES (
|
||||
#{ID}, #{userID}, #{knowledgeId}, #{conversationID}, #{messageID}, #{sysFileId}, #{fileName}, #{filePath}, #{fileSize},
|
||||
#{id}, #{userID}, #{knowledgeId}, #{conversationID}, #{messageID}, #{sysFileId}, #{fileName}, #{filePath}, #{fileSize},
|
||||
#{fileType}, #{mimeType}, #{extractedText}, #{difyDocumentId}, #{difyBatchId}, #{difyUploadFileId},
|
||||
#{chunkCount}, #{status}, #{errorMessage}, #{enabled}, #{displayStatus},
|
||||
#{createTime}, #{updateTime}, #{deleted}
|
||||
@@ -105,7 +105,7 @@
|
||||
<if test="displayStatus != null">display_status = #{displayStatus},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</set>
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- deleteUploadFile(逻辑删除文件记录) -->
|
||||
@@ -113,7 +113,7 @@
|
||||
UPDATE tb_ai_upload_file
|
||||
SET deleted = 1,
|
||||
delete_time = NOW()
|
||||
WHERE id = #{ID} AND deleted = 0
|
||||
WHERE id = #{id} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- selectUploadFileById(根据ID查询文件) -->
|
||||
|
||||
@@ -671,21 +671,21 @@ public class MessageServiceImpl implements MessageService {
|
||||
switch (target.getTargetType()) {
|
||||
case "dept":
|
||||
// 查询该部门及所有子部门的用户
|
||||
userIDs = userMapper.selectUserIdsByDeptId(target.getTargetId());
|
||||
logger.info("部门 {} 解析到 {} 个用户", target.getTargetId(), userIDs.size());
|
||||
userIDs = userMapper.selectUserIdsByDeptId(target.getTargetID());
|
||||
logger.info("部门 {} 解析到 {} 个用户", target.getTargetID(), userIDs.size());
|
||||
break;
|
||||
case "role":
|
||||
// 查询scopeDeptID及子部门中该角色的用户
|
||||
String scopeDeptID = target.getScopeDeptID();
|
||||
if (scopeDeptID == null || scopeDeptID.isEmpty()) {
|
||||
logger.warn("角色目标缺少 scopeDeptID,跳过:{}", target.getTargetId());
|
||||
logger.warn("角色目标缺少 scopeDeptID,跳过:{}", target.getTargetID());
|
||||
break;
|
||||
}
|
||||
userIDs = userMapper.selectUserIdsByDeptRole(scopeDeptID, target.getTargetId());
|
||||
logger.info("部门 {} 中角色 {} 解析到 {} 个用户", scopeDeptID, target.getTargetId(), userIDs.size());
|
||||
userIDs = userMapper.selectUserIdsByDeptRole(scopeDeptID, target.getTargetID());
|
||||
logger.info("部门 {} 中角色 {} 解析到 {} 个用户", scopeDeptID, target.getTargetID(), userIDs.size());
|
||||
break;
|
||||
case "user":
|
||||
userIDs.add(target.getTargetId());
|
||||
userIDs.add(target.getTargetID());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-BOLD.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-BOLD.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-EXTRALIGHT.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-EXTRALIGHT.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-HEAVY.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-HEAVY.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-LIGHT.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-LIGHT.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-MEDIUM.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-MEDIUM.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-NORMAL.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-NORMAL.OTF
Normal file
Binary file not shown.
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-REGULAR.OTF
Normal file
BIN
schoolNewsWeb/public/font/siyuan/SOURCEHANSANSCN-REGULAR.OTF
Normal file
Binary file not shown.
@@ -12,8 +12,7 @@
|
||||
|
||||
<style lang="scss">
|
||||
#app {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
|
||||
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
font-family: 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
height: 100vh;
|
||||
|
||||
@@ -75,9 +75,17 @@ export const chatApi = {
|
||||
|
||||
// 监听标准消息事件
|
||||
eventSource.addEventListener('message', (event) => {
|
||||
const data = event.data;
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
try {
|
||||
// 解析JSON字符串,处理Unicode转义
|
||||
const data = JSON.parse(event.data);
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
} catch (e) {
|
||||
// 如果不是JSON,直接使用原始数据
|
||||
const data = event.data;
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听结束事件
|
||||
@@ -335,9 +343,17 @@ export const chatApi = {
|
||||
|
||||
// 监听标准消息事件
|
||||
eventSource.addEventListener('message', (event) => {
|
||||
const data = event.data;
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
try {
|
||||
// 解析JSON字符串,处理Unicode转义
|
||||
const data = JSON.parse(event.data);
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
} catch (e) {
|
||||
// 如果不是JSON,直接使用原始数据
|
||||
const data = event.data;
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听结束事件
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 10C0 4.47715 4.47715 0 10 0H38C43.5229 0 48 4.47715 48 10V38C48 43.5229 43.5228 48 38 48H10C4.47715 48 0 43.5228 0 38V10Z" fill="#E7000B"/>
|
||||
<path d="M24 20V16H20" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30 20H18C16.8954 20 16 20.8954 16 22V30C16 31.1046 16.8954 32 18 32H30C31.1046 32 32 31.1046 32 30V22C32 20.8954 31.1046 20 30 20Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14 26H16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M32 26H34" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M27 25V27" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21 25V27" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="80" height="80" rx="40" fill="#C62828"/>
|
||||
<path d="M39.816 41.372H23.44V18.786H56.514V41.372H41.518C43.7873 44.3467 45.2593 46.3247 45.934 47.306L41.472 50.388C39.3253 47.2293 37.7153 44.9447 36.642 43.534L39.816 41.372ZM37.424 27.664V23.524H28.868V27.664H37.424ZM42.622 27.664H51.086V23.524H42.622V27.664ZM37.424 32.356H28.868V36.45H37.424V32.356ZM42.622 32.356V36.45H51.086V32.356H42.622ZM55.364 43.028C56.2227 44.3773 57.2807 46.1407 58.538 48.318C59.826 50.4953 60.884 52.3353 61.712 53.838L56.836 56.552C56.008 54.9267 54.996 53.056 53.8 50.94C52.604 48.7933 51.5767 47.0147 50.718 45.604L55.364 43.028ZM46.486 51.676C46.578 50.756 46.624 49.2687 46.624 47.214L51.73 48.272C51.73 49.2533 51.5767 51.17 51.27 54.022C51.1473 55.31 50.856 56.2913 50.396 56.966C49.9667 57.6407 49.292 58.116 48.372 58.392C47.4827 58.6987 46.1793 58.8827 44.462 58.944C42.4993 59.0053 40.9967 59.036 39.954 59.036C38.942 59.036 37.424 59.0053 35.4 58.944C33.3147 58.852 31.7967 58.392 30.846 57.564C29.926 56.736 29.466 55.402 29.466 53.562V43.488H34.756V51.492C34.756 52.32 34.94 52.9027 35.308 53.24C35.676 53.5773 36.2893 53.7767 37.148 53.838C37.884 53.8687 39.0033 53.884 40.506 53.884C41.978 53.884 43.082 53.8687 43.818 53.838C44.7993 53.8073 45.474 53.6233 45.842 53.286C46.21 52.9487 46.4247 52.412 46.486 51.676ZM18.472 55.08C19.3613 53.4853 20.2047 51.6913 21.002 49.698C21.83 47.7047 22.4893 45.742 22.98 43.81L28.178 45.006C27.5953 46.9687 26.89 49.0387 26.062 51.216C25.2647 53.3627 24.4367 55.2793 23.578 56.966L18.472 55.08Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 1.6 KiB |
@@ -1,5 +1,4 @@
|
||||
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="80" height="80" rx="40" fill="#C62828"/>
|
||||
<path d="M44.3335 20.4997C44.5794 20.4997 44.8244 20.5052 45.0679 20.5153C44.5924 21.8662 44.3335 23.3192 44.3335 24.8327C44.3335 32.0124 50.1538 37.8327 57.3335 37.8327C58.8471 37.8327 60.301 37.5739 61.6519 37.0983C61.662 37.3417 61.6665 37.5869 61.6665 37.8327C61.6665 47.4056 53.9064 55.1666 44.3335 55.1667V62.7497C33.5002 58.4163 18.3335 51.916 18.3335 37.8327C18.3337 28.26 26.0938 20.4998 35.6665 20.4997H44.3335ZM24.8335 41.444H29.8892V33.4997H24.8335V41.444ZM32.7778 33.4997V41.444H37.8335V33.4997H32.7778ZM56.314 16.859C56.6964 15.936 57.9708 15.936 58.353 16.859L58.9019 18.1833C59.8379 20.4428 61.5836 22.247 63.7788 23.2233L65.3325 23.9147C66.2225 24.3106 66.2226 25.6058 65.3325 26.0016L63.687 26.7331C61.5468 27.685 59.8316 29.4256 58.8794 31.611L58.3452 32.8366C57.9543 33.7336 56.713 33.7335 56.3218 32.8366L55.7876 31.611C54.8353 29.4256 53.1202 27.685 50.98 26.7331L49.3345 26.0016C48.4446 25.6058 48.4446 24.3105 49.3345 23.9147L50.8882 23.2233C53.0833 22.2469 54.8294 20.4428 55.7651 18.1833L56.314 16.859Z" fill="white"/>
|
||||
<rect width="80" height="80" rx="40" fill="#C62828"/>
|
||||
<path d="M39.816 41.372H23.44V18.786H56.514V41.372H41.518C43.7873 44.3467 45.2593 46.3247 45.934 47.306L41.472 50.388C39.3253 47.2293 37.7153 44.9447 36.642 43.534L39.816 41.372ZM37.424 27.664V23.524H28.868V27.664H37.424ZM42.622 27.664H51.086V23.524H42.622V27.664ZM37.424 32.356H28.868V36.45H37.424V32.356ZM42.622 32.356V36.45H51.086V32.356H42.622ZM55.364 43.028C56.2227 44.3773 57.2807 46.1407 58.538 48.318C59.826 50.4953 60.884 52.3353 61.712 53.838L56.836 56.552C56.008 54.9267 54.996 53.056 53.8 50.94C52.604 48.7933 51.5767 47.0147 50.718 45.604L55.364 43.028ZM46.486 51.676C46.578 50.756 46.624 49.2687 46.624 47.214L51.73 48.272C51.73 49.2533 51.5767 51.17 51.27 54.022C51.1473 55.31 50.856 56.2913 50.396 56.966C49.9667 57.6407 49.292 58.116 48.372 58.392C47.4827 58.6987 46.1793 58.8827 44.462 58.944C42.4993 59.0053 40.9967 59.036 39.954 59.036C38.942 59.036 37.424 59.0053 35.4 58.944C33.3147 58.852 31.7967 58.392 30.846 57.564C29.926 56.736 29.466 55.402 29.466 53.562V43.488H34.756V51.492C34.756 52.32 34.94 52.9027 35.308 53.24C35.676 53.5773 36.2893 53.7767 37.148 53.838C37.884 53.8687 39.0033 53.884 40.506 53.884C41.978 53.884 43.082 53.8687 43.818 53.838C44.7993 53.8073 45.474 53.6233 45.842 53.286C46.21 52.9487 46.4247 52.412 46.486 51.676ZM18.472 55.08C19.3613 53.4853 20.2047 51.6913 21.002 49.698C21.83 47.7047 22.4893 45.742 22.98 43.81L28.178 45.006C27.5953 46.9687 26.89 49.0387 26.062 51.216C25.2647 53.3627 24.4367 55.2793 23.578 56.966L18.472 55.08Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.6 KiB |
10
schoolNewsWeb/src/assets/imgs/finishtask.svg
Normal file
10
schoolNewsWeb/src/assets/imgs/finishtask.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="77" height="77" viewBox="0 0 77 77" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="77" height="77" rx="6" fill="white"/>
|
||||
<path d="M49.1296 16.4629C50.3467 16.463 51.3328 17.45 51.3328 18.667V45.1113H60.1482V53.9258C60.1482 57.5771 57.1882 60.5371 53.5369 60.5371H22.6853C19.0341 60.5371 16.074 57.5771 16.074 53.9258V18.667C16.074 17.4499 17.061 16.4629 18.2781 16.4629H49.1296ZM51.3328 53.9258C51.3328 55.1429 52.3198 56.1298 53.5369 56.1299C54.754 56.1299 55.741 55.1429 55.741 53.9258V49.5186H51.3328V53.9258ZM32.9167 38.917L28.1667 34.167L25.0007 37.334L32.9167 45.25L44.0007 34.167L40.8337 31L32.9167 38.917Z" fill="url(#paint0_linear_1534_4780)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1534_4780" x1="19.4445" y1="16.7219" x2="51.7222" y2="60.2775" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#82B7FD"/>
|
||||
<stop offset="1" stop-color="#2F6AFF"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 918 B |
9
schoolNewsWeb/src/assets/imgs/learningtask.svg
Normal file
9
schoolNewsWeb/src/assets/imgs/learningtask.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg width="53" height="53" viewBox="0 0 53 53" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M41.8702 48.4813H11.0183C7.36713 48.4813 4.40723 45.5215 4.40723 41.8702V6.61093C4.40723 5.39387 5.39387 4.40723 6.61093 4.40723H37.4628C38.6799 4.40723 39.6665 5.39387 39.6665 6.61093V33.0554H48.4813V41.8702C48.4813 45.5215 45.5215 48.4813 41.8702 48.4813ZM39.6665 37.4628V41.8702C39.6665 43.0873 40.6531 44.0739 41.8702 44.0739C43.0873 44.0739 44.0739 43.0873 44.0739 41.8702V37.4628H39.6665ZM13.222 15.4257V19.8332H30.8517V15.4257H13.222ZM13.222 24.2406V28.648H30.8517V24.2406H13.222ZM13.222 33.0554V37.4628H24.2406V33.0554H13.222Z" fill="url(#paint0_linear_1534_4772)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1534_4772" x1="7.77772" y1="4.66623" x2="40.0555" y2="48.2218" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FD9082"/>
|
||||
<stop offset="1" stop-color="#FD6D78"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 918 B |
@@ -5,6 +5,55 @@
|
||||
* @figma https://www.figma.com/design/4aM0yqyoAjtW2jTZcqPAtN
|
||||
*/
|
||||
|
||||
// ============ 字体声明 ============
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-EXTRALIGHT.OTF') format('opentype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-LIGHT.OTF') format('opentype');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-REGULAR.OTF') format('opentype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-MEDIUM.OTF') format('opentype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-BOLD.OTF') format('opentype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Han Sans SC';
|
||||
src: url('/font/siyuan/SOURCEHANSANSCN-HEAVY.OTF') format('opentype');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
// ============ 设计令牌 (Design Tokens) ============
|
||||
|
||||
// 颜色
|
||||
@@ -18,8 +67,8 @@ $color-bg-white: #FFFFFF; // 白色背景
|
||||
$color-border: #dcdfe6; // 边框
|
||||
|
||||
// 字体
|
||||
$font-family-cn: 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
$font-family-en: 'Nunito Sans', sans-serif;
|
||||
$font-family-cn: 'Source Han Sans SC', sans-serif;
|
||||
$font-family-en: 'Source Han Sans SC', sans-serif;
|
||||
$font-size-base: 14px;
|
||||
$line-height-base: 1.571428571em;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ withDefaults(defineProps<Props>(), {
|
||||
}
|
||||
|
||||
.head-title {
|
||||
font-family: 'MiSans VF', 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 630;
|
||||
font-size: 40px;
|
||||
line-height: 1.2;
|
||||
@@ -57,7 +57,7 @@ withDefaults(defineProps<Props>(), {
|
||||
}
|
||||
|
||||
.breadcrumb-label {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -72,7 +72,7 @@ withDefaults(defineProps<Props>(), {
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -84,7 +84,7 @@ withDefaults(defineProps<Props>(), {
|
||||
}
|
||||
|
||||
.separator {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-size: 14px;
|
||||
color: #C9CDD4;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,17 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
|
||||
const home = ref<boolean>(false);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
// 组件加载时根据当前路由判断是否在管理页
|
||||
onMounted(() => {
|
||||
// 如果当前路径以 /admin 开头,说明在管理页,应该显示"前往用户页"
|
||||
home.value = route.path.startsWith('/admin');
|
||||
});
|
||||
|
||||
function changeHome(){
|
||||
if(home.value){
|
||||
|
||||
@@ -196,7 +196,7 @@ function handleClick(menu: SysMenu) {
|
||||
color: #334155;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
line-height: 1.5;
|
||||
transition: color 0.3s;
|
||||
user-select: none;
|
||||
|
||||
@@ -63,7 +63,7 @@ function handleMenuClick(menu: SysMenu) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="notice-dropdown" :class="{ 'show': dropdownVisible }" :style="dropdownStyle"
|
||||
v-if="dropdownVisible" @mouseenter="openDropdown" @mouseleave="closeDropdown">
|
||||
<div class="notice-header">
|
||||
<h3>通知</h3>
|
||||
<h3>消息通知</h3>
|
||||
<span class="notice-count" v-if="unreadCount > 0">{{ unreadCount }}条未读</span>
|
||||
</div>
|
||||
<div class="notice-list" v-loading="loading">
|
||||
@@ -195,7 +195,7 @@ async function handleNoticeClick(item: MessageUserVO) {
|
||||
}
|
||||
|
||||
function viewAll() {
|
||||
router.push('/user/message');
|
||||
router.push('/user-center/message');
|
||||
forceCloseDropdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ input {
|
||||
padding: 0 90px 0 20px;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-size: 14px;
|
||||
color: #141F38;
|
||||
|
||||
|
||||
@@ -43,6 +43,18 @@
|
||||
</div>
|
||||
</Teleport>
|
||||
</div>
|
||||
|
||||
<!-- 特殊标签:专题报告和思政案例 -->
|
||||
<div
|
||||
v-for="tag in specialTags"
|
||||
:key="tag.tagID"
|
||||
class="nav-item special-tag"
|
||||
:class="{ active: isTagActive(tag) }"
|
||||
>
|
||||
<div class="nav-link" @click="handleTagClick(tag)">
|
||||
<span>{{ tag.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧用户区域 -->
|
||||
<div class="nav-right">
|
||||
@@ -56,11 +68,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import type { SysMenu } from '@/types';
|
||||
import { MenuType } from '@/types/enums';
|
||||
import type { Tag } from '@/types/resource';
|
||||
import { resourceTagApi } from '@/apis/resource';
|
||||
// @ts-ignore - Vue 3.5 组件导入兼容性
|
||||
import {UserDropdown, Search, Notice} from '@/components/base';
|
||||
const router = useRouter();
|
||||
@@ -70,11 +84,32 @@ const store = useStore();
|
||||
const activeDropdown = ref<string | null>(null);
|
||||
const searchKeyword = ref('');
|
||||
const dropdownPositions = ref<Record<string, { left: number; top: number; width: number }>>({});
|
||||
const specialTags = ref<Tag[]>([]); // 特殊标签:专题报告和思政案例
|
||||
|
||||
// 获取所有菜单
|
||||
const allMenus = computed(() => store.getters['auth/menuTree']);
|
||||
const userInfo = computed(() => store.getters['auth/user']);
|
||||
|
||||
// 加载特殊标签
|
||||
onMounted(async () => {
|
||||
await loadSpecialTags();
|
||||
});
|
||||
|
||||
// 加载特殊标签(专题报告和思政案例)
|
||||
async function loadSpecialTags() {
|
||||
try {
|
||||
const res = await resourceTagApi.getTagsByType(1); // 1 = 文章分类标签
|
||||
if (res.success && res.dataList) {
|
||||
// 只获取专题报告(tag005)和思政案例(tag006)
|
||||
specialTags.value = res.dataList.filter((tag: Tag) =>
|
||||
tag.tagID === 'tag_article_005' || tag.tagID === 'tag_article_006'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载特殊标签失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取第一层的导航菜单(MenuType.NAVIGATION),过滤掉用户相关菜单
|
||||
const navigationMenus = computed(() => {
|
||||
const menus = allMenus.value.filter((menu: SysMenu) => {
|
||||
@@ -116,6 +151,15 @@ function getNavigationChildren(menu: SysMenu): SysMenu[] {
|
||||
function isActive(menu: SysMenu): boolean {
|
||||
if (!menu.url) return false;
|
||||
|
||||
// 特殊处理:如果是资源中心菜单,且 URL 中有特殊标签的 tagID,则不激活
|
||||
if (menu.url === '/resource-center' && route.path === '/resource-center') {
|
||||
const tagID = route.query.tagID as string;
|
||||
// 如果 tagID 是特殊标签(专题报告或思政案例),则不激活资源中心菜单
|
||||
if (tagID === 'tag_article_005' || tagID === 'tag_article_006') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 精确匹配
|
||||
if (route.path === menu.url) return true;
|
||||
|
||||
@@ -206,6 +250,20 @@ function handleNavClick(menu: SysMenu) {
|
||||
}
|
||||
}
|
||||
|
||||
// 处理特殊标签点击
|
||||
function handleTagClick(tag: Tag) {
|
||||
// 导航到资源中心,并传递 tagID 参数
|
||||
router.push({
|
||||
path: '/resource-center',
|
||||
query: { tagID: tag.tagID }
|
||||
});
|
||||
}
|
||||
|
||||
// 判断标签是否激活
|
||||
function isTagActive(tag: Tag): boolean {
|
||||
return route.path === '/resource-center' && route.query.tagID === tag.tagID;
|
||||
}
|
||||
|
||||
// 处理搜索
|
||||
function handleSearch(keyword: string) {
|
||||
if (keyword && keyword.trim()) {
|
||||
@@ -256,7 +314,7 @@ function handleLogout() {
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 700;
|
||||
font-size: 20.6px;
|
||||
line-height: 1.31;
|
||||
@@ -328,7 +386,7 @@ function handleLogout() {
|
||||
gap: 2px;
|
||||
padding: 26px 21px;
|
||||
color: #141F38;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -380,7 +438,7 @@ function handleLogout() {
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
color: #333;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
@@ -425,7 +483,7 @@ function handleLogout() {
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 7px 20px;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<el-form-item label="助手描述">
|
||||
<el-input
|
||||
v-model="configForm.systemPrompt"
|
||||
v-model="configForm.description"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="请输入助手描述,介绍AI助手的功能、特点和用途..."
|
||||
@@ -104,7 +104,7 @@ defineOptions({
|
||||
const configForm = ref<AiAgentConfig>({
|
||||
name: '',
|
||||
avatar: '',
|
||||
systemPrompt: '',
|
||||
description: '',
|
||||
connectInternet: 0,
|
||||
modelName: '',
|
||||
modelProvider: 'dify',
|
||||
|
||||
@@ -348,7 +348,7 @@ function handleDialogClose() {
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
@@ -366,7 +366,7 @@ function handleDialogClose() {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
color: #FFFFFF;
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 1.43em;
|
||||
@@ -409,7 +409,7 @@ function handleDialogClose() {
|
||||
|
||||
.category-title {
|
||||
margin: 0;
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
line-height: 1.5em;
|
||||
@@ -417,7 +417,7 @@ function handleDialogClose() {
|
||||
}
|
||||
|
||||
.category-count {
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.5em;
|
||||
@@ -462,7 +462,7 @@ function handleDialogClose() {
|
||||
}
|
||||
|
||||
.tag-name {
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
@@ -478,7 +478,7 @@ function handleDialogClose() {
|
||||
background: #ECEEF2;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 1.33em;
|
||||
@@ -501,7 +501,7 @@ function handleDialogClose() {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 1.43em;
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<div class="message-avatar">
|
||||
<div class="avatar-circle ai-avatar">
|
||||
<img v-if="agentAvatarUrl" :src="agentAvatarUrl" alt="AI助手" class="ai-avatar-img" />
|
||||
<span v-else>🤖</span>
|
||||
<img v-else src="@/assets/imgs/assistant.svg" alt="AI助手" class="ai-avatar-img" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="message-content">
|
||||
@@ -1142,6 +1142,7 @@ onUnmounted(() => {
|
||||
.ai-agent {
|
||||
position: fixed;
|
||||
z-index: 50;
|
||||
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
&.expanded {
|
||||
top: 50%;
|
||||
|
||||
@@ -111,7 +111,7 @@ function handleClick() {
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
@@ -126,7 +126,7 @@ function handleClick() {
|
||||
flex-direction: column;
|
||||
|
||||
.article-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 1.25em;
|
||||
line-height: 1.4;
|
||||
@@ -141,7 +141,7 @@ function handleClick() {
|
||||
}
|
||||
|
||||
.article-desc {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
@@ -173,7 +173,7 @@ function handleClick() {
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
@@ -182,7 +182,7 @@ function handleClick() {
|
||||
}
|
||||
|
||||
.view-count {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
|
||||
@@ -113,7 +113,7 @@ function handleClick() {
|
||||
box-sizing: border-box;
|
||||
|
||||
.day {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 1.875em;
|
||||
line-height: 0.73;
|
||||
@@ -123,7 +123,7 @@ function handleClick() {
|
||||
}
|
||||
|
||||
.month {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
@@ -140,7 +140,7 @@ function handleClick() {
|
||||
flex-direction: column;
|
||||
|
||||
.card-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 1.25em;
|
||||
line-height: 1.4;
|
||||
@@ -155,7 +155,7 @@ function handleClick() {
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.57;
|
||||
|
||||
@@ -735,7 +735,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.article-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 28px;
|
||||
line-height: 28px;
|
||||
@@ -753,7 +753,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
@@ -780,7 +780,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
|
||||
@@ -69,7 +69,7 @@ function handleLearn() {
|
||||
background: #FFFFFF;
|
||||
border-radius: 12px;
|
||||
border: none;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 22.4px;
|
||||
|
||||
@@ -530,7 +530,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.course-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
@@ -539,7 +539,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.course-desc {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
@@ -568,7 +568,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
@@ -590,7 +590,7 @@ function formatDuration(minutes?: number): string {
|
||||
gap: 14px;
|
||||
|
||||
.progress-label {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
@@ -620,7 +620,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.progress-percent {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
@@ -637,7 +637,7 @@ function formatDuration(minutes?: number): string {
|
||||
:deep(.el-button) {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
padding: 8px 24px;
|
||||
@@ -727,7 +727,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -772,7 +772,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.chapter-name {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -806,7 +806,7 @@ function formatDuration(minutes?: number): string {
|
||||
flex: 1;
|
||||
|
||||
.node-number {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
@@ -825,7 +825,7 @@ function formatDuration(minutes?: number): string {
|
||||
}
|
||||
|
||||
.node-name {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
@@ -836,7 +836,7 @@ function formatDuration(minutes?: number): string {
|
||||
|
||||
.node-right {
|
||||
.node-status {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.57;
|
||||
|
||||
@@ -499,7 +499,7 @@ onMounted(() => {
|
||||
height: 80%;
|
||||
max-width: 1142px;
|
||||
margin: auto auto;
|
||||
box-shadow: 0px 4px 30px 0px rgba(176, 196, 225, 0.25);
|
||||
box-shadow: 0px 4px 30px 0px rgba(176, 196, 225, 0.5);
|
||||
border-radius: 30px;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
@@ -540,7 +540,7 @@ onMounted(() => {
|
||||
margin-top: 46.66px;
|
||||
|
||||
p {
|
||||
font-family: 'Taipei Sans TC Beta', 'PingFang SC', sans-serif;
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 50px;
|
||||
line-height: 1.42;
|
||||
@@ -606,7 +606,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -762,7 +762,7 @@ onMounted(() => {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
color: #FFFFFF;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
@@ -774,7 +774,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 1.8;
|
||||
@@ -788,7 +788,7 @@ onMounted(() => {
|
||||
width: 100%;
|
||||
|
||||
.register-link {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
line-height: 1.83;
|
||||
@@ -806,7 +806,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-size: 12px;
|
||||
line-height: 2;
|
||||
color: #D9D9D9;
|
||||
|
||||
@@ -517,7 +517,7 @@ onUnmounted(() => {
|
||||
height: 80%;
|
||||
max-width: 1142px;
|
||||
margin: auto auto;
|
||||
box-shadow: 0px 4px 30px 0px rgba(176, 196, 225, 0.25);
|
||||
box-shadow: 0px 4px 30px 0px rgba(176, 196, 225, 0.5);
|
||||
border-radius: 30px;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
@@ -557,7 +557,7 @@ onUnmounted(() => {
|
||||
margin-top: 46.66px;
|
||||
|
||||
p {
|
||||
font-family: 'Taipei Sans TC Beta', 'PingFang SC', sans-serif;
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 50px;
|
||||
line-height: 1.42;
|
||||
@@ -623,7 +623,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.register-title {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -718,7 +718,7 @@ onUnmounted(() => {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
color: #FFFFFF;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
@@ -730,7 +730,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 1.8;
|
||||
@@ -744,7 +744,7 @@ onUnmounted(() => {
|
||||
width: 100%;
|
||||
|
||||
.login-link {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
line-height: 1.83;
|
||||
@@ -762,7 +762,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-size: 12px;
|
||||
line-height: 2;
|
||||
color: #D9D9D9;
|
||||
|
||||
@@ -104,7 +104,7 @@ function getChartOption(): EChartsOption {
|
||||
axisLabel: {
|
||||
color: '#979797',
|
||||
fontSize: 14,
|
||||
fontFamily: 'PingFang SC'
|
||||
fontFamily: 'Source Han Sans SC'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
@@ -121,7 +121,7 @@ function getChartOption(): EChartsOption {
|
||||
axisLabel: {
|
||||
color: '#979797',
|
||||
fontSize: 14,
|
||||
fontFamily: 'PingFang SC'
|
||||
fontFamily: 'Source Han Sans SC";'
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
@@ -221,7 +221,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.progress-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 38px;
|
||||
@@ -230,7 +230,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.update-time {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -254,7 +254,7 @@ onUnmounted(() => {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
@@ -512,7 +512,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
@@ -527,7 +527,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
padding: 10px;
|
||||
|
||||
.task-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
@@ -536,7 +536,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
}
|
||||
|
||||
.task-description {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.5714285714285714;
|
||||
@@ -560,7 +560,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 1.5714285714285714;
|
||||
@@ -612,7 +612,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
gap: 8px;
|
||||
|
||||
.stat-label {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 1.5714285714285714;
|
||||
@@ -620,7 +620,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
@@ -654,7 +654,7 @@ function getItemStatusType(status?: number): 'info' | 'warning' | 'success' {
|
||||
|
||||
.progress-label,
|
||||
.progress-value {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
|
||||
@@ -234,7 +234,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.section {
|
||||
max-width: 1440px;
|
||||
// max-width: 1440px;
|
||||
margin: 0 auto;
|
||||
padding: 0 120px;
|
||||
margin-top: 60px;
|
||||
@@ -246,7 +246,7 @@ onMounted(() => {
|
||||
margin-bottom: 24px;
|
||||
|
||||
.section-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 28px;
|
||||
line-height: 38px;
|
||||
@@ -262,7 +262,7 @@ onMounted(() => {
|
||||
transition: color 0.3s;
|
||||
|
||||
span {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: 'Source Han Sans SC', sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
@@ -311,12 +311,14 @@ onMounted(() => {
|
||||
padding: 20px;
|
||||
|
||||
.header {
|
||||
max-width: 900px;
|
||||
// max-width: 900px;
|
||||
width: 90%;
|
||||
margin: 0 auto 20px;
|
||||
}
|
||||
|
||||
.detail-container {
|
||||
max-width: 900px;
|
||||
// max-width: 900px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
|
||||
.message-card {
|
||||
|
||||
@@ -347,7 +347,8 @@ onMounted(() => {
|
||||
|
||||
.my-message-list {
|
||||
padding: 20px;
|
||||
max-width: 1200px;
|
||||
width: 90%;
|
||||
// max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
min-height: calc(100vh - 76px - 40px);
|
||||
display: flex;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
:category-name="currentCategoryName"
|
||||
:show-article-mode="showArticle"
|
||||
/>
|
||||
<div class="search-wrapper">
|
||||
<!-- <div class="search-wrapper">
|
||||
<Search @search="handleSearch" />
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="content-wrapper">
|
||||
<div class="content-container">
|
||||
<ResourceSideBar
|
||||
@@ -37,11 +37,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ResourceSideBar, ResourceList, ResourceArticle } from './components';
|
||||
import { Search, CenterHead } from '@/components/base';
|
||||
import type { Resource, Tag } from '@/types/resource';
|
||||
import { resourceApi } from '@/apis/resource';
|
||||
import { resourceApi, resourceTagApi } from '@/apis/resource';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const showArticle = ref(false);
|
||||
const currentCategoryId = ref('tag_article_001');
|
||||
@@ -51,16 +55,59 @@ const searchKeyword = ref('');
|
||||
const resourceListRef = ref();
|
||||
const resourceList = ref<Resource[]>([]);
|
||||
|
||||
// 组件加载时检查 URL 参数
|
||||
onMounted(async () => {
|
||||
const tagID = route.query.tagID as string;
|
||||
if (tagID) {
|
||||
await loadTagInfo(tagID);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听路由参数变化
|
||||
watch(() => route.query.tagID, async (newTagID) => {
|
||||
if (newTagID && typeof newTagID === 'string') {
|
||||
await loadTagInfo(newTagID);
|
||||
}
|
||||
});
|
||||
|
||||
// 加载标签信息
|
||||
async function loadTagInfo(tagID: string) {
|
||||
try {
|
||||
const res = await resourceTagApi.getTagsByType(1); // 1 = 文章分类标签
|
||||
if (res.success && res.dataList) {
|
||||
const tag = res.dataList.find((t: Tag) => t.tagID === tagID);
|
||||
if (tag) {
|
||||
currentCategoryId.value = tag.tagID || '';
|
||||
currentCategoryName.value = tag.name || '';
|
||||
searchKeyword.value = '';
|
||||
showArticle.value = false;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载标签信息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCategoryChange(category: Tag) {
|
||||
currentCategoryId.value = category.tagID || category.id || '';
|
||||
currentCategoryName.value = category.name || '';
|
||||
searchKeyword.value = '';
|
||||
showArticle.value = false;
|
||||
|
||||
// 清除 URL 中的 tagID 参数,确保 URL 与实际显示的分类一致
|
||||
if (route.query.tagID) {
|
||||
router.replace({ path: route.path, query: {} });
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch(keyword: string) {
|
||||
searchKeyword.value = keyword;
|
||||
showArticle.value = false;
|
||||
|
||||
// 清除 URL 中的 tagID 参数
|
||||
if (route.query.tagID) {
|
||||
router.replace({ path: route.path, query: {} });
|
||||
}
|
||||
}
|
||||
|
||||
function handleListUpdated(list: Resource[]) {
|
||||
@@ -113,7 +160,8 @@ async function handleArticleNavigate(direction: 'prev' | 'next', resourceId: str
|
||||
padding: 20px 0;
|
||||
|
||||
:deep(.resource-search) {
|
||||
width: 1200px;
|
||||
// width: 1200px;
|
||||
width: 90%;
|
||||
height: 60px;
|
||||
padding: 0;
|
||||
|
||||
@@ -145,7 +193,7 @@ async function handleArticleNavigate(direction: 'prev' | 'next', resourceId: str
|
||||
}
|
||||
|
||||
.content-container {
|
||||
width: 1200px;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 24px;
|
||||
|
||||
@@ -48,7 +48,7 @@ function handleNavigate(direction: 'prev' | 'next') {
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
@@ -60,7 +60,7 @@ function handleCollect() {
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
|
||||
@@ -231,7 +231,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.resource-title {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 28px;
|
||||
line-height: 28px;
|
||||
@@ -251,7 +251,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
@@ -260,7 +260,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.resource-summary {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
@@ -278,7 +278,7 @@ defineExpose({
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-size: 14px;
|
||||
color: #979797;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ function handleCategoryClick(category: Tag) {
|
||||
}
|
||||
|
||||
.category-name {
|
||||
font-family: 'PingFang SC';
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
@@ -57,4 +57,12 @@ function handleMenuClick(menu: SysMenu) {
|
||||
min-height: 100vh;
|
||||
background: #F9F9F9;
|
||||
}
|
||||
:deep(.menu-container){
|
||||
width: 90%;
|
||||
max-width: none;
|
||||
}
|
||||
:deep(.main-content .container){
|
||||
width: 90%;
|
||||
max-width: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,20 +5,7 @@
|
||||
<div class="container">
|
||||
<!-- 任务进度 -->
|
||||
<h2 class="section-title">任务进度</h2>
|
||||
<div class="progress-card">
|
||||
<div class="progress-info">
|
||||
<div class="progress-header">
|
||||
<span class="progress-text">当前学习进度({{ completedCount }}/{{ totalCount }})</span>
|
||||
<!-- <span class="progress-percent">{{ progressPercent }}%</span> -->
|
||||
<!-- <span class="progress-level">{{ userLevel }}</span> -->
|
||||
</div>
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" :style="{ width: progressPercent + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress-card">
|
||||
<div class="task-stats">
|
||||
<div class="stat-card pending">
|
||||
<div class="stat-content">
|
||||
@@ -26,7 +13,7 @@
|
||||
<div class="stat-number">{{ pendingCount }}</div>
|
||||
</div>
|
||||
<div class="stat-icon pending-icon">
|
||||
<el-icon><DocumentCopy /></el-icon>
|
||||
<el-icon><img src="@/assets/imgs/learningtask.svg" /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +23,20 @@
|
||||
<div class="stat-number">{{ completedCount }}</div>
|
||||
</div>
|
||||
<div class="stat-icon completed-icon">
|
||||
<el-icon><DocumentChecked /></el-icon>
|
||||
<el-icon><img src="@/assets/imgs/finishtask.svg" /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress-info">
|
||||
<div class="progress-header">
|
||||
<span class="progress-text">当前学习进度({{ completedCount }}/{{ totalCount }})</span>
|
||||
<!-- <span class="progress-percent">{{ progressPercent }}%</span> -->
|
||||
<!-- <span class="progress-level">{{ userLevel }}</span> -->
|
||||
</div>
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" :style="{ width: progressPercent + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -310,8 +310,10 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
box-shadow: 0 17px 22.4px rgba(164, 182, 199, 0.1);
|
||||
|
||||
.progress-info {
|
||||
margin-bottom: 40px;
|
||||
|
||||
margin-top: 20px;
|
||||
border-radius: 10px;
|
||||
background: #F7F8F9;
|
||||
padding: 10px;
|
||||
.progress-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -338,16 +340,17 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
}
|
||||
|
||||
.progress-bar-container {
|
||||
// margin: 20px;
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 12px;
|
||||
background: #F7F8F9;
|
||||
background: #ffffff;
|
||||
border-radius: 27px;
|
||||
overflow: hidden;
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(143deg, #FD9082 1%, #FD6D78 99%);
|
||||
background: linear-gradient(143deg, #3D3D3D 1%, #3D3D3D 99%);
|
||||
border-radius: 27px;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
@@ -370,6 +373,8 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
align-items: center;
|
||||
|
||||
&.pending {
|
||||
background: linear-gradient(45deg, #ffffff 0%, #FFF1F0 100%);
|
||||
|
||||
.stat-icon {
|
||||
background: #FFF5F4;
|
||||
|
||||
@@ -384,7 +389,7 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
}
|
||||
|
||||
&.completed {
|
||||
background: #FBFDFF;
|
||||
background: linear-gradient(45deg, #ffffff 0%, #F0FAFF 100%);
|
||||
|
||||
.stat-icon {
|
||||
background: #EFF8FF;
|
||||
@@ -548,7 +553,7 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
|
||||
// 学习进度
|
||||
.task-progress {
|
||||
margin-bottom: auto;
|
||||
margin-top: auto;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.progress-header {
|
||||
@@ -593,7 +598,7 @@ function getDeadlineStatus(task: TaskItemVO): { show: boolean; text: string; typ
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-top: auto;
|
||||
// margin-top: auto;
|
||||
|
||||
.task-time {
|
||||
display: flex;
|
||||
|
||||
@@ -63,14 +63,14 @@ const menus = computed(() => {
|
||||
}
|
||||
|
||||
.user-card-wrapper {
|
||||
width: 100%;
|
||||
width: 90%;
|
||||
height: 25%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
width: 100%;
|
||||
width: 90%;
|
||||
|
||||
height: 75%;
|
||||
display: flex;
|
||||
|
||||
@@ -117,7 +117,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
@@ -130,7 +130,7 @@ onMounted(async () => {
|
||||
background: rgba(198, 40, 40, 0.05);
|
||||
border: 1px solid #C62828;
|
||||
border-radius: 4px;
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
@@ -178,7 +178,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.username {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
@@ -198,7 +198,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.gender-text {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
@@ -212,7 +212,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -226,7 +226,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
@@ -239,7 +239,7 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.level-text {
|
||||
font-family: 'PingFang SC', sans-serif;
|
||||
font-family: "Source Han Sans SC";
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
|
||||
Reference in New Issue
Block a user