release(custom): i
4
.env
@@ -2,8 +2,4 @@ VITE_TITLE = '捷兑通 - 平台端'
|
|||||||
|
|
||||||
VITE_PORT = 4000
|
VITE_PORT = 4000
|
||||||
|
|
||||||
VITE_WS_URL = 'www.wanzhuanyongcheng.cn/admin/data'
|
|
||||||
|
|
||||||
VITE_WS1_URL = 'www.jdt168.com/dice/home'
|
|
||||||
|
|
||||||
VITE_GAME_API = 'https://www.jdt168.com'
|
VITE_GAME_API = 'https://www.jdt168.com'
|
||||||
@@ -9,3 +9,9 @@ VITE_USE_PROXY = true
|
|||||||
|
|
||||||
# base api
|
# base api
|
||||||
VITE_BASE_API = '/admin'
|
VITE_BASE_API = '/admin'
|
||||||
|
|
||||||
|
|
||||||
|
VITE_WS1_URL = 'game.wanzhuanyongcheng.cn/dice/home'
|
||||||
|
VITE_WS_URL = 'test.wanzhuanyongcheng.cn/admin/data'
|
||||||
|
|
||||||
|
VITE_MER_LOGIN_URL = '//localhost:3100/#/login'
|
||||||
@@ -13,4 +13,11 @@ VITE_BASE_API = 'https://www.wanzhuanyongcheng.cn/admin'
|
|||||||
VITE_USE_COMPRESS = true
|
VITE_USE_COMPRESS = true
|
||||||
|
|
||||||
# 压缩类型
|
# 压缩类型
|
||||||
VITE_COMPRESS_TYPE = gzip
|
VITE_COMPRESS_TYPE = gzip
|
||||||
|
|
||||||
|
VITE_WS1_URL = 'www.jdt168.com/dice/home'
|
||||||
|
|
||||||
|
VITE_WS_URL = 'www.wanzhuanyongcheng.cn/admin/data'
|
||||||
|
|
||||||
|
|
||||||
|
VITE_MER_LOGIN_URL = '//www.wanzhuanyongcheng.cn/static/mer/#/login'
|
||||||
17
.env.test
@@ -1,7 +1,18 @@
|
|||||||
VITE_PUBLIC_PATH = '/'
|
# 资源公共路径,需要以 /开头和结尾
|
||||||
|
VITE_PUBLIC_PATH = '/static/admin'
|
||||||
|
|
||||||
# 是否启用MOCK
|
# 是否启用MOCK
|
||||||
VITE_USE_MOCK = true
|
VITE_USE_MOCK = false
|
||||||
|
|
||||||
|
# 是否启用代理
|
||||||
|
VITE_USE_PROXY = false
|
||||||
|
|
||||||
# base api
|
# base api
|
||||||
VITE_BASE_API = '/api'
|
VITE_BASE_API = '/admin'
|
||||||
|
|
||||||
|
|
||||||
|
VITE_WS1_URL = 'game.wanzhuanyongcheng.cn/dice/home'
|
||||||
|
VITE_WS_URL = 'test.wanzhuanyongcheng.cn/admin/data'
|
||||||
|
VITE_GAME_API = 'https://game.wanzhuanyongcheng.cn'
|
||||||
|
|
||||||
|
VITE_MER_LOGIN_URL = '//test.wanzhuanyongcheng.cn/static/mer/#/login'
|
||||||
5
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
12
.idea/admin.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
65
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
|
<HTMLCodeStyleSettings>
|
||||||
|
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||||
|
<option name="HTML_QUOTE_STYLE" value="Single" />
|
||||||
|
<option name="HTML_ENFORCE_QUOTES" value="true" />
|
||||||
|
</HTMLCodeStyleSettings>
|
||||||
|
<JSCodeStyleSettings version="0">
|
||||||
|
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</JSCodeStyleSettings>
|
||||||
|
<TypeScriptCodeStyleSettings version="0">
|
||||||
|
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
||||||
|
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||||
|
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||||
|
<option name="USE_DOUBLE_QUOTES" value="false" />
|
||||||
|
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||||
|
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
||||||
|
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||||
|
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||||
|
</TypeScriptCodeStyleSettings>
|
||||||
|
<VueCodeStyleSettings>
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||||
|
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||||
|
</VueCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="HTML">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
<option name="SMART_TABS" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JavaScript">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="TypeScript">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="Vue">
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/admin.iml" filepath="$PROJECT_DIR$/.idea/admin.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
217
README.md
@@ -1,217 +0,0 @@
|
|||||||
<p align="center">
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin">
|
|
||||||
<img alt="Vue Naive Admin Logo" width="200" src="./src/assets/images/logo.png">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin"><img alt="stars" src="https://badgen.net/github/stars/zclzone/vue-naive-admin"/></a>
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin"><img alt="forks" src="https://badgen.net/github/forks/zclzone/vue-naive-admin"/></a>
|
|
||||||
<a href="./LICENSE"><img alt="MIT License" src="https://badgen.net/github/license/zclzone/vue-naive-admin"/></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align='center'>
|
|
||||||
<b>中文</b> |
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin/blob/main/README.EN.md">English</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
### 简介
|
|
||||||
|
|
||||||
[Vue Naive Admin](https://github.com/zclzone/vue-naive-admin) 是一个 **完全开源免费且允许商用** 的后台管理模板,基于 `Vue3、Vite3、Pinia、Unocss 和 Naive UI` 等前端最新技术栈。相较于其他比较流行的后台管理模板,此项目更加简洁、轻量,风格清新,学习成本非常低,非常适合中小型项目或者个人项目。
|
|
||||||
|
|
||||||
### 功能
|
|
||||||
|
|
||||||
- 🍒 集成 [Naive UI](https://www.naiveui.com)
|
|
||||||
- 🍑 集成登陆、注销及权限验证
|
|
||||||
- 🍐 集成多环境配置,dev、测试、生产和github pages环境
|
|
||||||
- 🍎 集成 `eslint + prettier`,代码约束和格式化统一
|
|
||||||
- 🍌 集成 `husky + commitlint`,代码提交规范化
|
|
||||||
- 🍉 集成 `mock` 接口服务,dev 环境和发布环境都支持,可动态配置是否启用 mock 服务,不启用时不会加载 mock 包,减少打包体积
|
|
||||||
- 🍍 集成 `pinia`,vuex 的替代方案,轻量、简单、易用
|
|
||||||
- 📦 集成 `unplugin` 插件,自动导入,解放双手,开发效率直接起飞
|
|
||||||
- 🤹 集成 `iconify` 图标,支持自定义 svg 图标, 优雅使用icon
|
|
||||||
- 🍇 集成 `unocss`,antfu 开源的原子 css 解决方案,非常轻量
|
|
||||||
|
|
||||||
### 预览
|
|
||||||
|
|
||||||
[https://template.qszone.com](https://template.qszone.com)
|
|
||||||
|
|
||||||
[https://base.isme.top](https://base.isme.top)
|
|
||||||
|
|
||||||
### 文档
|
|
||||||
|
|
||||||
[Vue Naive Admin Docs](https://zclzone.github.io/vue-naive-admin-docs)
|
|
||||||
|
|
||||||
[语雀文档:Vue Naive Admin](https://www.yuque.com/qszone/vue-naive-admin)
|
|
||||||
|
|
||||||
### 快速开始
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 推荐配置git autocrlf 为 false(本项目规范使用lf换行符,此配置是为防止git自动将源文件转换为crlf)
|
|
||||||
# 不清楚为什么要这样做的请参考这篇文章:https://www.freesion.com/article/4532642129
|
|
||||||
git config --global core.autocrlf false
|
|
||||||
|
|
||||||
# 克隆项目
|
|
||||||
git clone https://github.com/zclzone/vue-naive-admin.git
|
|
||||||
|
|
||||||
# 进入项目目录
|
|
||||||
cd vue-naive-admin
|
|
||||||
|
|
||||||
# 安装依赖(建议使用pnpm: https://pnpm.io/zh/installation)
|
|
||||||
npm i -g pnpm # 装了可忽略
|
|
||||||
pnpm i # 或者 npm i
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 构建发布
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# 构建测试环境
|
|
||||||
pnpm build:test
|
|
||||||
|
|
||||||
# 构建github pages环境
|
|
||||||
pnpm build:github
|
|
||||||
|
|
||||||
# 构建生产环境
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 其他指令
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# eslint代码格式检查
|
|
||||||
pnpm lint
|
|
||||||
|
|
||||||
# 代码检查并修复
|
|
||||||
pnpm lint:fix
|
|
||||||
|
|
||||||
# 预览发布包效果(需先执行构建指令)
|
|
||||||
pnpm preview
|
|
||||||
|
|
||||||
# 提交代码(husky+commitlint)
|
|
||||||
pnpm cz
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### 目录说明
|
|
||||||
|
|
||||||
```
|
|
||||||
Vue Naive Admin
|
|
||||||
|-- .github // github相关,如推送github仓库后自动部署gh pages
|
|
||||||
|-- .husky // git commit钩子
|
|
||||||
|-- .vscode // vscode编辑器相关
|
|
||||||
| |-- extensions.json // 插件推荐
|
|
||||||
| |-- settings.json // 项目级别的vscode配置,优先级大于全局vscode配置
|
|
||||||
|-- build // 构建相关配置
|
|
||||||
| |-- constant.js // 构建相关的常量
|
|
||||||
| |-- utils.js // 构建相关的工具方法
|
|
||||||
| |-- config
|
|
||||||
| | |-- define.js // 注入全局常量,启动或打包后将添加到window中
|
|
||||||
| | |-- proxy.js // 代理配置
|
|
||||||
| |-- plugin
|
|
||||||
| | |-- html.js // vite-plugin-html插件,用于注入变量或者html标签
|
|
||||||
| | |-- mock.js // vite-plugin-mock插件,处理mock
|
|
||||||
| | |-- unplugin.js // unplugin相关插件,包含DefineOptions和自动导入
|
|
||||||
| |-- script // 打包完成后执行的一些node脚本(不重要)
|
|
||||||
| |-- build-cname.js // 自动生成cname
|
|
||||||
|-- mock // mock
|
|
||||||
| |-- utils.js // mock请求需要用到的工具方法
|
|
||||||
| |-- api // mock接口
|
|
||||||
|-- public // 公共资源,文件夹下的文件会在打包后会直接加到dist根目录下
|
|
||||||
|-- settings // 项目配置
|
|
||||||
| |-- proxy-config.js // 代理配置文件
|
|
||||||
| |-- theme.json // 主题配置项,主题色等
|
|
||||||
|-- src
|
|
||||||
| |-- api // 公共api
|
|
||||||
| |-- assets // 静态资源
|
|
||||||
| | |-- images // 图片
|
|
||||||
| | |-- svg // svg图标
|
|
||||||
| |-- components // 全局组件
|
|
||||||
| | |-- common // 公共组件
|
|
||||||
| | |-- icon // icon相关组件
|
|
||||||
| | |-- page // 页面组件
|
|
||||||
| | |-- query-bar // 查询选项
|
|
||||||
| | |-- table // 封装的表格组件
|
|
||||||
| |-- composables // 封装的组合式函数
|
|
||||||
| |-- layout // 布局相关组件
|
|
||||||
| | |-- components
|
|
||||||
| | |-- AppMain.vue // 主体内容
|
|
||||||
| | |-- header // 头部
|
|
||||||
| | |-- sidebar // 侧边菜单栏
|
|
||||||
| | |-- tags // 多页签栏
|
|
||||||
| |-- router // 路由
|
|
||||||
| | |-- guard // 路由守卫
|
|
||||||
| | |-- routes // 路由列表
|
|
||||||
| |-- store // 状态管理(pinia)
|
|
||||||
| | |-- modules // 模块
|
|
||||||
| | |-- app // 管理页面重新加载、折叠菜单栏和keepAlive等
|
|
||||||
| | |-- permission // 权限相关,管理权限菜单
|
|
||||||
| | |-- tags // 管理多页签
|
|
||||||
| | |-- user // 用户模块,管理用户信息、登录登出
|
|
||||||
| |-- styles // 样式
|
|
||||||
| |-- utils // 封装的工具方法
|
|
||||||
| | |-- auth // 权限相关,如token、跳转登录页等
|
|
||||||
| | |-- common // 通用
|
|
||||||
| | |-- http // 封装axios
|
|
||||||
| | |-- storage // 封装localStorage和sessionStorage
|
|
||||||
| |-- views // 页面
|
|
||||||
| | |-- demo // 示例
|
|
||||||
| | |-- error-page // 错误页
|
|
||||||
| | |-- login // 登录页
|
|
||||||
| | |-- workbench // 首页
|
|
||||||
| |-- App.vue
|
|
||||||
| |-- main.js
|
|
||||||
|-- .cz-config.js // git提交配置
|
|
||||||
|-- .editorconfig // 编辑器配置
|
|
||||||
|-- .env // 环境文件,所有环境都会载入
|
|
||||||
|-- .env.development // 开发环境文件
|
|
||||||
|-- .env.production // 生产环境文件
|
|
||||||
|-- .env.test // 测试环境文件
|
|
||||||
|-- .eslintignore // eslint忽略
|
|
||||||
|-- .eslintrc.js // eslint配置
|
|
||||||
|-- .gitignore // git忽略
|
|
||||||
|-- .prettierignore // prettier格式化忽略
|
|
||||||
|-- commitlint.config.js // commitlint规范配置
|
|
||||||
|-- index.html
|
|
||||||
|-- jsconfig.json // js配置
|
|
||||||
|-- LICENSE // 协议
|
|
||||||
|-- package.json // 依赖描述文件
|
|
||||||
|-- pnpm-lock.yaml // 依赖锁定文件
|
|
||||||
|-- prettier.config.js // prettier格式化配置
|
|
||||||
|-- README.md // 项目描述文档(英文)
|
|
||||||
|-- README.zh-CN.md // 项目描述文档(中文)
|
|
||||||
|-- unocss.config.js // unocss配置
|
|
||||||
|-- vite.config.js // vite配置
|
|
||||||
```
|
|
||||||
|
|
||||||
### TS 版本: Qs Admin
|
|
||||||
|
|
||||||
#### 源码
|
|
||||||
|
|
||||||
- github: [https://github.com/zclzone/qs-admin](https://github.com/zclzone/qs-admin)
|
|
||||||
- gitee: [https://gitee.com/zclzone/qs-admin-ts](https://gitee.com/zclzone/qs-admin-ts)
|
|
||||||
|
|
||||||
#### 预览
|
|
||||||
|
|
||||||
- [https://admin.qszone.com](https://admin.qszone.com)
|
|
||||||
- [https://zclzone.github.io/qs-admin](https://zclzone.github.io/qs-admin)
|
|
||||||
|
|
||||||
### 使用该项目的开源项目
|
|
||||||
|
|
||||||
- [gin-vue-blog](https://github.com/szluyu99/gin-vue-blog): Golang 全栈博客项目, 博客后台的前端基于 vue-naive-admin,对接真实后端服务,实现了后端控制路由等特性。
|
|
||||||
|
|
||||||
|
|
||||||
### 入群交流 & 关于作者
|
|
||||||
|
|
||||||
<a href="https://blog.qszone.com/about/">
|
|
||||||
<img src="https://assets.qszone.com/images/about.png" style="max-width: 400px" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### ☕ 赞助我
|
|
||||||
|
|
||||||
> 开源不易,请作者喝杯咖啡吧
|
|
||||||
<p>
|
|
||||||
<img src="https://assets.qszone.com/images/zhifu_weixin.jpg" style="width: 220px" />
|
|
||||||
<img src="https://assets.qszone.com/images/zhifu_zhifubao.jpg" style="width: 220px" />
|
|
||||||
</p>
|
|
||||||
@@ -7,7 +7,7 @@ export const PROXY_CONFIG = {
|
|||||||
* @转发路径 http://localhost:8080/user
|
* @转发路径 http://localhost:8080/user
|
||||||
*/
|
*/
|
||||||
'/admin': {
|
'/admin': {
|
||||||
target: 'https://www.wanzhuanyongcheng.cn',
|
target: 'https://test.wanzhuanyongcheng.cn',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
// rewrite: (path) => path.replace(new RegExp('^/api'), ''),
|
// rewrite: (path) => path.replace(new RegExp('^/api'), ''),
|
||||||
},
|
},
|
||||||
|
|||||||
36
package.json
@@ -31,28 +31,30 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@unocss/eslint-config": "^0.55.0",
|
"@unocss/eslint-config": "^0.55.7",
|
||||||
"@vueuse/core": "^10.3.0",
|
"@vueuse/core": "^10.5.0",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.5.1",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.10",
|
||||||
|
"echarts": "^5.4.3",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"md-editor-v3": "^4.2.2",
|
"md-editor-v3": "^4.7.0",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.11",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
"vue-router": "^4.2.4",
|
"vue-echarts": "^6.6.1",
|
||||||
|
"vue-router": "^4.2.5",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^17.7.1",
|
"@commitlint/cli": "^17.7.2",
|
||||||
"@commitlint/config-conventional": "^17.7.0",
|
"@commitlint/config-conventional": "^17.7.0",
|
||||||
"@iconify/json": "^2.2.100",
|
"@iconify/json": "^2.2.126",
|
||||||
"@iconify/vue": "^4.1.1",
|
"@iconify/vue": "^4.1.1",
|
||||||
"@unocss/preset-rem-to-px": "^0.55.0",
|
"@unocss/preset-rem-to-px": "^0.55.7",
|
||||||
"@vitejs/plugin-vue": "^4.2.3",
|
"@vitejs/plugin-vue": "^4.4.0",
|
||||||
"@vue/compiler-sfc": "^3.3.4",
|
"@vue/compiler-sfc": "^3.3.4",
|
||||||
"@zclzone/eslint-config": "^0.0.4",
|
"@zclzone/eslint-config": "^0.0.4",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
@@ -63,17 +65,17 @@
|
|||||||
"esno": "^0.17.0",
|
"esno": "^0.17.0",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"lint-staged": "^13.2.3",
|
"lint-staged": "^13.3.0",
|
||||||
"naive-ui": "^2.34.4",
|
"naive-ui": "^2.35.0",
|
||||||
"rollup-plugin-visualizer": "^5.9.2",
|
"rollup-plugin-visualizer": "^5.9.2",
|
||||||
"sass": "^1.65.1",
|
"sass": "^1.69.0",
|
||||||
"unocss": "0.55.0",
|
"unocss": "0.55.0",
|
||||||
"unplugin-auto-import": "^0.16.6",
|
"unplugin-auto-import": "^0.16.6",
|
||||||
"unplugin-icons": "^0.16.5",
|
"unplugin-icons": "^0.16.6",
|
||||||
"unplugin-vue-components": "^0.25.1",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-html": "^3.2.0",
|
"vite-plugin-html": "^3.2.0",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.8",
|
||||||
"vite-plugin-svg-icons": "^2.0.1"
|
"vite-plugin-svg-icons": "^2.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9555
pnpm-lock.yaml
generated
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 20 KiB |
2233
public/favicon.svg
|
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 20 KiB |
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"naiveThemeOverrides": {
|
"naiveThemeOverrides": {
|
||||||
"common": {
|
"common": {
|
||||||
"primaryColor": "#409EFFE3",
|
"primaryColor": "#316C72FF",
|
||||||
"primaryColorHover": "#316C72E3",
|
"primaryColorHover": "#316C72E3",
|
||||||
"primaryColorPressed": "#2B4C59FF",
|
"primaryColorPressed": "#2B4C59FF",
|
||||||
"primaryColorSuppl": "#316C72E3",
|
"primaryColorSuppl": "#316C72E3",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 20 KiB |
51
src/components/Echarts.vue
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<v-chart :loading="loading" class="chart" :option="option" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { use } from 'echarts/core'
|
||||||
|
import { BarChart, PieChart } from 'echarts/charts'
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
} from 'echarts/components'
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
|
||||||
|
use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
GridComponent,
|
||||||
|
BarChart,
|
||||||
|
CanvasRenderer,
|
||||||
|
PieChart,
|
||||||
|
DataZoomComponent,
|
||||||
|
])
|
||||||
|
|
||||||
|
import VChart, { THEME_KEY } from 'vue-echarts'
|
||||||
|
|
||||||
|
import { provide } from 'vue'
|
||||||
|
|
||||||
|
provide(THEME_KEY, 'white')
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
option: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route }">
|
||||||
<KeepAlive :include="keepAliveNames">
|
<KeepAlive :include="keepAliveNames">
|
||||||
<component :is="Component" v-if="!tagStore.reloading" :key="route.fullPath" />
|
<div h-full w-full>
|
||||||
|
<component :is="Component" v-if="!tagStore.reloading" :key="route.fullPath" />
|
||||||
|
</div>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</router-view>
|
</router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -89,11 +89,11 @@ function getMenuItem(route, basePath = '') {
|
|||||||
|
|
||||||
function getIcon(meta) {
|
function getIcon(meta) {
|
||||||
if (meta?.customIcon) return renderCustomIcon(meta.customIcon, { size: 18 })
|
if (meta?.customIcon) return renderCustomIcon(meta.customIcon, { size: 18 })
|
||||||
if (meta?.icon) return renderIcon(meta.icon, { size: 18 })
|
if (meta?.icon !== '无' && meta?.icon) return renderIcon(meta.icon, { size: 18 })
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuSelect(key, item) {
|
function handleMenuSelect(_, item) {
|
||||||
if (isExternal(item.path)) {
|
if (isExternal(item.path)) {
|
||||||
window.open(item.path)
|
window.open(item.path)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
21
src/main.js
@@ -18,6 +18,27 @@ async function setupApp() {
|
|||||||
|
|
||||||
await setupRouter(app)
|
await setupRouter(app)
|
||||||
|
|
||||||
|
app.directive('perms', {
|
||||||
|
mounted: (el, binding) => {
|
||||||
|
const { value } = binding
|
||||||
|
const permissions = JSON.parse(localStorage.getItem('roles'))
|
||||||
|
const all_permission = '*'
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
if (value.length > 0) {
|
||||||
|
const hasPermission = permissions.some((key) => {
|
||||||
|
return all_permission == key || value.includes(key)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!hasPermission) {
|
||||||
|
el.parentNode && el.parentNode.removeChild(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('like v-perms="[\'auth/menu/edit\']"')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router
|
|||||||
import { setupRouterGuard } from './guard'
|
import { setupRouterGuard } from './guard'
|
||||||
import { basicRoutes, EMPTY_ROUTE, NOT_FOUND_ROUTE } from './routes'
|
import { basicRoutes, EMPTY_ROUTE, NOT_FOUND_ROUTE } from './routes'
|
||||||
import { getToken, isNullOrWhitespace } from '@/utils'
|
import { getToken, isNullOrWhitespace } from '@/utils'
|
||||||
import { useUserStore, usePermissionStore } from '@/store'
|
import { usePermissionStore } from '@/store'
|
||||||
|
|
||||||
const isHash = true
|
const isHash = true
|
||||||
export const router = createRouter({
|
export const router = createRouter({
|
||||||
@@ -17,16 +17,6 @@ export async function setupRouter(app) {
|
|||||||
app.use(router)
|
app.use(router)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resetRouter() {
|
|
||||||
const basicRouteNames = getRouteNames(basicRoutes)
|
|
||||||
router.getRoutes().forEach((route) => {
|
|
||||||
const name = route.name
|
|
||||||
if (!basicRouteNames.includes(name)) {
|
|
||||||
router.removeRoute(name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function addDynamicRoutes() {
|
export async function addDynamicRoutes() {
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
|
|
||||||
@@ -38,10 +28,8 @@ export async function addDynamicRoutes() {
|
|||||||
|
|
||||||
// 有token的情况
|
// 有token的情况
|
||||||
try {
|
try {
|
||||||
const userStore = useUserStore()
|
|
||||||
const permissionStore = usePermissionStore()
|
const permissionStore = usePermissionStore()
|
||||||
!userStore.userId && (await userStore.getUserInfo())
|
const accessRoutes = permissionStore.generateRoutes()
|
||||||
const accessRoutes = permissionStore.generateRoutes(userStore.role)
|
|
||||||
accessRoutes.forEach((route) => {
|
accessRoutes.forEach((route) => {
|
||||||
!router.hasRoute(route.name) && router.addRoute(route)
|
!router.hasRoute(route.name) && router.addRoute(route)
|
||||||
})
|
})
|
||||||
@@ -49,6 +37,7 @@ export async function addDynamicRoutes() {
|
|||||||
router.addRoute(NOT_FOUND_ROUTE)
|
router.addRoute(NOT_FOUND_ROUTE)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,8 +47,8 @@ export function getRouteNames(routes) {
|
|||||||
|
|
||||||
function getRouteName(route) {
|
function getRouteName(route) {
|
||||||
const names = [route.name]
|
const names = [route.name]
|
||||||
if (route.children && route.children.length) {
|
if (route.subMenu && route.subMenu.length) {
|
||||||
names.push(...route.children.map((item) => getRouteName(item)).flat(1))
|
names.push(...route.subMenu.map((item) => getRouteName(item)).flat(1))
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// const Layout = () => import('@/layout/index.vue')
|
|
||||||
|
|
||||||
export const basicRoutes = [
|
export const basicRoutes = [
|
||||||
{
|
{
|
||||||
name: '404',
|
name: '404',
|
||||||
@@ -17,43 +15,6 @@ export const basicRoutes = [
|
|||||||
title: '登录页',
|
title: '登录页',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// {
|
|
||||||
// name: 'ExternalLink',
|
|
||||||
// path: '/external-link',
|
|
||||||
// component: Layout,
|
|
||||||
// meta: {
|
|
||||||
// title: '外部链接',
|
|
||||||
// icon: 'mdi:link-variant',
|
|
||||||
// order: 4,
|
|
||||||
// },
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// name: 'LinkGithubSrc',
|
|
||||||
// path: 'https://github.com/zclzone/vue-naive-admin',
|
|
||||||
// meta: {
|
|
||||||
// title: '源码 - github',
|
|
||||||
// icon: 'mdi:github',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'LinkGiteeSrc',
|
|
||||||
// path: 'https://gitee.com/zclzone/vue-naive-admin',
|
|
||||||
// meta: {
|
|
||||||
// title: '源码 - gitee',
|
|
||||||
// icon: 'simple-icons:gitee',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'LinkDocs',
|
|
||||||
// path: 'https://zclzone.github.io/vue-naive-admin-docs',
|
|
||||||
// meta: {
|
|
||||||
// title: '文档 - vuepress',
|
|
||||||
// icon: 'mdi:vuejs',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export const NOT_FOUND_ROUTE = {
|
export const NOT_FOUND_ROUTE = {
|
||||||
@@ -68,11 +29,3 @@ export const EMPTY_ROUTE = {
|
|||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
component: null,
|
component: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const modules = import.meta.glob('@/views/**/route.js', { eager: true })
|
|
||||||
const asyncRoutes = []
|
|
||||||
Object.keys(modules).forEach((key) => {
|
|
||||||
asyncRoutes.push(modules[key].default)
|
|
||||||
})
|
|
||||||
|
|
||||||
export { asyncRoutes }
|
|
||||||
|
|||||||
@@ -1,33 +1,105 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { asyncRoutes, basicRoutes } from '@/router/routes'
|
import { basicRoutes } from '@/router/routes'
|
||||||
|
import { RouterView } from 'vue-router'
|
||||||
|
|
||||||
function hasPermission(route, role) {
|
const Layout = () => import('@/layout/index.vue')
|
||||||
// * 不需要权限直接返回true
|
|
||||||
if (!route.meta?.requireAuth) return true
|
|
||||||
|
|
||||||
const routeRole = route.meta?.role ? route.meta.role : []
|
// 匹配views里面所有的.vue文件,动态引入
|
||||||
|
const modules = import.meta.glob('/src/views/**/*.vue')
|
||||||
|
|
||||||
// * 登录用户没有角色或者路由没有设置角色判定为没有权限
|
//
|
||||||
if (!role.length || !routeRole.length) return false
|
export function getModulesKey() {
|
||||||
|
return Object.keys(modules).map((item) => item.replace('/src/views/', '').replace('.vue', ''))
|
||||||
// * 路由指定的角色包含任一登录用户角色则判定有权限
|
|
||||||
return role.some((item) => routeRole.includes(item))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterAsyncRoutes(routes = [], role) {
|
// 动态加载组件
|
||||||
|
export function loadRouteView(component) {
|
||||||
|
try {
|
||||||
|
const key = Object.keys(modules).find((key) => {
|
||||||
|
return key.includes(`${component}.vue`)
|
||||||
|
})
|
||||||
|
if (key) {
|
||||||
|
return modules[key]
|
||||||
|
}
|
||||||
|
throw Error(`找不到组件${component},请确保组件路径正确`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
return RouterView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function hasPermission(route, role) {
|
||||||
|
// // * 不需要权限直接返回true
|
||||||
|
// if (!route.meta?.requireAuth) return true
|
||||||
|
|
||||||
|
// const routeRole = route.meta?.role ? route.meta.role : []
|
||||||
|
|
||||||
|
// // * 登录用户没有角色或者路由没有设置角色判定为没有权限
|
||||||
|
// if (!role.length || !routeRole.length) return false
|
||||||
|
|
||||||
|
// // * 路由指定的角色包含任一登录用户角色则判定有权限
|
||||||
|
// return role.some((item) => routeRole.includes(item))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 过滤异步路由
|
||||||
|
function filterAsyncRoutes(routes = [], firstRoute = true) {
|
||||||
const ret = []
|
const ret = []
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
if (hasPermission(route, role)) {
|
// 过滤掉type为3的路由
|
||||||
const curRoute = {
|
if (route.type === 3) return
|
||||||
...route,
|
const isHidden = route.is_show === 1 ? false : true
|
||||||
children: [],
|
|
||||||
}
|
const meta = {
|
||||||
if (route.children && route.children.length) {
|
requireAuth: true,
|
||||||
curRoute.children = filterAsyncRoutes(route.children, role)
|
title: route.name,
|
||||||
} else {
|
icon: route.icon,
|
||||||
Reflect.deleteProperty(curRoute, 'children')
|
order: route.sort,
|
||||||
}
|
}
|
||||||
ret.push(curRoute)
|
|
||||||
|
let redirect = ''
|
||||||
|
|
||||||
|
if (route.route === '/' && firstRoute) {
|
||||||
|
// 重定向
|
||||||
|
redirect = route.subMenu[0].route
|
||||||
|
}
|
||||||
|
|
||||||
|
const curRoute = {
|
||||||
|
path: route.route,
|
||||||
|
name: route.name,
|
||||||
|
isHidden,
|
||||||
|
meta,
|
||||||
|
redirect,
|
||||||
|
children: [],
|
||||||
|
}
|
||||||
|
if (route.subMenu && route.subMenu.length) {
|
||||||
|
curRoute.children = filterAsyncRoutes(route.subMenu, false)
|
||||||
|
} else {
|
||||||
|
Reflect.deleteProperty(curRoute, 'children')
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (route.type) {
|
||||||
|
case 1:
|
||||||
|
curRoute.component = firstRoute ? Layout : RouterView
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
curRoute.component = loadRouteView(route.components)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push(curRoute)
|
||||||
|
})
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归寻找type为3的路由
|
||||||
|
function findType3Routes(routes = []) {
|
||||||
|
const ret = []
|
||||||
|
routes.forEach((route) => {
|
||||||
|
if (route.type === 3) {
|
||||||
|
ret.push(route.api_route)
|
||||||
|
}
|
||||||
|
if (route.subMenu && route.subMenu.length) {
|
||||||
|
ret.push(...findType3Routes(route.subMenu))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return ret
|
return ret
|
||||||
@@ -48,8 +120,10 @@ export const usePermissionStore = defineStore('permission', {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
generateRoutes(role = []) {
|
generateRoutes() {
|
||||||
const accessRoutes = filterAsyncRoutes(asyncRoutes, role)
|
const menus = JSON.parse(localStorage.getItem('menu'))
|
||||||
|
const accessRoutes = filterAsyncRoutes(menus)
|
||||||
|
window.localStorage.setItem('roles', JSON.stringify(findType3Routes(menus)))
|
||||||
this.accessRoutes = accessRoutes
|
this.accessRoutes = accessRoutes
|
||||||
return accessRoutes
|
return accessRoutes
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { resetRouter } from '@/router'
|
// import { resetRouter } from '@/router'
|
||||||
import { useTagsStore, usePermissionStore } from '@/store'
|
import { useTagsStore, usePermissionStore } from '@/store'
|
||||||
import { removeToken, toLogin } from '@/utils'
|
import { removeToken, toLogin } from '@/utils'
|
||||||
// import api from '@/api'
|
// import api from '@/api'
|
||||||
@@ -18,7 +18,10 @@ export const useUserStore = defineStore('user', {
|
|||||||
return this.userInfo?.name
|
return this.userInfo?.name
|
||||||
},
|
},
|
||||||
avatar() {
|
avatar() {
|
||||||
return this.userInfo?.avatar
|
return (
|
||||||
|
this.userInfo?.avatar ||
|
||||||
|
'https://pic3.58cdn.com.cn/nowater/webim/big/n_v21bc7874294754e63a22b80febac9cf51.jpg'
|
||||||
|
)
|
||||||
},
|
},
|
||||||
role() {
|
role() {
|
||||||
return this.userInfo?.role || []
|
return this.userInfo?.role || []
|
||||||
@@ -41,7 +44,7 @@ export const useUserStore = defineStore('user', {
|
|||||||
removeToken()
|
removeToken()
|
||||||
resetTags()
|
resetTags()
|
||||||
resetPermission()
|
resetPermission()
|
||||||
resetRouter()
|
// resetRouter()
|
||||||
this.$reset()
|
this.$reset()
|
||||||
toLogin()
|
toLogin()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ export function resolveResError(code, message) {
|
|||||||
case 500:
|
case 500:
|
||||||
message = message ?? '服务器异常'
|
message = message ?? '服务器异常'
|
||||||
break
|
break
|
||||||
|
case 402:
|
||||||
|
message = message ?? '无权限访问'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
message = message ?? `【${code}】: 未知异常!`
|
message = message ?? `【${code}】: 未知异常!`
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -14,4 +14,6 @@ export function createAxios(options = {}) {
|
|||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
export const request = createAxios({})
|
export const request = createAxios({
|
||||||
|
baseURL: import.meta.env.VITE_BASE_API,
|
||||||
|
})
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { getToken } from '@/utils'
|
|||||||
import { resolveResError } from './helpers'
|
import { resolveResError } from './helpers'
|
||||||
|
|
||||||
export function reqResolve(config) {
|
export function reqResolve(config) {
|
||||||
if (config.url.includes('/dice')) {
|
// if (config.url.includes('/dice')) {
|
||||||
config.baseURL = import.meta.env.VITE_GAME_API
|
// config.baseURL = import.meta.env.VITE_GAME_API
|
||||||
} else {
|
// } else {
|
||||||
config.baseURL = import.meta.env.VITE_BASE_API
|
// config.baseURL = import.meta.env.VITE_BASE_API
|
||||||
}
|
// }
|
||||||
// 处理不需要token的请求
|
// 处理不需要token的请求
|
||||||
if (config.noNeedToken) {
|
if (config.noNeedToken) {
|
||||||
return config
|
return config
|
||||||
@@ -37,7 +37,7 @@ export function resResolve(response) {
|
|||||||
const code = data?.code ?? status
|
const code = data?.code ?? status
|
||||||
|
|
||||||
/** 根据code处理对应的操作,并返回处理后的message */
|
/** 根据code处理对应的操作,并返回处理后的message */
|
||||||
const message = resolveResError(code, data?.message ?? statusText)
|
const message = resolveResError(code, data?.msg ?? statusText)
|
||||||
|
|
||||||
/** 需要错误提醒 */
|
/** 需要错误提醒 */
|
||||||
!config.noNeedTip && window.$message?.error(message)
|
!config.noNeedTip && window.$message?.error(message)
|
||||||
|
|||||||
6
src/views/business/mer_class/api.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getList: (data) => request.post('/store/classify', data),
|
||||||
|
addClass: (data) => request.post('/store/classify/edit', data),
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
<n-button type="primary" @click="handleAdd(1)">新增商品分类</n-button>
|
<n-button v-perms="['/admin/store/classify/edit']" type="primary" @click="handleAdd(1)">
|
||||||
|
新增商户分类
|
||||||
|
</n-button>
|
||||||
<!-- {{ formValue }} -->
|
<!-- {{ formValue }} -->
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
<n-modal v-model:show="showModal">
|
<n-modal v-model:show="showModal">
|
||||||
<n-card
|
<n-card
|
||||||
@@ -45,9 +48,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, h } from 'vue'
|
import { onMounted, h, withDirectives, resolveDirective } from 'vue'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { NButton } from 'naive-ui'
|
import { NButton } from 'naive-ui'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
@@ -76,17 +80,20 @@ const columns = ref([
|
|||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render(row) {
|
||||||
return [
|
return [
|
||||||
h(
|
withDirectives(
|
||||||
NButton,
|
h(
|
||||||
{
|
NButton,
|
||||||
type: 'primary',
|
{
|
||||||
size: 'small',
|
type: 'primary',
|
||||||
onClick: () => {
|
size: 'small',
|
||||||
formValue.value = row
|
onClick: () => {
|
||||||
handleAdd(2)
|
formValue.value = row
|
||||||
|
handleAdd(2)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
() => '编辑'
|
||||||
() => '编辑'
|
),
|
||||||
|
[[vPerms, ['/admin/store/classify/edit']]]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -105,6 +112,7 @@ const rules = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const formValue = ref({
|
const formValue = ref({
|
||||||
|
ID: 0,
|
||||||
name: '',
|
name: '',
|
||||||
status: 1,
|
status: 1,
|
||||||
})
|
})
|
||||||
@@ -112,9 +120,9 @@ const formValue = ref({
|
|||||||
const showModal = ref(false)
|
const showModal = ref(false)
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -133,12 +141,12 @@ onMounted(() => {
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await api.getMerClass({
|
const res = await api.getList({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data
|
data.value = res.data.data
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
@@ -148,12 +156,13 @@ const getList = async () => {
|
|||||||
const modelTitle = ref('')
|
const modelTitle = ref('')
|
||||||
|
|
||||||
const handleAdd = (e) => {
|
const handleAdd = (e) => {
|
||||||
modelTitle.value = e === 1 ? '新增商品分类' : '编辑商品分类'
|
modelTitle.value = e === 1 ? '新增商户分类' : '编辑商户分类'
|
||||||
showModal.value = true
|
showModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
formValue.value = {
|
formValue.value = {
|
||||||
|
ID: 0,
|
||||||
name: '',
|
name: '',
|
||||||
status: 1,
|
status: 1,
|
||||||
}
|
}
|
||||||
@@ -165,7 +174,7 @@ const handleValidateClick = async (e) => {
|
|||||||
formRef.value?.validate(async (errors) => {
|
formRef.value?.validate(async (errors) => {
|
||||||
if (!errors) {
|
if (!errors) {
|
||||||
try {
|
try {
|
||||||
await api.addMerClass(formValue.value)
|
await api.addClass(formValue.value)
|
||||||
$message.success('成功')
|
$message.success('成功')
|
||||||
clear()
|
clear()
|
||||||
getList()
|
getList()
|
||||||
@@ -4,4 +4,6 @@ export default {
|
|||||||
getList: (data) => request.post('/store', data),
|
getList: (data) => request.post('/store', data),
|
||||||
addMer: (data) => request.post('/store/edit', data),
|
addMer: (data) => request.post('/store/edit', data),
|
||||||
getMerType: () => request.post('/store/getOther'),
|
getMerType: () => request.post('/store/getOther'),
|
||||||
|
// 一键登录
|
||||||
|
login: (data) => request.post('/store/easy/login', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
<!-- {{ formValue }} -->
|
<!-- {{ formValue }} -->
|
||||||
<n-button type="primary" @click="handleAdd(1)">新增商户</n-button>
|
<n-button v-perms="['/store/edit']" type="primary" @click="handleAdd(1)">新增商户</n-button>
|
||||||
<n-grid class="mb-10" x-gap="12" cols="6" collapsed>
|
<n-grid class="mb-10" x-gap="12" cols="6" collapsed>
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<n-drawer v-model:show="showModal" :width="502" placement="right">
|
<n-drawer v-model:show="showModal" :width="502" placement="right">
|
||||||
@@ -54,23 +55,26 @@
|
|||||||
:rules="rules"
|
:rules="rules"
|
||||||
size="medium"
|
size="medium"
|
||||||
>
|
>
|
||||||
<!-- <n-form-item label="商户头像:" path="img">
|
|
||||||
<n-upload
|
|
||||||
v-model:file-list="formValue.img"
|
|
||||||
action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f"
|
|
||||||
list-type="image-card"
|
|
||||||
>
|
|
||||||
点击上传
|
|
||||||
</n-upload>
|
|
||||||
</n-form-item> -->
|
|
||||||
<n-form-item label="商户名称:" path="name">
|
<n-form-item label="商户名称:" path="name">
|
||||||
<n-input v-model:value="formValue.name" placeholder="请输入商户名称" />
|
<n-input
|
||||||
|
v-model:value="formValue.name"
|
||||||
|
:disabled="isEdit"
|
||||||
|
placeholder="请输入商户名称"
|
||||||
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="负责人姓名:" path="username">
|
<n-form-item label="负责人姓名:" path="username">
|
||||||
<n-input v-model:value="formValue.username" placeholder="请输入负责人姓名" />
|
<n-input
|
||||||
|
v-model:value="formValue.username"
|
||||||
|
:disabled="isEdit"
|
||||||
|
placeholder="请输入负责人姓名"
|
||||||
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="商户手机号:" path="phone">
|
<n-form-item label="商户手机号:" path="phone">
|
||||||
<n-input v-model:value="formValue.phone" placeholder="请输入商户手机号" />
|
<n-input
|
||||||
|
v-model:value="formValue.phone"
|
||||||
|
:disabled="isEdit"
|
||||||
|
placeholder="请输入商户手机号"
|
||||||
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="商户座机:" path="mobile">
|
<n-form-item label="商户座机:" path="mobile">
|
||||||
<n-input v-model:value="formValue.mobile" placeholder="请输入商户座机" />
|
<n-input v-model:value="formValue.mobile" placeholder="请输入商户座机" />
|
||||||
@@ -88,13 +92,12 @@
|
|||||||
:options="classOptions"
|
:options="classOptions"
|
||||||
/>
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<!-- <n-form-item label="商户经纬度:" path="local">
|
<n-form-item v-if="!isEdit" label="商户密码:" path="password">
|
||||||
<n-input v-model:value="formValue.local" placeholder="请输入商户地址" />
|
|
||||||
<div ref="wrapRef" class="h-300 w-300"></div>
|
|
||||||
</n-form-item> -->
|
|
||||||
<n-form-item label="商户密码:" path="password">
|
|
||||||
<n-input v-model:value="formValue.password" placeholder="请输入商户密码" />
|
<n-input v-model:value="formValue.password" placeholder="请输入商户密码" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
<n-form-item v-else label="修改密码:" path="password">
|
||||||
|
<n-input v-model:value="formValue.password" placeholder="不修改密码请留空" />
|
||||||
|
</n-form-item>
|
||||||
<n-form-item label="商户类型:" path="bType">
|
<n-form-item label="商户类型:" path="bType">
|
||||||
<n-select
|
<n-select
|
||||||
v-model:value="formValue.bType"
|
v-model:value="formValue.bType"
|
||||||
@@ -137,7 +140,7 @@
|
|||||||
>
|
>
|
||||||
提交
|
提交
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button class="m-auto w-200" @click="handleClearValidateClick">重置</n-button>
|
<!-- <n-button class="m-auto w-200" @click="handleClearValidateClick">重置</n-button> -->
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
</n-drawer-content>
|
</n-drawer-content>
|
||||||
@@ -146,10 +149,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, h, unref, nextTick } from 'vue'
|
import { onMounted, ref, h, withDirectives, resolveDirective } from 'vue'
|
||||||
import { NButton } from 'naive-ui'
|
import { NButton } from 'naive-ui'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { useScript } from '@/hooks/useScript'
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
|
const isEdit = computed(() => (drawerTitle.value === '编辑商户' ? true : false))
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
@@ -177,19 +182,47 @@ const columns = ref([
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render: (row) => {
|
||||||
return [
|
return [
|
||||||
h(
|
withDirectives(
|
||||||
NButton,
|
h(
|
||||||
{
|
NButton,
|
||||||
type: 'primary',
|
{
|
||||||
size: 'small',
|
type: 'primary',
|
||||||
onClick: () => {
|
text: true,
|
||||||
formValue.value = row
|
size: 'small',
|
||||||
handleAdd(2)
|
onClick: () => {
|
||||||
|
formValue.value = { ...row }
|
||||||
|
Reflect.deleteProperty(formValue.value, 'password')
|
||||||
|
handleAdd(2)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
() => '编辑'
|
||||||
() => '编辑'
|
),
|
||||||
|
[[vPerms, ['/admin/store/edit']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
class: 'ml-10',
|
||||||
|
type: 'primary',
|
||||||
|
text: true,
|
||||||
|
size: 'small',
|
||||||
|
onClick: async () => {
|
||||||
|
const res = await api.login({
|
||||||
|
bid: row.bid,
|
||||||
|
})
|
||||||
|
window.open(
|
||||||
|
`${import.meta.env.VITE_MER_LOGIN_URL}?redirect=/workbench&type=${
|
||||||
|
res.data.type
|
||||||
|
}&tk=${res.data.token}`
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '一键登录'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/store/login']]]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -204,12 +237,12 @@ const showModal = ref(false)
|
|||||||
|
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
|
|
||||||
const drawerTitle = ref('')
|
const drawerTitle = ref('新增商户')
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -226,21 +259,6 @@ const QuryVal = ref({
|
|||||||
Status: null,
|
Status: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
// const defaultValueRef = () => ({
|
|
||||||
// name: '',
|
|
||||||
// username: '',
|
|
||||||
// phone: '',
|
|
||||||
// mobile: '',
|
|
||||||
// address: '',
|
|
||||||
// classId: null,
|
|
||||||
// local: '',
|
|
||||||
// password: '',
|
|
||||||
// bType: null,
|
|
||||||
// scaleType: null,
|
|
||||||
// scale: null,
|
|
||||||
// status: 2,
|
|
||||||
// })
|
|
||||||
|
|
||||||
let formValue = ref({
|
let formValue = ref({
|
||||||
name: '',
|
name: '',
|
||||||
username: '',
|
username: '',
|
||||||
@@ -323,42 +341,20 @@ const rules = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrapRef = ref(null)
|
|
||||||
const MapUrl =
|
|
||||||
'https://map.qq.com/api/gljs?v=1.exp&key=S3GBZ-WR26O-IXNW2-SXBOD-LZXV6-WAFNO&callback=initMap'
|
|
||||||
|
|
||||||
const { toPromise } = useScript({ src: MapUrl })
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initMap()
|
|
||||||
getList()
|
getList()
|
||||||
getMertype()
|
getMertype()
|
||||||
})
|
})
|
||||||
|
|
||||||
const initMap = async () => {
|
|
||||||
await toPromise()
|
|
||||||
await nextTick()
|
|
||||||
const wrapEl = unref(wrapRef.value)
|
|
||||||
if (!wrapEl) return
|
|
||||||
const TMap = window?.TMap
|
|
||||||
const center = new TMap.Map.LatLng(39.984104, 116.307503)
|
|
||||||
const map = new TMap.Map.Map(wrapEl, {
|
|
||||||
rotation: 20, //设置地图旋转角度
|
|
||||||
pitch: 30, //设置俯仰角度(0~45)
|
|
||||||
zoom: 12, //设置地图缩放级别
|
|
||||||
center: center, //设置地图中心点坐标
|
|
||||||
})
|
|
||||||
console.log(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const res = await api.getList({
|
const res = await api.getList({
|
||||||
...QuryVal.value,
|
...QuryVal.value,
|
||||||
PageNum: pagination.value.current,
|
PageNum: pagination.value.page,
|
||||||
PageSize: pagination.value.pageSize,
|
PageSize: pagination.value.pageSize,
|
||||||
})
|
})
|
||||||
data.value = res.data.data
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +370,7 @@ const getMertype = async () => {
|
|||||||
const clearQuryVal = () => {
|
const clearQuryVal = () => {
|
||||||
QuryVal.value = {
|
QuryVal.value = {
|
||||||
StoreName: '',
|
StoreName: '',
|
||||||
Status: '',
|
Status: null,
|
||||||
}
|
}
|
||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
@@ -384,14 +380,6 @@ const handleAdd = (e) => {
|
|||||||
showModal.value = true
|
showModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// const onPositiveClick = () => {
|
|
||||||
// showModal.value = false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const onNegativeClick = () => {
|
|
||||||
// showModal.value = false
|
|
||||||
// }
|
|
||||||
|
|
||||||
const handleValidateClick = (e) => {
|
const handleValidateClick = (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
formRef.value?.validate(async (errors) => {
|
formRef.value?.validate(async (errors) => {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
<n-button type="primary" @click="handleAdd(1)">新增商户类型</n-button>
|
<n-button v-perms="['/admin/typesof/edit']" type="primary" @click="handleAdd(1)">
|
||||||
|
新增商户类型
|
||||||
|
</n-button>
|
||||||
<!-- {{ formValue }} -->
|
<!-- {{ formValue }} -->
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
<n-modal v-model:show="showModal">
|
<n-modal v-model:show="showModal">
|
||||||
<n-card
|
<n-card
|
||||||
@@ -45,9 +48,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, h } from 'vue'
|
import { onMounted, h, withDirectives, resolveDirective } from 'vue'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { NButton } from 'naive-ui'
|
import { NButton } from 'naive-ui'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
@@ -76,17 +80,20 @@ const columns = ref([
|
|||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render(row) {
|
||||||
return [
|
return [
|
||||||
h(
|
withDirectives(
|
||||||
NButton,
|
h(
|
||||||
{
|
NButton,
|
||||||
type: 'primary',
|
{
|
||||||
size: 'small',
|
type: 'primary',
|
||||||
onClick: () => {
|
size: 'small',
|
||||||
formValue.value = row
|
onClick: () => {
|
||||||
handleAdd(2)
|
formValue.value = row
|
||||||
|
handleAdd(2)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
() => '编辑'
|
||||||
() => '编辑'
|
),
|
||||||
|
[[vPerms, ['/admin/typesof/edit']]]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -112,9 +119,9 @@ const formValue = ref({
|
|||||||
const showModal = ref(false)
|
const showModal = ref(false)
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -134,11 +141,11 @@ const getList = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await api.getMerType({
|
const res = await api.getMerType({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data
|
data.value = res.data.data
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 获取入驻审核列表
|
||||||
|
getAuditList: (data) => request.post('/process/store', data),
|
||||||
|
// 通过审核/不通过
|
||||||
|
passAudit: (data) => request.post('/process/store/edit', data),
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,209 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title"></CommonPage>
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-data-table
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
<!-- 详情 -->
|
||||||
|
<n-drawer v-model:show="active" :width="502" placement="right">
|
||||||
|
<n-drawer-content title="商户入驻详情">
|
||||||
|
<div>
|
||||||
|
<div>商户名称:{{ nowRow.name }}</div>
|
||||||
|
<div mt-10>用户姓名:{{ nowRow.username }}</div>
|
||||||
|
<div mt-10>联系电话:{{ nowRow.phone }}</div>
|
||||||
|
<div mt-10>开户行:{{ nowRow.bank }}</div>
|
||||||
|
<div mt-10>银行卡号:{{ nowRow.bank_card }}</div>
|
||||||
|
<div mt-10>商户类型:{{ atype.name }}</div>
|
||||||
|
<div mt-10>经营类目:{{ btype.name }}</div>
|
||||||
|
<div mt-10>
|
||||||
|
<div>营业执照:</div>
|
||||||
|
<n-image width="100" :src="nowRow.license" />
|
||||||
|
</div>
|
||||||
|
<div mt-10>
|
||||||
|
<div>法人身份证(正面):</div>
|
||||||
|
<n-image width="100" :src="nowRow.front" />
|
||||||
|
</div>
|
||||||
|
<div mt-10>
|
||||||
|
<div>法人身份证(反面):</div>
|
||||||
|
<n-image width="100" :src="nowRow.back" />
|
||||||
|
</div>
|
||||||
|
<div mt-10>
|
||||||
|
<div>门头照:</div>
|
||||||
|
<n-image-group>
|
||||||
|
<n-image
|
||||||
|
v-for="(item, index) in nowRow.img"
|
||||||
|
:key="index"
|
||||||
|
mr-10
|
||||||
|
width="100"
|
||||||
|
:src="item"
|
||||||
|
/>
|
||||||
|
</n-image-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div m-auto w-full flex justify-center>
|
||||||
|
<n-button mr-20 type="primary" @click="ok">通过</n-button>
|
||||||
|
<n-button mr-20 type="warning" @click="noOk">不通过</n-button>
|
||||||
|
<n-button @click="active = false">关闭</n-button>
|
||||||
|
</div>
|
||||||
|
</n-drawer-content>
|
||||||
|
</n-drawer>
|
||||||
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup></script>
|
<script setup>
|
||||||
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
import api from './api'
|
||||||
|
import api1 from '../mer_list/api'
|
||||||
|
import { NButton } from 'naive-ui'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const nowRow = ref({})
|
||||||
|
|
||||||
|
const active = ref(false)
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '商户名称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户姓名',
|
||||||
|
align: 'center',
|
||||||
|
key: 'username',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '联系电话',
|
||||||
|
align: 'center',
|
||||||
|
key: 'phone',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开户银行',
|
||||||
|
align: 'center',
|
||||||
|
key: 'bank',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '银行卡号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'bank_card',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'detail',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'primary',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowRow.value = {
|
||||||
|
...row,
|
||||||
|
img: row.img.split(','),
|
||||||
|
}
|
||||||
|
active.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '详情',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/process/store/edit']]]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([])
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
getMertype()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const res = await api.getAuditList({
|
||||||
|
pageNum: pagination.value.page,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const classOptions = ref([])
|
||||||
|
const typeOptions = ref([])
|
||||||
|
|
||||||
|
const getMertype = async () => {
|
||||||
|
const res = await api1.getMerType()
|
||||||
|
classOptions.value = res.data.class
|
||||||
|
typeOptions.value = res.data.type
|
||||||
|
}
|
||||||
|
|
||||||
|
const atype = computed(() => {
|
||||||
|
return typeOptions.value.find((item) => {
|
||||||
|
if (item.ID === nowRow.value.bType) return item
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const btype = computed(() => {
|
||||||
|
return classOptions.value.find((item) => {
|
||||||
|
if (item.ID === nowRow.value.classId) return item
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const ok = async () => {
|
||||||
|
$dialog.warning({
|
||||||
|
title: '提示',
|
||||||
|
content: '同意后无法撤销,确认同意吗?',
|
||||||
|
positiveText: '确定',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: async () => {
|
||||||
|
const res = await api.passAudit({
|
||||||
|
bid: nowRow.value.bid,
|
||||||
|
status: 1,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
},
|
||||||
|
onNegativeClick: () => {
|
||||||
|
$message.warning('已取消操作')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const noOk = async () => {
|
||||||
|
const res = await api.passAudit({
|
||||||
|
bid: nowRow.value.bid,
|
||||||
|
status: 2,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
nowRow.value = {}
|
||||||
|
active.value = false
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/merchant',
|
path: '/merchant',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/mer_list',
|
redirect: '/mer_list',
|
||||||
|
meta: {
|
||||||
|
title: '商户管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Merlist',
|
name: 'Merlist',
|
||||||
@@ -16,6 +21,16 @@ export default {
|
|||||||
order: 10,
|
order: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Classlist',
|
||||||
|
path: 'mer_class',
|
||||||
|
component: () => import('./mer_class/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '商户分类',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Mertype',
|
name: 'Mertype',
|
||||||
path: 'mer_type',
|
path: 'mer_type',
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import { request } from '@/utils'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getMerClass: (data) => request.post('/classify', data),
|
|
||||||
addMerClass: (data) => request.post('/classify/edit', data),
|
|
||||||
}
|
|
||||||
@@ -8,33 +8,214 @@
|
|||||||
:bordered="false"
|
:bordered="false"
|
||||||
remote
|
remote
|
||||||
/>
|
/>
|
||||||
|
<!-- 拒绝 -->
|
||||||
|
<n-modal v-model:show="isNoteModel">
|
||||||
|
<n-card
|
||||||
|
style="width: 500px"
|
||||||
|
title="拒绝信息"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-input v-model:value="notesVal" type="textarea" placeholder="请输入拒绝理由...." />
|
||||||
|
<div m-auto p-10>
|
||||||
|
<n-button type="primary" @click="veeify">确定</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
<!-- 豆子设置 -->
|
||||||
|
<n-modal v-model:show="isDzModel">
|
||||||
|
<n-card
|
||||||
|
style="width: 500px"
|
||||||
|
title="赠送/比例"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-form ref="formRef" :model="nowRow" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="24">
|
||||||
|
<n-form-item-gi :span="20" label="赠送豆子" path="pulse_number">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="nowRow.pulse_number"
|
||||||
|
clearable
|
||||||
|
:precision="2"
|
||||||
|
placeholder="请输入赠送豆子数量...."
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="20" label="赠送积分" path="integral">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="nowRow.integral"
|
||||||
|
clearable
|
||||||
|
:precision="2"
|
||||||
|
placeholder="请输入赠送积分数量...."
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="18" label="分佣类型" path="commission_type">
|
||||||
|
<n-select
|
||||||
|
v-model:value="nowRow.commission_type"
|
||||||
|
placeholder="请选择分佣类型"
|
||||||
|
clearable
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
label: '百分比',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数值',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="20" label="分佣比例" path="commission">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="nowRow.commission"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入分佣比例...."
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="12">
|
||||||
|
<div m-auto p-10>
|
||||||
|
<n-button type="primary" @click="veeify">确定</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
<!-- 商品详情 -->
|
||||||
|
<n-drawer v-model:show="showDrawer" :width="502">
|
||||||
|
<n-drawer-content title="商品详情" closable>
|
||||||
|
<n-space vertical>
|
||||||
|
<div>
|
||||||
|
<span>商品分类:</span>
|
||||||
|
<span>{{ goodInfo.class_name }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品名称:</span>
|
||||||
|
<span>{{ goodInfo.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div flex items-center>
|
||||||
|
<span>封面:</span>
|
||||||
|
<n-image width="100" :src="goodInfo.cover" />
|
||||||
|
</div>
|
||||||
|
<div flex items-center>
|
||||||
|
<span>轮播图:</span>
|
||||||
|
<div w-400 overflow-auto>
|
||||||
|
<n-image
|
||||||
|
v-for="(url, index) in goodInfo.rotation?.split(',')"
|
||||||
|
:key="index"
|
||||||
|
width="100"
|
||||||
|
:src="url"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品价格:</span>
|
||||||
|
<span>{{ goodInfo.number }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>市场价格:</span>
|
||||||
|
<span>{{ goodInfo.market_num }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品库存:</span>
|
||||||
|
<span>{{ goodInfo.stock }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品简介:</span>
|
||||||
|
<span>{{ goodInfo.profile }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品详情:</span>
|
||||||
|
<div v-html="goodInfo.details"></div>
|
||||||
|
</div>
|
||||||
|
</n-space>
|
||||||
|
</n-drawer-content>
|
||||||
|
</n-drawer>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { NDropdown, NButton } from 'naive-ui'
|
import { NButton, NImage, NSpace, NEllipsis } from 'naive-ui'
|
||||||
import { h } from 'vue'
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const isNoteModel = ref(false)
|
||||||
|
|
||||||
|
const isDzModel = ref(false)
|
||||||
|
|
||||||
|
const goodInfo = ref({})
|
||||||
|
|
||||||
|
const showDrawer = ref(false)
|
||||||
|
|
||||||
|
const notesVal = ref('')
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
pulse_number: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请输入赠送豆子数量',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
integral: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请输入赠送积分数量',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
commission_type: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请选择分佣类型',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
commission: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请输入分佣比例',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const nowRow = ref({})
|
||||||
|
const nowKey = ref(null)
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '商品名称',
|
title: '商品名称',
|
||||||
key: 'name',
|
slot: 'name',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 200px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品封面',
|
title: '商品封面',
|
||||||
slot: 'cover',
|
slot: 'cover',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('img', {
|
return h(NImage, {
|
||||||
src: row.cover,
|
src: row.cover,
|
||||||
style: {
|
width: '30',
|
||||||
width: '30px',
|
|
||||||
height: '30px',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -44,7 +225,7 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品价格',
|
title: '商品价格(元)',
|
||||||
key: 'number',
|
key: 'number',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
@@ -53,52 +234,130 @@ const columns = ref([
|
|||||||
key: 'stock',
|
key: 'stock',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '赠送豆子',
|
||||||
|
key: 'pulse_number',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '赠送积分',
|
||||||
|
key: 'integral',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分佣类型',
|
||||||
|
slot: 'commission_type',
|
||||||
|
align: 'center',
|
||||||
|
render(row) {
|
||||||
|
return row.commission_type === 1 ? '百分比' : '数值'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分佣比例',
|
||||||
|
key: 'commission',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '商品状态',
|
title: '商品状态',
|
||||||
slot: 'status',
|
slot: 'status',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
return row.status === 0 ? '待审核' : row.status === 1 ? '已审核' : '已拒绝'
|
return row.status === 3 ? '待审核' : row.status === 1 ? '已审核' : '已拒绝'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
key: 'notes',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
const el = []
|
let el = []
|
||||||
|
if (row.status === 3) {
|
||||||
if (row.status === 0) {
|
el = [
|
||||||
el.push(
|
|
||||||
h(
|
h(
|
||||||
NDropdown,
|
NSpace,
|
||||||
{
|
{
|
||||||
trigger: 'click',
|
justify: 'center',
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: '审核',
|
|
||||||
key: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '拒绝',
|
|
||||||
key: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onSelect: (key) => {
|
|
||||||
veeify(key, row)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
() =>
|
{
|
||||||
h(
|
default: () => [
|
||||||
NButton,
|
withDirectives(
|
||||||
{
|
h(
|
||||||
type: 'primary',
|
NButton,
|
||||||
text: true,
|
{
|
||||||
|
type: 'primary',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowKey.value = 1
|
||||||
|
nowRow.value = { ...row }
|
||||||
|
veeify()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '审核通过'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/goods/process']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'error',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowKey.value = 2
|
||||||
|
nowRow.value = { ...row }
|
||||||
|
isNoteModel.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '审核拒绝'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/goods/process']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowKey.value = 3
|
||||||
|
goodInfo.value = { ...row }
|
||||||
|
showDrawer.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '商品详情'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/goods/process']]]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
el = [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'info',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowRow.value = { ...row }
|
||||||
|
nowKey.value = 3
|
||||||
|
isDzModel.value = true
|
||||||
},
|
},
|
||||||
() => '审核'
|
},
|
||||||
)
|
{
|
||||||
)
|
default: () => '赠送/比例',
|
||||||
)
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/goods/process']]]
|
||||||
|
),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return el
|
return el
|
||||||
@@ -109,9 +368,9 @@ const columns = ref([
|
|||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
itamCount: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -131,24 +390,47 @@ const getList = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await api.getHotlist({
|
const res = await api.getHotlist({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data || []
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const veeify = async (key, row) => {
|
const clear = () => {
|
||||||
const res = await api.getHotStatus({
|
isNoteModel.value = false
|
||||||
gid: row.gid,
|
isDzModel.value = false
|
||||||
status: key,
|
notesVal.value = ''
|
||||||
})
|
nowRow.value = {}
|
||||||
console.log(res)
|
}
|
||||||
getList()
|
|
||||||
|
const veeify = async () => {
|
||||||
|
let data = {}
|
||||||
|
if (nowKey.value === 1 || nowKey.value === 2) {
|
||||||
|
data = {
|
||||||
|
gid: nowRow.value.gid,
|
||||||
|
status: nowKey.value,
|
||||||
|
notes: notesVal.value,
|
||||||
|
}
|
||||||
|
await api.getHotStatus(data)
|
||||||
|
await getList()
|
||||||
|
clear()
|
||||||
|
} else {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
data = {
|
||||||
|
...nowRow.value,
|
||||||
|
}
|
||||||
|
await api.getHotStatus(data)
|
||||||
|
await getList()
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import { request } from '@/utils'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
getPointlist: (data) => request.post('/point/goods', data),
|
getPointlist: (data) => request.post('/point/goods', data),
|
||||||
getPointStatus: (data) => request.post('/point/goods/process', data),
|
setPointStatus: (data) => request.post('/point/goods/process', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,34 +6,122 @@
|
|||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
|
<!-- 拒绝 -->
|
||||||
|
<n-modal v-model:show="isNoteModel">
|
||||||
|
<n-card
|
||||||
|
style="width: 500px"
|
||||||
|
title="拒绝信息"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-input v-model:value="notesVal" type="textarea" placeholder="请输入拒绝理由...." />
|
||||||
|
<div m-auto p-10>
|
||||||
|
<n-button type="primary" @click="veeify">确定</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
<!-- 商品详情 -->
|
||||||
|
<n-drawer v-model:show="showDrawer" :width="502">
|
||||||
|
<n-drawer-content title="商品详情" closable>
|
||||||
|
<n-space vertical>
|
||||||
|
<div>
|
||||||
|
<span>商品分类:</span>
|
||||||
|
<span>{{ goodInfo.class_name }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品名称:</span>
|
||||||
|
<span>{{ goodInfo.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div flex items-center>
|
||||||
|
<span>封面:</span>
|
||||||
|
<n-image width="100" :src="goodInfo.cover" />
|
||||||
|
</div>
|
||||||
|
<div flex items-center>
|
||||||
|
<span w-90>轮播图:</span>
|
||||||
|
<div flex flex-wrap>
|
||||||
|
<n-image
|
||||||
|
v-for="(url, index) in goodInfo.rotation?.split(',')"
|
||||||
|
:key="index"
|
||||||
|
width="100"
|
||||||
|
:src="url"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品价格:</span>
|
||||||
|
<span>{{ goodInfo.number }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>市场价格:</span>
|
||||||
|
<span>{{ goodInfo.market_num }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品库存:</span>
|
||||||
|
<span>{{ goodInfo.stock }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品简介:</span>
|
||||||
|
<span>{{ goodInfo.profile }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品详情:</span>
|
||||||
|
<div v-html="goodInfo.details"></div>
|
||||||
|
</div>
|
||||||
|
</n-space>
|
||||||
|
</n-drawer-content>
|
||||||
|
</n-drawer>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { NDropdown, NButton } from 'naive-ui'
|
import { NEllipsis, NButton, NImage, NSpace } from 'naive-ui'
|
||||||
import { h } from 'vue'
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const isNoteModel = ref(false)
|
||||||
|
|
||||||
|
const goodInfo = ref({})
|
||||||
|
|
||||||
|
const showDrawer = ref(false)
|
||||||
|
|
||||||
|
const notesVal = ref('')
|
||||||
|
|
||||||
|
const nowRow = ref({})
|
||||||
|
const nowKey = ref(null)
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '商品名称',
|
title: '商品名称',
|
||||||
key: 'name',
|
slot: 'name',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 200px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品封面',
|
title: '商品封面',
|
||||||
slot: 'cover',
|
slot: 'cover',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('img', {
|
return h(NImage, {
|
||||||
src: row.cover,
|
src: row.cover,
|
||||||
style: {
|
width: '30',
|
||||||
width: '30px',
|
|
||||||
height: '30px',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -57,50 +145,81 @@ const columns = ref([
|
|||||||
slot: 'status',
|
slot: 'status',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
return row.status === 0 ? '待审核' : row.status === 1 ? '已审核' : '已拒绝'
|
return row.status === 3 ? '待审核' : row.status === 1 ? '已审核' : '已拒绝'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
key: 'notes',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render(row) {
|
render(row) {
|
||||||
const el = []
|
if (row.status === 3) {
|
||||||
|
return [
|
||||||
if (row.status === 0) {
|
|
||||||
el.push(
|
|
||||||
h(
|
h(
|
||||||
NDropdown,
|
NSpace,
|
||||||
{
|
{
|
||||||
trigger: 'click',
|
justify: 'center',
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: '审核',
|
|
||||||
key: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '拒绝',
|
|
||||||
key: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onSelect: (key) => {
|
|
||||||
veeify(key, row)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
() =>
|
{
|
||||||
h(
|
default: () => [
|
||||||
NButton,
|
withDirectives(
|
||||||
{
|
h(
|
||||||
type: 'primary',
|
NButton,
|
||||||
text: true,
|
{
|
||||||
},
|
type: 'primary',
|
||||||
() => '审核'
|
text: true,
|
||||||
)
|
onClick: () => {
|
||||||
)
|
nowKey.value = 1
|
||||||
)
|
nowRow.value = { ...row }
|
||||||
|
veeify()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '审核通过'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/point/goods/process']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'error',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowKey.value = 2
|
||||||
|
nowRow.value = { ...row }
|
||||||
|
isNoteModel.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '审核拒绝'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/point/goods/process']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'info',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
nowKey.value = 3
|
||||||
|
goodInfo.value = { ...row }
|
||||||
|
showDrawer.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => '商品详情'
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/point/goods/process']]]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
return el
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -108,9 +227,9 @@ const columns = ref([
|
|||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -130,25 +249,30 @@ const getList = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await api.getPointlist({
|
const res = await api.getPointlist({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data || []
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const veeify = async (key, row) => {
|
const clear = () => {
|
||||||
console.log(typeof key)
|
isNoteModel.value = false
|
||||||
const res = await api.getPointStatus({
|
notesVal.value = ''
|
||||||
gid: row.gid,
|
}
|
||||||
status: key,
|
|
||||||
|
const veeify = async () => {
|
||||||
|
await api.setPointStatus({
|
||||||
|
gid: nowRow.value.gid,
|
||||||
|
status: nowKey.value,
|
||||||
|
notes: notesVal.value,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
getList()
|
getList()
|
||||||
|
clear()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,12 @@ export default {
|
|||||||
path: '/commodity',
|
path: '/commodity',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/commodity_class',
|
redirect: '/commodity_class',
|
||||||
|
meta: {
|
||||||
|
title: '商品管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
|
||||||
name: 'CommodityClass',
|
|
||||||
path: 'commodity_class',
|
|
||||||
component: () => import('./commodity_class/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '商品分类',
|
|
||||||
icon: 'mdi:account-multiple',
|
|
||||||
order: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'HotList',
|
name: 'HotList',
|
||||||
path: 'hot_list',
|
path: 'hot_list',
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage show-footer>
|
|
||||||
<n-space size="large">
|
|
||||||
<n-card title="按钮 Button">
|
|
||||||
<n-space>
|
|
||||||
<n-button>Default</n-button>
|
|
||||||
<n-button type="tertiary">Tertiary</n-button>
|
|
||||||
<n-button type="primary">Primary</n-button>
|
|
||||||
<n-button type="info">Info</n-button>
|
|
||||||
<n-button type="success">Success</n-button>
|
|
||||||
<n-button type="warning">Warning</n-button>
|
|
||||||
<n-button type="error">Error</n-button>
|
|
||||||
</n-space>
|
|
||||||
</n-card>
|
|
||||||
|
|
||||||
<n-card title="带 Icon 的按钮">
|
|
||||||
<n-space>
|
|
||||||
<n-button type="info">
|
|
||||||
<TheIcon icon="material-symbols:add" :size="18" class="mr-5" />
|
|
||||||
新增
|
|
||||||
</n-button>
|
|
||||||
<n-button type="error">
|
|
||||||
<TheIcon icon="material-symbols:delete-outline" :size="18" class="mr-5" />
|
|
||||||
删除
|
|
||||||
</n-button>
|
|
||||||
<n-button type="warning">
|
|
||||||
<TheIcon icon="material-symbols:edit-outline" :size="18" class="mr-5" />
|
|
||||||
编辑
|
|
||||||
</n-button>
|
|
||||||
<n-button type="primary">
|
|
||||||
<TheIcon icon="majesticons:eye-line" :size="18" class="mr-5" />
|
|
||||||
查看
|
|
||||||
</n-button>
|
|
||||||
</n-space>
|
|
||||||
</n-card>
|
|
||||||
</n-space>
|
|
||||||
|
|
||||||
<n-space size="large" mt-30>
|
|
||||||
<n-card min-w-340 title="通知 Notification">
|
|
||||||
<n-space>
|
|
||||||
<n-button @click="notify('info')">信息</n-button>
|
|
||||||
<n-button @click="notify('success')">成功</n-button>
|
|
||||||
<n-button @click="notify('warning')">警告</n-button>
|
|
||||||
<n-button @click="notify('error')">错误</n-button>
|
|
||||||
</n-space>
|
|
||||||
</n-card>
|
|
||||||
|
|
||||||
<n-card min-w-340 title="确认弹窗 Dialog">
|
|
||||||
<n-button type="error" @click="handleDelete">
|
|
||||||
<icon-mi:delete mr-5 />
|
|
||||||
删除
|
|
||||||
</n-button>
|
|
||||||
</n-card>
|
|
||||||
|
|
||||||
<n-card min-w-340 title="消息提醒 Message">
|
|
||||||
<n-button :loading="loading" type="primary" @click="handleLogin">
|
|
||||||
<icon-mdi:login v-show="!loading" mr-5 />
|
|
||||||
登陆
|
|
||||||
</n-button>
|
|
||||||
</n-card>
|
|
||||||
</n-space>
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const handleDelete = function () {
|
|
||||||
$dialog.confirm({
|
|
||||||
content: '确认删除?',
|
|
||||||
confirm() {
|
|
||||||
$message.success('删除成功')
|
|
||||||
},
|
|
||||||
cancel() {
|
|
||||||
$message.warning('已取消')
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
function handleLogin() {
|
|
||||||
loading.value = true
|
|
||||||
$message.loading('登陆中...')
|
|
||||||
setTimeout(() => {
|
|
||||||
$message.error('登陆失败')
|
|
||||||
$message.loading('正在尝试重新登陆...')
|
|
||||||
setTimeout(() => {
|
|
||||||
$message.success('登陆成功')
|
|
||||||
loading.value = false
|
|
||||||
}, 2000)
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
|
|
||||||
function notify(type) {
|
|
||||||
$notification[type]({
|
|
||||||
content: '说点啥呢',
|
|
||||||
meta: '想不出来',
|
|
||||||
duration: 2500,
|
|
||||||
keepAliveOnHover: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage show-footer>
|
|
||||||
<div w-350>
|
|
||||||
<n-input v-model:value="inputVal" />
|
|
||||||
<n-input-number v-model:value="number" mt-30 />
|
|
||||||
<p mt-20 text-center text-14 color-gray>注:右击标签重新加载可重置keep-alive</p>
|
|
||||||
</div>
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
defineOptions({ name: 'KeepAlive' })
|
|
||||||
|
|
||||||
const inputVal = ref('')
|
|
||||||
const number = ref(0)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
$message.success('onMounted')
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
$message.error('onUnmounted')
|
|
||||||
})
|
|
||||||
|
|
||||||
onActivated(() => {
|
|
||||||
$message.info('onActivated')
|
|
||||||
})
|
|
||||||
onDeactivated(() => {
|
|
||||||
$message.warning('onDeactivated')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
const Layout = () => import('@/layout/index.vue')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Test',
|
|
||||||
path: '/base',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/base/index',
|
|
||||||
isHidden: true,
|
|
||||||
meta: {
|
|
||||||
title: '基础功能',
|
|
||||||
icon: 'majesticons:compass-line',
|
|
||||||
order: 1,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'BaseComponents',
|
|
||||||
path: 'index',
|
|
||||||
component: () => import('./index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '基础组件',
|
|
||||||
icon: 'material-symbols:auto-awesome-outline-rounded',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Unocss',
|
|
||||||
path: 'unocss',
|
|
||||||
component: () => import('./unocss/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: 'Unocss',
|
|
||||||
icon: 'material-symbols:auto-awesome-outline-rounded',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'KeepAlive',
|
|
||||||
path: 'keep-alive',
|
|
||||||
component: () => import('./keep-alive/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: 'KeepAlive',
|
|
||||||
icon: 'material-symbols:auto-awesome-outline-rounded',
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage show-footer>
|
|
||||||
<p>
|
|
||||||
文档:
|
|
||||||
<a c-blue hover-decoration-underline href="https://uno.antfu.me/" target="_blank">
|
|
||||||
https://uno.antfu.me/
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
playground:
|
|
||||||
<a c-blue hover-decoration-underline href="https://unocss.antfu.me/play/" target="_blank">
|
|
||||||
https://unocss.antfu.me/play/
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div mt-20 w-350 f-c-c flex-col>
|
|
||||||
<div flex flex-wrap justify-around rounded-10 p-10 border="1 solid #ccc">
|
|
||||||
<div m-20 h-50 w-50 f-c-c rounded-5 p-10 border="1 solid">
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div m-20 h-50 w-50 flex justify-between rounded-5 p-10 border="1 solid">
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 self-end rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div m-20 h-50 w-50 flex justify-between rounded-5 p-10 border="1 solid">
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 self-center rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 self-end rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div m-20 h-50 w-50 flex justify-between rounded-5 p-10 border="1 solid">
|
|
||||||
<div flex-col justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div flex-col justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div m-20 h-50 w-50 flex-col items-center justify-between rounded-5 p-10 border="1 solid">
|
|
||||||
<div w-full flex justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<div w-full flex justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div m-20 h-50 w-50 flex-col justify-between rounded-5 p-10 border="1 solid">
|
|
||||||
<div w-full flex justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div w-full flex justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
<div w-full flex justify-between>
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
<span h-6 w-6 rounded-3 bg-black dark:bg-white />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h2 mt-10 text-14 font-normal color-gray>Flex 骰子</h2>
|
|
||||||
</div>
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage>
|
|
||||||
<div h-60 flex items-center bg-white pl-20 pr-20 dark:bg-dark>
|
|
||||||
<input
|
|
||||||
v-model="post.title"
|
|
||||||
class="mr-20 flex-1 pb-15 pt-15 text-20 font-bold color-primary"
|
|
||||||
dark:bg-dark
|
|
||||||
type="text"
|
|
||||||
placeholder="输入文章标题..."
|
|
||||||
/>
|
|
||||||
<n-button type="primary" style="width: 80px" :loading="btnLoading" @click="handleSavePost">
|
|
||||||
<TheIcon v-if="!btnLoading" icon="line-md:confirm-circle" class="mr-5" :size="18" />
|
|
||||||
保存
|
|
||||||
</n-button>
|
|
||||||
</div>
|
|
||||||
<MdEditor v-model="post.content" style="height: calc(100vh - 305px)" dark:bg-dark />
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { MdEditor } from 'md-editor-v3'
|
|
||||||
import 'md-editor-v3/lib/style.css'
|
|
||||||
|
|
||||||
defineOptions({ name: 'MDEditor' })
|
|
||||||
|
|
||||||
// refs
|
|
||||||
let post = ref({})
|
|
||||||
let btnLoading = ref(false)
|
|
||||||
|
|
||||||
function handleSavePost() {
|
|
||||||
btnLoading.value = true
|
|
||||||
$message.loading('正在保存...')
|
|
||||||
setTimeout(() => {
|
|
||||||
$message.success('保存成功')
|
|
||||||
btnLoading.value = false
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.md-preview {
|
|
||||||
ul,
|
|
||||||
ol {
|
|
||||||
list-style: revert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<template>
|
|
||||||
<AppPage>
|
|
||||||
<div class="h-full flex-col" border="1 solid #ccc" dark:bg-dark>
|
|
||||||
<WangToolbar
|
|
||||||
border-b="1px solid #ccc"
|
|
||||||
:editor="editorRef"
|
|
||||||
:default-config="toolbarConfig"
|
|
||||||
mode="default"
|
|
||||||
/>
|
|
||||||
<WangEditor
|
|
||||||
v-model="valueHtml"
|
|
||||||
style="flex: 1; overflow-y: hidden"
|
|
||||||
:default-config="editorConfig"
|
|
||||||
mode="default"
|
|
||||||
@on-created="handleCreated"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
|
||||||
import { Editor as WangEditor, Toolbar as WangToolbar } from '@wangeditor/editor-for-vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'RichTextEditor' })
|
|
||||||
const editorRef = shallowRef()
|
|
||||||
const toolbarConfig = { excludeKeys: 'fullScreen' }
|
|
||||||
const editorConfig = { placeholder: '请输入内容...', MENU_CONF: {} }
|
|
||||||
const valueHtml = ref('')
|
|
||||||
|
|
||||||
const handleCreated = (editor) => {
|
|
||||||
editorRef.value = editor
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
html.dark {
|
|
||||||
--w-e-textarea-bg-color: #333;
|
|
||||||
--w-e-textarea-color: #fff;
|
|
||||||
--w-e-toolbar-bg-color: #333;
|
|
||||||
--w-e-toolbar-color: #fff;
|
|
||||||
--w-e-toolbar-active-bg-color: #666;
|
|
||||||
--w-e-toolbar-active-color: #fff;
|
|
||||||
/* ...其他... */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
const Layout = () => import('@/layout/index.vue')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Demo',
|
|
||||||
path: '/demo',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/demo/crud',
|
|
||||||
meta: {
|
|
||||||
title: '示例页面',
|
|
||||||
customIcon: 'logo',
|
|
||||||
role: ['admin'],
|
|
||||||
requireAuth: true,
|
|
||||||
order: 3,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'Crud',
|
|
||||||
path: 'crud',
|
|
||||||
component: () => import('./table/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: 'CRUD表格',
|
|
||||||
icon: 'ic:baseline-table-view',
|
|
||||||
role: ['admin'],
|
|
||||||
requireAuth: true,
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'MDEditor',
|
|
||||||
path: 'md-editor',
|
|
||||||
component: () => import('./editor/md-editor.vue'),
|
|
||||||
meta: {
|
|
||||||
title: 'MD编辑器',
|
|
||||||
icon: 'ri:markdown-line',
|
|
||||||
role: ['admin'],
|
|
||||||
requireAuth: true,
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'RichTextEditor',
|
|
||||||
path: 'rich-text',
|
|
||||||
component: () => import('./editor/rich-text.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '富文本编辑器',
|
|
||||||
icon: 'ic:sharp-text-rotation-none',
|
|
||||||
role: ['admin'],
|
|
||||||
requireAuth: true,
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Upload',
|
|
||||||
path: 'upload',
|
|
||||||
component: () => import('./upload/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '图片上传',
|
|
||||||
icon: 'mdi:upload',
|
|
||||||
role: ['admin'],
|
|
||||||
requireAuth: true,
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { request } from '@/utils'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getPosts: (params = {}) => request.get('posts', { params }),
|
|
||||||
getPostById: (id) => request.get(`/post/${id}`),
|
|
||||||
addPost: (data) => request.post('/post', data),
|
|
||||||
updatePost: (data) => request.put(`/post/${data.id}`, data),
|
|
||||||
deletePost: (id) => request.delete(`/post/${id}`),
|
|
||||||
}
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage show-footer title="文章">
|
|
||||||
<template #action>
|
|
||||||
<div>
|
|
||||||
<n-button type="primary" secondary @click="$table?.handleExport()">
|
|
||||||
<TheIcon icon="mdi:download" :size="18" class="mr-5" />
|
|
||||||
导出
|
|
||||||
</n-button>
|
|
||||||
<n-button type="primary" class="ml-16" @click="handleAdd">
|
|
||||||
<TheIcon icon="material-symbols:add" :size="18" class="mr-5" />
|
|
||||||
新建文章
|
|
||||||
</n-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<CrudTable
|
|
||||||
ref="$table"
|
|
||||||
v-model:query-items="queryItems"
|
|
||||||
:extra-params="extraParams"
|
|
||||||
:scroll-x="1200"
|
|
||||||
:columns="columns"
|
|
||||||
:get-data="api.getPosts"
|
|
||||||
@on-checked="onChecked"
|
|
||||||
@on-data-change="(data) => (tableData = data)"
|
|
||||||
>
|
|
||||||
<template #queryBar>
|
|
||||||
<QueryBarItem label="标题" :label-width="50">
|
|
||||||
<n-input
|
|
||||||
v-model:value="queryItems.title"
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入标题"
|
|
||||||
@keypress.enter="$table?.handleSearch"
|
|
||||||
/>
|
|
||||||
</QueryBarItem>
|
|
||||||
</template>
|
|
||||||
</CrudTable>
|
|
||||||
<!-- 新增/编辑/查看 -->
|
|
||||||
<CrudModal
|
|
||||||
v-model:visible="modalVisible"
|
|
||||||
:title="modalTitle"
|
|
||||||
:loading="modalLoading"
|
|
||||||
:show-footer="modalAction !== 'view'"
|
|
||||||
@on-save="handleSave"
|
|
||||||
>
|
|
||||||
<n-form
|
|
||||||
ref="modalFormRef"
|
|
||||||
label-placement="left"
|
|
||||||
label-align="left"
|
|
||||||
:label-width="80"
|
|
||||||
:model="modalForm"
|
|
||||||
:disabled="modalAction === 'view'"
|
|
||||||
>
|
|
||||||
<n-form-item label="作者" path="author">
|
|
||||||
<n-input v-model:value="modalForm.author" disabled />
|
|
||||||
</n-form-item>
|
|
||||||
<n-form-item
|
|
||||||
label="文章标题"
|
|
||||||
path="title"
|
|
||||||
:rule="{
|
|
||||||
required: true,
|
|
||||||
message: '请输入文章标题',
|
|
||||||
trigger: ['input', 'blur'],
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<n-input v-model:value="modalForm.title" placeholder="请输入文章标题" />
|
|
||||||
</n-form-item>
|
|
||||||
<n-form-item
|
|
||||||
label="文章内容"
|
|
||||||
path="content"
|
|
||||||
:rule="{
|
|
||||||
required: true,
|
|
||||||
message: '请输入文章内容',
|
|
||||||
trigger: ['input', 'blur'],
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<n-input
|
|
||||||
v-model:value="modalForm.content"
|
|
||||||
placeholder="请输入文章内容"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{
|
|
||||||
minRows: 3,
|
|
||||||
maxRows: 5,
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
</n-form>
|
|
||||||
</CrudModal>
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { NButton, NSwitch } from 'naive-ui'
|
|
||||||
import { formatDateTime, renderIcon, isNullOrUndef } from '@/utils'
|
|
||||||
import { useCRUD } from '@/composables'
|
|
||||||
import api from './api'
|
|
||||||
|
|
||||||
defineOptions({ name: 'Crud' })
|
|
||||||
|
|
||||||
const $table = ref(null)
|
|
||||||
/** 表格数据,触发搜索的时候会更新这个值 */
|
|
||||||
const tableData = ref([])
|
|
||||||
/** QueryBar筛选参数(可选) */
|
|
||||||
const queryItems = ref({})
|
|
||||||
/** 补充参数(可选) */
|
|
||||||
const extraParams = ref({})
|
|
||||||
|
|
||||||
onActivated(() => {
|
|
||||||
$table.value?.handleSearch()
|
|
||||||
})
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{ type: 'selection', fixed: 'left' },
|
|
||||||
{
|
|
||||||
title: '发布',
|
|
||||||
key: 'isPublish',
|
|
||||||
width: 60,
|
|
||||||
align: 'center',
|
|
||||||
fixed: 'left',
|
|
||||||
render(row) {
|
|
||||||
return h(NSwitch, {
|
|
||||||
size: 'small',
|
|
||||||
rubberBand: false,
|
|
||||||
value: row['isPublish'],
|
|
||||||
loading: !!row.publishing,
|
|
||||||
onUpdateValue: () => handlePublish(row),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ title: '标题', key: 'title', width: 150, ellipsis: { tooltip: true } },
|
|
||||||
{ title: '分类', key: 'category', width: 80, ellipsis: { tooltip: true } },
|
|
||||||
{ title: '创建人', key: 'author', width: 80 },
|
|
||||||
{
|
|
||||||
title: '创建时间',
|
|
||||||
key: 'createDate',
|
|
||||||
width: 150,
|
|
||||||
render(row) {
|
|
||||||
return h('span', formatDateTime(row['createDate']))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '最后更新时间',
|
|
||||||
key: 'updateDate',
|
|
||||||
width: 150,
|
|
||||||
render(row) {
|
|
||||||
return h('span', formatDateTime(row['updateDate']))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
key: 'actions',
|
|
||||||
width: 240,
|
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
|
||||||
hideInExcel: true,
|
|
||||||
render(row) {
|
|
||||||
return [
|
|
||||||
h(
|
|
||||||
NButton,
|
|
||||||
{
|
|
||||||
size: 'small',
|
|
||||||
type: 'primary',
|
|
||||||
secondary: true,
|
|
||||||
onClick: () => handleView(row),
|
|
||||||
},
|
|
||||||
{ default: () => '查看', icon: renderIcon('majesticons:eye-line', { size: 14 }) }
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
NButton,
|
|
||||||
{
|
|
||||||
size: 'small',
|
|
||||||
type: 'primary',
|
|
||||||
style: 'margin-left: 15px;',
|
|
||||||
onClick: () => handleEdit(row),
|
|
||||||
},
|
|
||||||
{ default: () => '编辑', icon: renderIcon('material-symbols:edit-outline', { size: 14 }) }
|
|
||||||
),
|
|
||||||
|
|
||||||
h(
|
|
||||||
NButton,
|
|
||||||
{
|
|
||||||
size: 'small',
|
|
||||||
type: 'error',
|
|
||||||
style: 'margin-left: 15px;',
|
|
||||||
onClick: () => handleDelete(row.id),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
default: () => '删除',
|
|
||||||
icon: renderIcon('material-symbols:delete-outline', { size: 14 }),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// 选中事件
|
|
||||||
function onChecked(rowKeys) {
|
|
||||||
if (rowKeys.length) $message.info(`选中${rowKeys.join(' ')}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发布
|
|
||||||
function handlePublish(row) {
|
|
||||||
if (isNullOrUndef(row.id)) return
|
|
||||||
|
|
||||||
row.publishing = true
|
|
||||||
setTimeout(() => {
|
|
||||||
row.isPublish = !row.isPublish
|
|
||||||
row.publishing = false
|
|
||||||
$message?.success(row.isPublish ? '已发布' : '已取消发布')
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
modalVisible,
|
|
||||||
modalAction,
|
|
||||||
modalTitle,
|
|
||||||
modalLoading,
|
|
||||||
handleAdd,
|
|
||||||
handleDelete,
|
|
||||||
handleEdit,
|
|
||||||
handleView,
|
|
||||||
handleSave,
|
|
||||||
modalForm,
|
|
||||||
modalFormRef,
|
|
||||||
} = useCRUD({
|
|
||||||
name: '文章',
|
|
||||||
initForm: { author: '大脸怪' },
|
|
||||||
doCreate: api.addPost,
|
|
||||||
doDelete: api.deletePost,
|
|
||||||
doUpdate: api.updatePost,
|
|
||||||
refresh: () => $table.value?.handleSearch(),
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<template>
|
|
||||||
<CommonPage>
|
|
||||||
<n-upload
|
|
||||||
class="mx-auto w-[75%] p-20 text-center"
|
|
||||||
:custom-request="handleUpload"
|
|
||||||
:show-file-list="false"
|
|
||||||
accept=".png,.jpg,.jpeg"
|
|
||||||
@before-upload="onBeforeUpload"
|
|
||||||
>
|
|
||||||
<n-upload-dragger>
|
|
||||||
<div class="h-150 f-c-c flex-col">
|
|
||||||
<TheIcon icon="mdi:upload" :size="68" class="mb-12 c-primary" />
|
|
||||||
<n-text class="text-14 c-gray">点击或者拖动文件到该区域来上传</n-text>
|
|
||||||
</div>
|
|
||||||
</n-upload-dragger>
|
|
||||||
</n-upload>
|
|
||||||
|
|
||||||
<n-card v-if="imgList && imgList.length" class="mt-16 items-center">
|
|
||||||
<n-image-group>
|
|
||||||
<n-space justify="space-between" align="center">
|
|
||||||
<n-card v-for="(item, index) in imgList" :key="index" class="w-280 hover:card-shadow">
|
|
||||||
<div class="h-160 f-c-c">
|
|
||||||
<n-image width="200" :src="item.url" />
|
|
||||||
</div>
|
|
||||||
<n-space class="mt-16" justify="space-evenly">
|
|
||||||
<n-button dashed type="primary" @click="copy(item.url)">url</n-button>
|
|
||||||
<n-button dashed type="primary" @click="copy(``)">
|
|
||||||
MD
|
|
||||||
</n-button>
|
|
||||||
<n-button
|
|
||||||
dashed
|
|
||||||
type="primary"
|
|
||||||
@click="copy(`<img src="${item.url}" />`)"
|
|
||||||
>
|
|
||||||
img
|
|
||||||
</n-button>
|
|
||||||
</n-space>
|
|
||||||
</n-card>
|
|
||||||
<div v-for="i in 4" :key="i" class="w-280" />
|
|
||||||
</n-space>
|
|
||||||
</n-image-group>
|
|
||||||
</n-card>
|
|
||||||
</CommonPage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { useClipboard } from '@vueuse/core'
|
|
||||||
defineOptions({ name: 'Upload' })
|
|
||||||
|
|
||||||
const { copy, copied } = useClipboard()
|
|
||||||
|
|
||||||
const imgList = reactive([
|
|
||||||
{ url: 'https://cdn.qszone.com/images/5c23d52f880511ebb6edd017c2d2eca2.jpg' },
|
|
||||||
{ url: 'https://cdn.qszone.com/images/5c23d52f880511ebb6edd017c2d2eca2.jpg' },
|
|
||||||
{ url: 'https://cdn.qszone.com/images/5c23d52f880511ebb6edd017c2d2eca2.jpg' },
|
|
||||||
{ url: 'https://cdn.qszone.com/images/5c23d52f880511ebb6edd017c2d2eca2.jpg' },
|
|
||||||
])
|
|
||||||
|
|
||||||
watch(copied, (val) => {
|
|
||||||
val && $message.success('已复制到剪切板')
|
|
||||||
})
|
|
||||||
|
|
||||||
function onBeforeUpload({ file }) {
|
|
||||||
if (!file.file?.type.startsWith('image/')) {
|
|
||||||
$message.error('只能上传图片')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleUpload({ file, onFinish }) {
|
|
||||||
if (!file || !file.type) {
|
|
||||||
$message.error('请选择文件')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟上传
|
|
||||||
$message.loading('上传中...')
|
|
||||||
setTimeout(() => {
|
|
||||||
$message.success('上传成功')
|
|
||||||
imgList.push({ fileName: file.name, url: URL.createObjectURL(file.file) })
|
|
||||||
onFinish()
|
|
||||||
}, 1500)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
7
src/views/finance/api.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getData: (data) => request.post('/store/withdraw', data),
|
||||||
|
// 审核提现
|
||||||
|
passAudit: (data) => request.post('/store/withdraw/edit', data),
|
||||||
|
}
|
||||||
358
src/views/finance/index.vue
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-row gutter="12">
|
||||||
|
<n-col :span="24">
|
||||||
|
<div flex>
|
||||||
|
<n-card w-400>
|
||||||
|
<n-statistic label="总提现金额(含已驳回)" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.total / 100"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-400>
|
||||||
|
<n-statistic label="待处理金额" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.service / 100"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-400>
|
||||||
|
<n-statistic label="已审核金额" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.count / 100"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10>
|
||||||
|
<span w-80>提现状态:</span>
|
||||||
|
<n-radio-group v-model:value="queryData.status" class="ml-10">
|
||||||
|
<n-radio-button
|
||||||
|
v-for="song in songs"
|
||||||
|
:key="song.value"
|
||||||
|
:value="song.value"
|
||||||
|
:label="song.label"
|
||||||
|
/>
|
||||||
|
</n-radio-group>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-80>号码搜索:</span>
|
||||||
|
<n-input v-model:value="queryData.word" style="width: 25%" placeholder="请输入手机号码" />
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="10">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-80>申请时间:</span>
|
||||||
|
<n-date-picker
|
||||||
|
v-model:formatted-value="queryData.time"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
type="daterange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10>
|
||||||
|
<n-button type="primary" @click="getList">搜索</n-button>
|
||||||
|
<n-button ml-10 @click="clearQueryData">重置</n-button>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
</n-row>
|
||||||
|
<n-data-table
|
||||||
|
class="mt-10"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
<!-- 打款记录 -->
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 500px"
|
||||||
|
title="打款记录"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="1" :x-gap="24">
|
||||||
|
<n-form-item-gi :span="12" label="打款截图" path="img">
|
||||||
|
<Upload v-model:list="model.img" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi>
|
||||||
|
<div w-full flex justify-center>
|
||||||
|
<n-button type="primary" @click="ok">确定</n-button>
|
||||||
|
<n-button class="ml-10" @click="clear">关闭</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import api from './api'
|
||||||
|
import { NButton, NImage, NTag } from 'naive-ui'
|
||||||
|
import Upload from '@/components/Upload.vue'
|
||||||
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
const vRole = [[vPerms, ['/admin/store/withdraw/edit']]]
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
status: '',
|
||||||
|
word: '',
|
||||||
|
time: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const songs = ref([
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '已审核',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '已驳回',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '待审核',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const nowRow = ref({})
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
img: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
img: { required: true, type: 'array', message: '请上传打款截图' },
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '名字',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '电话',
|
||||||
|
key: 'phone',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '银行名称',
|
||||||
|
key: 'bank',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '银行卡号',
|
||||||
|
key: 'bank_card',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '账户名称',
|
||||||
|
key: 'bank_name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '法人',
|
||||||
|
key: 'bank_user',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '提现金额',
|
||||||
|
slot: 'integral',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h('span', {}, row.integral / 100)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '审核状态',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'status',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : row.status === 2 ? 'error' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '已审核' : row.status === 2 ? '已驳回' : '待审核'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '申请时间',
|
||||||
|
key: 'add_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打款截图',
|
||||||
|
slot: 'img',
|
||||||
|
render: (row) => {
|
||||||
|
return h(NImage, {
|
||||||
|
src: row.status_img,
|
||||||
|
width: '50',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'action',
|
||||||
|
render: (row) => {
|
||||||
|
if (row.status === 3) {
|
||||||
|
return [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
type: 'primary',
|
||||||
|
onClick: () => {
|
||||||
|
nowRow.value = row
|
||||||
|
showModal.value = true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '审核',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
vRole
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
class: 'ml-10',
|
||||||
|
text: true,
|
||||||
|
type: 'error',
|
||||||
|
onClick: () => {
|
||||||
|
nowRow.value = row
|
||||||
|
refuse()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '拒绝',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
vRole
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const loading = ref(false)
|
||||||
|
const data = ref([])
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const query_data = {
|
||||||
|
Status: queryData.value.status || '',
|
||||||
|
Phone: queryData.value.word || '',
|
||||||
|
StartTime: queryData.value.time === null ? '' : queryData.value.time[0] || '',
|
||||||
|
EndTime: queryData.value.time === null ? '' : queryData.value.time[1] || '',
|
||||||
|
}
|
||||||
|
const res = await api.getData({
|
||||||
|
pageNum: pagination.value.page,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
...query_data,
|
||||||
|
})
|
||||||
|
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
cardData.value.total = res.data.all
|
||||||
|
cardData.value.service = res.data.audit_integral
|
||||||
|
cardData.value.count = res.data.success_integral
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = async () => {
|
||||||
|
model.value = {
|
||||||
|
img: [],
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
formRef.value?.restoreValidation()
|
||||||
|
await getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const ok = () => {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
const res = await api.passAudit({
|
||||||
|
bid: nowRow.value.bid,
|
||||||
|
wid: nowRow.value.wid,
|
||||||
|
img: model.value.img[0].url,
|
||||||
|
status: 1,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const refuse = async () => {
|
||||||
|
const res = await api.passAudit({
|
||||||
|
bid: nowRow.value.bid,
|
||||||
|
wid: nowRow.value.wid,
|
||||||
|
img: model.value.img[0]?.url || '',
|
||||||
|
status: 2,
|
||||||
|
})
|
||||||
|
clear()
|
||||||
|
$message.success(res.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearQueryData = () => {
|
||||||
|
queryData.value = {
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
25
src/views/finance/route.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: '财务管理',
|
||||||
|
path: '/finance',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/finance_list',
|
||||||
|
meta: {
|
||||||
|
title: '财务管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'financelist',
|
||||||
|
path: 'finance_list',
|
||||||
|
component: () => import('./index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '商户提现',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -1,8 +1,17 @@
|
|||||||
import { request } from '@/utils'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getData: () => request.post('/dice/getisStart'),
|
getData: () => request.post('/getisStart'),
|
||||||
setStatus: (data) => request.post('/dice/isStart', data),
|
setStatus: (data) => request.post('/isStart', data),
|
||||||
getDS: () => request.post('/dice/getBetting'),
|
getDS: () => request.post('/getBetting'),
|
||||||
setDS: (data) => request.post('/dice/setBetting', data),
|
setDS: (data) => request.post('/setBetting', data),
|
||||||
|
getKJList: () => request.post('/draw'),
|
||||||
|
// 获取统计
|
||||||
|
getStatistics: (data) => request.post('/user/betting/list', data),
|
||||||
|
|
||||||
|
// log
|
||||||
|
getLog: () => request.post('/log'),
|
||||||
|
|
||||||
|
// 宙斯详情
|
||||||
|
getDetail: (data) => request.post('/log/betting/list', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
<div flex>
|
<div flex items-center>
|
||||||
<div flex>
|
<div mr-20 flex>
|
||||||
<div>游戏状态:</div>
|
<div>游戏状态:</div>
|
||||||
<n-switch
|
<n-switch
|
||||||
v-model:value="val1"
|
v-model:value="val1"
|
||||||
@@ -10,7 +10,11 @@
|
|||||||
@update:value="handleUpdateValue1"
|
@update:value="handleUpdateValue1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div ml-20 flex>
|
<div flex items-center>
|
||||||
|
<div>开奖记录:</div>
|
||||||
|
<n-button type="primary" @click="openData">预览</n-button>
|
||||||
|
</div>
|
||||||
|
<!-- <div ml-20 flex>
|
||||||
<div>点杀状态:</div>
|
<div>点杀状态:</div>
|
||||||
<n-switch
|
<n-switch
|
||||||
v-model:value="val"
|
v-model:value="val"
|
||||||
@@ -18,55 +22,119 @@
|
|||||||
:unchecked-value="2"
|
:unchecked-value="2"
|
||||||
@update:value="handleUpdateValue"
|
@update:value="handleUpdateValue"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div flex>
|
<div flex>
|
||||||
<div>
|
<div>
|
||||||
预开期数:
|
预开期数:
|
||||||
<span text-25>{{ list[0]?.periods || 0 }}</span>
|
<span text-25>{{ list[0]?.Periods || 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div ml-20>
|
<div ml-20>
|
||||||
剩余开奖时间:
|
剩余开奖时间:
|
||||||
<span text-25>{{ time || 0 }}</span>
|
<span text-25>{{ time || 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div ml-20>
|
||||||
|
本局总下注:
|
||||||
|
<span text-25>{{ totalA || 0 }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<n-spin size="large" :show="show">
|
||||||
<div flex flex-wrap justify-between>
|
<div flex flex-wrap justify-between>
|
||||||
|
<n-card
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.ID"
|
||||||
|
class="mb-10 mt-10 h-120 w-250 flex-shrink-0 cursor-pointer"
|
||||||
|
:title="item.name"
|
||||||
|
>
|
||||||
|
<p text-25 op-60 :style="{ color: item.count === 0 ? 'green' : 'red' }">
|
||||||
|
{{ item.count }}
|
||||||
|
</p>
|
||||||
|
</n-card>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
</div>
|
||||||
|
</n-spin>
|
||||||
|
<n-spin size="large" :show="show1">
|
||||||
|
<div flex flex-wrap justify-between>
|
||||||
|
<n-card
|
||||||
|
v-for="item in list1"
|
||||||
|
:key="item.ID"
|
||||||
|
class="mb-10 mt-10 h-150 w-250 flex-shrink-0 cursor-pointer"
|
||||||
|
:title="`${item.NumName}(${item.Name})`"
|
||||||
|
>
|
||||||
|
<p text-25 op-60 :style="{ color: item.Total === 0 ? 'green' : 'red' }">
|
||||||
|
{{ item.Total }}
|
||||||
|
</p>
|
||||||
|
<n-popconfirm @positive-click="handleUpdateValue(item.ID)">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button>你猜</n-button>
|
||||||
|
</template>
|
||||||
|
一切都将一去杳然,任何人都无法将其捕获。
|
||||||
|
</n-popconfirm>
|
||||||
|
</n-card>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
<div h-0 w-250></div>
|
||||||
|
</div>
|
||||||
|
</n-spin>
|
||||||
|
<!-- 开奖记录 -->
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
<n-card
|
<n-card
|
||||||
v-for="item in list"
|
style="width: 900px"
|
||||||
:key="item.ID"
|
title="开奖记录"
|
||||||
class="mb-10 mt-10 w-300 flex-shrink-0 cursor-pointer"
|
:bordered="false"
|
||||||
:title="item.name"
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
>
|
>
|
||||||
<p text-25 op-60 :style="{ color: item.count === 0 ? 'green' : 'red' }">{{ item.count }}</p>
|
<n-data-table
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:max-height="600"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="false"
|
||||||
|
/>
|
||||||
</n-card>
|
</n-card>
|
||||||
<div h-0 w-300></div>
|
</n-modal>
|
||||||
<div h-0 w-300></div>
|
|
||||||
</div>
|
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { h } from 'vue'
|
||||||
import api from '../api'
|
import api from '../api'
|
||||||
|
import { getToken } from '@/utils'
|
||||||
|
|
||||||
const ws = new WebSocket(`wss://${import.meta.env.VITE_WS_URL}`)
|
const ws = new WebSocket(`wss://${import.meta.env.VITE_WS_URL}`)
|
||||||
|
|
||||||
const ws1 = new WebSocket(`wss://${import.meta.env.VITE_WS1_URL}`)
|
const ws1 = new WebSocket(`wss://${import.meta.env.VITE_WS1_URL}`)
|
||||||
|
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
|
const list1 = ref([])
|
||||||
|
|
||||||
const val1 = ref(null)
|
const val1 = ref(null)
|
||||||
const val = ref(null)
|
// const val = ref(null)
|
||||||
|
|
||||||
const time = ref(null)
|
const time = ref(null)
|
||||||
|
|
||||||
|
const show = ref(true)
|
||||||
|
const show1 = ref(true)
|
||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
console.log('1连接成功')
|
console.log('1连接成功')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const totalA = ref(null)
|
||||||
|
|
||||||
ws.onmessage = (msg) => {
|
ws.onmessage = (msg) => {
|
||||||
const res = JSON.parse(msg.data)
|
const res = JSON.parse(msg.data)
|
||||||
list.value = res
|
list.value = res.betting.sort((a, b) => b.Total - a.Total)
|
||||||
|
show.value = false
|
||||||
|
list1.value = res.list.sort((a, b) => b.Total - a.Total)
|
||||||
|
show1.value = false
|
||||||
|
totalA.value = res.total
|
||||||
}
|
}
|
||||||
|
|
||||||
ws1.onopen = () => {
|
ws1.onopen = () => {
|
||||||
@@ -87,14 +155,14 @@ ws1.onmessage = (msg) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
get_data()
|
// get_data()
|
||||||
get_data1()
|
get_data1()
|
||||||
})
|
})
|
||||||
|
|
||||||
const get_data = async () => {
|
// const get_data = async () => {
|
||||||
const res = await api.getDS()
|
// const res = await api.getDS()
|
||||||
val.value = res.data.diceStatus
|
// val.value = res.data.diceStatus
|
||||||
}
|
// }
|
||||||
const get_data1 = async () => {
|
const get_data1 = async () => {
|
||||||
const res = await api.getData()
|
const res = await api.getData()
|
||||||
val1.value = res.data.diceStart
|
val1.value = res.data.diceStart
|
||||||
@@ -106,10 +174,13 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
const handleUpdateValue = async (e) => {
|
const handleUpdateValue = async (e) => {
|
||||||
const res = await api.setDS({
|
const res = await api.setDS({
|
||||||
status: e,
|
status: 1,
|
||||||
|
id: e,
|
||||||
|
user_id: getToken(),
|
||||||
|
Periods: list.value[0]?.Periods,
|
||||||
})
|
})
|
||||||
$message.success(res.msg)
|
$message.success(res.msg)
|
||||||
get_data()
|
// get_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUpdateValue1 = async (e) => {
|
const handleUpdateValue1 = async (e) => {
|
||||||
@@ -119,6 +190,48 @@ const handleUpdateValue1 = async (e) => {
|
|||||||
$message.success(res.msg)
|
$message.success(res.msg)
|
||||||
get_data1()
|
get_data1()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '期数',
|
||||||
|
key: 'Periods',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖号码',
|
||||||
|
key: 'Name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖时间',
|
||||||
|
key: 'DrawTime',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖号码',
|
||||||
|
slot: 'Num',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h('p', `${row.Start}-${row.End}`)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([])
|
||||||
|
const openData = async () => {
|
||||||
|
try {
|
||||||
|
showModal.value = true
|
||||||
|
loading.value = true
|
||||||
|
const res = await api.getKJList()
|
||||||
|
console.log(res)
|
||||||
|
data.value = res.data.data
|
||||||
|
loading.value = false
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/game',
|
path: '/game',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/game_data',
|
redirect: '/game_data',
|
||||||
|
meta: {
|
||||||
|
title: '游戏管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Gamelist',
|
name: 'Gamelist',
|
||||||
@@ -12,6 +17,27 @@ export default {
|
|||||||
component: () => import('./data/index.vue'),
|
component: () => import('./data/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '实时数据',
|
title: '实时数据',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'statistics',
|
||||||
|
path: 'game_statistics',
|
||||||
|
component: () => import('./statistics/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '数据统计',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'zs',
|
||||||
|
path: 'game_zs',
|
||||||
|
component: () => import('./zs/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '宙斯统计',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
order: 10,
|
order: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
250
src/views/game/statistics/index.vue
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-grid class="mb-10" x-gap="12" :cols="4">
|
||||||
|
<n-gi>
|
||||||
|
<n-date-picker
|
||||||
|
v-model:formatted-value="range"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
type="daterange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-button type="primary" @click="getList">搜索</n-button>
|
||||||
|
<n-button ml-10 @click="clear">重置</n-button>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
<!-- <n-grid class="mb-10" x-gap="12" :cols="3">
|
||||||
|
<n-gi>
|
||||||
|
<n-card>
|
||||||
|
<n-statistic label="总下注">
|
||||||
|
<n-number-animation :from="0" :to="TYVal.total" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-card>
|
||||||
|
<n-statistic label="总赔付">
|
||||||
|
<n-number-animation :from="0" :to="TYVal.totalNum" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-card>
|
||||||
|
<n-statistic label="总盈利">
|
||||||
|
<n-number-animation :from="0" :to="TYVal.total / 10 - TYVal.totalNum / 100" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid> -->
|
||||||
|
<div w-full flex items-center>
|
||||||
|
<Echarts :loading="loading" :option="option" />
|
||||||
|
<Echarts :loading="loading" :option="option1" />
|
||||||
|
</div>
|
||||||
|
<div w-full flex items-center justify-between>
|
||||||
|
<n-card title="开奖记录" :bordered="false" content-style="padding: 0;">
|
||||||
|
<n-data-table
|
||||||
|
:max-height="500"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:bordered="true"
|
||||||
|
:virtual-scroll="true"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import api from '../api.js'
|
||||||
|
import Echarts from '@/components/Echarts.vue'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const range = ref(null)
|
||||||
|
|
||||||
|
const option = ref({
|
||||||
|
title: {
|
||||||
|
text: '单期下注(豆子)/赔付(积分) 统计',
|
||||||
|
left: 'center',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// legend: {
|
||||||
|
// data: ['下注(豆子)', '赔付(积分)'],
|
||||||
|
// left: 'left',
|
||||||
|
// type: 'scroll',
|
||||||
|
// },
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '下注(豆子)',
|
||||||
|
data: [],
|
||||||
|
type: 'bar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '赔付(积分)',
|
||||||
|
data: [],
|
||||||
|
type: 'bar',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'slider',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const option1 = ref({
|
||||||
|
title: {
|
||||||
|
text: '总下注(豆子)/总赔付(积分)',
|
||||||
|
left: 'center',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'right',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: '50%',
|
||||||
|
data: [],
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const TYVal = ref({
|
||||||
|
total: 0,
|
||||||
|
totalNum: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '期数',
|
||||||
|
key: 'Periods',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖号码',
|
||||||
|
key: 'Name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下注',
|
||||||
|
key: 'NumberSum',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '赔付',
|
||||||
|
key: 'TotalCount',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
key: 'Date',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
range.value = null
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const dataObj = {
|
||||||
|
StartTime: dayjs().format('YYYY-MM-DD'),
|
||||||
|
EndTime: dayjs().format('YYYY-MM-DD'),
|
||||||
|
}
|
||||||
|
if (range.value) {
|
||||||
|
dataObj.StartTime = range.value[0]
|
||||||
|
dataObj.EndTime = range.value[1]
|
||||||
|
}
|
||||||
|
const res = await api.getStatistics(dataObj)
|
||||||
|
const newData = res.data.data || []
|
||||||
|
data.value = newData
|
||||||
|
TYVal.value = {
|
||||||
|
total: res.data.total,
|
||||||
|
totalNum: res.data.totalDices,
|
||||||
|
}
|
||||||
|
option.value.xAxis.data = []
|
||||||
|
option.value.series[0].data = []
|
||||||
|
option.value.series[1].data = []
|
||||||
|
option1.value.series[0].data = []
|
||||||
|
if (newData.length > 0) {
|
||||||
|
res.data.data.forEach((item) => {
|
||||||
|
const a = (
|
||||||
|
((res.data.total * 10) / (res.data.total * 10 + res.data.totalDices)) *
|
||||||
|
100
|
||||||
|
).toFixed(2)
|
||||||
|
const b = ((res.data.totalDices / (res.data.total * 10 + res.data.totalDices)) * 100).toFixed(
|
||||||
|
2
|
||||||
|
)
|
||||||
|
option.value.xAxis.data.push(`第${item.Periods}期-${item.Name}`)
|
||||||
|
option.value.series[0].name = `下注(豆子): ${a}%`
|
||||||
|
option.value.series[0].data.push(item.NumberSum)
|
||||||
|
option.value.series[1].name = `赔付(积分): ${b}%`
|
||||||
|
option.value.series[1].data.push(item.TotalCount)
|
||||||
|
})
|
||||||
|
|
||||||
|
const a = (((res.data.total * 10) / (res.data.total * 10 + res.data.totalDices)) * 100).toFixed(
|
||||||
|
2
|
||||||
|
)
|
||||||
|
const b = ((res.data.totalDices / (res.data.total * 10 + res.data.totalDices)) * 100).toFixed(2)
|
||||||
|
|
||||||
|
option1.value.series[0].data.push({ value: res.data.total, name: `总下注: ${a}%` })
|
||||||
|
option1.value.series[0].data.push({
|
||||||
|
value: res.data.totalDices,
|
||||||
|
name: `总赔付: ${b}%`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chart {
|
||||||
|
width: 50%;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
189
src/views/game/zs/index.vue
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-data-table
|
||||||
|
:max-height="500"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:bordered="true"
|
||||||
|
:virtual-scroll="true"
|
||||||
|
:pagination="pagination"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
<!-- -->
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 800px"
|
||||||
|
title="宙斯的眷顾"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-data-table
|
||||||
|
:loading="zsLoading"
|
||||||
|
:columns="zsColumns"
|
||||||
|
:data="zsData"
|
||||||
|
:pagination="zsPagination"
|
||||||
|
:bordered="false"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import api from '../api.js'
|
||||||
|
import { NButton } from 'naive-ui'
|
||||||
|
import { h, ref, onMounted } from 'vue'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '期数',
|
||||||
|
key: 'periods',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖号码',
|
||||||
|
key: 'betting_name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖数字',
|
||||||
|
key: 'betting_number',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作人',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开奖时间',
|
||||||
|
key: 'draw_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作时间',
|
||||||
|
key: 'add_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作IP',
|
||||||
|
key: 'ip',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
strong: true,
|
||||||
|
secondary: true,
|
||||||
|
onClick: () => {
|
||||||
|
openModal(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ default: () => '查看' }
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getData()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await api.getLog({
|
||||||
|
pageNum: pagination.value.page,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
}
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const zsLoading = ref(false)
|
||||||
|
|
||||||
|
const zsColumns = ref([
|
||||||
|
{
|
||||||
|
title: '期数',
|
||||||
|
key: 'Periods',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数字',
|
||||||
|
key: 'PeriodsNum',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '总投注(豆子)',
|
||||||
|
key: 'NumberSum',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '赔付(积分)',
|
||||||
|
key: 'TotalCount',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '选中用户',
|
||||||
|
key: 'User',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '电话号码',
|
||||||
|
key: 'Phone',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const zsData = ref([])
|
||||||
|
|
||||||
|
const zsPagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
zsPagination.value.page = page
|
||||||
|
getData()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const openModal = async (row) => {
|
||||||
|
showModal.value = true
|
||||||
|
zsLoading.value = true
|
||||||
|
const res = await api.getDetail({
|
||||||
|
periods: row.periods,
|
||||||
|
draw_time: row.draw_time,
|
||||||
|
pageNum: zsPagination.value.page,
|
||||||
|
pageSize: zsPagination.value.pageSize,
|
||||||
|
})
|
||||||
|
zsData.value = res.data.data || []
|
||||||
|
zsPagination.value.itemCount = res.data.total
|
||||||
|
zsLoading.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -100,8 +100,8 @@ async function handleLogin() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
$message.loading('正在验证...')
|
$message.loading('正在验证...')
|
||||||
const res = await api.login({ phone: name, password: password.toString() })
|
const res = await api.login({ phone: name, password: password.toString() })
|
||||||
console.log(res.data.token)
|
|
||||||
$message.success('登录成功')
|
$message.success('登录成功')
|
||||||
|
window.localStorage.setItem('menu', JSON.stringify(res.data.auth))
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
if (isRemember.value) {
|
if (isRemember.value) {
|
||||||
lStorage.set('loginInfo', { name, password })
|
lStorage.set('loginInfo', { name, password })
|
||||||
@@ -117,7 +117,6 @@ async function handleLogin() {
|
|||||||
router.push('/')
|
router.push('/')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
|
||||||
$message.removeMessage()
|
$message.removeMessage()
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|||||||
@@ -1,25 +1,155 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-row gutter="12">
|
||||||
|
<n-col :span="24">
|
||||||
|
<div flex>
|
||||||
|
<n-card w-500>
|
||||||
|
<n-statistic label="订单流水(元)" tabular-nums>
|
||||||
|
<n-number-animation :from="0" :to="cardData.total" :precision="2" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<!-- <n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单佣金(元)" tabular-nums>
|
||||||
|
<n-number-animation :from="0" :to="Number(cardData.service)" :precision="2" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card> -->
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单数量" tabular-nums>
|
||||||
|
<n-number-animation :from="0" :to="cardData.count" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24" mt-10>
|
||||||
|
<div>
|
||||||
|
<span>订单状态:</span>
|
||||||
|
<n-radio-group v-model:value="queryData.status">
|
||||||
|
<n-radio-button
|
||||||
|
v-for="song in songs"
|
||||||
|
:key="song.value"
|
||||||
|
:value="song.value"
|
||||||
|
:label="song.label"
|
||||||
|
/>
|
||||||
|
</n-radio-group>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<div w-100>关键字搜索:</div>
|
||||||
|
<n-input-group>
|
||||||
|
<n-select
|
||||||
|
v-model:value="queryData.selectKey"
|
||||||
|
:style="{ width: '15%' }"
|
||||||
|
:options="selectOptions"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
<n-input v-model:value="queryData.word" :style="{ width: '20%' }" />
|
||||||
|
</n-input-group>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="10">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-100>订单时间:</span>
|
||||||
|
<n-date-picker
|
||||||
|
v-model:formatted-value="queryData.time"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="datetimerange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10>
|
||||||
|
<n-button type="primary" @click="getList">搜索</n-button>
|
||||||
|
<n-button ml-10 @click="clear">重置</n-button>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
</n-row>
|
||||||
<n-data-table
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
:scroll-x="1800"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import api from './api'
|
import api from './api'
|
||||||
|
import { NEllipsis } from 'naive-ui'
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const songs = ref([
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '待付款',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '待核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '已核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '已过期',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
label: '已销售',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectOptions = ref([
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
label: '商品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '用户昵称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '手机号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '订单号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '商家名称',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '订单号',
|
title: '订单号',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'oid',
|
key: 'oid',
|
||||||
|
width: 200,
|
||||||
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户',
|
title: '用户',
|
||||||
@@ -27,15 +157,46 @@ const columns = ref([
|
|||||||
key: 'user_name',
|
key: 'user_name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品名称',
|
title: '用户电话',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'goods_name',
|
key: 'phone',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品价格',
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'goods_name',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 240px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.goods_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品数量',
|
||||||
|
align: 'center',
|
||||||
|
key: 'count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单总价',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'number',
|
key: 'number',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '商家名称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'store_name',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '订单佣金(元)',
|
||||||
|
// align: 'center',
|
||||||
|
// key: 'commission_number',
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
title: '订单状态',
|
title: '订单状态',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@@ -45,20 +206,30 @@ const columns = ref([
|
|||||||
case 0:
|
case 0:
|
||||||
return h('span', '待付款')
|
return h('span', '待付款')
|
||||||
case 1:
|
case 1:
|
||||||
return h('span', '待使用')
|
return h('span', '待核销')
|
||||||
case 2:
|
case 2:
|
||||||
return h('span', '已完成')
|
return h('span', '已核销')
|
||||||
case 3:
|
case 3:
|
||||||
return h('span', '已过期')
|
return h('span', '已过期')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '下单时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '核销时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'cancel_time',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render() {
|
||||||
console.log(row)
|
// console.log(row)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -66,9 +237,9 @@ const columns = ref([
|
|||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -87,17 +258,52 @@ onMounted(() => {
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
const query_data = {
|
||||||
|
Status: queryData.value.status || '',
|
||||||
|
StartTime: queryData.value.time === null ? '' : queryData.value.time[0] || '',
|
||||||
|
EndTime: queryData.value.time === null ? '' : queryData.value.time[1] || '',
|
||||||
|
}
|
||||||
|
switch (queryData.value.selectKey) {
|
||||||
|
case 0:
|
||||||
|
query_data['GoodsName'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
query_data['UserName'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
query_data['Phone'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
query_data['Oid'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
query_data['StoreName'] = queryData.value.word
|
||||||
|
}
|
||||||
const res = await api.getOrder({
|
const res = await api.getOrder({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
|
...query_data,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data || []
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
cardData.value.total = res.data.number
|
||||||
|
cardData.value.service = res.data.commission
|
||||||
|
cardData.value.count = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
queryData.value = {
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -1,41 +1,200 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<!-- {{ queryData }} -->
|
||||||
|
<n-row gutter="12">
|
||||||
|
<n-col :span="24">
|
||||||
|
<div flex>
|
||||||
|
<n-card w-500>
|
||||||
|
<n-statistic label="订单流水(积分)" tabular-nums>
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :from="0" :to="cardData.total" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单佣金(积分)" tabular-nums>
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :from="0" :to="cardData.service" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单数量" tabular-nums>
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :from="0" :to="cardData.count" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10>
|
||||||
|
<span>订单状态:</span>
|
||||||
|
<n-radio-group v-model:value="queryData.status">
|
||||||
|
<n-radio-button
|
||||||
|
v-for="song in songs"
|
||||||
|
:key="song.value"
|
||||||
|
:value="song.value"
|
||||||
|
:label="song.label"
|
||||||
|
/>
|
||||||
|
</n-radio-group>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<div w-100>订单搜索:</div>
|
||||||
|
<n-input-group>
|
||||||
|
<n-select
|
||||||
|
v-model:value="queryData.selectKey"
|
||||||
|
:style="{ width: '15%' }"
|
||||||
|
:options="selectOptions"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
<n-input v-model:value="queryData.word" :style="{ width: '20%' }" />
|
||||||
|
</n-input-group>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="10">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-100>订单时间:</span>
|
||||||
|
<n-date-picker
|
||||||
|
v-model:formatted-value="queryData.time"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="datetimerange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="24">
|
||||||
|
<div mt-10>
|
||||||
|
<n-button type="primary" @click="getList">搜索</n-button>
|
||||||
|
<n-button ml-10 @click="clear">重置</n-button>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
</n-row>
|
||||||
<n-data-table
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import api from './api'
|
import api from './api'
|
||||||
|
import { NEllipsis } from 'naive-ui'
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const songs = ref([
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '待付款',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '待核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '已核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '已过期',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
label: '已销售',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectOptions = ref([
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
label: '商品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '用户昵称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '手机号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '订单号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '商家名称',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '订单号',
|
title: '订单号',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'oid',
|
key: 'oid',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '订单归属商户',
|
||||||
|
align: 'center',
|
||||||
|
key: 'store_name',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '用户',
|
title: '用户',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'user_name',
|
key: 'user_name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品名称',
|
title: '用户电话',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'goods_name',
|
key: 'phone',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品价格',
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'goods_name',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 240px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.goods_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品数量',
|
||||||
|
align: 'center',
|
||||||
|
key: 'count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单总价',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'number',
|
key: 'number',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '订单佣金',
|
||||||
|
align: 'center',
|
||||||
|
key: 'commission',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '订单状态',
|
title: '订单状态',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@@ -45,30 +204,40 @@ const columns = ref([
|
|||||||
case 0:
|
case 0:
|
||||||
return h('span', '待付款')
|
return h('span', '待付款')
|
||||||
case 1:
|
case 1:
|
||||||
return h('span', '待使用')
|
return h('span', '待核销')
|
||||||
case 2:
|
case 2:
|
||||||
return h('span', '已完成')
|
return h('span', '已核销')
|
||||||
case 3:
|
case 3:
|
||||||
return h('span', '已过期')
|
return h('span', '已过期')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '下单时间',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'action',
|
key: 'add_time',
|
||||||
render(row) {
|
|
||||||
console.log(row)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '核销时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'cancel_time',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '操作',
|
||||||
|
// align: 'center',
|
||||||
|
// slot: 'action',
|
||||||
|
// render(row) {
|
||||||
|
// console.log(row)
|
||||||
|
// },
|
||||||
|
// },
|
||||||
])
|
])
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -87,17 +256,53 @@ onMounted(() => {
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
const query_data = {
|
||||||
|
Status: queryData.value.status || '',
|
||||||
|
StartTime: queryData.value.time === null ? '' : queryData.value.time[0] || '',
|
||||||
|
EndTime: queryData.value.time === null ? '' : queryData.value.time[1] || '',
|
||||||
|
}
|
||||||
|
switch (queryData.value.selectKey) {
|
||||||
|
case 0:
|
||||||
|
query_data['GoodsName'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
query_data['UserName'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
query_data['Phone'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
query_data['Oid'] = queryData.value.word
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
query_data['StoreName'] = queryData.value.word
|
||||||
|
break
|
||||||
|
}
|
||||||
const res = await api.getPoint({
|
const res = await api.getPoint({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
|
...query_data,
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data || []
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
cardData.value.total = res.data.number
|
||||||
|
cardData.value.service = res.data.commission
|
||||||
|
cardData.value.count = res.data.total
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
queryData.value = {
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/order',
|
path: '/order',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/order_list',
|
redirect: '/order_list',
|
||||||
|
meta: {
|
||||||
|
title: '订单管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Orderlist',
|
name: 'Orderlist',
|
||||||
|
|||||||
805
src/views/system/acc/acc_menu/ant-design-meta.json
Normal file
@@ -0,0 +1,805 @@
|
|||||||
|
{
|
||||||
|
"name": "Ant Design Icons",
|
||||||
|
"total": 789,
|
||||||
|
"version": "4.3.1",
|
||||||
|
"license": {
|
||||||
|
"title": "MIT",
|
||||||
|
"spdx": "MIT"
|
||||||
|
},
|
||||||
|
"samples": ["pushpin-filled", "pie-chart-outlined", "shopping-twotone"],
|
||||||
|
"height": 16,
|
||||||
|
"category": "General",
|
||||||
|
"palette": false,
|
||||||
|
"id": "ant-design",
|
||||||
|
"icons": [
|
||||||
|
"account-book-filled",
|
||||||
|
"account-book-outlined",
|
||||||
|
"account-book-twotone",
|
||||||
|
"aim-outlined",
|
||||||
|
"alert-filled",
|
||||||
|
"alert-outlined",
|
||||||
|
"alert-twotone",
|
||||||
|
"alibaba-outlined",
|
||||||
|
"align-center-outlined",
|
||||||
|
"align-left-outlined",
|
||||||
|
"align-right-outlined",
|
||||||
|
"alipay-circle-filled",
|
||||||
|
"alipay-circle-outlined",
|
||||||
|
"alipay-outlined",
|
||||||
|
"alipay-square-filled",
|
||||||
|
"aliwangwang-filled",
|
||||||
|
"aliwangwang-outlined",
|
||||||
|
"aliyun-outlined",
|
||||||
|
"amazon-circle-filled",
|
||||||
|
"amazon-outlined",
|
||||||
|
"amazon-square-filled",
|
||||||
|
"android-filled",
|
||||||
|
"android-outlined",
|
||||||
|
"ant-cloud-outlined",
|
||||||
|
"ant-design-outlined",
|
||||||
|
"apartment-outlined",
|
||||||
|
"api-filled",
|
||||||
|
"api-outlined",
|
||||||
|
"api-twotone",
|
||||||
|
"apple-filled",
|
||||||
|
"apple-outlined",
|
||||||
|
"appstore-add-outlined",
|
||||||
|
"appstore-filled",
|
||||||
|
"appstore-outlined",
|
||||||
|
"appstore-twotone",
|
||||||
|
"area-chart-outlined",
|
||||||
|
"arrow-down-outlined",
|
||||||
|
"arrow-left-outlined",
|
||||||
|
"arrow-right-outlined",
|
||||||
|
"arrow-up-outlined",
|
||||||
|
"arrows-alt-outlined",
|
||||||
|
"audio-filled",
|
||||||
|
"audio-muted-outlined",
|
||||||
|
"audio-outlined",
|
||||||
|
"audio-twotone",
|
||||||
|
"audit-outlined",
|
||||||
|
"backward-filled",
|
||||||
|
"backward-outlined",
|
||||||
|
"bank-filled",
|
||||||
|
"bank-outlined",
|
||||||
|
"bank-twotone",
|
||||||
|
"bar-chart-outlined",
|
||||||
|
"barcode-outlined",
|
||||||
|
"bars-outlined",
|
||||||
|
"behance-circle-filled",
|
||||||
|
"behance-outlined",
|
||||||
|
"behance-square-filled",
|
||||||
|
"behance-square-outlined",
|
||||||
|
"bell-filled",
|
||||||
|
"bell-outlined",
|
||||||
|
"bell-twotone",
|
||||||
|
"bg-colors-outlined",
|
||||||
|
"block-outlined",
|
||||||
|
"bold-outlined",
|
||||||
|
"book-filled",
|
||||||
|
"book-outlined",
|
||||||
|
"book-twotone",
|
||||||
|
"border-bottom-outlined",
|
||||||
|
"border-horizontal-outlined",
|
||||||
|
"border-inner-outlined",
|
||||||
|
"border-left-outlined",
|
||||||
|
"border-outer-outlined",
|
||||||
|
"border-outlined",
|
||||||
|
"border-right-outlined",
|
||||||
|
"border-top-outlined",
|
||||||
|
"border-verticle-outlined",
|
||||||
|
"borderless-table-outlined",
|
||||||
|
"box-plot-filled",
|
||||||
|
"box-plot-outlined",
|
||||||
|
"box-plot-twotone",
|
||||||
|
"branches-outlined",
|
||||||
|
"bug-filled",
|
||||||
|
"bug-outlined",
|
||||||
|
"bug-twotone",
|
||||||
|
"build-filled",
|
||||||
|
"build-outlined",
|
||||||
|
"build-twotone",
|
||||||
|
"bulb-filled",
|
||||||
|
"bulb-outlined",
|
||||||
|
"bulb-twotone",
|
||||||
|
"calculator-filled",
|
||||||
|
"calculator-outlined",
|
||||||
|
"calculator-twotone",
|
||||||
|
"calendar-filled",
|
||||||
|
"calendar-outlined",
|
||||||
|
"calendar-twotone",
|
||||||
|
"camera-filled",
|
||||||
|
"camera-outlined",
|
||||||
|
"camera-twotone",
|
||||||
|
"car-filled",
|
||||||
|
"car-outlined",
|
||||||
|
"car-twotone",
|
||||||
|
"caret-down-filled",
|
||||||
|
"caret-down-outlined",
|
||||||
|
"caret-left-filled",
|
||||||
|
"caret-left-outlined",
|
||||||
|
"caret-right-filled",
|
||||||
|
"caret-right-outlined",
|
||||||
|
"caret-up-filled",
|
||||||
|
"caret-up-outlined",
|
||||||
|
"carry-out-filled",
|
||||||
|
"carry-out-outlined",
|
||||||
|
"carry-out-twotone",
|
||||||
|
"check-circle-filled",
|
||||||
|
"check-circle-outlined",
|
||||||
|
"check-circle-twotone",
|
||||||
|
"check-outlined",
|
||||||
|
"check-square-filled",
|
||||||
|
"check-square-outlined",
|
||||||
|
"check-square-twotone",
|
||||||
|
"chrome-filled",
|
||||||
|
"chrome-outlined",
|
||||||
|
"ci-circle-filled",
|
||||||
|
"ci-circle-outlined",
|
||||||
|
"ci-circle-twotone",
|
||||||
|
"ci-outlined",
|
||||||
|
"ci-twotone",
|
||||||
|
"clear-outlined",
|
||||||
|
"clock-circle-filled",
|
||||||
|
"clock-circle-outlined",
|
||||||
|
"clock-circle-twotone",
|
||||||
|
"close-circle-filled",
|
||||||
|
"close-circle-outlined",
|
||||||
|
"close-circle-twotone",
|
||||||
|
"close-outlined",
|
||||||
|
"close-square-filled",
|
||||||
|
"close-square-outlined",
|
||||||
|
"close-square-twotone",
|
||||||
|
"cloud-download-outlined",
|
||||||
|
"cloud-filled",
|
||||||
|
"cloud-outlined",
|
||||||
|
"cloud-server-outlined",
|
||||||
|
"cloud-sync-outlined",
|
||||||
|
"cloud-twotone",
|
||||||
|
"cloud-upload-outlined",
|
||||||
|
"cluster-outlined",
|
||||||
|
"code-filled",
|
||||||
|
"code-outlined",
|
||||||
|
"code-sandbox-circle-filled",
|
||||||
|
"code-sandbox-outlined",
|
||||||
|
"code-sandbox-square-filled",
|
||||||
|
"code-twotone",
|
||||||
|
"codepen-circle-filled",
|
||||||
|
"codepen-circle-outlined",
|
||||||
|
"codepen-outlined",
|
||||||
|
"codepen-square-filled",
|
||||||
|
"coffee-outlined",
|
||||||
|
"column-height-outlined",
|
||||||
|
"column-width-outlined",
|
||||||
|
"comment-outlined",
|
||||||
|
"compass-filled",
|
||||||
|
"compass-outlined",
|
||||||
|
"compass-twotone",
|
||||||
|
"compress-outlined",
|
||||||
|
"console-sql-outlined",
|
||||||
|
"contacts-filled",
|
||||||
|
"contacts-outlined",
|
||||||
|
"contacts-twotone",
|
||||||
|
"container-filled",
|
||||||
|
"container-outlined",
|
||||||
|
"container-twotone",
|
||||||
|
"control-filled",
|
||||||
|
"control-outlined",
|
||||||
|
"control-twotone",
|
||||||
|
"copy-filled",
|
||||||
|
"copy-outlined",
|
||||||
|
"copy-twotone",
|
||||||
|
"copyright-circle-filled",
|
||||||
|
"copyright-circle-outlined",
|
||||||
|
"copyright-circle-twotone",
|
||||||
|
"copyright-outlined",
|
||||||
|
"copyright-twotone",
|
||||||
|
"credit-card-filled",
|
||||||
|
"credit-card-outlined",
|
||||||
|
"credit-card-twotone",
|
||||||
|
"crown-filled",
|
||||||
|
"crown-outlined",
|
||||||
|
"crown-twotone",
|
||||||
|
"customer-service-filled",
|
||||||
|
"customer-service-outlined",
|
||||||
|
"customer-service-twotone",
|
||||||
|
"dash-outlined",
|
||||||
|
"dashboard-filled",
|
||||||
|
"dashboard-outlined",
|
||||||
|
"dashboard-twotone",
|
||||||
|
"database-filled",
|
||||||
|
"database-outlined",
|
||||||
|
"database-twotone",
|
||||||
|
"delete-column-outlined",
|
||||||
|
"delete-filled",
|
||||||
|
"delete-outlined",
|
||||||
|
"delete-row-outlined",
|
||||||
|
"delete-twotone",
|
||||||
|
"delivered-procedure-outlined",
|
||||||
|
"deployment-unit-outlined",
|
||||||
|
"desktop-outlined",
|
||||||
|
"diff-filled",
|
||||||
|
"diff-outlined",
|
||||||
|
"diff-twotone",
|
||||||
|
"dingding-outlined",
|
||||||
|
"dingtalk-circle-filled",
|
||||||
|
"dingtalk-outlined",
|
||||||
|
"dingtalk-square-filled",
|
||||||
|
"disconnect-outlined",
|
||||||
|
"dislike-filled",
|
||||||
|
"dislike-outlined",
|
||||||
|
"dislike-twotone",
|
||||||
|
"dollar-circle-filled",
|
||||||
|
"dollar-circle-outlined",
|
||||||
|
"dollar-circle-twotone",
|
||||||
|
"dollar-outlined",
|
||||||
|
"dollar-twotone",
|
||||||
|
"dot-chart-outlined",
|
||||||
|
"double-left-outlined",
|
||||||
|
"double-right-outlined",
|
||||||
|
"down-circle-filled",
|
||||||
|
"down-circle-outlined",
|
||||||
|
"down-circle-twotone",
|
||||||
|
"down-outlined",
|
||||||
|
"down-square-filled",
|
||||||
|
"down-square-outlined",
|
||||||
|
"down-square-twotone",
|
||||||
|
"download-outlined",
|
||||||
|
"drag-outlined",
|
||||||
|
"dribbble-circle-filled",
|
||||||
|
"dribbble-outlined",
|
||||||
|
"dribbble-square-filled",
|
||||||
|
"dribbble-square-outlined",
|
||||||
|
"dropbox-circle-filled",
|
||||||
|
"dropbox-outlined",
|
||||||
|
"dropbox-square-filled",
|
||||||
|
"edit-filled",
|
||||||
|
"edit-outlined",
|
||||||
|
"edit-twotone",
|
||||||
|
"ellipsis-outlined",
|
||||||
|
"enter-outlined",
|
||||||
|
"environment-filled",
|
||||||
|
"environment-outlined",
|
||||||
|
"environment-twotone",
|
||||||
|
"euro-circle-filled",
|
||||||
|
"euro-circle-outlined",
|
||||||
|
"euro-circle-twotone",
|
||||||
|
"euro-outlined",
|
||||||
|
"euro-twotone",
|
||||||
|
"exception-outlined",
|
||||||
|
"exclamation-circle-filled",
|
||||||
|
"exclamation-circle-outlined",
|
||||||
|
"exclamation-circle-twotone",
|
||||||
|
"exclamation-outlined",
|
||||||
|
"expand-alt-outlined",
|
||||||
|
"expand-outlined",
|
||||||
|
"experiment-filled",
|
||||||
|
"experiment-outlined",
|
||||||
|
"experiment-twotone",
|
||||||
|
"export-outlined",
|
||||||
|
"eye-filled",
|
||||||
|
"eye-invisible-filled",
|
||||||
|
"eye-invisible-outlined",
|
||||||
|
"eye-invisible-twotone",
|
||||||
|
"eye-outlined",
|
||||||
|
"eye-twotone",
|
||||||
|
"facebook-filled",
|
||||||
|
"facebook-outlined",
|
||||||
|
"fall-outlined",
|
||||||
|
"fast-backward-filled",
|
||||||
|
"fast-backward-outlined",
|
||||||
|
"fast-forward-filled",
|
||||||
|
"fast-forward-outlined",
|
||||||
|
"field-binary-outlined",
|
||||||
|
"field-number-outlined",
|
||||||
|
"field-string-outlined",
|
||||||
|
"field-time-outlined",
|
||||||
|
"file-add-filled",
|
||||||
|
"file-add-outlined",
|
||||||
|
"file-add-twotone",
|
||||||
|
"file-done-outlined",
|
||||||
|
"file-excel-filled",
|
||||||
|
"file-excel-outlined",
|
||||||
|
"file-excel-twotone",
|
||||||
|
"file-exclamation-filled",
|
||||||
|
"file-exclamation-outlined",
|
||||||
|
"file-exclamation-twotone",
|
||||||
|
"file-filled",
|
||||||
|
"file-gif-outlined",
|
||||||
|
"file-image-filled",
|
||||||
|
"file-image-outlined",
|
||||||
|
"file-image-twotone",
|
||||||
|
"file-jpg-outlined",
|
||||||
|
"file-markdown-filled",
|
||||||
|
"file-markdown-outlined",
|
||||||
|
"file-markdown-twotone",
|
||||||
|
"file-outlined",
|
||||||
|
"file-pdf-filled",
|
||||||
|
"file-pdf-outlined",
|
||||||
|
"file-pdf-twotone",
|
||||||
|
"file-ppt-filled",
|
||||||
|
"file-ppt-outlined",
|
||||||
|
"file-ppt-twotone",
|
||||||
|
"file-protect-outlined",
|
||||||
|
"file-search-outlined",
|
||||||
|
"file-sync-outlined",
|
||||||
|
"file-text-filled",
|
||||||
|
"file-text-outlined",
|
||||||
|
"file-text-twotone",
|
||||||
|
"file-twotone",
|
||||||
|
"file-unknown-filled",
|
||||||
|
"file-unknown-outlined",
|
||||||
|
"file-unknown-twotone",
|
||||||
|
"file-word-filled",
|
||||||
|
"file-word-outlined",
|
||||||
|
"file-word-twotone",
|
||||||
|
"file-zip-filled",
|
||||||
|
"file-zip-outlined",
|
||||||
|
"file-zip-twotone",
|
||||||
|
"filter-filled",
|
||||||
|
"filter-outlined",
|
||||||
|
"filter-twotone",
|
||||||
|
"fire-filled",
|
||||||
|
"fire-outlined",
|
||||||
|
"fire-twotone",
|
||||||
|
"flag-filled",
|
||||||
|
"flag-outlined",
|
||||||
|
"flag-twotone",
|
||||||
|
"folder-add-filled",
|
||||||
|
"folder-add-outlined",
|
||||||
|
"folder-add-twotone",
|
||||||
|
"folder-filled",
|
||||||
|
"folder-open-filled",
|
||||||
|
"folder-open-outlined",
|
||||||
|
"folder-open-twotone",
|
||||||
|
"folder-outlined",
|
||||||
|
"folder-twotone",
|
||||||
|
"folder-view-outlined",
|
||||||
|
"font-colors-outlined",
|
||||||
|
"font-size-outlined",
|
||||||
|
"fork-outlined",
|
||||||
|
"form-outlined",
|
||||||
|
"format-painter-filled",
|
||||||
|
"format-painter-outlined",
|
||||||
|
"forward-filled",
|
||||||
|
"forward-outlined",
|
||||||
|
"frown-filled",
|
||||||
|
"frown-outlined",
|
||||||
|
"frown-twotone",
|
||||||
|
"fullscreen-exit-outlined",
|
||||||
|
"fullscreen-outlined",
|
||||||
|
"function-outlined",
|
||||||
|
"fund-filled",
|
||||||
|
"fund-outlined",
|
||||||
|
"fund-projection-screen-outlined",
|
||||||
|
"fund-twotone",
|
||||||
|
"fund-view-outlined",
|
||||||
|
"funnel-plot-filled",
|
||||||
|
"funnel-plot-outlined",
|
||||||
|
"funnel-plot-twotone",
|
||||||
|
"gateway-outlined",
|
||||||
|
"gif-outlined",
|
||||||
|
"gift-filled",
|
||||||
|
"gift-outlined",
|
||||||
|
"gift-twotone",
|
||||||
|
"github-filled",
|
||||||
|
"github-outlined",
|
||||||
|
"gitlab-filled",
|
||||||
|
"gitlab-outlined",
|
||||||
|
"global-outlined",
|
||||||
|
"gold-filled",
|
||||||
|
"gold-outlined",
|
||||||
|
"gold-twotone",
|
||||||
|
"golden-filled",
|
||||||
|
"google-circle-filled",
|
||||||
|
"google-outlined",
|
||||||
|
"google-plus-circle-filled",
|
||||||
|
"google-plus-outlined",
|
||||||
|
"google-plus-square-filled",
|
||||||
|
"google-square-filled",
|
||||||
|
"group-outlined",
|
||||||
|
"hdd-filled",
|
||||||
|
"hdd-outlined",
|
||||||
|
"hdd-twotone",
|
||||||
|
"heart-filled",
|
||||||
|
"heart-outlined",
|
||||||
|
"heart-twotone",
|
||||||
|
"heat-map-outlined",
|
||||||
|
"highlight-filled",
|
||||||
|
"highlight-outlined",
|
||||||
|
"highlight-twotone",
|
||||||
|
"history-outlined",
|
||||||
|
"holder-outlined",
|
||||||
|
"home-filled",
|
||||||
|
"home-outlined",
|
||||||
|
"home-twotone",
|
||||||
|
"hourglass-filled",
|
||||||
|
"hourglass-outlined",
|
||||||
|
"hourglass-twotone",
|
||||||
|
"html5-filled",
|
||||||
|
"html5-outlined",
|
||||||
|
"html5-twotone",
|
||||||
|
"idcard-filled",
|
||||||
|
"idcard-outlined",
|
||||||
|
"idcard-twotone",
|
||||||
|
"ie-circle-filled",
|
||||||
|
"ie-outlined",
|
||||||
|
"ie-square-filled",
|
||||||
|
"import-outlined",
|
||||||
|
"inbox-outlined",
|
||||||
|
"info-circle-filled",
|
||||||
|
"info-circle-outlined",
|
||||||
|
"info-circle-twotone",
|
||||||
|
"info-outlined",
|
||||||
|
"insert-row-above-outlined",
|
||||||
|
"insert-row-below-outlined",
|
||||||
|
"insert-row-left-outlined",
|
||||||
|
"insert-row-right-outlined",
|
||||||
|
"instagram-filled",
|
||||||
|
"instagram-outlined",
|
||||||
|
"insurance-filled",
|
||||||
|
"insurance-outlined",
|
||||||
|
"insurance-twotone",
|
||||||
|
"interaction-filled",
|
||||||
|
"interaction-outlined",
|
||||||
|
"interaction-twotone",
|
||||||
|
"issues-close-outlined",
|
||||||
|
"italic-outlined",
|
||||||
|
"key-outlined",
|
||||||
|
"laptop-outlined",
|
||||||
|
"layout-filled",
|
||||||
|
"layout-outlined",
|
||||||
|
"layout-twotone",
|
||||||
|
"left-circle-filled",
|
||||||
|
"left-circle-outlined",
|
||||||
|
"left-circle-twotone",
|
||||||
|
"left-outlined",
|
||||||
|
"left-square-filled",
|
||||||
|
"left-square-outlined",
|
||||||
|
"left-square-twotone",
|
||||||
|
"like-filled",
|
||||||
|
"like-outlined",
|
||||||
|
"like-twotone",
|
||||||
|
"line-chart-outlined",
|
||||||
|
"line-height-outlined",
|
||||||
|
"line-outlined",
|
||||||
|
"link-outlined",
|
||||||
|
"linkedin-filled",
|
||||||
|
"linkedin-outlined",
|
||||||
|
"loading-3-quarters-outlined",
|
||||||
|
"loading-outlined",
|
||||||
|
"lock-filled",
|
||||||
|
"lock-outlined",
|
||||||
|
"lock-twotone",
|
||||||
|
"login-outlined",
|
||||||
|
"logout-outlined",
|
||||||
|
"mac-command-filled",
|
||||||
|
"mac-command-outlined",
|
||||||
|
"mail-filled",
|
||||||
|
"mail-outlined",
|
||||||
|
"mail-twotone",
|
||||||
|
"man-outlined",
|
||||||
|
"medicine-box-filled",
|
||||||
|
"medicine-box-outlined",
|
||||||
|
"medicine-box-twotone",
|
||||||
|
"medium-circle-filled",
|
||||||
|
"medium-outlined",
|
||||||
|
"medium-square-filled",
|
||||||
|
"medium-workmark-outlined",
|
||||||
|
"meh-filled",
|
||||||
|
"meh-outlined",
|
||||||
|
"meh-twotone",
|
||||||
|
"menu-fold-outlined",
|
||||||
|
"menu-outlined",
|
||||||
|
"menu-unfold-outlined",
|
||||||
|
"merge-cells-outlined",
|
||||||
|
"message-filled",
|
||||||
|
"message-outlined",
|
||||||
|
"message-twotone",
|
||||||
|
"minus-circle-filled",
|
||||||
|
"minus-circle-outlined",
|
||||||
|
"minus-circle-twotone",
|
||||||
|
"minus-outlined",
|
||||||
|
"minus-square-filled",
|
||||||
|
"minus-square-outlined",
|
||||||
|
"minus-square-twotone",
|
||||||
|
"mobile-filled",
|
||||||
|
"mobile-outlined",
|
||||||
|
"mobile-twotone",
|
||||||
|
"money-collect-filled",
|
||||||
|
"money-collect-outlined",
|
||||||
|
"money-collect-twotone",
|
||||||
|
"monitor-outlined",
|
||||||
|
"more-outlined",
|
||||||
|
"node-collapse-outlined",
|
||||||
|
"node-expand-outlined",
|
||||||
|
"node-index-outlined",
|
||||||
|
"notification-filled",
|
||||||
|
"notification-outlined",
|
||||||
|
"notification-twotone",
|
||||||
|
"number-outlined",
|
||||||
|
"one-to-one-outlined",
|
||||||
|
"ordered-list-outlined",
|
||||||
|
"paper-clip-outlined",
|
||||||
|
"partition-outlined",
|
||||||
|
"pause-circle-filled",
|
||||||
|
"pause-circle-outlined",
|
||||||
|
"pause-circle-twotone",
|
||||||
|
"pause-outlined",
|
||||||
|
"pay-circle-filled",
|
||||||
|
"pay-circle-outlined",
|
||||||
|
"percentage-outlined",
|
||||||
|
"phone-filled",
|
||||||
|
"phone-outlined",
|
||||||
|
"phone-twotone",
|
||||||
|
"pic-center-outlined",
|
||||||
|
"pic-left-outlined",
|
||||||
|
"pic-right-outlined",
|
||||||
|
"picture-filled",
|
||||||
|
"picture-outlined",
|
||||||
|
"picture-twotone",
|
||||||
|
"pie-chart-filled",
|
||||||
|
"pie-chart-outlined",
|
||||||
|
"pie-chart-twotone",
|
||||||
|
"play-circle-filled",
|
||||||
|
"play-circle-outlined",
|
||||||
|
"play-circle-twotone",
|
||||||
|
"play-square-filled",
|
||||||
|
"play-square-outlined",
|
||||||
|
"play-square-twotone",
|
||||||
|
"plus-circle-filled",
|
||||||
|
"plus-circle-outlined",
|
||||||
|
"plus-circle-twotone",
|
||||||
|
"plus-outlined",
|
||||||
|
"plus-square-filled",
|
||||||
|
"plus-square-outlined",
|
||||||
|
"plus-square-twotone",
|
||||||
|
"pound-circle-filled",
|
||||||
|
"pound-circle-outlined",
|
||||||
|
"pound-circle-twotone",
|
||||||
|
"pound-outlined",
|
||||||
|
"poweroff-outlined",
|
||||||
|
"printer-filled",
|
||||||
|
"printer-outlined",
|
||||||
|
"printer-twotone",
|
||||||
|
"profile-filled",
|
||||||
|
"profile-outlined",
|
||||||
|
"profile-twotone",
|
||||||
|
"project-filled",
|
||||||
|
"project-outlined",
|
||||||
|
"project-twotone",
|
||||||
|
"property-safety-filled",
|
||||||
|
"property-safety-outlined",
|
||||||
|
"property-safety-twotone",
|
||||||
|
"pull-request-outlined",
|
||||||
|
"pushpin-filled",
|
||||||
|
"pushpin-outlined",
|
||||||
|
"pushpin-twotone",
|
||||||
|
"qq-circle-filled",
|
||||||
|
"qq-outlined",
|
||||||
|
"qq-square-filled",
|
||||||
|
"qrcode-outlined",
|
||||||
|
"question-circle-filled",
|
||||||
|
"question-circle-outlined",
|
||||||
|
"question-circle-twotone",
|
||||||
|
"question-outlined",
|
||||||
|
"radar-chart-outlined",
|
||||||
|
"radius-bottomleft-outlined",
|
||||||
|
"radius-bottomright-outlined",
|
||||||
|
"radius-setting-outlined",
|
||||||
|
"radius-upleft-outlined",
|
||||||
|
"radius-upright-outlined",
|
||||||
|
"read-filled",
|
||||||
|
"read-outlined",
|
||||||
|
"reconciliation-filled",
|
||||||
|
"reconciliation-outlined",
|
||||||
|
"reconciliation-twotone",
|
||||||
|
"red-envelope-filled",
|
||||||
|
"red-envelope-outlined",
|
||||||
|
"red-envelope-twotone",
|
||||||
|
"reddit-circle-filled",
|
||||||
|
"reddit-outlined",
|
||||||
|
"reddit-square-filled",
|
||||||
|
"redo-outlined",
|
||||||
|
"reload-outlined",
|
||||||
|
"rest-filled",
|
||||||
|
"rest-outlined",
|
||||||
|
"rest-twotone",
|
||||||
|
"retweet-outlined",
|
||||||
|
"right-circle-filled",
|
||||||
|
"right-circle-outlined",
|
||||||
|
"right-circle-twotone",
|
||||||
|
"right-outlined",
|
||||||
|
"right-square-filled",
|
||||||
|
"right-square-outlined",
|
||||||
|
"right-square-twotone",
|
||||||
|
"rise-outlined",
|
||||||
|
"robot-filled",
|
||||||
|
"robot-outlined",
|
||||||
|
"rocket-filled",
|
||||||
|
"rocket-outlined",
|
||||||
|
"rocket-twotone",
|
||||||
|
"rollback-outlined",
|
||||||
|
"rotate-left-outlined",
|
||||||
|
"rotate-right-outlined",
|
||||||
|
"safety-certificate-filled",
|
||||||
|
"safety-certificate-outlined",
|
||||||
|
"safety-certificate-twotone",
|
||||||
|
"safety-outlined",
|
||||||
|
"save-filled",
|
||||||
|
"save-outlined",
|
||||||
|
"save-twotone",
|
||||||
|
"scan-outlined",
|
||||||
|
"schedule-filled",
|
||||||
|
"schedule-outlined",
|
||||||
|
"schedule-twotone",
|
||||||
|
"scissor-outlined",
|
||||||
|
"search-outlined",
|
||||||
|
"security-scan-filled",
|
||||||
|
"security-scan-outlined",
|
||||||
|
"security-scan-twotone",
|
||||||
|
"select-outlined",
|
||||||
|
"send-outlined",
|
||||||
|
"setting-filled",
|
||||||
|
"setting-outlined",
|
||||||
|
"setting-twotone",
|
||||||
|
"shake-outlined",
|
||||||
|
"share-alt-outlined",
|
||||||
|
"shop-filled",
|
||||||
|
"shop-outlined",
|
||||||
|
"shop-twotone",
|
||||||
|
"shopping-cart-outlined",
|
||||||
|
"shopping-filled",
|
||||||
|
"shopping-outlined",
|
||||||
|
"shopping-twotone",
|
||||||
|
"shrink-outlined",
|
||||||
|
"signal-filled",
|
||||||
|
"sisternode-outlined",
|
||||||
|
"sketch-circle-filled",
|
||||||
|
"sketch-outlined",
|
||||||
|
"sketch-square-filled",
|
||||||
|
"skin-filled",
|
||||||
|
"skin-outlined",
|
||||||
|
"skin-twotone",
|
||||||
|
"skype-filled",
|
||||||
|
"skype-outlined",
|
||||||
|
"slack-circle-filled",
|
||||||
|
"slack-outlined",
|
||||||
|
"slack-square-filled",
|
||||||
|
"slack-square-outlined",
|
||||||
|
"sliders-filled",
|
||||||
|
"sliders-outlined",
|
||||||
|
"sliders-twotone",
|
||||||
|
"small-dash-outlined",
|
||||||
|
"smile-filled",
|
||||||
|
"smile-outlined",
|
||||||
|
"smile-twotone",
|
||||||
|
"snippets-filled",
|
||||||
|
"snippets-outlined",
|
||||||
|
"snippets-twotone",
|
||||||
|
"solution-outlined",
|
||||||
|
"sort-ascending-outlined",
|
||||||
|
"sort-descending-outlined",
|
||||||
|
"sound-filled",
|
||||||
|
"sound-outlined",
|
||||||
|
"sound-twotone",
|
||||||
|
"split-cells-outlined",
|
||||||
|
"star-filled",
|
||||||
|
"star-outlined",
|
||||||
|
"star-twotone",
|
||||||
|
"step-backward-filled",
|
||||||
|
"step-backward-outlined",
|
||||||
|
"step-forward-filled",
|
||||||
|
"step-forward-outlined",
|
||||||
|
"stock-outlined",
|
||||||
|
"stop-filled",
|
||||||
|
"stop-outlined",
|
||||||
|
"stop-twotone",
|
||||||
|
"strikethrough-outlined",
|
||||||
|
"subnode-outlined",
|
||||||
|
"swap-left-outlined",
|
||||||
|
"swap-outlined",
|
||||||
|
"swap-right-outlined",
|
||||||
|
"switcher-filled",
|
||||||
|
"switcher-outlined",
|
||||||
|
"switcher-twotone",
|
||||||
|
"sync-outlined",
|
||||||
|
"table-outlined",
|
||||||
|
"tablet-filled",
|
||||||
|
"tablet-outlined",
|
||||||
|
"tablet-twotone",
|
||||||
|
"tag-filled",
|
||||||
|
"tag-outlined",
|
||||||
|
"tag-twotone",
|
||||||
|
"tags-filled",
|
||||||
|
"tags-outlined",
|
||||||
|
"tags-twotone",
|
||||||
|
"taobao-circle-filled",
|
||||||
|
"taobao-circle-outlined",
|
||||||
|
"taobao-outlined",
|
||||||
|
"taobao-square-filled",
|
||||||
|
"team-outlined",
|
||||||
|
"thunderbolt-filled",
|
||||||
|
"thunderbolt-outlined",
|
||||||
|
"thunderbolt-twotone",
|
||||||
|
"to-top-outlined",
|
||||||
|
"tool-filled",
|
||||||
|
"tool-outlined",
|
||||||
|
"tool-twotone",
|
||||||
|
"trademark-circle-filled",
|
||||||
|
"trademark-circle-outlined",
|
||||||
|
"trademark-circle-twotone",
|
||||||
|
"trademark-outlined",
|
||||||
|
"transaction-outlined",
|
||||||
|
"translation-outlined",
|
||||||
|
"trophy-filled",
|
||||||
|
"trophy-outlined",
|
||||||
|
"trophy-twotone",
|
||||||
|
"twitter-circle-filled",
|
||||||
|
"twitter-outlined",
|
||||||
|
"twitter-square-filled",
|
||||||
|
"underline-outlined",
|
||||||
|
"undo-outlined",
|
||||||
|
"ungroup-outlined",
|
||||||
|
"unlock-filled",
|
||||||
|
"unlock-outlined",
|
||||||
|
"unlock-twotone",
|
||||||
|
"unordered-list-outlined",
|
||||||
|
"up-circle-filled",
|
||||||
|
"up-circle-outlined",
|
||||||
|
"up-circle-twotone",
|
||||||
|
"up-outlined",
|
||||||
|
"up-square-filled",
|
||||||
|
"up-square-outlined",
|
||||||
|
"up-square-twotone",
|
||||||
|
"upload-outlined",
|
||||||
|
"usb-filled",
|
||||||
|
"usb-outlined",
|
||||||
|
"usb-twotone",
|
||||||
|
"user-add-outlined",
|
||||||
|
"user-delete-outlined",
|
||||||
|
"user-outlined",
|
||||||
|
"user-switch-outlined",
|
||||||
|
"usergroup-add-outlined",
|
||||||
|
"usergroup-delete-outlined",
|
||||||
|
"verified-outlined",
|
||||||
|
"vertical-align-bottom-outlined",
|
||||||
|
"vertical-align-middle-outlined",
|
||||||
|
"vertical-align-top-outlined",
|
||||||
|
"vertical-left-outlined",
|
||||||
|
"vertical-right-outlined",
|
||||||
|
"video-camera-add-outlined",
|
||||||
|
"video-camera-filled",
|
||||||
|
"video-camera-outlined",
|
||||||
|
"video-camera-twotone",
|
||||||
|
"wallet-filled",
|
||||||
|
"wallet-outlined",
|
||||||
|
"wallet-twotone",
|
||||||
|
"warning-filled",
|
||||||
|
"warning-outlined",
|
||||||
|
"warning-twotone",
|
||||||
|
"wechat-filled",
|
||||||
|
"wechat-outlined",
|
||||||
|
"weibo-circle-filled",
|
||||||
|
"weibo-circle-outlined",
|
||||||
|
"weibo-outlined",
|
||||||
|
"weibo-square-filled",
|
||||||
|
"weibo-square-outlined",
|
||||||
|
"whats-app-outlined",
|
||||||
|
"wifi-outlined",
|
||||||
|
"windows-filled",
|
||||||
|
"windows-outlined",
|
||||||
|
"woman-outlined",
|
||||||
|
"yahoo-filled",
|
||||||
|
"yahoo-outlined",
|
||||||
|
"youtube-filled",
|
||||||
|
"youtube-outlined",
|
||||||
|
"yuque-filled",
|
||||||
|
"yuque-outlined",
|
||||||
|
"zhihu-circle-filled",
|
||||||
|
"zhihu-outlined",
|
||||||
|
"zhihu-square-filled",
|
||||||
|
"zoom-in-outlined",
|
||||||
|
"zoom-out-outlined"
|
||||||
|
]
|
||||||
|
}
|
||||||
431
src/views/system/acc/acc_menu/index.vue
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="'(非技术人员勿动)'">
|
||||||
|
<n-button v-perms="['/admin/auth/menu/set']" type="primary" @click="openModal(1)">
|
||||||
|
添加菜单
|
||||||
|
</n-button>
|
||||||
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
:row-key="rowKey"
|
||||||
|
children-key="subMenu"
|
||||||
|
/>
|
||||||
|
<!-- 添加菜单 -->
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 500px"
|
||||||
|
title="添加/编辑菜单"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<!-- {{ model }} -->
|
||||||
|
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="24" :x-gap="24">
|
||||||
|
<n-form-item-gi :span="16" label="父级分类:" path="pid">
|
||||||
|
<n-cascader
|
||||||
|
v-model:value="model.pid"
|
||||||
|
placeholder="请选择菜单目录"
|
||||||
|
expand-trigger="click"
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
ID: 0,
|
||||||
|
name: '顶层菜单',
|
||||||
|
pid: 0,
|
||||||
|
},
|
||||||
|
...data,
|
||||||
|
]"
|
||||||
|
check-strategy="all"
|
||||||
|
show-path
|
||||||
|
label-field="name"
|
||||||
|
value-field="ID"
|
||||||
|
children-field="subMenu"
|
||||||
|
separator="->"
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="权限类型:" path="type">
|
||||||
|
<n-select
|
||||||
|
v-model:value="model.type"
|
||||||
|
placeholder="请选择菜单类型"
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
label: '目录',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '菜单',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '按钮',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="model.type !== 3" :span="24" label="菜单图标:" path="icon">
|
||||||
|
<div>
|
||||||
|
<n-input-group flex items-center>
|
||||||
|
<TheIcon :icon="model.icon" :size="30" />
|
||||||
|
<n-input
|
||||||
|
v-model:value="model.icon"
|
||||||
|
placeholder="请选择菜单图标"
|
||||||
|
:style="{ width: '100%' }"
|
||||||
|
/>
|
||||||
|
<n-button type="primary" ghost @click="iconModal = true">+</n-button>
|
||||||
|
</n-input-group>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="model.type !== 3" :span="10" label="是否开启:" path="status">
|
||||||
|
<n-switch v-model:value="model.status" :checked-value="1" :unchecked-value="2" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="model.type !== 3" :span="10" label="是否显示:" path="isShow">
|
||||||
|
<n-switch v-model:value="model.isShow" :checked-value="1" :unchecked-value="2" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="菜单名称:" path="name">
|
||||||
|
<n-input v-model:value="model.name" placeholder="请填写菜单名称" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi
|
||||||
|
v-if="model.type === 2 || model.type === 1"
|
||||||
|
:span="16"
|
||||||
|
label="菜单路径:"
|
||||||
|
path="route"
|
||||||
|
>
|
||||||
|
<n-input v-model:value="model.route" placeholder="请填写菜单路径" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi
|
||||||
|
v-if="model.type === 3 || model.type === 2"
|
||||||
|
:span="16"
|
||||||
|
label="权限标识:"
|
||||||
|
path="api_route"
|
||||||
|
>
|
||||||
|
<n-input v-model:value="model.api_route" placeholder="请填写权限标识" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="model.type === 2" :span="16" label="组件路径:" path="components">
|
||||||
|
<n-input v-model:value="model.components" placeholder="请填写组件路径" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="model.type === 2" :span="16" label="菜单参数:" path="params">
|
||||||
|
<n-input v-model:value="model.params" placeholder="请填写菜单参数" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="菜单排序:" path="sort">
|
||||||
|
<n-input-number v-model:value="model.sort" :min="0" placeholder="越低越靠前" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="18">
|
||||||
|
<div m-auto>
|
||||||
|
<n-button type="primary" @click="handleValidateClick">保存</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
<!-- 图标 -->
|
||||||
|
<n-modal v-model:show="iconModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 600px"
|
||||||
|
title="选择菜单图标"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<div h-500 w-full flex flex-wrap overflow-auto>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in antIconList.icons"
|
||||||
|
:key="index"
|
||||||
|
@click="clickIcon(`ant-design:${item}`)"
|
||||||
|
>
|
||||||
|
<TheIcon :icon="`ant-design:${item}`" :size="40" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
import api from '../api'
|
||||||
|
import TheIcon from '@/components/icon/TheIcon.vue'
|
||||||
|
import { NTag, NButton } from 'naive-ui'
|
||||||
|
import antIconList from './ant-design-meta.json'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
const iconModal = ref(false)
|
||||||
|
|
||||||
|
const rowKey = (row) => {
|
||||||
|
return row.subMenu || []
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '菜单名称',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '菜单图标',
|
||||||
|
slot: 'icon',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(TheIcon, {
|
||||||
|
icon: row.icon,
|
||||||
|
size: 20,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
slot: 'type',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: () => (row.type === 1 ? '目录' : row.type === 2 ? '菜单' : '按钮'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路径',
|
||||||
|
key: 'route',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '权限标识',
|
||||||
|
key: 'api_route',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路由参数',
|
||||||
|
key: 'params',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '组件路径',
|
||||||
|
key: 'components',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
key: 'sort',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否启用',
|
||||||
|
solt: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '启用' : '禁用'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否显示',
|
||||||
|
solt: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.is_show === 1 ? 'success' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.is_show === 1 ? '显示' : '隐藏'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
openModal(2, row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '编辑',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/auth/menu/set']]]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const res = await api.getMenuList()
|
||||||
|
data.value = res.data.data || []
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
id: null,
|
||||||
|
pid: null,
|
||||||
|
type: null,
|
||||||
|
icon: '',
|
||||||
|
status: 1,
|
||||||
|
isShow: 1,
|
||||||
|
name: '',
|
||||||
|
route: '',
|
||||||
|
params: '',
|
||||||
|
sort: 0,
|
||||||
|
components: '',
|
||||||
|
api_route: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
pid: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请选择菜单目录',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
required: true,
|
||||||
|
type: 'number',
|
||||||
|
message: '请选择菜单类型',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请填写菜单名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请填写菜单路径',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
required: true,
|
||||||
|
message: '请填写组件路径',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const openModal = (type, row = {}) => {
|
||||||
|
// get_dir_list()
|
||||||
|
|
||||||
|
if (type === 2) {
|
||||||
|
model.value = {
|
||||||
|
id: row.ID,
|
||||||
|
type: row.type,
|
||||||
|
icon: row.icon,
|
||||||
|
status: row.status,
|
||||||
|
isShow: row.isShow,
|
||||||
|
name: row.name,
|
||||||
|
route: row.route,
|
||||||
|
params: row.params,
|
||||||
|
sort: row.sort,
|
||||||
|
pid: row.pid,
|
||||||
|
components: row.components,
|
||||||
|
api_route: row.api_route,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickIcon = (icon) => {
|
||||||
|
model.value.icon = icon
|
||||||
|
iconModal.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleValidateClick = () => {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
try {
|
||||||
|
const dataObj = {
|
||||||
|
ID: model.value.id || '',
|
||||||
|
Icon: model.value.icon,
|
||||||
|
Type: model.value.type,
|
||||||
|
Status: model.value.status,
|
||||||
|
IsShow: model.value.isShow,
|
||||||
|
Name: model.value.name,
|
||||||
|
Route: model.value.route,
|
||||||
|
Params: model.value.params,
|
||||||
|
Sort: model.value.sort,
|
||||||
|
Pid: model.value.pid || '',
|
||||||
|
Components: model.value.components || '',
|
||||||
|
ApiRoute: model.value.api_route || '',
|
||||||
|
}
|
||||||
|
const res = await api.addMenu(dataObj)
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
formRef.value?.restoreValidation()
|
||||||
|
|
||||||
|
model.value = {
|
||||||
|
pid: null,
|
||||||
|
type: null,
|
||||||
|
icon: '',
|
||||||
|
status: 1,
|
||||||
|
isShow: 1,
|
||||||
|
name: '',
|
||||||
|
route: '',
|
||||||
|
params: '',
|
||||||
|
components: '',
|
||||||
|
sort: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal.value = false
|
||||||
|
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
221
src/views/system/acc/acc_role/index.vue
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-button v-perms="['/admin/auth/set']" type="primary" @click="openModal(1)">添加角色</n-button>
|
||||||
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 600px"
|
||||||
|
title="添加/编辑角色"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<!-- {{ model.AuthId }} -->
|
||||||
|
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="24" :x-gap="24">
|
||||||
|
<n-form-item-gi :span="16" label="角色名称:" path="Name">
|
||||||
|
<n-input v-model:value="model.Name" placeholder="请输入角色名称" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="角色权限:" path="AuthId">
|
||||||
|
<n-tree
|
||||||
|
:data="menus"
|
||||||
|
:default-checked-keys="model.AuthId"
|
||||||
|
label-field="name"
|
||||||
|
value-field="ID"
|
||||||
|
key-field="ID"
|
||||||
|
children-field="subMenu"
|
||||||
|
checkable
|
||||||
|
cascade
|
||||||
|
virtual-scroll
|
||||||
|
@update:checked-keys="updateCheckedKeys"
|
||||||
|
@update:indeterminate-keys="updateIndeterminateKeys"
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="角色状态:" path="Status">
|
||||||
|
<n-switch v-model:value="model.Status" :unchecked-value="2" :checked-value="1" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="18">
|
||||||
|
<div m-auto>
|
||||||
|
<n-button type="primary" @click="handleValidateClick">保存</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import api from '../api'
|
||||||
|
import { NTag, NButton } from 'naive-ui'
|
||||||
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '角色名称',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色状态',
|
||||||
|
slot: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '启用' : '禁用'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
openModal(2, row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '编辑',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/auth/set']]]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
Name: '',
|
||||||
|
AuthId: [],
|
||||||
|
Status: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
Name: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入角色名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
AuthId: {
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: '请选择角色权限',
|
||||||
|
trigger: ['blur', 'input'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
get_menu_list()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await api.getRoleList({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const menus = ref([])
|
||||||
|
|
||||||
|
const get_menu_list = async () => {
|
||||||
|
const res = await api.getMenuList()
|
||||||
|
menus.value = res.data.data
|
||||||
|
}
|
||||||
|
|
||||||
|
const openModal = (type, row = {}) => {
|
||||||
|
if (type === 2) {
|
||||||
|
model.value = {
|
||||||
|
ID: row.ID,
|
||||||
|
Name: row.name,
|
||||||
|
AuthId: JSON.parse(row.auth_id),
|
||||||
|
Status: row.status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
formRef.value?.restoreValidation()
|
||||||
|
model.value = {
|
||||||
|
Name: '',
|
||||||
|
AuthId: [],
|
||||||
|
Status: 2,
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const handleValidateClick = () => {
|
||||||
|
formRef.value?.validate(async (valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
const res = await api.addRole(model.value)
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateCheckedKeys = (value) => {
|
||||||
|
model.value.AuthId = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateIndeterminateKeys = (value) => {
|
||||||
|
model.value.AuthId = [...model.value.AuthId, ...value]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
297
src/views/system/acc/acc_user/index.vue
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-button v-perms="['/admin/manage/set']" type="primary" @click="openModal(1)">
|
||||||
|
添加管理员
|
||||||
|
</n-button>
|
||||||
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 600px"
|
||||||
|
title="添加/编辑角色"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="24" :x-gap="24">
|
||||||
|
<n-form-item-gi :span="16" label="名称:" path="Name">
|
||||||
|
<n-input v-model:value="model.Name" placeholder="请输入管理员名称" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="账号:" path="Phone">
|
||||||
|
<n-input v-model:value="model.Phone" placeholder="请输入管理员账号(手机号码)" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-if="nowType === 1" :span="16" label="密码:" path="Password">
|
||||||
|
<n-input v-model:value="model.Password" placeholder="请输入管理员密码" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi v-else :span="16" label="新密码:">
|
||||||
|
<n-input v-model:value="model.Password" placeholder="不修改请留空" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="角色:" path="AuthId">
|
||||||
|
<n-select
|
||||||
|
v-model:value="model.AuthId"
|
||||||
|
multiple
|
||||||
|
:options="roles"
|
||||||
|
label-field="name"
|
||||||
|
value-field="ID"
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="16" label="角色状态:" path="Status">
|
||||||
|
<n-switch v-model:value="model.Status" :unchecked-value="2" :checked-value="1" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="18">
|
||||||
|
<div m-auto>
|
||||||
|
<n-button type="primary" @click="handleValidateClick">保存</n-button>
|
||||||
|
<n-button ml-10 @click="clear">取消</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { h, withDirectives, resolveDirective } from 'vue'
|
||||||
|
import api from '../api'
|
||||||
|
import { NTag, NButton } from 'naive-ui'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '管理员名称',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '账号',
|
||||||
|
key: 'phone',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色',
|
||||||
|
slot: 'auth_id',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
const nowRow = { ...row, auth_id: JSON.parse(row.auth_id) }
|
||||||
|
const roleName = []
|
||||||
|
roles.value.forEach((item) => {
|
||||||
|
nowRow.auth_id.forEach((itm) => {
|
||||||
|
if (item.ID === itm) {
|
||||||
|
roleName.push(item.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return h(
|
||||||
|
'span',
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: () => roleName.join(' | '),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色状态',
|
||||||
|
slot: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '启用' : '禁用'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
openModal(2, row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '编辑',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/manage/set']]]
|
||||||
|
),
|
||||||
|
withDirectives(
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
class: 'ml-10',
|
||||||
|
type: 'error',
|
||||||
|
text: true,
|
||||||
|
onClick: () => {
|
||||||
|
delVerifyUser(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '删除',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[[vPerms, ['/admin/manage/delete']]]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
Name: '',
|
||||||
|
AuthId: null,
|
||||||
|
Phone: '',
|
||||||
|
Password: '',
|
||||||
|
Status: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
Name: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入角色名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
AuthId: {
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: '请选择分配权限',
|
||||||
|
trigger: ['blur'],
|
||||||
|
},
|
||||||
|
Phone: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入管理员账号(手机号码)',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
Password: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入管理员密码',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
get_role_list()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await api.getAdminList({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const roles = ref([])
|
||||||
|
|
||||||
|
const get_role_list = async () => {
|
||||||
|
const res = await api.getRoleList()
|
||||||
|
roles.value = res.data.data || []
|
||||||
|
}
|
||||||
|
|
||||||
|
const nowType = ref(1)
|
||||||
|
|
||||||
|
const openModal = (type, row = {}) => {
|
||||||
|
nowType.value = type
|
||||||
|
get_role_list()
|
||||||
|
if (type === 2) {
|
||||||
|
model.value = {
|
||||||
|
ID: row.ID,
|
||||||
|
Name: row.name,
|
||||||
|
AuthId: JSON.parse(row.auth_id),
|
||||||
|
Status: row.status,
|
||||||
|
Phone: row.phone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
formRef.value?.restoreValidation()
|
||||||
|
model.value = {
|
||||||
|
Name: '',
|
||||||
|
AuthId: null,
|
||||||
|
Phone: '',
|
||||||
|
Password: '',
|
||||||
|
Status: 2,
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const handleValidateClick = () => {
|
||||||
|
formRef.value?.validate(async (valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
const res = await api.addAdmin(model.value)
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const delVerifyUser = async (row) => {
|
||||||
|
$dialog.error({
|
||||||
|
title: '提示',
|
||||||
|
content: '删除无法撤销,请谨慎!',
|
||||||
|
positiveText: '确定',
|
||||||
|
negativeText: '取消',
|
||||||
|
onPositiveClick: async () => {
|
||||||
|
const res = await api.delVerifyUser({
|
||||||
|
uid: row.uid,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
24
src/views/system/acc/api.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 获取权限列表
|
||||||
|
getMenuList: () => request.post('/auth/menu'),
|
||||||
|
|
||||||
|
// 获取菜单目录
|
||||||
|
getDirList: (data) => request.post('/auth/menu/parent', data),
|
||||||
|
|
||||||
|
// 添加/修改菜单
|
||||||
|
addMenu: (data) => request.post('/auth/menu/set', data),
|
||||||
|
|
||||||
|
// 获取角色列表
|
||||||
|
getRoleList: (data) => request.post('/auth', data),
|
||||||
|
|
||||||
|
// 添加/修改角色
|
||||||
|
addRole: (data) => request.post('/auth/set', data),
|
||||||
|
// 获取管理员列表
|
||||||
|
getAdminList: (data) => request.post('/manage', data),
|
||||||
|
// 添加/修改管理员
|
||||||
|
addAdmin: (data) => request.post('/manage/set', data),
|
||||||
|
// 删除核销人员
|
||||||
|
delVerifyUser: (data) => request.post('/manage/delete', data),
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
<n-button type="primary" @click="handleAdd(1)">新增幻灯片</n-button>
|
<n-button v-perms="['/admin/rotation/edit']" type="primary" @click="handleAdd(1)">
|
||||||
|
新增幻灯片
|
||||||
|
</n-button>
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
/>
|
/>
|
||||||
<n-modal v-model:show="showModal">
|
<n-modal v-model:show="showModal">
|
||||||
<n-card
|
<n-card
|
||||||
@@ -44,10 +47,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, h } from 'vue'
|
import { onMounted, h, withDirectives, resolveDirective } from 'vue'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { NButton } from 'naive-ui'
|
import { NButton, NImage } from 'naive-ui'
|
||||||
import Upload from '@/components/Upload.vue'
|
import Upload from '@/components/Upload.vue'
|
||||||
|
const vPerms = resolveDirective('perms')
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
@@ -62,12 +66,9 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'url',
|
slot: 'url',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('img', {
|
return h(NImage, {
|
||||||
|
width: '50',
|
||||||
src: row.url[0]?.url || '',
|
src: row.url[0]?.url || '',
|
||||||
style: {
|
|
||||||
width: '30px',
|
|
||||||
height: '30px',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -85,17 +86,20 @@ const columns = ref([
|
|||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render(row) {
|
||||||
return [
|
return [
|
||||||
h(
|
withDirectives(
|
||||||
NButton,
|
h(
|
||||||
{
|
NButton,
|
||||||
type: 'primary',
|
{
|
||||||
size: 'small',
|
type: 'primary',
|
||||||
onClick: () => {
|
size: 'small',
|
||||||
formValue.value = row
|
onClick: () => {
|
||||||
handleAdd(2)
|
formValue.value = row
|
||||||
|
handleAdd(2)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
() => '编辑'
|
||||||
() => '编辑'
|
),
|
||||||
|
[[vPerms, ['/admin/rotation/edit']]]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/sys',
|
path: '/sys',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/sys_banner',
|
redirect: '/sys_banner',
|
||||||
|
meta: {
|
||||||
|
title: '系统管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Sysbanner',
|
name: 'Sysbanner',
|
||||||
@@ -26,5 +31,47 @@ export default {
|
|||||||
order: 10,
|
order: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'SysAcc',
|
||||||
|
path: 'sys_acc',
|
||||||
|
redirect: '/sys_acc_user',
|
||||||
|
meta: {
|
||||||
|
title: '权限管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'SysAccUser',
|
||||||
|
path: 'sys_acc_user',
|
||||||
|
component: () => import('./acc/acc_user/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '账号管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SysAccRole',
|
||||||
|
path: 'sys_acc_role',
|
||||||
|
component: () => import('./acc/acc_role/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '角色管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SysAccMenu',
|
||||||
|
path: 'sys_acc_menu',
|
||||||
|
component: () => import('./acc/acc_menu/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '菜单权限',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,14 @@
|
|||||||
/>
|
/>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item>
|
<n-form-item>
|
||||||
<n-button attr-type="button" @click="handleValidateClick">保存</n-button>
|
<n-button
|
||||||
|
v-perms="['/admin/userConfig/edit']"
|
||||||
|
attr-type="button"
|
||||||
|
type="primary"
|
||||||
|
@click="handleValidateClick"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</n-button>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
|
|||||||
@@ -2,4 +2,14 @@ import { request } from '@/utils'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
getUser: (data) => request.post('/user', data),
|
getUser: (data) => request.post('/user', data),
|
||||||
|
// 获取活动订单
|
||||||
|
gethdlist: (data) => request.post('/user/order', data),
|
||||||
|
// 获取积分订单
|
||||||
|
getjflist: (data) => request.post('/user/point/order', data),
|
||||||
|
// 获取豆子记录
|
||||||
|
getdzJllist: (data) => request.post('/user/pluse', data),
|
||||||
|
// 获取积分记录
|
||||||
|
getjfJllist: (data) => request.post('/user/point', data),
|
||||||
|
// 获取推广记录
|
||||||
|
gettgJllist: (data) => request.post('/user/referee/point', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,225 @@
|
|||||||
<template>
|
<template>
|
||||||
<CommonPage show-footer :title="$route.title">
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-grid class="mb-10" x-gap="12">
|
||||||
|
<n-gi :span="24">
|
||||||
|
<div flex>
|
||||||
|
<n-card w-500>
|
||||||
|
<n-statistic label="用户积分(留存)" tabular-nums>
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :from="0" :to="cardData.integral" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="用户豆子(留存)" tabular-nums>
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :from="0" :to="cardData.pulse" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="今日新增用户" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.today_user"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="用户总流水(元)" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.total_number"
|
||||||
|
:precision="2"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="总佣金(积分)" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.referee"
|
||||||
|
:precision="2"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="平台总用户" tabular-nums>
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:from="0"
|
||||||
|
:to="cardData.total_user"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
</div>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi span="12" mt-10 flex items-center>
|
||||||
|
<span w-100>筛选条件:</span>
|
||||||
|
<n-input-group>
|
||||||
|
<n-select
|
||||||
|
v-model:value="queryParams.selectKey"
|
||||||
|
:style="{ width: '20%' }"
|
||||||
|
:options="selectOptions"
|
||||||
|
placeholder="请选择"
|
||||||
|
/>
|
||||||
|
<n-input v-model:value="queryParams.word" :style="{ width: '30%' }" />
|
||||||
|
</n-input-group>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi span="24" mt-10 flex items-center>
|
||||||
|
<n-button type="primary" @click="getList">查询</n-button>
|
||||||
|
<n-button ml-10 @click="clear">重置</n-button>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="data"
|
:data="data"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
@update:sorter="handleSorterChange"
|
||||||
/>
|
/>
|
||||||
|
<!-- 用户详情 -->
|
||||||
|
<n-drawer v-model:show="isDrawer" :width="1000" placement="right" :mask-closable="false">
|
||||||
|
<n-drawer-content title="用户详情" closable>
|
||||||
|
<div flex items-center>
|
||||||
|
<img rounded-full :src="nowRow.avatarUrl" width="70" />
|
||||||
|
<div ml-10>
|
||||||
|
<div>昵称:{{ nowRow.nickName }}</div>
|
||||||
|
<div>电话:{{ nowRow.phone }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div mt-10 w-200 flex items-center justify-between text-center>
|
||||||
|
<div>
|
||||||
|
<div>用户积分</div>
|
||||||
|
<div text-red>{{ nowRow.integral }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>用户豆子</div>
|
||||||
|
<div text-red>{{ nowRow.pulse }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-tabs v-model:value="tabVal" type="line" animated @update-value="tabsChange">
|
||||||
|
<n-tab name="1" tab="活动订单"></n-tab>
|
||||||
|
<n-tab name="2" tab="积分订单"></n-tab>
|
||||||
|
<n-tab name="3" tab="豆子记录"></n-tab>
|
||||||
|
<n-tab name="4" tab="积分记录"></n-tab>
|
||||||
|
<n-tab name="5" tab="推广记录"></n-tab>
|
||||||
|
</n-tabs>
|
||||||
|
<n-row gutter="12">
|
||||||
|
<n-col :span="12">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-100>时间筛选:</span>
|
||||||
|
<n-date-picker
|
||||||
|
v-model:formatted-value="queryData.time"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="datetimerange"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="10" v-if="tabVal === '4'">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span w-100>条件筛选:</span>
|
||||||
|
<n-select
|
||||||
|
v-model:value="queryData.selectKey"
|
||||||
|
:style="{ width: '30%' }"
|
||||||
|
:options="[
|
||||||
|
{
|
||||||
|
label: '取消订单',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '支付订单',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '商品赠送',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
placeholder="请选择类型"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
<n-col :span="4">
|
||||||
|
<div mt-10>
|
||||||
|
<n-button type="primary" @click="getTabsList">搜索</n-button>
|
||||||
|
<n-button ml-10 @click="tabsClear">重置</n-button>
|
||||||
|
</div>
|
||||||
|
</n-col>
|
||||||
|
</n-row>
|
||||||
|
<n-data-table
|
||||||
|
class="mt-5"
|
||||||
|
:columns="tabsColumns"
|
||||||
|
:loading="tabsLoading"
|
||||||
|
:data="tabsData"
|
||||||
|
:pagination="tabsPagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
</n-drawer-content>
|
||||||
|
</n-drawer>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { h } from 'vue'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
|
import { NDropdown, NButton, NEllipsis } from 'naive-ui'
|
||||||
|
import TheIcon from '@/components/icon/TheIcon.vue'
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const queryParams = ref({
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
time: null,
|
||||||
|
selectKey: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
integral: 0,
|
||||||
|
pulse: 0,
|
||||||
|
today_user: 0,
|
||||||
|
total_number: 0,
|
||||||
|
total_user: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{
|
||||||
|
label: '用户昵称',
|
||||||
|
value: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '用户电话',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const isDrawer = ref(false)
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'ID',
|
key: 'ID',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '昵称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'nickName',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '头像',
|
title: '头像',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'avatar',
|
slot: 'avatar',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('img', {
|
return h('img', {
|
||||||
src: row.avatar,
|
src: row.avatarUrl,
|
||||||
style: {
|
style: {
|
||||||
width: '30px',
|
width: '30px',
|
||||||
height: '30px',
|
height: '30px',
|
||||||
@@ -45,18 +237,59 @@ const columns = ref([
|
|||||||
title: '用户积分',
|
title: '用户积分',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'integral',
|
key: 'integral',
|
||||||
|
sorter: true,
|
||||||
|
sortOrder: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户豆子',
|
title: '用户豆子',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'pulse',
|
key: 'pulse',
|
||||||
|
sorter: true,
|
||||||
|
sortOrder: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render(row) {
|
||||||
console.log(row)
|
return [
|
||||||
|
h(
|
||||||
|
NDropdown,
|
||||||
|
{
|
||||||
|
trigger: 'click',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '用户详情',
|
||||||
|
key: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onSelect: (key) => {
|
||||||
|
switch (key) {
|
||||||
|
case 1:
|
||||||
|
openDrawer(row)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
iconPlacement: 'right',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '更多',
|
||||||
|
icon: () =>
|
||||||
|
h(TheIcon, {
|
||||||
|
icon: 'ant-design:down-outlined',
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -64,9 +297,9 @@ const columns = ref([
|
|||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
current: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
itemCount: 0,
|
||||||
onChange: (page) => {
|
onChange: (page) => {
|
||||||
pagination.value.page = page
|
pagination.value.page = page
|
||||||
getList()
|
getList()
|
||||||
@@ -82,20 +315,290 @@ onMounted(() => {
|
|||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
queryParams.value = {
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
const query_data = {}
|
||||||
|
switch (queryParams.value.selectKey) {
|
||||||
|
case 0:
|
||||||
|
query_data['UserName'] = queryParams.value.word
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
query_data['Phone'] = queryParams.value.word
|
||||||
|
break
|
||||||
|
}
|
||||||
const res = await api.getUser({
|
const res = await api.getUser({
|
||||||
pageNum: pagination.value.current,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
|
...query_data,
|
||||||
})
|
})
|
||||||
console.log(res)
|
data.value = res.data.data || []
|
||||||
data.value = res.data.data
|
pagination.value.itemCount = res.data.total_user
|
||||||
|
cardData.value.today_user = res.data.today_user
|
||||||
|
cardData.value.total_user = res.data.total_user
|
||||||
|
cardData.value.total_number = res.data.total_number
|
||||||
|
cardData.value.integral = res.data.integral
|
||||||
|
cardData.value.pulse = res.data.pulse
|
||||||
|
cardData.value.referee = res.data.referee
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$message.error(error.msg)
|
$message.error(error.msg)
|
||||||
}
|
}
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nowRow = ref({})
|
||||||
|
|
||||||
|
const tabVal = ref('1')
|
||||||
|
|
||||||
|
const tabsLoading = ref(false)
|
||||||
|
const tabsColumns = ref([])
|
||||||
|
const tabsData = ref([])
|
||||||
|
const tabsPagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
tabsPagination.value.page = page
|
||||||
|
getTabsList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const openDrawer = (row) => {
|
||||||
|
nowRow.value = row
|
||||||
|
isDrawer.value = true
|
||||||
|
// getTabsList()
|
||||||
|
tabsChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabsChange = async (e = '1') => {
|
||||||
|
tabVal.value = e
|
||||||
|
tabsData.value = []
|
||||||
|
tabsColumns.value = []
|
||||||
|
if (tabVal.value === '1' || tabVal.value === '2') {
|
||||||
|
tabsColumns.value = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'oid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品封面',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'cover',
|
||||||
|
render: (row) => {
|
||||||
|
return h('img', {
|
||||||
|
src: row.cover,
|
||||||
|
style: {
|
||||||
|
width: '50px',
|
||||||
|
height: '50px',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'goods_name',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 240px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.goods_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品价格',
|
||||||
|
align: 'center',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'status',
|
||||||
|
render: (row) => {
|
||||||
|
let nameStr = ''
|
||||||
|
switch (row.status) {
|
||||||
|
case 0:
|
||||||
|
nameStr = '待付款'
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
nameStr = '待使用'
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
nameStr = '已使用'
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
nameStr = '已过期'
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
'span',
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: () => nameStr,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下单时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else if (tabVal.value === '3') {
|
||||||
|
tabsColumns.value = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'oid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'goods_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '消费金额',
|
||||||
|
align: 'center',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下单时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else if (tabVal.value === '4') {
|
||||||
|
tabsColumns.value = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'oid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'goods_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '积分',
|
||||||
|
align: 'center',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
tabsColumns.value = [
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'oid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户昵称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'nick_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'goods_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '获得积分',
|
||||||
|
align: 'center',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tabsPagination.value.page = 1
|
||||||
|
getTabsList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTabsList = async () => {
|
||||||
|
tabsLoading.value = true
|
||||||
|
let res
|
||||||
|
const data = {
|
||||||
|
uid: nowRow.value.uid,
|
||||||
|
pageNum: tabsPagination.value.page,
|
||||||
|
pageSize: tabsPagination.value.pageSize,
|
||||||
|
StartTime: queryData.value.time === null ? '' : queryData.value.time[0] || '',
|
||||||
|
EndTime: queryData.value.time === null ? '' : queryData.value.time[1] || '',
|
||||||
|
}
|
||||||
|
switch (tabVal.value) {
|
||||||
|
case '1':
|
||||||
|
res = await api.gethdlist(data)
|
||||||
|
break
|
||||||
|
case '2':
|
||||||
|
res = await api.getjflist(data)
|
||||||
|
break
|
||||||
|
case '3':
|
||||||
|
res = await api.getdzJllist(data)
|
||||||
|
break
|
||||||
|
case '4':
|
||||||
|
data['Type'] = queryData.value.selectKey
|
||||||
|
res = await api.getjfJllist(data)
|
||||||
|
break
|
||||||
|
case '5':
|
||||||
|
res = await api.gettgJllist(data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tabsData.value = res.data.data || []
|
||||||
|
tabsPagination.value.itemCount = res.data.total
|
||||||
|
tabsLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSorterChange = (sorter) => {
|
||||||
|
if (!loading.value) {
|
||||||
|
loading.value = true
|
||||||
|
switch (sorter.columnKey) {
|
||||||
|
case 'pulse':
|
||||||
|
columns.value[5].sortOrder = !sorter ? false : sorter.order
|
||||||
|
data.value = data.value.sort((a, b) => {
|
||||||
|
if (sorter.order === 'descend') return b.pulse - a.pulse
|
||||||
|
return a.pulse - b.pulse
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'integral':
|
||||||
|
columns.value[4].sortOrder = !sorter ? false : sorter.order
|
||||||
|
data.value = data.value.sort((a, b) => {
|
||||||
|
if (sorter.order === 'descend') return b.integral - a.integral
|
||||||
|
return a.integral - b.integral
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabsClear = async () => {
|
||||||
|
queryData.value = {
|
||||||
|
time: null,
|
||||||
|
selectKey: null,
|
||||||
|
}
|
||||||
|
await getTabsList()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/user',
|
path: '/user',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/user_list',
|
redirect: '/user_list',
|
||||||
|
meta: {
|
||||||
|
title: '用户管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Userlist',
|
name: 'Userlist',
|
||||||
@@ -12,6 +17,7 @@ export default {
|
|||||||
component: () => import('./index/index.vue'),
|
component: () => import('./index/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '用户列表',
|
title: '用户列表',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
order: 10,
|
order: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||