mirror of
https://gitee.com/likeadmin/likeadmin_java.git
synced 2026-06-11 00:37:09 +08:00
Compare commits
111 Commits
wjx2022091
...
1.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83f57ad01d | ||
|
|
e05348206e | ||
|
|
f4e4130cab | ||
|
|
0817b16615 | ||
|
|
f3b10f07b1 | ||
|
|
e191fc8d26 | ||
|
|
8052475e40 | ||
|
|
0cc7c8e7b9 | ||
|
|
9b5b625680 | ||
|
|
5d06003895 | ||
|
|
061543a191 | ||
|
|
c073cc65a7 | ||
|
|
5b9af90590 | ||
|
|
61ef48d446 | ||
|
|
331997e1e9 | ||
|
|
a4b6b2d6c8 | ||
|
|
140249aca8 | ||
|
|
6719e1b4f1 | ||
|
|
6bf572a01a | ||
|
|
b74724084e | ||
|
|
580c06686a | ||
|
|
235ab92413 | ||
|
|
4b58de936c | ||
|
|
611f59941f | ||
|
|
8db1cff376 | ||
|
|
6cb4ad95a7 | ||
|
|
5e9db85f86 | ||
|
|
11c06ec81e | ||
|
|
551a042582 | ||
|
|
eb0ab251d5 | ||
|
|
19e2d1c03b | ||
|
|
71066b6d83 | ||
|
|
6f11895f70 | ||
|
|
909b4f03a0 | ||
|
|
48e39fa4f9 | ||
|
|
b20738061e | ||
|
|
808cda3277 | ||
|
|
42c7936f40 | ||
|
|
dacded0e7a | ||
|
|
b2cf624380 | ||
|
|
5faf6aa301 | ||
|
|
b66eb35abb | ||
|
|
ee8636ec54 | ||
|
|
a6d3ffb016 | ||
|
|
04a5d121a8 | ||
|
|
a70c5f6fc3 | ||
|
|
6dc8cc78a2 | ||
|
|
78db1ace6d | ||
|
|
158125c3d0 | ||
|
|
abc001b76b | ||
|
|
4574db504a | ||
|
|
dfc50e2623 | ||
|
|
04290c78de | ||
|
|
a717ee326c | ||
|
|
5e844a1d38 | ||
|
|
cbdb12f5d7 | ||
|
|
a8e08053be | ||
|
|
a70ec891d7 | ||
|
|
d12cae1937 | ||
|
|
78726b8373 | ||
|
|
5dfea2ad46 | ||
|
|
6e0f1ade38 | ||
|
|
f89d34915b | ||
|
|
8db154f01d | ||
|
|
878f740bda | ||
|
|
1df98b147a | ||
|
|
cadad25176 | ||
|
|
73984d52c0 | ||
|
|
c3ea44292f | ||
|
|
02317bee8e | ||
|
|
61dc2bf16d | ||
|
|
db45652f28 | ||
|
|
51b35b664d | ||
|
|
29999f4e4a | ||
|
|
77fb6acc2d | ||
|
|
b512eac708 | ||
|
|
654c7b3c11 | ||
|
|
fe5522dc2d | ||
|
|
aee93d81b4 | ||
|
|
56da1c18dd | ||
|
|
ccd4747203 | ||
|
|
5240b89b35 | ||
|
|
db7a0e3161 | ||
|
|
8f52978021 | ||
|
|
83469090dd | ||
|
|
fa4de3214d | ||
|
|
65da3d4a3a | ||
|
|
a7e50bf511 | ||
|
|
e40689135f | ||
|
|
3560cd45c5 | ||
|
|
8d75e4c934 | ||
|
|
9393de9063 | ||
|
|
e0f11a53e2 | ||
|
|
b142dee20f | ||
|
|
3d83b85588 | ||
|
|
18cbb4374c | ||
|
|
ba7560b9e2 | ||
|
|
b7e010b634 | ||
|
|
8167380abe | ||
|
|
c69c104cd6 | ||
|
|
370cde09c4 | ||
|
|
5ae19337d9 | ||
|
|
387b38a009 | ||
|
|
8ee7d03ce2 | ||
|
|
9be1caf811 | ||
|
|
53071be070 | ||
|
|
769c1c0ff6 | ||
|
|
b660028a6c | ||
|
|
4ee067a1f7 | ||
|
|
3f699d3c7c | ||
|
|
2db501d36d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,5 +5,6 @@
|
||||
target/
|
||||
application-dev.yml
|
||||
application-pro.yml
|
||||
application-dem.yml
|
||||
application-prod.yml
|
||||
application-test.yml
|
||||
214
LICENSE
214
LICENSE
@@ -1,201 +1,21 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
MIT License
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (c) 2022 likeshop技术社区
|
||||
|
||||
1. Definitions.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
26
README.md
26
README.md
@@ -1,5 +1,5 @@
|
||||
<h1 align="center">likeadmin通用管理后台(Java)</h1>
|
||||
<h4 align="center">🚀快速开发、🛠️ 一键生成代码、📱手机自适应</h4>
|
||||
<h4 align="center">🚀快速开发、🛠️ 一键生成代码、✅后台多端自适应、📱手机端uniapp前台</h4>
|
||||
<p align="center">
|
||||
<a href="https://www.java.com/zh-CN/download/"><img src="https://img.shields.io/badge/JAVA-8-d74f11"> </a><a href="#"> <img src="https://img.shields.io/badge/Spring Boot-2-5ea931"> </a><a href="https://www.tslang.cn/"><img src="https://img.shields.io/badge/TypeScript-3-294e80"></a> <a href="#"><img src="https://img.shields.io/badge/Vue.js-3-4eb883"> </a><a href="#"><img src="https://img.shields.io/badge/vite-2-ffc018"> </a><a href="#"><img src="https://img.shields.io/badge/Element Plus-2-409eff"> </a><a target="_blank" href="https://www.docker.com/"><img src="https://img.shields.io/badge/Docker--139cff"></a>
|
||||
<div align="center">
|
||||
@@ -7,9 +7,14 @@
|
||||
</div>
|
||||
<br>
|
||||
|
||||
## 👀体验后台
|
||||
|
||||
## 👀体验
|
||||
### 管理后台
|
||||
地址:https://demo-java.likeadmin.cn <br>
|
||||
账号:admin 密码:123456
|
||||
### 手机端uniapp前台
|
||||
<img width="40%" src="https://md.likeshop.cn/server/index.php?s=/api/attachment/visitFile&sign=260c0869d9ba7e692b2db1e216078241" /><br>
|
||||
|
||||
|
||||
|
||||
## 👨💻简介
|
||||
@@ -20,24 +25,33 @@
|
||||
1.likeadmin已经搭建好前后端分离的底层,包含程序安装、登录、登出、工作台、菜单权限控制、角色、管理员、部门管理、岗位管理、素材管理、网站设置、图库管理等基础功能,无需重复造轮子。更有开发者工具功能,一生成代码,大大节省开发时间。<br>
|
||||
2.可视化系统程序安装界面,可自定义安装数据,开发者可快速扩展发行自己的软件产品。<br>
|
||||
3.likeadmin定位为通用的软件系统管理后台,方便开发者快速开发软件系统,文档清晰、代码易懂、简单易用。<br>
|
||||
4.未来将持续集成通用的微信/支付宝支付,阿里云/腾讯云短信,阿里云/腾讯云OSS等通用模块。
|
||||
4.手机端uniapp前台,含导导航配置、微信登录、个人登录等等基础功能,方便根据业务开发含手机前台的项目。
|
||||
|
||||
|
||||
### 🐙 后端架构方面
|
||||
1.服务端使用JAVA8开发,性能有突破性的提升。<br>
|
||||
2.使用Spring Boot2.5框架,目前国内流行的JAVA框架,高性能、简单易用、文档齐全、支持Mave高级项目管理工具、支持Redis等。
|
||||
### 🐹 前端架构方面
|
||||
#### 后台
|
||||
1.使用最流性的前后端分离方案typescript、vue3、vite开发,保持了代码的简洁、一致和规范。<br>
|
||||
2.后台界面使用element-plus UI框架,简单精美的后台界面,丰富的组件库,方便快速开发,满足各种后台交互。
|
||||
<br>
|
||||
### 前台
|
||||
手机端uniapp前台,可以编译成手机H5网页、微信小程序、安卓App,苹果App等客户端。<br>
|
||||
### 🛠️ 代码生成器
|
||||
一键生成前后端业务代码,大大提示开发效率。
|
||||
|
||||
### 🖥️界面预览
|
||||
一键生成前后端业务代码,大大提示开发效率。<br>
|
||||
## 界面预览
|
||||
### 🖥️后台页面
|
||||
<br>
|
||||

