diff --git a/app/Models/ReportLink.php b/app/Models/ReportLink.php new file mode 100644 index 000000000..12a4a5d0e --- /dev/null +++ b/app/Models/ReportLink.php @@ -0,0 +1,86 @@ +hasOne(Report::class, 'id', 'report_id'); + } + + /** + * 生成链接 + * @param $rid + * @param $userid + * @param $refresh + * @return array + */ + public static function generateLink($rid, $userid, $refresh = false) + { + $report = Report::find($rid); + if (empty($report)) { + throw new ApiException('报告不存在或已被删除'); + } + if ($report->userid != $userid) { + if (!ReportReceive::whereRid($rid)->whereUserid($userid)->exists()) { + throw new ApiException('您没有权限查看该报告'); + } + } + $reportLink = ReportLink::whereRid($rid)->whereUserid($userid)->first(); + if (empty($reportLink)) { + $reportLink = ReportLink::createInstance([ + 'rid' => $rid, + 'userid' => $userid, + 'code' => base64_encode("{$rid},{$userid}," . Base::generatePassword()), + ]); + $reportLink->save(); + } else { + if ($refresh == 'yes') { + $reportLink->code = base64_encode("{$rid},{$userid}," . Base::generatePassword()); + $reportLink->save(); + } + } + return [ + 'id' => $rid, + 'url' => Base::fillUrl('single/report/detail/' . $reportLink->code), + 'code' => $reportLink->code, + 'num' => $reportLink->num + ]; + } +} diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php index 825746df5..89ab2d20c 100644 --- a/app/Models/WebSocketDialogMsg.php +++ b/app/Models/WebSocketDialogMsg.php @@ -962,6 +962,18 @@ class WebSocketDialogMsg extends AbstractModel throw new ApiException('文件分享错误'); } } + } elseif ($matchChar[1] === "%") { + if (Base::isNumber($keyId)) { + $reportLink = ReportLink::generateLink($keyId, User::userid()); + $keyId = $reportLink['code']; + } else { + preg_match("/\/single\/report\/detail\/(.*?)$/i", $keyId, $match); + if ($match && strlen($match[1]) >= 8) { + $keyId = $match[1]; + } else { + throw new ApiException('报告分享错误'); + } + } } $text = str_replace($matchs[0][$key], "[:{$matchChar[1]}:{$keyId}:{$matchValye[1]}:]", $text); } @@ -1044,6 +1056,7 @@ class WebSocketDialogMsg extends AbstractModel $text = preg_replace("/\[:@:(.*?):(.*?):\]/i", "@$2", $text); $text = preg_replace("/\[:#:(.*?):(.*?):\]/is", "#$2", $text); $text = preg_replace("/\[:~:(.*?):(.*?):\]/i", "~$2", $text); + $text = preg_replace("/\[:%:(.*?):(.*?):\]/i", "%$2", $text); $text = preg_replace("/\[:QUICK:(.*?):(.*?):\]/i", "$2", $text); return preg_replace("/^(
<\/p>)+|(
<\/p>)+$/i", "", $text);
}
diff --git a/database/migrations/2025_03_15_164703_create_report_links_table.php b/database/migrations/2025_03_15_164703_create_report_links_table.php
new file mode 100644
index 000000000..a0b1cd136
--- /dev/null
+++ b/database/migrations/2025_03_15_164703_create_report_links_table.php
@@ -0,0 +1,35 @@
+bigIncrements('id');
+ $table->bigInteger('rid')->nullable()->default(0)->index()->comment('报告ID');
+ $table->integer('num')->nullable()->default(0)->comment('累计访问');
+ $table->string('code')->nullable()->default('')->comment('链接码');
+ $table->bigInteger('userid')->nullable()->default(0)->index()->comment('会员ID');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('report_links');
+ }
+}
diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue
index 9f64aef6f..98ee6b2f0 100644
--- a/resources/assets/js/pages/manage/components/DialogWrapper.vue
+++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue
@@ -3340,8 +3340,14 @@ export default {
this.$refs.input.setText(text)
} else {
if (text.indexOf("mention") > -1) {
- text = text.replace(/]*)>~([^>]*)<\/a>/g, '~$3')
- text = text.replace(/([@#])([^>]*)<\/span>/g, '$3$4')
+ text = text.replace(
+ /]*>([~%])([^>]*)<\/a>/g,
+ '$3$4'
+ )
+ text = text.replace(
+ /([@#])([^>]*)<\/span>/g,
+ '$3$4'
+ )
}
text = text.replace(/]*>/gi, match => {
return match.replace(/(width|height)="\d+"\s*/ig, "");
diff --git a/resources/assets/sass/dark.scss b/resources/assets/sass/dark.scss
index 99dfdfb77..63c8ff486 100644
--- a/resources/assets/sass/dark.scss
+++ b/resources/assets/sass/dark.scss
@@ -274,7 +274,9 @@ body.dark-mode-reverse {
color: #000000;
&.file,
- &[data-denotation-char="~"] {
+ &.report,
+ &[data-denotation-char="~"],
+ &[data-denotation-char="%"] {
color: #0027a1 !important;
}
}
diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss
index 50c276fae..6b39af888 100644
--- a/resources/assets/sass/pages/components/dialog-wrapper.scss
+++ b/resources/assets/sass/pages/components/dialog-wrapper.scss
@@ -1513,7 +1513,9 @@
}
&.file,
- &[data-denotation-char="~"] {
+ &.report,
+ &[data-denotation-char="~"],
+ &[data-denotation-char="%"] {
color: #436FF6 !important;
}