|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
### 📱手机端前台界面
|
||||
<div class="half">
|
||||
<img width="30%" src="https://md.likeshop.cn/server/index.php?s=/api/attachment/visitFile&sign=2dbac190afadfb6650a04c8af44980e1" /> <img width="30%" src="https://md.likeshop.cn/server/index.php?s=/api/attachment/visitFile&sign=73adbdb91ff5c43ca3e694a99effae7a" /> <img width="30%" src="https://md.likeshop.cn/server/index.php?s=/api/attachment/visitFile&sign=55b51eaebd7d696f96ccbf60d4694368" />
|
||||
</div><br>
|
||||
|
||||
### 🪐接口文档
|
||||
[点击这里进入更多更详细文档。](https://www.likeadmin.cn "点击这里进入更多更详细文档。")
|
||||
@@ -1,4 +0,0 @@
|
||||
NODE_ENV = 'development'
|
||||
|
||||
# 请求域名
|
||||
VITE_APP_BASE_URL='https://likeadmin-java.yixiangonline.com'
|
||||
4
admin/.env.development.example
Normal file
4
admin/.env.development.example
Normal file
@@ -0,0 +1,4 @@
|
||||
NODE_ENV = 'development'
|
||||
|
||||
# 请求域名
|
||||
VITE_APP_BASE_URL=''
|
||||
3
admin/.gitignore
vendored
3
admin/.gitignore
vendored
@@ -30,3 +30,6 @@ components.d.ts
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# .env
|
||||
.env.development
|
||||
.env.production
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
"vite": "^3.0.0",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-tsc": "^0.38.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/utils/request'
|
||||
import { firstToUpperCase } from '@/utils/util'
|
||||
|
||||
// 微信公众号配置保存
|
||||
export function setOaConfig(params: any) {
|
||||
@@ -47,12 +48,11 @@ export function setOaMenuPublish(params: Menu | any) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return { Promise }
|
||||
* @param { string } type
|
||||
* @description 获取回复列表
|
||||
* @description 默认回复列表
|
||||
*/
|
||||
export function getOaReplyList(params: { type: string }) {
|
||||
return request.get({ url: '/channel/oaReply/list', params })
|
||||
export function getOaReplyList(params: any) {
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.get({ url: `/channel/oaReply${type}/list`, params })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,8 +60,9 @@ export function getOaReplyList(params: { type: string }) {
|
||||
* @param { number } id
|
||||
* @description 回复列表删除
|
||||
*/
|
||||
export function oaReplyDel(params: { id: number }) {
|
||||
return request.post({ url: '/channel/oaReply/del', params })
|
||||
export function oaReplyDel(params: any) {
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.post({ url: `/channel/oaReply${type}/del`, params })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,8 +70,9 @@ export function oaReplyDel(params: { id: number }) {
|
||||
* @param { number } id
|
||||
* @description 回复状态修改
|
||||
*/
|
||||
export function changeOaReplyStatus(params: { id: number }) {
|
||||
return request.post({ url: '/channel/oaReply/status', params })
|
||||
export function changeOaReplyStatus(params: any) {
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.post({ url: `/channel/oaReply${type}/status`, params })
|
||||
}
|
||||
|
||||
export interface Reply {
|
||||
@@ -85,25 +87,26 @@ export interface Reply {
|
||||
}
|
||||
/**
|
||||
* @return { Promise }
|
||||
* @description 回复添加
|
||||
* @description 默认回复编辑
|
||||
*/
|
||||
export function oaReplyAdd(params: Reply) {
|
||||
return request.post({ url: '/channel/oaReply/add', params })
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.post({ url: `/channel/oaReply${type}/add`, params })
|
||||
}
|
||||
|
||||
/**
|
||||
* @return { Promise }
|
||||
* @description 回复编辑
|
||||
* @description 默认回复编辑
|
||||
*/
|
||||
export function oaReplyEdit(params: Reply) {
|
||||
return request.post({ url: '/channel/oaReply/edit', params })
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.post({ url: `/channel/oaReply${type}/edit`, params })
|
||||
}
|
||||
|
||||
/**
|
||||
* @return { Promise }
|
||||
* @param { string } type
|
||||
* @description 获取回复详情
|
||||
* @description 默认回复详情
|
||||
*/
|
||||
export function getOaReplyDetail(params: { id: number }) {
|
||||
return request.get({ url: '/channel/oaReply/detail', params })
|
||||
export function getOaReplyDetail(params: any) {
|
||||
const type = firstToUpperCase(params.type)
|
||||
return request.get({ url: `/channel/oaReply${type}/detail`, params })
|
||||
}
|
||||
|
||||
BIN
admin/src/assets/images/no_perms.png
Normal file
BIN
admin/src/assets/images/no_perms.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -15,9 +15,10 @@
|
||||
/>
|
||||
<material-picker
|
||||
ref="materialPickerRef"
|
||||
:type="fileType"
|
||||
:limit="-1"
|
||||
hidden-upload
|
||||
@change="imageSelectChange"
|
||||
@change="selectChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -39,12 +40,10 @@ const props = withDefaults(
|
||||
}>(),
|
||||
{
|
||||
modelValue: '',
|
||||
mode: 'simple',
|
||||
mode: 'default',
|
||||
height: '100%',
|
||||
width: 'auto',
|
||||
toolbarConfig: () => ({
|
||||
excludeKeys: ['fullScreen']
|
||||
})
|
||||
toolbarConfig: () => ({})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -55,16 +54,24 @@ const emit = defineEmits<{
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef()
|
||||
const materialPickerRef = shallowRef<InstanceType<typeof MaterialPicker>>()
|
||||
const fileType = ref('')
|
||||
|
||||
let insertImageFn: any
|
||||
let insertFn: any
|
||||
|
||||
const editorConfig: Partial<IEditorConfig> = {
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
customBrowseAndUpload(insertFn: any) {
|
||||
console.log(insertFn)
|
||||
customBrowseAndUpload(insert: any) {
|
||||
fileType.value = 'image'
|
||||
materialPickerRef.value?.showPopup(-1)
|
||||
insertImageFn = insertFn
|
||||
insertFn = insert
|
||||
}
|
||||
},
|
||||
uploadVideo: {
|
||||
customBrowseAndUpload(insert: any) {
|
||||
fileType.value = 'video'
|
||||
materialPickerRef.value?.showPopup(-1)
|
||||
insertFn = insert
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,9 +90,9 @@ const valueHtml = computed({
|
||||
}
|
||||
})
|
||||
|
||||
const imageSelectChange = (image: string[]) => {
|
||||
image.forEach((url) => {
|
||||
insertImageFn(url)
|
||||
const selectChange = (fileUrl: string[]) => {
|
||||
fileUrl.forEach((url) => {
|
||||
insertFn(url)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -100,3 +107,37 @@ const handleCreated = (editor: any) => {
|
||||
editorRef.value = editor // 记录 editor 实例,重要!
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.w-e-full-screen-container {
|
||||
z-index: 999999;
|
||||
}
|
||||
.w-e-text-container [data-slate-editor] ul {
|
||||
list-style: disc;
|
||||
}
|
||||
.w-e-text-container [data-slate-editor] ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,7 +20,11 @@ const props = defineProps({
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
...imageProps
|
||||
...imageProps,
|
||||
hideOnClickModal: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const styles = computed<CSSProperties>(() => {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="file-item" :style="{ height: fileSize, width: fileSize }">
|
||||
<div class="file-item relative" :style="{ height: fileSize, width: fileSize }">
|
||||
<el-image class="image" v-if="type == 'image'" fit="contain" :src="uri"></el-image>
|
||||
<video class="video" v-else-if="type == 'video'" :src="uri"></video>
|
||||
<div
|
||||
v-if="type == 'video'"
|
||||
class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] rounded-full w-5 h-5 flex justify-center items-center bg-[rgba(0,0,0,0.3)]"
|
||||
>
|
||||
<icon name="el-icon-CaretRight" :size="18" color="#fff" />
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,8 +45,7 @@ export function useCate(type: number) {
|
||||
}
|
||||
|
||||
// 添加分组
|
||||
const handleAddCate = async () => {
|
||||
const { value } = await feedback.prompt('', '添加分组')
|
||||
const handleAddCate = async (value: string) => {
|
||||
await fileCateAdd({
|
||||
type,
|
||||
name: value,
|
||||
@@ -56,8 +55,7 @@ export function useCate(type: number) {
|
||||
}
|
||||
|
||||
// 编辑分组
|
||||
const handleEditCate = async (name: string, id: number) => {
|
||||
const { value } = await feedback.prompt('', '重命分组', { inputValue: name })
|
||||
const handleEditCate = async (value: string, id: number) => {
|
||||
await fileCateEdit({
|
||||
id,
|
||||
name: value
|
||||
@@ -180,8 +178,7 @@ export function useFile(
|
||||
clearSelect()
|
||||
}
|
||||
|
||||
const handleFileRename = async (name: string, id: number) => {
|
||||
const { value } = await feedback.prompt('', '重命名', { inputValue: name })
|
||||
const handleFileRename = async (value: string, id: number) => {
|
||||
await fileRename({
|
||||
id,
|
||||
name: value
|
||||
|
||||
@@ -34,12 +34,22 @@
|
||||
<span class="muted m-r-10">···</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<div
|
||||
<popover-input
|
||||
v-perms="['common:album:cateRename']"
|
||||
@click="handleEditCate(data.name, data.id)"
|
||||
@confirm="handleEditCate($event, data.id)"
|
||||
size="default"
|
||||
:value="data.name"
|
||||
width="400px"
|
||||
:limit="20"
|
||||
show-limit
|
||||
teleported
|
||||
>
|
||||
<el-dropdown-item>命名分组</el-dropdown-item>
|
||||
</div>
|
||||
<div>
|
||||
<el-dropdown-item>
|
||||
命名分组
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</popover-input>
|
||||
<div
|
||||
v-perms="['common:album:cateDel']"
|
||||
@click="handleDeleteCate(data.id)"
|
||||
@@ -57,9 +67,17 @@
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-2 border-t border-br">
|
||||
<el-button @click="handleAddCate" v-perms="['common:album:cateAdd']">
|
||||
添加分组
|
||||
</el-button>
|
||||
<popover-input
|
||||
v-perms="['common:album:cateAdd']"
|
||||
@confirm="handleAddCate"
|
||||
size="default"
|
||||
width="400px"
|
||||
:limit="20"
|
||||
show-limit
|
||||
teleported
|
||||
>
|
||||
<el-button> 添加分组 </el-button>
|
||||
</popover-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="material__center flex flex-col">
|
||||
@@ -195,14 +213,18 @@
|
||||
|
||||
<overflow-tooltip class="mt-1" :content="item.name" />
|
||||
<div class="operation-btns flex items-center">
|
||||
<el-button
|
||||
<popover-input
|
||||
v-perms="['common:album:albumRename']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleFileRename(item.name, item.id)"
|
||||
@confirm="handleFileRename($event, item.id)"
|
||||
size="default"
|
||||
:value="item.name"
|
||||
width="400px"
|
||||
:limit="50"
|
||||
show-limit
|
||||
teleported
|
||||
>
|
||||
重命名
|
||||
</el-button>
|
||||
<el-button type="primary" link> 重命名 </el-button>
|
||||
</popover-input>
|
||||
<el-button type="primary" link @click="handlePreview(item.uri)">
|
||||
查看
|
||||
</el-button>
|
||||
@@ -226,27 +248,33 @@
|
||||
<el-checkbox :modelValue="isSelect(row.id)" @change="selectFile(row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图片" width="60">
|
||||
<el-table-column label="图片" width="100">
|
||||
<template #default="{ row }">
|
||||
<file-item :uri="row.uri" file-size="40px"></file-item>
|
||||
<file-item :uri="row.uri" file-size="50px" :type="type"></file-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="名称" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-link @click.stop="handlePreview(row.uri)">{{ row.name }}</el-link>
|
||||
<el-link @click.stop="handlePreview(row.uri)" :underline="false">
|
||||
{{ row.name }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="上传时间" min-width="100" />
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="inline-block" v-perms="['common:album:albumRename']">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click.stop="handleFileRename(row.name, row.id)"
|
||||
<popover-input
|
||||
@confirm="handleFileRename($event, row.id)"
|
||||
size="default"
|
||||
:value="row.name"
|
||||
width="400px"
|
||||
:limit="50"
|
||||
show-limit
|
||||
teleported
|
||||
>
|
||||
重命名
|
||||
</el-button>
|
||||
<el-button type="primary" link> 重命名 </el-button>
|
||||
</popover-input>
|
||||
</div>
|
||||
<div class="inline-block">
|
||||
<el-button type="primary" link @click.stop="handlePreview(row.uri)">
|
||||
|
||||
@@ -214,6 +214,7 @@ export default defineComponent({
|
||||
|
||||
const handleClose = () => {
|
||||
nextTick(() => {
|
||||
if (props.hiddenUpload) fileList.value = []
|
||||
materialRef.value?.clearSelect()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@
|
||||
:width="width"
|
||||
trigger="contextmenu"
|
||||
class="popover-input"
|
||||
:teleported="false"
|
||||
:teleported="teleported"
|
||||
:persistent="false"
|
||||
popper-class="!p-0"
|
||||
>
|
||||
<div class="flex">
|
||||
<div class="flex p-3" @click.stop="">
|
||||
<div class="popover-input__input mr-[10px] flex-1">
|
||||
<el-select
|
||||
class="flex-1"
|
||||
size="small"
|
||||
:size="size"
|
||||
v-if="type == 'select'"
|
||||
v-model="inputValue"
|
||||
:teleported="false"
|
||||
:teleported="teleported"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
@@ -27,14 +29,17 @@
|
||||
<el-input
|
||||
v-else
|
||||
v-model.trim="inputValue"
|
||||
:maxlength="limit"
|
||||
:show-word-limit="showLimit"
|
||||
:type="type"
|
||||
size="small"
|
||||
:size="size"
|
||||
clearable
|
||||
:placeholder="placeholder"
|
||||
/>
|
||||
</div>
|
||||
<div class="popover-input__btns flex-none">
|
||||
<el-button link @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" size="small" @click="handleConfirm">确定</el-button>
|
||||
<el-button link @click="close">取消</el-button>
|
||||
<el-button type="primary" :size="size" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
@@ -60,7 +65,7 @@ const props = defineProps({
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 250
|
||||
default: '300px'
|
||||
},
|
||||
placeholder: String,
|
||||
disabled: {
|
||||
@@ -70,6 +75,22 @@ const props = defineProps({
|
||||
options: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => []
|
||||
},
|
||||
size: {
|
||||
type: String as PropType<'default' | 'small' | 'large'>,
|
||||
default: 'default'
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
showLimit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
teleported: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['confirm'])
|
||||
@@ -99,7 +120,8 @@ watch(
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
useEventListener(document.body, 'click', () => {
|
||||
|
||||
useEventListener(document.documentElement, 'click', () => {
|
||||
if (inPopover.value) return
|
||||
close()
|
||||
})
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:on-success="handleSuccess"
|
||||
:on-exceed="handleExceed"
|
||||
:on-error="handleError"
|
||||
:accept="getAccept"
|
||||
>
|
||||
<slot></slot>
|
||||
</el-upload>
|
||||
@@ -110,18 +111,30 @@ export default defineComponent({
|
||||
emit('error')
|
||||
}
|
||||
const handleExceed = () => {
|
||||
feedback.msgError('超出上传上限,请重新上传')
|
||||
feedback.msgError(`超出上传上限${props.limit},请重新上传`)
|
||||
}
|
||||
const handleClose = () => {
|
||||
uploadRefs.value?.clearFiles()
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const getAccept = computed(() => {
|
||||
switch (props.type) {
|
||||
case 'image':
|
||||
return '.jpj,.png,.gif,.jpeg,.ico,.bmp'
|
||||
case 'video':
|
||||
return '.wmv,.avi,.mov,.mp4,.flv,.rmvb'
|
||||
default:
|
||||
return '*'
|
||||
}
|
||||
})
|
||||
return {
|
||||
uploadRefs,
|
||||
action,
|
||||
headers,
|
||||
visible,
|
||||
fileList,
|
||||
getAccept,
|
||||
handleProgress,
|
||||
handleSuccess,
|
||||
handleError,
|
||||
|
||||
@@ -37,7 +37,7 @@ const options = reactive({
|
||||
mirror: false, //镜像画面
|
||||
ligthOff: false, //关灯模式
|
||||
volume: 0.3, //默认音量大小
|
||||
control: false, //是否显示控制器
|
||||
control: true, //是否显示控制器
|
||||
title: '', //视频名称
|
||||
poster: '', //封面
|
||||
...props
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const config = {
|
||||
terminal: 1,
|
||||
title: '后台管理系统',
|
||||
version: '1.1.6',
|
||||
baseUrl: `${import.meta.env.VITE_APP_BASE_URL}/`,
|
||||
urlPrefix: 'api',
|
||||
timeout: 20 * 1000
|
||||
terminal: 1, //终端
|
||||
title: '后台管理系统', //网站默认标题
|
||||
version: '1.2.0', //版本号
|
||||
baseUrl: `${import.meta.env.VITE_APP_BASE_URL || ''}/`, //请求接口域名
|
||||
urlPrefix: 'api', //请求默认前缀
|
||||
timeout: 10 * 1000 //请求超时时长
|
||||
}
|
||||
|
||||
export default config
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
const defaultSetting = {
|
||||
sideWidth: 200,
|
||||
sideTheme: 'light',
|
||||
sideDarkColor: '#1d2124',
|
||||
theme: '#4A5DFF',
|
||||
openMultipleTabs: true,
|
||||
successTheme: '#67c23a',
|
||||
warningTheme: '#e6a23c',
|
||||
dangerTheme: '#f56c6c',
|
||||
errorTheme: '#f56c6c',
|
||||
infoTheme: '#909399'
|
||||
isUniqueOpened: false, //只展开一个一级菜单
|
||||
sideWidth: 200, //侧边栏宽度
|
||||
sideTheme: 'light', //侧边栏主题
|
||||
sideDarkColor: '#1d2124', //侧边栏深色主题颜色
|
||||
openMultipleTabs: true, // 是否开启多标签tab栏
|
||||
theme: '#4A5DFF', //主题色
|
||||
successTheme: '#67c23a', //成功主题色
|
||||
warningTheme: '#e6a23c', //警告主题色
|
||||
dangerTheme: '#f56c6c', //危险主题色
|
||||
errorTheme: '#f56c6c', //错误主题色
|
||||
infoTheme: '#909399' //信息主题色
|
||||
}
|
||||
//以上各种主题色分别对应element-plus的几种行为主题
|
||||
|
||||
export default defaultSetting
|
||||
|
||||
47
admin/src/hooks/useMultipleTabs.ts
Normal file
47
admin/src/hooks/useMultipleTabs.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import useTabsStore from '@/stores/modules/multipleTabs'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
|
||||
export default function useMultipleTabs() {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const tabsStore = useTabsStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const tabsLists = computed(() => {
|
||||
return tabsStore.getTabList
|
||||
})
|
||||
|
||||
const currentTab = computed(() => {
|
||||
return route.fullPath
|
||||
})
|
||||
|
||||
const addTab = () => {
|
||||
if (!settingStore.openMultipleTabs) return
|
||||
tabsStore.addTab(router)
|
||||
}
|
||||
|
||||
const removeTab = (fullPath?: any) => {
|
||||
if (!settingStore.openMultipleTabs) return
|
||||
fullPath = fullPath ?? route.fullPath
|
||||
tabsStore.removeTab(fullPath, router)
|
||||
}
|
||||
|
||||
const removeOtherTab = () => {
|
||||
if (!settingStore.openMultipleTabs) return
|
||||
tabsStore.removeOtherTab(route)
|
||||
}
|
||||
|
||||
const removeAllTab = () => {
|
||||
if (!settingStore.openMultipleTabs) return
|
||||
tabsStore.removeAllTab(router)
|
||||
}
|
||||
|
||||
return {
|
||||
tabsLists,
|
||||
currentTab,
|
||||
addTab,
|
||||
removeTab,
|
||||
removeOtherTab,
|
||||
removeAllTab
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
<div class="flex-1 min-w-0">
|
||||
<el-tabs
|
||||
:model-value="currentTab"
|
||||
:closable="tabsState.length > 1"
|
||||
:closable="tabsLists.length > 1"
|
||||
@tab-change="handleChange"
|
||||
@tab-remove="handleRemove"
|
||||
@tab-remove="removeTab($event)"
|
||||
>
|
||||
<template v-for="item in tabsState" :key="item.path">
|
||||
<el-tab-pane :label="item.title" :name="item.path"></el-tab-pane>
|
||||
<template v-for="item in tabsLists" :key="item.fullPath">
|
||||
<el-tab-pane :label="item.title" :name="item.fullPath"></el-tab-pane>
|
||||
</template>
|
||||
</el-tabs>
|
||||
</div>
|
||||
@@ -28,40 +28,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
import { useWatchRoute } from '@/hooks/useWatchRoute'
|
||||
import useTabsStore, { getRouteParams } from '@/stores/modules/multipleTabs'
|
||||
const router = useRouter()
|
||||
const tabsStore = useTabsStore()
|
||||
const { route } = useWatchRoute((route) => {
|
||||
tabsStore.addTab(route, router)
|
||||
const { removeOtherTab, addTab, removeAllTab, removeTab, tabsLists, currentTab } = useMultipleTabs()
|
||||
useWatchRoute(() => {
|
||||
addTab()
|
||||
})
|
||||
|
||||
const currentTab = computed(() => {
|
||||
return route.path
|
||||
})
|
||||
|
||||
const tabsState = computed(() => {
|
||||
return tabsStore.getTabList
|
||||
})
|
||||
|
||||
const handleChange = (path: any) => {
|
||||
const tabItem = tabsStore.tasMap[path]
|
||||
const handleChange = (fullPath: any) => {
|
||||
const tabItem = tabsStore.tasMap[fullPath]
|
||||
router.push(getRouteParams(tabItem))
|
||||
}
|
||||
|
||||
const handleRemove = (path: any) => {
|
||||
tabsStore.removeTab(path, router)
|
||||
}
|
||||
const handleCommand = (command: any) => {
|
||||
switch (command) {
|
||||
case 'closeCurrent':
|
||||
handleRemove(route.path)
|
||||
removeTab()
|
||||
break
|
||||
case 'closeOther':
|
||||
tabsStore.removeOtherTab(route.path)
|
||||
removeOtherTab()
|
||||
break
|
||||
case 'closeAll':
|
||||
tabsStore.removeAllTab(router)
|
||||
removeAllTab()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-4">
|
||||
<router-view v-if="isRouteShow" v-slot="{ Component, route }">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
<keep-alive :include="includeList" :max="20">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
@@ -12,8 +14,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useTabsStore from '@/stores/modules/multipleTabs'
|
||||
import useSettingStore from '@/stores/modules/setting'
|
||||
const appStore = useAppStore()
|
||||
const tabsStore = useTabsStore()
|
||||
const settingStore = useSettingStore()
|
||||
const isRouteShow = computed(() => appStore.isRouteShow)
|
||||
const includeList = computed(() => (settingStore.openMultipleTabs ? tabsStore.getCacheTabList : []))
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
||||
@@ -47,6 +47,16 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item mb-5 flex justify-between items-center">
|
||||
<span class="text-tx-secondary">只展开一个一级菜单</span>
|
||||
<div>
|
||||
<el-switch
|
||||
v-model="isUniqueOpened"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item mb-5">
|
||||
<div class="text-tx-secondary mb-4">菜单栏宽度</div>
|
||||
<div><el-input-number v-model="sideWidth" :min="180" :max="250" /></div>
|
||||
@@ -65,7 +75,6 @@ import theme_light from '@/assets/images/theme_white.png'
|
||||
import theme_dark from '@/assets/images/theme_black.png'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const predefineColors = ref(['#409EFF', '#28C76F', '#EA5455', '#FF9F43', '#01CFE8', '#4A5DFF'])
|
||||
const sideThemeList = [
|
||||
{
|
||||
@@ -102,6 +111,18 @@ const openMultipleTabs = computed({
|
||||
}
|
||||
})
|
||||
|
||||
const isUniqueOpened = computed({
|
||||
get() {
|
||||
return settingStore.isUniqueOpened
|
||||
},
|
||||
set(value) {
|
||||
settingStore.setSetting({
|
||||
key: 'isUniqueOpened',
|
||||
value
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const sideWidth = computed({
|
||||
get() {
|
||||
return settingStore.sideWidth
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
:default-active="activeMenu"
|
||||
:collapse="isCollapsed"
|
||||
mode="vertical"
|
||||
:unique-opened="true"
|
||||
:unique-opened="uniqueOpened"
|
||||
@select="$emit('select')"
|
||||
>
|
||||
<menu-item
|
||||
@@ -41,6 +41,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
uniqueOpened: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
theme: {
|
||||
type: String
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
:routes="routes"
|
||||
:isCollapsed="isCollapsed"
|
||||
:width="settingStore.sideWidth"
|
||||
:unique-opened="settingStore.isUniqueOpened"
|
||||
:config="menuProp"
|
||||
:theme="sideTheme"
|
||||
@select="handleSelect"
|
||||
|
||||
@@ -11,6 +11,7 @@ import { INDEX_ROUTE, INDEX_ROUTE_NAME } from './router/routes'
|
||||
import { PageEnum } from './enums/pageEnum'
|
||||
import useTabsStore from './stores/modules/multipleTabs'
|
||||
import { clearAuthInfo } from './utils/auth'
|
||||
import config from './config'
|
||||
|
||||
// NProgress配置
|
||||
NProgress.configure({ showSpinner: false })
|
||||
@@ -22,6 +23,7 @@ const whiteList: string[] = [PageEnum.LOGIN, PageEnum.ERROR_403]
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// 开始 Progress Bar
|
||||
NProgress.start()
|
||||
document.title = to.meta.title ?? config.title
|
||||
const userStore = useUserStore()
|
||||
const tabsStore = useTabsStore()
|
||||
if (userStore.token) {
|
||||
@@ -42,7 +44,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
const routeName = findFirstValidRoute(routes)
|
||||
// 没有有效路由跳转到403页面
|
||||
if (!routeName) {
|
||||
await userStore.logout()
|
||||
clearAuthInfo()
|
||||
next(PageEnum.ERROR_403)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ export function findFirstValidRoute(routes: RouteRecordRaw[]): string | undefine
|
||||
}
|
||||
//通过权限字符查询路由路径
|
||||
export function getRoutePath(perms: string) {
|
||||
const router = useRouter()
|
||||
return router.getRoutes().find((item) => item.meta?.perms == perms)?.path || ''
|
||||
const routerObj = useRouter() || router
|
||||
return routerObj.getRoutes().find((item) => item.meta?.perms == perms)?.path || ''
|
||||
}
|
||||
|
||||
// 重置路由
|
||||
|
||||
@@ -11,6 +11,7 @@ import { PageEnum } from '@/enums/pageEnum'
|
||||
|
||||
interface TabItem {
|
||||
name: RouteRecordName
|
||||
fullPath: string
|
||||
path: string
|
||||
title?: string
|
||||
query?: LocationQuery
|
||||
@@ -24,8 +25,8 @@ interface TabsSate {
|
||||
indexRouteName: RouteRecordName
|
||||
}
|
||||
|
||||
const getHasTabIndex = (path: string, tabList: TabItem[]) => {
|
||||
return tabList.findIndex((item) => item.path == path)
|
||||
const getHasTabIndex = (fullPath: string, tabList: TabItem[]) => {
|
||||
return tabList.findIndex((item) => item.fullPath == fullPath)
|
||||
}
|
||||
|
||||
const isCannotAddRoute = (route: RouteLocationNormalized, router: Router) => {
|
||||
@@ -39,8 +40,12 @@ const isCannotAddRoute = (route: RouteLocationNormalized, router: Router) => {
|
||||
return false
|
||||
}
|
||||
|
||||
const findTabsIndex = (path: string, tabList: TabItem[]) => {
|
||||
return tabList.findIndex((item) => item.path === path)
|
||||
const findTabsIndex = (fullPath: string, tabList: TabItem[]) => {
|
||||
return tabList.findIndex((item) => item.fullPath === fullPath)
|
||||
}
|
||||
|
||||
const getComponentName = (route: RouteLocationNormalized) => {
|
||||
return route.matched.at(-1)?.components?.default?.name
|
||||
}
|
||||
|
||||
export const getRouteParams = (tabItem: TabItem) => {
|
||||
@@ -63,45 +68,67 @@ const useTabsStore = defineStore({
|
||||
getters: {
|
||||
getTabList(): TabItem[] {
|
||||
return this.tabList
|
||||
},
|
||||
getCacheTabList(): string[] {
|
||||
return Array.from(this.cacheTabList)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setRouteName(name: RouteRecordName) {
|
||||
this.indexRouteName = name
|
||||
},
|
||||
addCache(componentName?: string) {
|
||||
if (componentName) this.cacheTabList.add(componentName)
|
||||
},
|
||||
removeCache(componentName?: string) {
|
||||
if (componentName && this.cacheTabList.has(componentName)) {
|
||||
this.cacheTabList.delete(componentName)
|
||||
}
|
||||
console.log(this.cacheTabList)
|
||||
},
|
||||
clearCache() {
|
||||
this.cacheTabList.clear()
|
||||
},
|
||||
resetState() {
|
||||
this.cacheTabList = new Set()
|
||||
this.tabList = []
|
||||
this.tasMap = {}
|
||||
this.indexRouteName = ''
|
||||
},
|
||||
addTab(route: RouteLocationNormalized, router: Router) {
|
||||
const { name, path, query, meta, params } = route
|
||||
addTab(router: Router) {
|
||||
const route = unref(router.currentRoute)
|
||||
const { name, query, meta, params, fullPath, path } = route
|
||||
if (isCannotAddRoute(route, router)) return
|
||||
const hasTabIndex = getHasTabIndex(path!, this.tabList)
|
||||
|
||||
const hasTabIndex = getHasTabIndex(fullPath!, this.tabList)
|
||||
const componentName = getComponentName(route)
|
||||
const tabItem = {
|
||||
name: name!,
|
||||
path,
|
||||
fullPath,
|
||||
title: meta?.title,
|
||||
query,
|
||||
params
|
||||
}
|
||||
this.tasMap[path] = tabItem
|
||||
this.tasMap[fullPath] = tabItem
|
||||
if (meta?.keepAlive) {
|
||||
this.addCache(componentName)
|
||||
}
|
||||
if (hasTabIndex != -1) {
|
||||
this.tabList.splice(hasTabIndex, 1, tabItem)
|
||||
return
|
||||
}
|
||||
|
||||
this.tabList.push(tabItem)
|
||||
},
|
||||
removeTab(path: string, router: Router) {
|
||||
removeTab(fullPath: string, router: Router) {
|
||||
const { currentRoute, push } = router
|
||||
const index = findTabsIndex(path, this.tabList)
|
||||
const index = findTabsIndex(fullPath, this.tabList)
|
||||
// 移除tab
|
||||
if (this.tabList.length > 1) {
|
||||
index !== -1 && this.tabList.splice(index, 1)
|
||||
}
|
||||
if (path !== currentRoute.value.path) {
|
||||
const componentName = getComponentName(currentRoute.value)
|
||||
this.removeCache(componentName)
|
||||
if (fullPath !== currentRoute.value.fullPath) {
|
||||
return
|
||||
}
|
||||
// 删除选中的tab
|
||||
@@ -116,17 +143,24 @@ const useTabsStore = defineStore({
|
||||
const toRoute = getRouteParams(toTab)
|
||||
push(toRoute)
|
||||
},
|
||||
removeOtherTab(path: string) {
|
||||
this.tabList = this.tabList.filter((item) => item.path == path)
|
||||
removeOtherTab(route: RouteLocationNormalized) {
|
||||
this.tabList = this.tabList.filter((item) => item.fullPath == route.fullPath)
|
||||
const componentName = getComponentName(route)
|
||||
this.cacheTabList.forEach((name) => {
|
||||
if (componentName !== name) {
|
||||
this.removeCache(name)
|
||||
}
|
||||
})
|
||||
},
|
||||
removeAllTab(router: Router) {
|
||||
const { push, currentRoute } = router
|
||||
const { path, name } = unref(currentRoute)
|
||||
const { name } = unref(currentRoute)
|
||||
if (name == this.indexRouteName) {
|
||||
this.removeOtherTab(path)
|
||||
this.removeOtherTab(currentRoute.value)
|
||||
return
|
||||
}
|
||||
this.tabList = []
|
||||
this.clearCache()
|
||||
push(PageEnum.INDEX)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ const useUserStore = defineStore({
|
||||
this.token = ''
|
||||
this.userInfo = {}
|
||||
this.perms = []
|
||||
this.menu = []
|
||||
},
|
||||
login(playload: any) {
|
||||
const { account, password } = playload
|
||||
@@ -54,8 +53,9 @@ const useUserStore = defineStore({
|
||||
logout() {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout()
|
||||
.then((data) => {
|
||||
router.push(PageEnum.LOGIN)
|
||||
.then(async (data) => {
|
||||
this.token = ''
|
||||
await router.push(PageEnum.LOGIN)
|
||||
clearAuthInfo()
|
||||
resolve(data)
|
||||
})
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
--el-messagebox-width: 350px;
|
||||
}
|
||||
.el-date-editor {
|
||||
--el-date-editor-width: 235px;
|
||||
--el-date-editor-width: 280px;
|
||||
.el-range-input {
|
||||
font-size: var(--el-font-size-small);
|
||||
}
|
||||
@@ -115,6 +115,9 @@
|
||||
.el-image__error {
|
||||
font-size: 12px;
|
||||
}
|
||||
.el-tabs__nav-wrap::after {
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.el-pagination > .el-pagination__jump {
|
||||
|
||||
@@ -12,7 +12,7 @@ export function clearAuthInfo() {
|
||||
const userStore = useUserStore()
|
||||
const tabsStore = useTabsStore()
|
||||
userStore.resetState()
|
||||
tabsStore.resetState()
|
||||
tabsStore.$reset()
|
||||
cache.remove(TOKEN_KEY)
|
||||
resetRouter()
|
||||
}
|
||||
|
||||
@@ -71,11 +71,10 @@ export class Axios {
|
||||
this.removeCancelToken(err.config?.url!)
|
||||
}
|
||||
|
||||
if (err.code == AxiosError.ECONNABORTED) {
|
||||
setTimeout(() => {
|
||||
console.log(err)
|
||||
if (err.code == AxiosError.ECONNABORTED || err.code == AxiosError.ERR_NETWORK) {
|
||||
return new Promise((resolve) => setTimeout(resolve, 500)).then(() =>
|
||||
this.retryRequest(err)
|
||||
}, 500)
|
||||
)
|
||||
}
|
||||
return Promise.reject(err)
|
||||
}
|
||||
@@ -103,17 +102,17 @@ export class Axios {
|
||||
retryRequest(error: AxiosError) {
|
||||
const config = error.config
|
||||
const { retryCount, isOpenRetry } = config.requestOptions
|
||||
if (!isOpenRetry && config.method?.toUpperCase() == RequestMethodsEnum.POST) {
|
||||
return
|
||||
if (!isOpenRetry || config.method?.toUpperCase() == RequestMethodsEnum.POST) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
config.retryCount = config.retryCount ?? 0
|
||||
|
||||
if (config.retryCount >= retryCount) {
|
||||
return
|
||||
return Promise.reject(error)
|
||||
}
|
||||
config.retryCount++
|
||||
|
||||
this.axiosInstance.request(config)
|
||||
return this.axiosInstance.request(config)
|
||||
}
|
||||
/**
|
||||
* @description get请求
|
||||
|
||||
@@ -160,3 +160,12 @@ export const getNonDuplicateID = (length = 8) => {
|
||||
idStr += Math.random().toString(36).substring(3, length)
|
||||
return idStr
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 单词首字母大写
|
||||
* @param { String } str
|
||||
* @return { String } id
|
||||
*/
|
||||
export const firstToUpperCase = (str = '') => {
|
||||
return str.toLowerCase().replace(/( |^)[a-z]/g, ($1) => $1.toUpperCase())
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<image-contain :src="config.webBackdrop" :width="400" height="100%" />
|
||||
</div>
|
||||
<div
|
||||
class="login-form bg-body flex flex-col px-10 pt-10 md:w-[400px] w-[375px] flex-none mx-auto"
|
||||
class="login-form bg-body flex flex-col justify-center px-10 py-10 md:w-[400px] w-[375px] flex-none mx-auto"
|
||||
>
|
||||
<div class="text-center text-3xl font-medium mb-8">{{ config.webName }}</div>
|
||||
<el-form ref="formRef" :model="formData" size="large" :rules="rules">
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="articleColumn">
|
||||
import { articleCateDelete, articleCateLists, articleCateStatus } from '@/api/article'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
<el-input
|
||||
v-model="formData.title"
|
||||
placeholder="请输入文章标题"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 3 }"
|
||||
maxlength="64"
|
||||
show-word-limit
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
@@ -42,6 +46,10 @@
|
||||
<el-input
|
||||
v-model="formData.intro"
|
||||
placeholder="请输入文章简介"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
:maxlength="200"
|
||||
show-word-limit
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
@@ -50,8 +58,10 @@
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
:autosize="{ minRows: 6, maxRows: 6 }"
|
||||
v-model="formData.summary"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
@@ -101,11 +111,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="articleListsEdit">
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import { articleCateAll, articleDetail, articleEdit, articleAdd } from '@/api/article'
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -123,6 +134,7 @@ const formData = reactive({
|
||||
summary: ''
|
||||
})
|
||||
|
||||
const { removeTab } = useMultipleTabs()
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
const rules = reactive({
|
||||
title: [{ required: true, message: '请输入文章标题', trigger: 'blur' }],
|
||||
@@ -155,6 +167,7 @@ const handleSave = async () => {
|
||||
await articleAdd(formData)
|
||||
}
|
||||
feedback.msgSuccess('操作成功')
|
||||
removeTab()
|
||||
router.back()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||
<el-form-item label="文章标题">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.title"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="栏目名称">
|
||||
<el-select class="w-56" v-model="queryParams.cid">
|
||||
<el-select class="w-[280px]" v-model="queryParams.cid">
|
||||
<el-option label="全部" value />
|
||||
<el-option
|
||||
v-for="item in optionsData.articleCate"
|
||||
@@ -22,7 +22,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文章状态">
|
||||
<el-select class="w-56" v-model="queryParams.isShow">
|
||||
<el-select class="w-[280px]" v-model="queryParams.isShow">
|
||||
<el-option label="全部" value />
|
||||
<el-option label="显示" :value="1" />
|
||||
<el-option label="隐藏" :value="0" />
|
||||
@@ -37,9 +37,9 @@
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div>
|
||||
<router-link
|
||||
v-perms="['article:add']"
|
||||
v-perms="['article:add', 'article:add/edit']"
|
||||
:to="{
|
||||
path: getRoutePath('article:edit')
|
||||
path: getRoutePath('article:add/edit')
|
||||
}"
|
||||
>
|
||||
<el-button type="primary" class="mb-4">
|
||||
@@ -54,10 +54,11 @@
|
||||
<el-table-column label="ID" prop="id" min-width="80" />
|
||||
<el-table-column label="封面" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-image
|
||||
<image-contain
|
||||
v-if="row.image"
|
||||
:src="row.image"
|
||||
class="w-[60px] h-[45px]"
|
||||
:width="60"
|
||||
:height="45"
|
||||
:preview-src-list="[row.image]"
|
||||
preview-teleported
|
||||
fit="contain"
|
||||
@@ -88,10 +89,10 @@
|
||||
<el-table-column label="发布时间" prop="createTime" min-width="120" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-perms="['article:edit']" type="primary" link>
|
||||
<el-button v-perms="['article:edit','article:add/edit']" type="primary" link>
|
||||
<router-link
|
||||
:to="{
|
||||
path: getRoutePath('article:edit'),
|
||||
path: getRoutePath('article:add/edit'),
|
||||
query: {
|
||||
id: row.id
|
||||
}
|
||||
@@ -117,7 +118,7 @@
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="articleLists">
|
||||
import { articleLists, articleDelete, articleStatus, articleCateAll } from '@/api/article'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
@@ -159,5 +160,9 @@ const handleDelete = async (id: number) => {
|
||||
getLists()
|
||||
}
|
||||
|
||||
onActivated(() => {
|
||||
getLists()
|
||||
})
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="h5Config">
|
||||
import { getH5Config, setH5Config } from '@/api/channel/h5'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="weappConfig">
|
||||
import { getWeappConfig, setWeappConfig } from '@/api/channel/weapp'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="wxDevConfig">
|
||||
import { getWxDevConfig, setWxDevConfig } from '@/api/channel/wx_dev'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="wxOaConfig">
|
||||
import { getOaConfig, setOaConfig } from '@/api/channel/wx_oa'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" name="wxOaMenu">
|
||||
import OaPhone from './menu_com/oa-phone.vue'
|
||||
import OaAttr from './menu_com/oa-attr.vue'
|
||||
import { useMenuOa } from './menu_com/useMenuOa'
|
||||
|
||||
@@ -10,24 +10,30 @@
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div>
|
||||
<el-button class="mb-4" type="primary" @click="handleAdd()">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyDefault:add']"
|
||||
class="mb-4"
|
||||
type="primary"
|
||||
@click="handleAdd()"
|
||||
>
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table size="large" :data="lists">
|
||||
<el-table size="large" :data="pager.lists" v-loading="pager.loading">
|
||||
<el-table-column label="规则名称" prop="name" min-width="120" />
|
||||
<el-table-column label="回复类型" min-width="120">
|
||||
<template #default="{ row }">
|
||||
{{ getContentType(1) }}
|
||||
{{ getContentType(row.contentType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="回复内容" prop="content" min-width="120" />
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-perms="['channel:oaReplyDefault:status']"
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@@ -38,25 +44,40 @@
|
||||
<el-table-column label="排序" prop="sort" min-width="120" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleEdit(row)"> 编辑 </el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row.id)">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyDefault:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyDefault:del']"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</el-card>
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { oaReplyDel, getOaReplyList, changeOaReplyStatus } from '@/api/channel/wx_oa'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
const showEdit = ref(false)
|
||||
const lists = ref()
|
||||
|
||||
const type = 'default'
|
||||
const getContentType = computed(() => {
|
||||
return (val: number) => {
|
||||
switch (val) {
|
||||
@@ -66,33 +87,36 @@ const getContentType = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const getLists = async () => {
|
||||
lists.value = await getOaReplyList({ type: 'default' })
|
||||
}
|
||||
const { pager, getLists } = usePaging({
|
||||
fetchFun: getOaReplyList,
|
||||
params: {
|
||||
type
|
||||
}
|
||||
})
|
||||
|
||||
const handleAdd = async () => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('add', 'default')
|
||||
editRef.value?.open('add', type)
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('edit', 'default')
|
||||
editRef.value?.open('edit', type)
|
||||
editRef.value?.getDetail(data)
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await oaReplyDel({ id })
|
||||
await oaReplyDel({ id, type })
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
const changeStatus = async (id: number) => {
|
||||
try {
|
||||
await changeOaReplyStatus({ id })
|
||||
await changeOaReplyStatus({ id, type })
|
||||
feedback.msgSuccess('修改成功')
|
||||
getLists()
|
||||
} catch (error) {
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
v-model="formData.content"
|
||||
:autosize="{ minRows: 4, maxRows: 4 }"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
placeholder="请输入回复内容"
|
||||
/>
|
||||
</div>
|
||||
@@ -70,7 +72,7 @@
|
||||
</el-form-item> -->
|
||||
<el-form-item label="排序">
|
||||
<div class="flex-1">
|
||||
<el-input v-model="formData.sort" placeholder="请输入" />
|
||||
<el-input-number v-model="formData.sort" :min="0"/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态">
|
||||
@@ -170,7 +172,8 @@ const setFormData = (data: Record<any, any>) => {
|
||||
|
||||
const getDetail = async (row: Record<string, any>) => {
|
||||
const data = await getOaReplyDetail({
|
||||
id: row.id
|
||||
id: row.id,
|
||||
type: formData.type
|
||||
})
|
||||
setFormData(data)
|
||||
}
|
||||
|
||||
@@ -10,14 +10,19 @@
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div>
|
||||
<el-button class="mb-4" type="primary" @click="handleAdd()">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyFollow:add']"
|
||||
class="mb-4"
|
||||
type="primary"
|
||||
@click="handleAdd()"
|
||||
>
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table size="large" :data="lists">
|
||||
<el-table size="large" :data="pager.lists" v-loading="pager.loading">
|
||||
<el-table-column label="规则名称" prop="name" min-width="120" />
|
||||
<el-table-column label="回复类型" min-width="120">
|
||||
<template #default="{ row }">
|
||||
@@ -28,6 +33,7 @@
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-perms="['channel:oaReplyFollow:status']"
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@@ -38,25 +44,41 @@
|
||||
<el-table-column label="排序" prop="sort" min-width="120" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleEdit(row)"> 编辑 </el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row.id)">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyFollow:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyFollow:del']"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</el-card>
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { oaReplyDel, getOaReplyList, changeOaReplyStatus } from '@/api/channel/wx_oa'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
const showEdit = ref(false)
|
||||
const lists = ref()
|
||||
|
||||
const type = 'follow'
|
||||
const getContentType = computed(() => {
|
||||
return (val: number) => {
|
||||
switch (val) {
|
||||
@@ -66,33 +88,36 @@ const getContentType = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const getLists = async () => {
|
||||
lists.value = await getOaReplyList({ type: 'follow' })
|
||||
}
|
||||
const { pager, getLists } = usePaging({
|
||||
fetchFun: getOaReplyList,
|
||||
params: {
|
||||
type
|
||||
}
|
||||
})
|
||||
|
||||
const handleAdd = async () => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('add', 'follow')
|
||||
editRef.value?.open('add', type)
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('edit', 'follow')
|
||||
editRef.value?.open('edit', type)
|
||||
editRef.value?.getDetail(data)
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await oaReplyDel({ id })
|
||||
await oaReplyDel({ id, type })
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
const changeStatus = async (id: number) => {
|
||||
try {
|
||||
await changeOaReplyStatus({ id })
|
||||
await changeOaReplyStatus({ id, type })
|
||||
feedback.msgSuccess('修改成功')
|
||||
getLists()
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,14 +10,19 @@
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div>
|
||||
<el-button class="mb-4" type="primary" @click="handleAdd()">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyKeyword:add']"
|
||||
class="mb-4"
|
||||
type="primary"
|
||||
@click="handleAdd()"
|
||||
>
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table size="large" :data="lists">
|
||||
<el-table size="large" :data="pager.lists" v-loading="pager.loading">
|
||||
<el-table-column label="规则名称" prop="name" min-width="120" />
|
||||
|
||||
<el-table-column label="关键词" prop="keyword" min-width="120" />
|
||||
@@ -34,6 +39,7 @@
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-perms="['channel:oaReplyKeyword:status']"
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@@ -44,24 +50,39 @@
|
||||
<el-table-column label="排序" prop="sort" min-width="120" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleEdit(row)"> 编辑 </el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row.id)">
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyKeyword:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['channel:oaReplyKeyword:del']"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</el-card>
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { oaReplyDel, getOaReplyList, changeOaReplyStatus } from '@/api/channel/wx_oa'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
const showEdit = ref(false)
|
||||
const lists = ref()
|
||||
|
||||
const getMatchingType = computed(() => {
|
||||
return (val: number) => {
|
||||
@@ -82,34 +103,37 @@ const getContentType = computed(() => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const getLists = async () => {
|
||||
lists.value = await getOaReplyList({ type: 'keyword' })
|
||||
}
|
||||
const type = 'keyword'
|
||||
const { pager, getLists } = usePaging({
|
||||
fetchFun: getOaReplyList,
|
||||
params: {
|
||||
type
|
||||
}
|
||||
})
|
||||
|
||||
const handleAdd = async () => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('add', 'keyword')
|
||||
editRef.value?.open('add', type)
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('edit', 'keyword')
|
||||
editRef.value?.open('edit', type)
|
||||
editRef.value?.getDetail(data)
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await oaReplyDel({ id })
|
||||
await oaReplyDel({ id, type })
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
const changeStatus = async (id: number) => {
|
||||
try {
|
||||
await changeOaReplyStatus({ id })
|
||||
await changeOaReplyStatus({ id, type })
|
||||
feedback.msgSuccess('修改成功')
|
||||
getLists()
|
||||
} catch (error) {
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="consumerDetail">
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { getUserDetail, userEdit } from '@/api/consumer'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||
<el-form-item label="用户信息">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.keyword"
|
||||
placeholder="用户编号/昵称/手机号码"
|
||||
clearable
|
||||
@@ -18,7 +18,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="注册来源">
|
||||
<el-select class="w-56" v-model="queryParams.channel">
|
||||
<el-select class="w-[280px]" v-model="queryParams.channel">
|
||||
<el-option
|
||||
v-for="(item, key) in ClientMap"
|
||||
:key="key"
|
||||
@@ -70,7 +70,7 @@
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="consumerLists">
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import { getRoutePath } from '@/router'
|
||||
import { getUserList } from '@/api/consumer'
|
||||
@@ -86,6 +86,9 @@ const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
fetchFun: getUserList,
|
||||
params: queryParams
|
||||
})
|
||||
onActivated(() => {
|
||||
getLists()
|
||||
})
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="decorationPages">
|
||||
import Menu from '../component/pages/menu.vue'
|
||||
import Preview from '../component/pages/preview.vue'
|
||||
import AttrSetting from '../component/pages/attr-setting.vue'
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="decorationTabbar">
|
||||
import { getDecorateTabbar, setDecorateTabbar } from '@/api/decoration'
|
||||
import feedback from '@/utils/feedback'
|
||||
import Draggable from 'vuedraggable'
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<el-input
|
||||
v-model="formData.base.tableName"
|
||||
placeholder="请输入表名称"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -26,6 +27,7 @@
|
||||
<el-input
|
||||
v-model="formData.base.tableComment"
|
||||
placeholder="请输入表描述"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -34,6 +36,7 @@
|
||||
<el-input
|
||||
v-model="formData.base.entityName"
|
||||
placeholder="请输入实体类名称"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -43,6 +46,7 @@
|
||||
<el-input
|
||||
v-model="formData.base.authorName"
|
||||
placeholder="请输入作者"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -50,9 +54,12 @@
|
||||
<div class="w-80">
|
||||
<el-input
|
||||
v-model="formData.base.remarks"
|
||||
class="el-input"
|
||||
class="w-full"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:autosize="{ minRows: 4, maxRows: 4 }"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -90,7 +97,7 @@
|
||||
v-model="row.isRequired"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
></el-checkbox>
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="插入" width="80">
|
||||
@@ -99,7 +106,7 @@
|
||||
v-model="row.isInsert"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
></el-checkbox>
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编辑" width="80">
|
||||
@@ -108,7 +115,7 @@
|
||||
v-model="row.isEdit"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
></el-checkbox>
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="列表" width="80">
|
||||
@@ -117,7 +124,7 @@
|
||||
v-model="row.isList"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
></el-checkbox>
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询" width="80">
|
||||
@@ -126,7 +133,7 @@
|
||||
v-model="row.isQuery"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
></el-checkbox>
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="查询方式">
|
||||
@@ -196,6 +203,7 @@
|
||||
<el-input
|
||||
v-model="formData.gen.moduleName"
|
||||
placeholder="请输入模块名"
|
||||
clearable
|
||||
/>
|
||||
<div class="form-tips">生成文件所在模块名</div>
|
||||
</div>
|
||||
@@ -205,6 +213,7 @@
|
||||
<el-input
|
||||
v-model="formData.gen.functionName"
|
||||
placeholder="请输入功能名称"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -223,6 +232,7 @@
|
||||
<el-input
|
||||
v-model="formData.gen.genPath"
|
||||
placeholder="请输入自定义路径"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -272,14 +282,14 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="tableEdit">
|
||||
import { generateEdit, tableDetail } from '@/api/tools/code'
|
||||
import { dictTypeAll } from '@/api/setting/dict'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { menuLists } from '@/api/perms/menu'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
enum GenTpl {
|
||||
CRUD = 'crud',
|
||||
TREE = 'tree'
|
||||
@@ -292,6 +302,7 @@ enum GenType {
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { removeTab } = useMultipleTabs()
|
||||
const activeName = ref('column')
|
||||
const formData = reactive({
|
||||
base: {
|
||||
@@ -363,6 +374,7 @@ const handleSave = async () => {
|
||||
const { base, column, gen } = formData
|
||||
await generateEdit({ ...base, ...gen, column })
|
||||
feedback.msgSuccess('操作成功')
|
||||
removeTab()
|
||||
router.back()
|
||||
} catch (error: any) {
|
||||
for (const err in error) {
|
||||
|
||||
@@ -3,10 +3,20 @@
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-form class="mb-[-16px]" :model="formData" inline>
|
||||
<el-form-item label="表名称">
|
||||
<el-input class="w-56" v-model="formData.tableName" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
v-model="formData.tableName"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="表描述">
|
||||
<el-input class="w-56" v-model="formData.tableComment" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
v-model="formData.tableComment"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||
@@ -138,7 +148,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="codeGenerate">
|
||||
import {
|
||||
generateTable,
|
||||
syncColumn,
|
||||
@@ -228,5 +238,9 @@ const handleCommand = (command: any, row: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
onActivated(() => {
|
||||
getLists()
|
||||
})
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
||||
@@ -13,10 +13,20 @@
|
||||
</template>
|
||||
<el-form class="ls-form" :model="formData" inline>
|
||||
<el-form-item label="表名称">
|
||||
<el-input class="w-56" v-model="formData.tableName" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
v-model="formData.tableName"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="表描述">
|
||||
<el-input class="w-56" v-model="formData.tableComment" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
v-model="formData.tableComment"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<div class="error404">
|
||||
<error
|
||||
code="403"
|
||||
title="您的账号权限不足,请联系管理员添加权限!"
|
||||
:show-btn="false"
|
||||
></error>
|
||||
<error code="403" title="您的账号权限不足,请联系管理员添加权限!" :show-btn="false">
|
||||
<template #content>
|
||||
<div class="flex justify-center">
|
||||
<img class="w-[150px] h-[150px]" src="@/assets/images/no_perms.png" alt="" />
|
||||
</div>
|
||||
</template>
|
||||
</error>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<template>
|
||||
<div class="error">
|
||||
<div>
|
||||
<div class="error-code">{{ code }}</div>
|
||||
<div class="lg lighter mt-7 mb-7">{{ title }}</div>
|
||||
<slot name="content">
|
||||
<div class="error-code">{{ code }}</div>
|
||||
</slot>
|
||||
<div class="text-lg text-tx-secondary mt-7 mb-7">{{ title }}</div>
|
||||
<el-button v-if="showBtn" type="primary" @click="router.go(-1)">
|
||||
{{ second }} 秒后返回上一页
|
||||
</el-button>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="materialCenter">
|
||||
const tabsMap = [
|
||||
{
|
||||
type: 'image',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-page-header content="编辑通知设置" @back="$router.back()" />
|
||||
<el-page-header :content="$route.meta.title" @back="$router.back()" />
|
||||
</el-card>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@@ -37,16 +37,14 @@
|
||||
<div class="w-full max-w-[320px]">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
:autosize="{ minRows: 6, maxRows: 6 }"
|
||||
v-model="formData.smsNotice.content"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-tips">
|
||||
可选变量 用户昵称:nickname 订单编号:order_sn 支付时间:pay_time
|
||||
<br />
|
||||
示例:亲爱的${nickname},您的订单${order_sn}已支付成功,商家正在快马加鞭为您安排发货。
|
||||
<br />
|
||||
生效条件:1、管理后台完成短信设置。2、第三方短信平台申请模板。
|
||||
<div v-for="(item, index) in formData.smsNotice.tips" :key="index">
|
||||
{{ item }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -58,10 +56,11 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="noticeEdit">
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { noticeDetail, setNoticeConfig } from '@/api/message'
|
||||
import useMultipleTabs from '@/hooks/useMultipleTabs'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -75,7 +74,8 @@ const formData = reactive({
|
||||
smsNotice: {
|
||||
status: 0,
|
||||
templateId: '',
|
||||
content: ''
|
||||
content: '',
|
||||
tips: []
|
||||
}
|
||||
})
|
||||
|
||||
@@ -95,7 +95,7 @@ const rules = {
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const { removeTab } = useMultipleTabs()
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
|
||||
const getDetails = async () => {
|
||||
@@ -114,6 +114,7 @@ const handleSave = async () => {
|
||||
await formRef.value?.validate()
|
||||
await setNoticeConfig(formData)
|
||||
feedback.msgSuccess('操作成功')
|
||||
removeTab()
|
||||
router.back()
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="notice">
|
||||
import { noticeLists } from '@/api/message'
|
||||
import { getRoutePath } from '@/router'
|
||||
|
||||
@@ -87,5 +87,9 @@ const getLists = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
onActivated(() => {
|
||||
getLists()
|
||||
})
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<edit-popup ref="editRef" @success="getLists" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="shortLetter">
|
||||
import { smsLists } from '@/api/message'
|
||||
import EditPopup from './edit.vue'
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
|
||||
@@ -71,7 +71,7 @@ const formData = reactive({
|
||||
})
|
||||
const checkMobile = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
return callback(new Error('手机号不能为空'))
|
||||
return callback()
|
||||
} else {
|
||||
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
|
||||
console.log(reg.test(value))
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||
<el-form-item label="部门名称" prop="name">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.name"
|
||||
clearable
|
||||
@keyup.enter="getLists"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="部门状态" prop="isStop">
|
||||
<el-select class="w-56" v-model="queryParams.isStop">
|
||||
<el-select class="w-[280px]" v-model="queryParams.isStop">
|
||||
<el-option label="全部" value />
|
||||
<el-option label="正常" value="0" />
|
||||
<el-option label="停用" value="1" />
|
||||
@@ -91,7 +91,7 @@
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="department">
|
||||
import type { ElTable, FormInstance } from 'element-plus'
|
||||
import EditPopup from './edit.vue'
|
||||
import { deptDelete, deptLists } from '@/api/org/department'
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
placeholder="请输入备注"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位状态" prop="isStop">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||
<el-form-item label="岗位编码">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.code"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
@@ -12,14 +12,14 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位名称">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.name"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位状态">
|
||||
<el-select class="w-56" v-model="queryParams.isStop">
|
||||
<el-select class="w-[280px]" v-model="queryParams.isStop">
|
||||
<el-option label="全部" value />
|
||||
<el-option label="正常" :value="0" />
|
||||
<el-option label="停用" :value="1" />
|
||||
@@ -51,7 +51,7 @@
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="添加时间" prop="createTime" min-width="180" />
|
||||
<el-table-column label="部门状态" prop="isStop" min-width="100">
|
||||
<el-table-column label="岗位状态" prop="isStop" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="ml-2" :type="row.isStop ? 'danger' : ''">
|
||||
{{ row.isStop ? '停用' : '正常' }}
|
||||
@@ -86,7 +86,7 @@
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="post">
|
||||
import { postDelete, postLists } from '@/api/org/post'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<el-form-item label="管理员账号">
|
||||
<el-input
|
||||
v-model="formData.username"
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
@@ -13,13 +13,13 @@
|
||||
<el-form-item label="管理员名称">
|
||||
<el-input
|
||||
v-model="formData.nickname"
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员角色">
|
||||
<el-select class="w-56" v-model="formData.role">
|
||||
<el-select class="w-[280px]" v-model="formData.role">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option
|
||||
v-for="(item, index) in optionsData.role"
|
||||
@@ -100,7 +100,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="admin">
|
||||
import { adminLists, adminDelete, adminStatus } from '@/api/perms/admin'
|
||||
import { roleAll } from '@/api/perms/role'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
|
||||
@@ -73,7 +73,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="选中菜单" prop="p" v-if="formData.menuType == MenuEnum.MENU">
|
||||
<el-form-item
|
||||
label="选中菜单"
|
||||
prop="selected"
|
||||
v-if="formData.menuType == MenuEnum.MENU"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<el-input
|
||||
v-model="formData.selected"
|
||||
@@ -116,20 +120,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item
|
||||
v-if="formData.menuType == MenuEnum.MENU"
|
||||
label="是否缓存"
|
||||
prop="isCache"
|
||||
required
|
||||
>
|
||||
<div>
|
||||
<el-radio-group v-model="formData.isCache">
|
||||
<el-radio :label="1">缓存</el-radio>
|
||||
<el-radio :label="0">不缓存</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="form-tips">选择缓存则会被`keep-alive`缓存</div>
|
||||
</div>
|
||||
</el-form-item> -->
|
||||
<el-form-item
|
||||
v-if="formData.menuType == MenuEnum.MENU"
|
||||
label="是否缓存"
|
||||
prop="isCache"
|
||||
required
|
||||
>
|
||||
<div>
|
||||
<el-radio-group v-model="formData.isCache">
|
||||
<el-radio :label="1">缓存</el-radio>
|
||||
<el-radio :label="0">不缓存</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="form-tips">选择缓存则会被`keep-alive`缓存</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.menuType != MenuEnum.BUTTON"
|
||||
label="是否显示"
|
||||
@@ -220,7 +224,7 @@ const formData = reactive({
|
||||
//路由参数
|
||||
params: '',
|
||||
//是否缓存 0=否, 1=是
|
||||
isCache: 0,
|
||||
isCache: 1,
|
||||
//是否显示 0=否, 1=是
|
||||
isShow: 1,
|
||||
//是否禁用 0=否, 1=是
|
||||
@@ -259,15 +263,12 @@ const formRules = {
|
||||
}
|
||||
const menuOptions = ref<any[]>([])
|
||||
|
||||
const pageOptions = ref<any[]>([])
|
||||
|
||||
const getMenu = async () => {
|
||||
const data: any = await menuLists()
|
||||
const menu = { id: 0, menuName: '顶级', children: [] }
|
||||
pageOptions.value = arrayToTree(
|
||||
const menu: any = { id: 0, menuName: '顶级', children: [] }
|
||||
menu.children = arrayToTree(
|
||||
treeToArray(data).filter((item) => item.menuType != MenuEnum.BUTTON)
|
||||
)
|
||||
menu.children = data
|
||||
menuOptions.value.push(menu)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="menu">
|
||||
import { menuDelete, menuLists } from '@/api/perms/menu'
|
||||
import type { ElTable } from 'element-plus'
|
||||
import { MenuEnum } from '@/enums/appEnums'
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
placeholder="请输入备注"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="role">
|
||||
import { roleLists, roleDelete } from '@/api/perms/role'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<div>
|
||||
<el-input-number v-model="formData.sort" />
|
||||
<el-input-number v-model="formData.sort" :min="0" />
|
||||
<div class="form-tips">数值越大越排前</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -42,7 +42,14 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" type="textarea" rows="4" clearable />
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
clearable
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</popup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-page-header class="mb-4" content="数据管理" @back="$router.back()" />
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" inline>
|
||||
<el-form-item label="字典名称">
|
||||
<el-select class="w-56" v-model="queryParams.dictType" @change="getLists">
|
||||
<el-select class="w-[280px]" v-model="queryParams.dictType" @change="getLists">
|
||||
<el-option
|
||||
v-for="item in optionsData.dictType"
|
||||
:label="item.dictName"
|
||||
@@ -15,14 +15,14 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="数据名称">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.name"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据状态">
|
||||
<el-select class="w-56" v-model="queryParams.status">
|
||||
<el-select class="w-[280px]" v-model="queryParams.status">
|
||||
<el-option label="全部" value />
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="停用" :value="0" />
|
||||
@@ -71,7 +71,12 @@
|
||||
<el-tag v-else type="danger">停用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="remark" min-width="120" />
|
||||
<el-table-column
|
||||
label="备注"
|
||||
prop="remark"
|
||||
min-width="120"
|
||||
show-tooltip-when-overflow
|
||||
/>
|
||||
<el-table-column label="排序" prop="sort" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
@@ -104,7 +109,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="dictData">
|
||||
import { dictDataDelete, dictDataLists, dictTypeAll } from '@/api/setting/dict'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
|
||||
@@ -28,7 +28,14 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="dictRemark">
|
||||
<el-input v-model="formData.dictRemark" type="textarea" rows="4" clearable />
|
||||
<el-input
|
||||
v-model="formData.dictRemark"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
clearable
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</popup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" inline>
|
||||
<el-form-item label="字典名称">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.dictName"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
@@ -12,14 +12,14 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="字典类型">
|
||||
<el-input
|
||||
class="w-56"
|
||||
class="w-[280px]"
|
||||
v-model="queryParams.dictType"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select class="w-56" v-model="queryParams.dictStatus">
|
||||
<el-select class="w-[280px]" v-model="queryParams.dictStatus">
|
||||
<el-option label="全部" value />
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="停用" :value="0" />
|
||||
@@ -68,7 +68,11 @@
|
||||
<el-tag v-else type="danger">停用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="dictRemark" />
|
||||
<el-table-column
|
||||
label="备注"
|
||||
prop="dictRemark"
|
||||
show-tooltip-when-overflow
|
||||
/>
|
||||
<el-table-column label="创建时间" prop="createTime" min-width="180" />
|
||||
<el-table-column label="操作" width="190" fixed="right">
|
||||
<template #default="{ row }">
|
||||
@@ -80,20 +84,17 @@
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['setting:dict:data:list']"
|
||||
type="primary"
|
||||
link
|
||||
@click="
|
||||
$router.push({
|
||||
<el-button v-perms="['setting:dict:data:list']" type="primary" link>
|
||||
<router-link
|
||||
:to="{
|
||||
path: getRoutePath('setting:dict:data:list'),
|
||||
query: {
|
||||
type: row.dictType
|
||||
}
|
||||
})
|
||||
"
|
||||
>
|
||||
数据管理
|
||||
}"
|
||||
>
|
||||
数据管理
|
||||
</router-link>
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['setting:dict:type:del']"
|
||||
@@ -116,7 +117,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="dictType">
|
||||
import { dictTypeDelete, dictTypeLists } from '@/api/setting/dict'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import { getRoutePath } from '@/router'
|
||||
|
||||
@@ -9,30 +9,36 @@
|
||||
<el-radio :label="0">关闭</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="form-tips">默认开始,关闭则前端不显示该功能</div>
|
||||
<div class="form-tips">默认开启,关闭则前端不显示该功能</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div class="flex">
|
||||
<div class="flex-1 w-3/5">
|
||||
<el-button type="primary" class="mb-4" @click="handleAdd">添加</el-button>
|
||||
<div class="lg:flex">
|
||||
<div class="flex-1 min-w-0">
|
||||
<el-button type="primary" class="mb-4" @click="handleAdd">
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
添加
|
||||
</el-button>
|
||||
<el-table size="large" :data="formData.list">
|
||||
<el-table-column label="ID" prop="id" width="120">
|
||||
<template #default="{ $index }">
|
||||
{{ $index }}
|
||||
<el-table-column label="关键词" prop="describe" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
v-model.trim="row.name"
|
||||
clearable
|
||||
placeholder="请输入关键字"
|
||||
show-word-limit
|
||||
maxlength="30"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关键词" prop="describe" min-width="160">
|
||||
<el-table-column label="排序" prop="describe" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.name" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" prop="describe" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.sort" type="number" />
|
||||
<el-input v-model="row.sort" type="number" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="80" fixed="right">
|
||||
@@ -50,8 +56,8 @@
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="w-2/5 hot-search-phone">
|
||||
<span class="mb-4">- 热搜预览图 -</span>
|
||||
<div class="flex-none hot-search-phone mt-4 lg:mt-0 lg:ml-4">
|
||||
<div class="mb-4 text-center">- 热搜预览图 -</div>
|
||||
<div class="hot-search-phone-content">
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-com">
|
||||
@@ -63,7 +69,12 @@
|
||||
<!-- 热门搜索 -->
|
||||
<div class="hot-search-title">热门搜索</div>
|
||||
<div class="hot-search-text">
|
||||
<span v-for="(text, index) in list" :key="index">{{ text.name }}</span>
|
||||
<span
|
||||
class="truncate max-w-full"
|
||||
v-for="(text, index) in list"
|
||||
:key="index"
|
||||
>{{ text.name }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,7 +87,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" name="search">
|
||||
import { getSearch, setSearch } from '@/api/setting/search'
|
||||
import type { Search } from '@/api/setting/search'
|
||||
import feedback from '@/utils/feedback'
|
||||
@@ -87,7 +98,7 @@ const formData = reactive<Search>({
|
||||
})
|
||||
|
||||
const list = computed(() => {
|
||||
return [...formData.list].sort((v1, v2) => v2.sort - v1.sort)
|
||||
return formData.list.filter((item) => item.name).sort((v1, v2) => v2.sort - v1.sort)
|
||||
})
|
||||
|
||||
// 获取登录注册数据
|
||||
@@ -105,7 +116,7 @@ const getData = async () => {
|
||||
|
||||
const handleAdd = () => {
|
||||
formData.list.push({
|
||||
name: '关键字',
|
||||
name: '',
|
||||
sort: 0
|
||||
})
|
||||
}
|
||||
@@ -130,12 +141,10 @@ getData()
|
||||
<style lang="scss" scoped>
|
||||
.hot-search {
|
||||
.hot-search-phone {
|
||||
margin-left: 20px;
|
||||
@apply flex flex-col items-center;
|
||||
|
||||
width: 300px;
|
||||
&-content {
|
||||
width: 280px;
|
||||
height: 494px;
|
||||
width: 100%;
|
||||
height: 530px;
|
||||
padding: 12px 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e6e6e6;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<edit-popup ref="editRef" @success="getLists" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="storage">
|
||||
import { storageLists } from '@/api/setting/storage'
|
||||
import EditPopup from './edit.vue'
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" name="cache">
|
||||
import { systemCache } from '@/api/setting/system'
|
||||
import vCharts from 'vue-echarts'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="environment">
|
||||
import { systemInfo } from '@/api/setting/system'
|
||||
const loading = ref(false)
|
||||
const info = ref({
|
||||
|
||||
@@ -4,22 +4,34 @@
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-form class="ls-form" :model="formData" inline>
|
||||
<el-form-item label="管理员">
|
||||
<el-input class="w-56" placeholder="请输入" v-model="formData.username" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
placeholder="请输入"
|
||||
v-model="formData.username"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="访问方式">
|
||||
<el-select class="w-56" v-model="formData.type" placeholder="请选择">
|
||||
<el-select class="w-[280px]" v-model="formData.type" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="(item, index) in visitType"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="来源IP">
|
||||
<el-input class="w-56" placeholder="请输入" v-model="formData.ip" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
placeholder="请输入"
|
||||
v-model="formData.ip"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="访问时间">
|
||||
@@ -30,7 +42,13 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="访问链接">
|
||||
<el-input class="w-56" placeholder="请输入" v-model="formData.url" />
|
||||
<el-input
|
||||
class="w-[280px]"
|
||||
placeholder="请输入"
|
||||
v-model="formData.url"
|
||||
clearable
|
||||
@keyup.enter="resetPage"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@@ -61,7 +79,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" name="journal">
|
||||
import { systemLogLists } from '@/api/setting/system'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="loginRegister">
|
||||
import type { LoginSetup } from '@/api/setting/user'
|
||||
import { getLogin, setLogin } from '@/api/setting/user'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="userSetup">
|
||||
import { getUserSetup, setUserSetup } from '@/api/setting/user'
|
||||
import feedback from '@/utils/feedback'
|
||||
// import type { FormInstance } from 'element-plus'
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="webFilling">
|
||||
import { getCopyright, setCopyright } from '@/api/setting/website'
|
||||
import feedback from '@/utils/feedback'
|
||||
// 表单数据
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="webInformation">
|
||||
import { getWebsite, setWebsite } from '@/api/setting/website'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</footer-btns>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" naem="webProtocol">
|
||||
import { getProtocol, setProtocol } from '@/api/setting/website'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" name="userSetting">
|
||||
import { setUserInfo } from '@/api/user'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup name="workbench">
|
||||
import { getWorkbench } from '@/api/app'
|
||||
import vCharts from 'vue-echarts'
|
||||
import menu_admin from './image/menu_admin.png'
|
||||
|
||||
1
admin/typings/router.d.ts
vendored
1
admin/typings/router.d.ts
vendored
@@ -9,5 +9,6 @@ declare module 'vue-router' {
|
||||
hidden?: boolean
|
||||
activeMenu?: string
|
||||
hideTab?: boolean
|
||||
keepAlive?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
|
||||
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
// base: '/admin/',
|
||||
@@ -36,7 +36,8 @@ export default defineConfig({
|
||||
// 配置路劲在你的src里的svg存放文件
|
||||
iconDirs: [fileURLToPath(new URL('./src/assets/icons', import.meta.url))],
|
||||
symbolId: 'local-icon-[dir]-[name]'
|
||||
})
|
||||
}),
|
||||
vueSetupExtend()
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
@@ -692,6 +692,16 @@
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-core@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.39.tgz#0d77e635f4bdb918326669155a2dc977c053943e"
|
||||
integrity sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/shared" "3.2.39"
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-dom@3.2.37", "@vue/compiler-dom@^3.2.37":
|
||||
version "3.2.37"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5"
|
||||
@@ -700,6 +710,14 @@
|
||||
"@vue/compiler-core" "3.2.37"
|
||||
"@vue/shared" "3.2.37"
|
||||
|
||||
"@vue/compiler-dom@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf"
|
||||
integrity sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
|
||||
"@vue/compiler-sfc@3.2.37", "@vue/compiler-sfc@^3.2.37":
|
||||
version "3.2.37"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4"
|
||||
@@ -716,6 +734,22 @@
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-sfc@^3.2.29":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2"
|
||||
integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/compiler-dom" "3.2.39"
|
||||
"@vue/compiler-ssr" "3.2.39"
|
||||
"@vue/reactivity-transform" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-ssr@3.2.37":
|
||||
version "3.2.37"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff"
|
||||
@@ -724,6 +758,14 @@
|
||||
"@vue/compiler-dom" "3.2.37"
|
||||
"@vue/shared" "3.2.37"
|
||||
|
||||
"@vue/compiler-ssr@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633"
|
||||
integrity sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
|
||||
"@vue/devtools-api@^6.1.4", "@vue/devtools-api@^6.2.1":
|
||||
version "6.2.1"
|
||||
resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz#6f2948ff002ec46df01420dfeff91de16c5b4092"
|
||||
@@ -757,6 +799,17 @@
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity-transform@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz#da6ae6c8fd77791b9ae21976720d116591e1c4aa"
|
||||
integrity sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity@3.2.37", "@vue/reactivity@^3.2.37":
|
||||
version "3.2.37"
|
||||
resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848"
|
||||
@@ -794,6 +847,11 @@
|
||||
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702"
|
||||
integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==
|
||||
|
||||
"@vue/shared@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
|
||||
integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
|
||||
|
||||
"@vue/tsconfig@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz#4a61dbd29783d01ddab504276dcf0c2b6988654f"
|
||||
@@ -4159,6 +4217,14 @@ vite-plugin-svg-icons@^2.0.1:
|
||||
svg-baker "1.7.0"
|
||||
svgo "^2.8.0"
|
||||
|
||||
vite-plugin-vue-setup-extend@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmmirror.com/vite-plugin-vue-setup-extend/-/vite-plugin-vue-setup-extend-0.4.0.tgz#ebbbe265320039b8c6a3b9fcae3b8d152ecf4a13"
|
||||
integrity sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==
|
||||
dependencies:
|
||||
"@vue/compiler-sfc" "^3.2.29"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
vite@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.npmmirror.com/vite/-/vite-3.0.8.tgz#aa095ad8e3e5da46d9ec7e878f262678965d6531"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
# 请求域名
|
||||
VITE_APP_BASE_URL='https://likeadmin-java-api.yixiangonline.com'
|
||||
1
frontend/assets/403.154a9511.js
Normal file
1
frontend/assets/403.154a9511.js
Normal file
@@ -0,0 +1 @@
|
||||
import o from"./error.2b025df1.js";import{d as r,o as i,c as p,V as m,M as e,a as t}from"./@vue.cab01781.js";import"./element-plus.8115766e.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./vue-router.5046cc50.js";import"./index.53063276.js";import"./lodash.b68d77aa.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";const s="/assets/no_perms.a56e95a5.png",u={class:"error404"},a=t("div",{class:"flex justify-center"},[t("img",{class:"w-[150px] h-[150px]",src:s,alt:""})],-1),Q=r({__name:"403",setup(c){return(n,_)=>(i(),p("div",u,[m(o,{code:"403",title:"\u60A8\u7684\u8D26\u53F7\u6743\u9650\u4E0D\u8DB3\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650\uFF01","show-btn":!1},{content:e(()=>[a]),_:1})]))}});export{Q as default};
|
||||
@@ -1 +0,0 @@
|
||||
import o from"./error.1294af0d.js";import{d as r,o as t,c as m,V as p}from"./@vue.cab01781.js";import"./element-plus.374f5afd.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./vue-router.5046cc50.js";import"./index.66650ce1.js";import"./lodash.b68d77aa.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";const i={class:"error404"},L=r({__name:"403",setup(u){return(e,s)=>(t(),m("div",i,[p(o,{code:"403",title:"\u60A8\u7684\u8D26\u53F7\u6743\u9650\u4E0D\u8DB3\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650\uFF01","show-btn":!1})]))}});export{L as default};
|
||||
@@ -1 +1 @@
|
||||
import o from"./error.1294af0d.js";import{d as r,o as t,c as m,V as p}from"./@vue.cab01781.js";import"./element-plus.374f5afd.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./vue-router.5046cc50.js";import"./index.66650ce1.js";import"./lodash.b68d77aa.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";const i={class:"error404"},L=r({__name:"404",setup(e){return(u,c)=>(t(),m("div",i,[p(o,{code:"404",title:"\u54CE\u5440\uFF0C\u51FA\u9519\u4E86\uFF01\u60A8\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728\u2026"})]))}});export{L as default};
|
||||
import o from"./error.2b025df1.js";import{d as r,o as t,c as m,V as p}from"./@vue.cab01781.js";import"./element-plus.8115766e.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./vue-router.5046cc50.js";import"./index.53063276.js";import"./lodash.b68d77aa.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";const i={class:"error404"},L=r({__name:"404",setup(e){return(u,c)=>(t(),m("div",i,[p(o,{code:"404",title:"\u54CE\u5440\uFF0C\u51FA\u9519\u4E86\uFF01\u60A8\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728\u2026"})]))}});export{L as default};
|
||||
@@ -1 +1 @@
|
||||
import"./add-nav.vue_vue_type_script_setup_true_lang.70d03ce8.js";import{_ as R}from"./add-nav.vue_vue_type_script_setup_true_lang.70d03ce8.js";import"./element-plus.374f5afd.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./index.43820743.js";import"./index.66650ce1.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.f006aa63.js";import"./index.48f7fb70.js";import"./picker.69d8af88.js";import"./index.3369bc1b.js";import"./usePaging.bfe23d97.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";export{R as default};
|
||||
import"./add-nav.vue_vue_type_script_setup_true_lang.4d0f9da8.js";import{_ as S}from"./add-nav.vue_vue_type_script_setup_true_lang.4d0f9da8.js";import"./element-plus.8115766e.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./index.2e76481a.js";import"./index.53063276.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.45f93d74.js";import"./index.15556fef.js";import"./picker.6a412a5d.js";import"./index.3647ec2c.js";import"./usePaging.52ce9b34.js";import"./index.vue_vue_type_script_setup_true_lang.23d9d5f1.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";export{S as default};
|
||||
@@ -1 +1 @@
|
||||
import{B as F,w as b}from"./element-plus.374f5afd.js";import{_ as v}from"./index.43820743.js";import{_ as B}from"./picker.f006aa63.js";import{_ as A}from"./picker.69d8af88.js";import{f as _,b as y}from"./index.66650ce1.js";import{d as D,o as u,c as r,a as e,W as E,a8 as C,L as w,M as m,V as t,T as U}from"./@vue.cab01781.js";const N={class:"bg-fill-light flex items-center w-full p-4 mb-4"},$={class:"upload-btn w-[60px] h-[60px]"},z={class:"ml-3 flex-1"},L={class:"flex"},T=e("span",{class:"text-tx-regular flex-none mr-3"},"\u540D\u79F0",-1),I={class:"flex mt-[18px]"},M=e("span",{class:"text-tx-regular flex-none mr-3"},"\u94FE\u63A5",-1),P=U("\u6DFB\u52A0"),K=D({__name:"add-nav",props:{modelValue:{type:Array,default:()=>[]},max:{type:Number,default:10},min:{type:Number,default:1}},setup(d){const l=d,p=()=>{var a;((a=l.modelValue)==null?void 0:a.length)<l.max?l.modelValue.push({image:"",name:"\u5BFC\u822A\u540D\u79F0",link:{}}):_.msgError(`\u6700\u591A\u6DFB\u52A0${l.max}\u4E2A`)},i=a=>{var s;if(((s=l.modelValue)==null?void 0:s.length)<=l.min)return _.msgError(`\u6700\u5C11\u4FDD\u7559${l.min}\u4E2A`);l.modelValue.splice(a,1)};return(a,s)=>{const f=y,x=A,V=F,h=B,g=v,k=b;return u(),r("div",null,[e("div",null,[(u(!0),r(E,null,C(d.modelValue,(o,c)=>(u(),w(g,{class:"max-w-[400px]",key:c,onClose:n=>i(c)},{default:m(()=>[e("div",N,[t(x,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body",size:"60px","exclude-domain":""},{upload:m(()=>[e("div",$,[t(f,{name:"el-icon-Plus",size:20})])]),_:2},1032,["modelValue","onUpdate:modelValue"]),e("div",z,[e("div",L,[T,t(V,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"\u8BF7\u8F93\u5165\u540D\u79F0"},null,8,["modelValue","onUpdate:modelValue"])]),e("div",I,[M,t(h,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])])])])]),_:2},1032,["onClose"]))),128))]),e("div",null,[t(k,{type:"primary",onClick:p},{default:m(()=>[P]),_:1})])])}}});export{K as _};
|
||||
import{C as F,w as b}from"./element-plus.8115766e.js";import{_ as v}from"./index.2e76481a.js";import{_ as A}from"./picker.45f93d74.js";import{_ as B}from"./picker.6a412a5d.js";import{f as _,b as y}from"./index.53063276.js";import{d as C,o as u,c as r,a as e,W as D,a8 as E,L as w,M as m,V as t,T as U}from"./@vue.cab01781.js";const N={class:"bg-fill-light flex items-center w-full p-4 mb-4"},$={class:"upload-btn w-[60px] h-[60px]"},z={class:"ml-3 flex-1"},L={class:"flex"},T=e("span",{class:"text-tx-regular flex-none mr-3"},"\u540D\u79F0",-1),I={class:"flex mt-[18px]"},M=e("span",{class:"text-tx-regular flex-none mr-3"},"\u94FE\u63A5",-1),P=U("\u6DFB\u52A0"),K=C({__name:"add-nav",props:{modelValue:{type:Array,default:()=>[]},max:{type:Number,default:10},min:{type:Number,default:1}},setup(d){const l=d,p=()=>{var a;((a=l.modelValue)==null?void 0:a.length)<l.max?l.modelValue.push({image:"",name:"\u5BFC\u822A\u540D\u79F0",link:{}}):_.msgError(`\u6700\u591A\u6DFB\u52A0${l.max}\u4E2A`)},i=a=>{var s;if(((s=l.modelValue)==null?void 0:s.length)<=l.min)return _.msgError(`\u6700\u5C11\u4FDD\u7559${l.min}\u4E2A`);l.modelValue.splice(a,1)};return(a,s)=>{const f=y,x=B,V=F,h=A,g=v,k=b;return u(),r("div",null,[e("div",null,[(u(!0),r(D,null,E(d.modelValue,(o,c)=>(u(),w(g,{class:"max-w-[400px]",key:c,onClose:n=>i(c)},{default:m(()=>[e("div",N,[t(x,{modelValue:o.image,"onUpdate:modelValue":n=>o.image=n,"upload-class":"bg-body",size:"60px","exclude-domain":""},{upload:m(()=>[e("div",$,[t(f,{name:"el-icon-Plus",size:20})])]),_:2},1032,["modelValue","onUpdate:modelValue"]),e("div",z,[e("div",L,[T,t(V,{modelValue:o.name,"onUpdate:modelValue":n=>o.name=n,placeholder:"\u8BF7\u8F93\u5165\u540D\u79F0"},null,8,["modelValue","onUpdate:modelValue"])]),e("div",I,[M,t(h,{modelValue:o.link,"onUpdate:modelValue":n=>o.link=n},null,8,["modelValue","onUpdate:modelValue"])])])])]),_:2},1032,["onClose"]))),128))]),e("div",null,[t(k,{type:"primary",onClick:p},{default:m(()=>[P]),_:1})])])}}});export{K as _};
|
||||
@@ -1 +1 @@
|
||||
import{r as e}from"./index.66650ce1.js";function a(t){return e.get({url:"/article/cate/list",params:t})}function l(t){return e.get({url:"/article/cate/all",params:t})}function i(t){return e.post({url:"/article/cate/add",params:t})}function c(t){return e.post({url:"/article/cate/edit",params:t})}function u(t){return e.post({url:"/article/cate/del",params:t})}function n(t){return e.get({url:"/article/cate/detail",params:t})}function s(t){return e.post({url:"/article/cate/change",params:t})}function o(t){return e.get({url:"/article/list",params:t})}function d(t){return e.post({url:"/article/add",params:t})}function f(t){return e.post({url:"/article/edit",params:t})}function p(t){return e.post({url:"/article/del",params:t})}function g(t){return e.get({url:"/article/detail",params:t})}function C(t){return e.post({url:"/article/change",params:t})}export{c as a,i as b,n as c,u as d,s as e,a as f,g,l as h,f as i,d as j,C as k,p as l,o as m};
|
||||
import{r as e}from"./index.53063276.js";function a(t){return e.get({url:"/article/cate/list",params:t})}function l(t){return e.get({url:"/article/cate/all",params:t})}function i(t){return e.post({url:"/article/cate/add",params:t})}function c(t){return e.post({url:"/article/cate/edit",params:t})}function u(t){return e.post({url:"/article/cate/del",params:t})}function n(t){return e.get({url:"/article/cate/detail",params:t})}function s(t){return e.post({url:"/article/cate/change",params:t})}function o(t){return e.get({url:"/article/list",params:t})}function d(t){return e.post({url:"/article/add",params:t})}function f(t){return e.post({url:"/article/edit",params:t})}function p(t){return e.post({url:"/article/del",params:t})}function g(t){return e.get({url:"/article/detail",params:t})}function C(t){return e.post({url:"/article/change",params:t})}export{c as a,i as b,n as c,u as d,s as e,a as f,g,l as h,f as i,d as j,C as k,p as l,o as m};
|
||||
1
frontend/assets/attr-setting.345fe675.js
Normal file
1
frontend/assets/attr-setting.345fe675.js
Normal file
@@ -0,0 +1 @@
|
||||
import"./attr-setting.vue_vue_type_script_setup_true_lang.173991cf.js";import{_ as cm}from"./attr-setting.vue_vue_type_script_setup_true_lang.173991cf.js";import"./index.8b3d114e.js";import"./attr.vue_vue_type_script_setup_true_lang.22676784.js";import"./element-plus.8115766e.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./index.2e76481a.js";import"./index.53063276.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.45f93d74.js";import"./index.15556fef.js";import"./picker.6a412a5d.js";import"./index.3647ec2c.js";import"./usePaging.52ce9b34.js";import"./index.vue_vue_type_script_setup_true_lang.23d9d5f1.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";import"./content.vue_vue_type_script_setup_true_lang.c187246b.js";import"./decoration-img.e07a9eab.js";import"./attr.vue_vue_type_script_setup_true_lang.7393e332.js";import"./content.cbf0d4cf.js";import"./attr.vue_vue_type_script_setup_true_lang.dd81a142.js";import"./add-nav.vue_vue_type_script_setup_true_lang.4d0f9da8.js";import"./content.1302931d.js";import"./attr.vue_vue_type_script_setup_true_lang.bec38aae.js";import"./content.vue_vue_type_script_setup_true_lang.e5408794.js";import"./attr.vue_vue_type_script_setup_true_lang.06a2fa18.js";import"./content.250698bc.js";import"./decoration.a3e48437.js";import"./attr.vue_vue_type_script_setup_true_lang.0b87e513.js";import"./content.d99d9dd5.js";import"./attr.vue_vue_type_script_setup_true_lang.4d4e4b9a.js";import"./content.vue_vue_type_script_setup_true_lang.f8910cfe.js";import"./attr.vue_vue_type_script_setup_true_lang.0583d8bc.js";import"./content.90ee9825.js";export{cm as default};
|
||||
@@ -1 +0,0 @@
|
||||
import"./attr-setting.vue_vue_type_script_setup_true_lang.e2ec5101.js";import{_ as em}from"./attr-setting.vue_vue_type_script_setup_true_lang.e2ec5101.js";import"./index.22f954e7.js";import"./attr.vue_vue_type_script_setup_true_lang.6fade7a2.js";import"./element-plus.374f5afd.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./index.43820743.js";import"./index.66650ce1.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.f006aa63.js";import"./index.48f7fb70.js";import"./picker.69d8af88.js";import"./index.3369bc1b.js";import"./usePaging.bfe23d97.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";import"./content.vue_vue_type_script_setup_true_lang.19e8b204.js";import"./decoration-img.408cc614.js";import"./attr.vue_vue_type_script_setup_true_lang.813de30c.js";import"./content.ae4e83bb.js";import"./attr.vue_vue_type_script_setup_true_lang.9f826c96.js";import"./add-nav.vue_vue_type_script_setup_true_lang.70d03ce8.js";import"./content.149b5e3a.js";import"./attr.vue_vue_type_script_setup_true_lang.b9715116.js";import"./content.vue_vue_type_script_setup_true_lang.65f9983c.js";import"./attr.vue_vue_type_script_setup_true_lang.06a2fa18.js";import"./content.edf66e1e.js";import"./decoration.46adad8f.js";import"./attr.vue_vue_type_script_setup_true_lang.0b87e513.js";import"./content.6b6901ee.js";import"./attr.vue_vue_type_script_setup_true_lang.a36dcde8.js";import"./content.vue_vue_type_script_setup_true_lang.4d93935e.js";import"./attr.vue_vue_type_script_setup_true_lang.0583d8bc.js";import"./content.f4970cf1.js";export{em as default};
|
||||
@@ -1 +1 @@
|
||||
import{w as i}from"./index.22f954e7.js";import{d as l,o as t,c as d,a as m,U as f,L as c,R as p,u as g,aK as b}from"./@vue.cab01781.js";const u={class:"pages-setting"},w={class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2"},k=l({__name:"attr-setting",props:{widget:{type:Object,default:()=>({})}},setup(e){return(y,x)=>{var s,a,n,o,r;return t(),d("div",u,[m("div",w,f((s=e.widget)==null?void 0:s.title),1),(t(),c(b,null,[(t(),c(p((n=g(i)[(a=e.widget)==null?void 0:a.name])==null?void 0:n.attr),{class:"pt-5 pr-4",content:(o=e.widget)==null?void 0:o.content,styles:(r=e.widget)==null?void 0:r.styles},null,8,["content","styles"]))],1024))])}}});export{k as _};
|
||||
import{w as i}from"./index.8b3d114e.js";import{d as l,o as t,c as d,a as m,U as f,L as c,R as p,u as g,aK as b}from"./@vue.cab01781.js";const u={class:"pages-setting"},w={class:"title flex items-center before:w-[3px] before:h-[14px] before:block before:bg-primary before:mr-2"},k=l({__name:"attr-setting",props:{widget:{type:Object,default:()=>({})}},setup(e){return(y,x)=>{var s,a,n,o,r;return t(),d("div",u,[m("div",w,f((s=e.widget)==null?void 0:s.title),1),(t(),c(b,null,[(t(),c(p((n=g(i)[(a=e.widget)==null?void 0:a.name])==null?void 0:n.attr),{class:"pt-5 pr-4",content:(o=e.widget)==null?void 0:o.content,styles:(r=e.widget)==null?void 0:r.styles},null,8,["content","styles"]))],1024))])}}});export{k as _};
|
||||
@@ -1 +1 @@
|
||||
import"./attr.vue_vue_type_script_setup_true_lang.9f826c96.js";import{_ as S}from"./attr.vue_vue_type_script_setup_true_lang.9f826c96.js";import"./element-plus.374f5afd.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./add-nav.vue_vue_type_script_setup_true_lang.70d03ce8.js";import"./index.43820743.js";import"./index.66650ce1.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.f006aa63.js";import"./index.48f7fb70.js";import"./picker.69d8af88.js";import"./index.3369bc1b.js";import"./usePaging.bfe23d97.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";export{S as default};
|
||||
import"./attr.vue_vue_type_script_setup_true_lang.dd81a142.js";import{_ as T}from"./attr.vue_vue_type_script_setup_true_lang.dd81a142.js";import"./element-plus.8115766e.js";import"./@vue.cab01781.js";import"./@vueuse.724ed0af.js";import"./@element-plus.92b4185f.js";import"./lodash-es.29c53eac.js";import"./dayjs.66926594.js";import"./axios.2d915936.js";import"./async-validator.fb49d0f5.js";import"./@ctrl.82a509e0.js";import"./@popperjs.36402333.js";import"./escape-html.e5dfadb9.js";import"./normalize-wheel-es.8aeb3683.js";import"./add-nav.vue_vue_type_script_setup_true_lang.4d0f9da8.js";import"./index.2e76481a.js";import"./index.53063276.js";import"./lodash.b68d77aa.js";import"./vue-router.5046cc50.js";import"./pinia.e85e8286.js";import"./vue-demi.bfae2336.js";import"./css-color-function.a8f9466d.js";import"./color.903ca10f.js";import"./clone.9d64bb7a.js";import"./color-convert.69e17089.js";import"./color-string.e356f5de.js";import"./color-name.e7a4e1d3.js";import"./nprogress.a96d99f2.js";import"./vue-clipboard3.91d4fd5f.js";import"./clipboard.c0a70c0c.js";import"./echarts.6ad8c478.js";import"./zrender.f91f2f01.js";import"./highlight.js.4ebdf9a4.js";import"./@highlightjs.0ab41b7b.js";import"./picker.45f93d74.js";import"./index.15556fef.js";import"./picker.6a412a5d.js";import"./index.3647ec2c.js";import"./usePaging.52ce9b34.js";import"./index.vue_vue_type_script_setup_true_lang.23d9d5f1.js";import"./vue3-video-play.05975c53.js";import"./vuedraggable.a5db575d.js";import"./vue.de4be77f.js";import"./sortablejs.cd7e2c7e.js";export{T as default};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user