From 5c7b6054364568a81596b4bba1d23ed553df515d Mon Sep 17 00:00:00 2001 From: cst Date: Fri, 17 Jul 2026 08:51:48 +0800 Subject: [PATCH] fix: add iconfont to eslintignore, fix commitlint config --- .eslintignore | 1 + .vscode/settings.json | 2 +- babel.config.js | 17 + commitlint.config.js => commitlint.config.cjs | 0 src/App.tsx | 12 +- src/assets/iconfont/demo.css | 545 +++++++ src/assets/iconfont/demo_index.html | 1410 +++++++++++++++++ src/assets/iconfont/iconfont.css | 232 +++ src/assets/iconfont/iconfont.eot | Bin 0 -> 16128 bytes src/assets/iconfont/iconfont.js | 67 + src/assets/iconfont/iconfont.json | 380 +++++ src/assets/iconfont/iconfont.svg | 125 ++ src/assets/iconfont/iconfont.ttf | Bin 0 -> 15960 bytes src/assets/iconfont/iconfont.woff | Bin 0 -> 9508 bytes src/assets/iconfont/iconfont.woff2 | Bin 0 -> 8084 bytes src/assets/styles/index.less | 10 + src/hooks/useBasicLayout.ts | 91 +- src/hooks/useBreadcrumb.ts | 41 +- src/layouts/BasicLayout.module.less | 183 ++- src/layouts/BasicLayout.tsx | 162 +- src/main.ts | 1 + src/router/index.ts | 4 +- src/router/routes.ts | 183 ++- src/router/utils.ts | 59 +- src/types/index.ts | 3 +- src/views/Dashboard.module.less | 27 - src/views/Dashboard.tsx | 67 - .../Dashboard/components/AddVenueModal.tsx | 184 +++ src/views/Dashboard/index.module.less | 86 + src/views/Dashboard/index.tsx | 247 +++ src/views/Dashboard/model/index.ts | 2 + src/views/Dashboard/model/services.ts | 119 ++ .../Dashboard/model/useDashboardModel.ts | 83 + src/views/venue/list/index.module.less | 67 + src/views/venue/list/index.tsx | 139 ++ src/views/venue/list/model/index.ts | 2 + src/views/venue/list/model/services.ts | 72 + .../venue/list/model/useVenueListModel.ts | 54 + src/views/venue/records/index.module.less | 67 + src/views/venue/records/index.tsx | 137 ++ src/views/venue/records/model/index.ts | 2 + src/views/venue/records/model/services.ts | 64 + .../records/model/useVenueRecordsModel.ts | 54 + vite.config.ts | 6 + 44 files changed, 4782 insertions(+), 225 deletions(-) create mode 100644 babel.config.js rename commitlint.config.js => commitlint.config.cjs (100%) create mode 100644 src/assets/iconfont/demo.css create mode 100644 src/assets/iconfont/demo_index.html create mode 100644 src/assets/iconfont/iconfont.css create mode 100644 src/assets/iconfont/iconfont.eot create mode 100644 src/assets/iconfont/iconfont.js create mode 100644 src/assets/iconfont/iconfont.json create mode 100644 src/assets/iconfont/iconfont.svg create mode 100644 src/assets/iconfont/iconfont.ttf create mode 100644 src/assets/iconfont/iconfont.woff create mode 100644 src/assets/iconfont/iconfont.woff2 delete mode 100644 src/views/Dashboard.module.less delete mode 100644 src/views/Dashboard.tsx create mode 100644 src/views/Dashboard/components/AddVenueModal.tsx create mode 100644 src/views/Dashboard/index.module.less create mode 100644 src/views/Dashboard/index.tsx create mode 100644 src/views/Dashboard/model/index.ts create mode 100644 src/views/Dashboard/model/services.ts create mode 100644 src/views/Dashboard/model/useDashboardModel.ts create mode 100644 src/views/venue/list/index.module.less create mode 100644 src/views/venue/list/index.tsx create mode 100644 src/views/venue/list/model/index.ts create mode 100644 src/views/venue/list/model/services.ts create mode 100644 src/views/venue/list/model/useVenueListModel.ts create mode 100644 src/views/venue/records/index.module.less create mode 100644 src/views/venue/records/index.tsx create mode 100644 src/views/venue/records/model/index.ts create mode 100644 src/views/venue/records/model/services.ts create mode 100644 src/views/venue/records/model/useVenueRecordsModel.ts diff --git a/.eslintignore b/.eslintignore index cc6fa79..b4bca4a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,4 @@ public *.config.js *.config.ts start-debug.js +src/assets/iconfont diff --git a/.vscode/settings.json b/.vscode/settings.json index ea1e0d1..3cd6249 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,7 +12,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[less]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.css-language-features" }, "files.associations": { "*.vue": "vue" diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..d00dd12 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,17 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + chrome: '80', + firefox: '75', + safari: '14', + edge: '80', + }, + useBuiltIns: 'usage', + corejs: 3, + }, + ], + ], +}; diff --git a/commitlint.config.js b/commitlint.config.cjs similarity index 100% rename from commitlint.config.js rename to commitlint.config.cjs diff --git a/src/App.tsx b/src/App.tsx index ba5b391..4c2d3ea 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,7 +12,17 @@ export default defineComponent({ setup() { const theme = { token: { - colorPrimary: '#1677ff', + colorPrimary: '#1890ff', + colorSuccess: '#52c41a', + colorWarning: '#faad14', + colorError: '#ff4d4f', + colorInfo: '#1890ff', + colorBgBase: '#ffffff', + colorBgContainer: '#ffffff', + colorBgElevated: '#ffffff', + colorBgLayout: '#f0f2f5', + colorTextBase: '#262626', + borderRadius: 6, }, }; diff --git a/src/assets/iconfont/demo.css b/src/assets/iconfont/demo.css new file mode 100644 index 0000000..8a05f6e --- /dev/null +++ b/src/assets/iconfont/demo.css @@ -0,0 +1,545 @@ +/* Logo 字体 */ +@font-face { + font-family: 'iconfont logo'; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') + format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') + format('svg'); +} + +.logo { + font-family: 'iconfont logo'; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: + font-size 0.25s linear, + width 0.25s linear; + -moz-transition: + font-size 0.25s linear, + width 0.25s linear; + transition: + font-size 0.25s linear, + width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown > p, +.markdown > blockquote, +.markdown > .highlight, +.markdown > ol, +.markdown > ul { + width: 80%; +} + +.markdown ul > li { + list-style: circle; +} + +.markdown > ul li, +.markdown blockquote ul > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown > ul li p, +.markdown > ol li p { + margin: 0.6em 0; +} + +.markdown ol > li { + list-style: decimal; +} + +.markdown > ol li, +.markdown blockquote ol > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown > table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown > table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown > table th, +.markdown > table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown > table th { + background: #f7f7f7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown > br, +.markdown > p > br { + clear: both; +} + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +/* 代码高亮 */ +/* PrismJS 1.15.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*='language-'], +pre[class*='language-'] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*='language-']::-moz-selection, +pre[class*='language-'] ::-moz-selection, +code[class*='language-']::-moz-selection, +code[class*='language-'] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*='language-']::selection, +pre[class*='language-'] ::selection, +code[class*='language-']::selection, +code[class*='language-'] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*='language-'], + pre[class*='language-'] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*='language-'] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; +} + +:not(pre) > code[class*='language-'], +pre[class*='language-'] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*='language-'] { + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: 0.7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, 0.5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #dd4a68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/src/assets/iconfont/demo_index.html b/src/assets/iconfont/demo_index.html new file mode 100644 index 0000000..5184e09 --- /dev/null +++ b/src/assets/iconfont/demo_index.html @@ -0,0 +1,1410 @@ + + + + + iconfont Demo + + + + + + + + + + + + + +
+

+ + +

+ +
+
+
    + +
  • + +
    场馆
    +
    
    +
  • + +
  • + +
    灯-点亮
    +
    
    +
  • + +
  • + +
    灯-关闭
    +
    
    +
  • + +
  • + +
    刷新
    +
    
    +
  • + +
  • + +
    关闭
    +
    
    +
  • + +
  • + +
    添加
    +
    
    +
  • + +
  • + +
    签到码
    +
    
    +
  • + +
  • + +
    日历
    +
    
    +
  • + +
  • + +
    分组title
    +
    
    +
  • + +
  • + +
    成功
    +
    
    +
  • + +
  • + +
    存草稿
    +
    
    +
  • + +
  • + +
    图片
    +
    
    +
  • + +
  • + +
    微信支付
    +
    
    +
  • + +
  • + +
    删除
    +
    
    +
  • + +
  • + +
    钱包
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    金币
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    分享
    +
    
    +
  • + +
  • + +
    修改
    +
    
    +
  • + +
  • + +
    编辑
    +
    
    +
  • + +
  • + +
    更多1
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    添加
    +
    
    +
  • + +
  • + +
    更多
    +
    
    +
  • + +
  • + +
    电话
    +
    
    +
  • + +
  • + +
    撤销
    +
    
    +
  • + +
  • + +
    微信
    +
    
    +
  • + +
  • + +
    分组
    +
    
    +
  • + +
  • + +
    点名
    +
    
    +
  • + +
  • + +
    套餐
    +
    
    +
  • + +
  • + +
    特价
    +
    
    +
  • + +
  • + +
    满减
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    分享
    +
    
    +
  • + +
  • + +
    浏览量
    +
    
    +
  • + +
  • + +
    日历
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    定位
    +
    
    +
  • + +
  • + +
    关闭
    +
    
    +
  • + +
  • + +
    收藏
    +
    
    +
  • + +
  • + +
    时间
    +
    
    +
  • + +
  • + +
    场馆
    +
    
    +
  • + +
  • + +
    未选中
    +
    
    +
  • + +
  • + +
    选择
    +
    
    +
  • + +
  • + +
    选择-fill
    +
    
    +
  • + +
  • + +
    选中
    +
    
    +
  • + +
  • + +
    微信支付
    +
    
    +
  • + +
  • + +
    +
    
    +
  • + +
  • + +
    联系我们
    +
    
    +
  • + +
  • + +
    余额
    +
    
    +
  • + +
+
+

Unicode 引用

+
+ +

Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • +
+
+

注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)

+
+

Unicode 使用步骤如下:

+

第一步:拷贝项目下面生成的 @font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot?t=1784185072587'); /* IE9 */
+  src: url('iconfont.eot?t=1784185072587#iefix') format('embedded-opentype'), /* IE6-IE8 */
+       url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
+       url('iconfont.woff?t=1784185072587') format('woff'),
+       url('iconfont.ttf?t=1784185072587') format('truetype'),
+       url('iconfont.svg?t=1784185072587#iconfont') format('svg');
+}
+
+

第二步:定义使用 iconfont 的样式

+
.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
+<span class="iconfont">&#x33;</span>
+
+
+

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    + 场馆 +
    +
    .icon-changguan1 +
    +
  • + +
  • + +
    + 灯-点亮 +
    +
    .icon-deng-dianliang +
    +
  • + +
  • + +
    + 灯-关闭 +
    +
    .icon-deng-guanbi +
    +
  • + +
  • + +
    + 刷新 +
    +
    .icon-shuaxin +
    +
  • + +
  • + +
    + 关闭 +
    +
    .icon-guanbi1 +
    +
  • + +
  • + +
    + 添加 +
    +
    .icon-tianjia1 +
    +
  • + +
  • + +
    + 签到码 +
    +
    .icon-qiandaoma +
    +
  • + +
  • + +
    + 日历 +
    +
    .icon-rili1 +
    +
  • + +
  • + +
    + 分组title +
    +
    .icon-fenzutitle +
    +
  • + +
  • + +
    + 成功 +
    +
    .icon-chenggong +
    +
  • + +
  • + +
    + 存草稿 +
    +
    .icon-cuncaogao +
    +
  • + +
  • + +
    + 图片 +
    +
    .icon-tupian +
    +
  • + +
  • + +
    + 微信支付 +
    +
    .icon-weixinzhifu1 +
    +
  • + +
  • + +
    + 删除 +
    +
    .icon-shanchu +
    +
  • + +
  • + +
    + 钱包 +
    +
    .icon-qianbao +
    +
  • + +
  • + +
    + 男 +
    +
    .icon-nan +
    +
  • + +
  • + +
    + 金币 +
    +
    .icon-jinbi +
    +
  • + +
  • + +
    + 女 +
    +
    .icon-nv +
    +
  • + +
  • + +
    + 分享 +
    +
    .icon-fenxiang1 +
    +
  • + +
  • + +
    + 修改 +
    +
    .icon-xiugai +
    +
  • + +
  • + +
    + 编辑 +
    +
    .icon-bianji +
    +
  • + +
  • + +
    + 更多1 +
    +
    .icon-gengduo1 +
    +
  • + +
  • + +
    + 上 +
    +
    .icon-shang +
    +
  • + +
  • + +
    + 添加 +
    +
    .icon-tianjia +
    +
  • + +
  • + +
    + 更多 +
    +
    .icon-gengduo +
    +
  • + +
  • + +
    + 电话 +
    +
    .icon-dianhua +
    +
  • + +
  • + +
    + 撤销 +
    +
    .icon-chexiao +
    +
  • + +
  • + +
    + 微信 +
    +
    .icon-weixin +
    +
  • + +
  • + +
    + 分组 +
    +
    .icon-fenzu +
    +
  • + +
  • + +
    + 点名 +
    +
    .icon-dianming +
    +
  • + +
  • + +
    + 套餐 +
    +
    .icon-taocan +
    +
  • + +
  • + +
    + 特价 +
    +
    .icon-tejia +
    +
  • + +
  • + +
    + 满减 +
    +
    .icon-manjian +
    +
  • + +
  • + +
    + 票 +
    +
    .icon-piao +
    +
  • + +
  • + +
    + 勾 +
    +
    .icon-gou +
    +
  • + +
  • + +
    + 分享 +
    +
    .icon-fenxiang +
    +
  • + +
  • + +
    + 浏览量 +
    +
    .icon-liulanliang +
    +
  • + +
  • + +
    + 日历 +
    +
    .icon-rili +
    +
  • + +
  • + +
    + 左 +
    +
    .icon-zuo +
    +
  • + +
  • + +
    + 下 +
    +
    .icon-xia +
    +
  • + +
  • + +
    + 定位 +
    +
    .icon-dingwei +
    +
  • + +
  • + +
    + 关闭 +
    +
    .icon-guanbi +
    +
  • + +
  • + +
    + 收藏 +
    +
    .icon-shoucang +
    +
  • + +
  • + +
    + 时间 +
    +
    .icon-shijian +
    +
  • + +
  • + +
    + 场馆 +
    +
    .icon-changguan +
    +
  • + +
  • + +
    + 未选中 +
    +
    .icon-weixuanzhong +
    +
  • + +
  • + +
    + 选择 +
    +
    .icon-xuanze +
    +
  • + +
  • + +
    + 选择-fill +
    +
    .icon-xuanze-fill +
    +
  • + +
  • + +
    + 选中 +
    +
    .icon-xuanzhong +
    +
  • + +
  • + +
    + 微信支付 +
    +
    .icon-weixinzhifu +
    +
  • + +
  • + +
    + 右 +
    +
    .icon-you +
    +
  • + +
  • + +
    + 联系我们 +
    +
    .icon-lianxiwomen +
    +
  • + +
  • + +
    + 余额 +
    +
    .icon-yue +
    +
  • + +
+
+

font-class 引用

+
+ +

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 fontclass 代码:

+
<link rel="stylesheet" href="./iconfont.css">
+
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont icon-xxx"></span>
+
+
+

" + iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    场馆
    +
    #icon-changguan1
    +
  • + +
  • + +
    灯-点亮
    +
    #icon-deng-dianliang
    +
  • + +
  • + +
    灯-关闭
    +
    #icon-deng-guanbi
    +
  • + +
  • + +
    刷新
    +
    #icon-shuaxin
    +
  • + +
  • + +
    关闭
    +
    #icon-guanbi1
    +
  • + +
  • + +
    添加
    +
    #icon-tianjia1
    +
  • + +
  • + +
    签到码
    +
    #icon-qiandaoma
    +
  • + +
  • + +
    日历
    +
    #icon-rili1
    +
  • + +
  • + +
    分组title
    +
    #icon-fenzutitle
    +
  • + +
  • + +
    成功
    +
    #icon-chenggong
    +
  • + +
  • + +
    存草稿
    +
    #icon-cuncaogao
    +
  • + +
  • + +
    图片
    +
    #icon-tupian
    +
  • + +
  • + +
    微信支付
    +
    #icon-weixinzhifu1
    +
  • + +
  • + +
    删除
    +
    #icon-shanchu
    +
  • + +
  • + +
    钱包
    +
    #icon-qianbao
    +
  • + +
  • + +
    +
    #icon-nan
    +
  • + +
  • + +
    金币
    +
    #icon-jinbi
    +
  • + +
  • + +
    +
    #icon-nv
    +
  • + +
  • + +
    分享
    +
    #icon-fenxiang1
    +
  • + +
  • + +
    修改
    +
    #icon-xiugai
    +
  • + +
  • + +
    编辑
    +
    #icon-bianji
    +
  • + +
  • + +
    更多1
    +
    #icon-gengduo1
    +
  • + +
  • + +
    +
    #icon-shang
    +
  • + +
  • + +
    添加
    +
    #icon-tianjia
    +
  • + +
  • + +
    更多
    +
    #icon-gengduo
    +
  • + +
  • + +
    电话
    +
    #icon-dianhua
    +
  • + +
  • + +
    撤销
    +
    #icon-chexiao
    +
  • + +
  • + +
    微信
    +
    #icon-weixin
    +
  • + +
  • + +
    分组
    +
    #icon-fenzu
    +
  • + +
  • + +
    点名
    +
    #icon-dianming
    +
  • + +
  • + +
    套餐
    +
    #icon-taocan
    +
  • + +
  • + +
    特价
    +
    #icon-tejia
    +
  • + +
  • + +
    满减
    +
    #icon-manjian
    +
  • + +
  • + +
    +
    #icon-piao
    +
  • + +
  • + +
    +
    #icon-gou
    +
  • + +
  • + +
    分享
    +
    #icon-fenxiang
    +
  • + +
  • + +
    浏览量
    +
    #icon-liulanliang
    +
  • + +
  • + +
    日历
    +
    #icon-rili
    +
  • + +
  • + +
    +
    #icon-zuo
    +
  • + +
  • + +
    +
    #icon-xia
    +
  • + +
  • + +
    定位
    +
    #icon-dingwei
    +
  • + +
  • + +
    关闭
    +
    #icon-guanbi
    +
  • + +
  • + +
    收藏
    +
    #icon-shoucang
    +
  • + +
  • + +
    时间
    +
    #icon-shijian
    +
  • + +
  • + +
    场馆
    +
    #icon-changguan
    +
  • + +
  • + +
    未选中
    +
    #icon-weixuanzhong
    +
  • + +
  • + +
    选择
    +
    #icon-xuanze
    +
  • + +
  • + +
    选择-fill
    +
    #icon-xuanze-fill
    +
  • + +
  • + +
    选中
    +
    #icon-xuanzhong
    +
  • + +
  • + +
    微信支付
    +
    #icon-weixinzhifu
    +
  • + +
  • + +
    +
    #icon-you
    +
  • + +
  • + +
    联系我们
    +
    #icon-lianxiwomen
    +
  • + +
  • + +
    余额
    +
    #icon-yue
    +
  • + +
+
+

Symbol 引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>
+
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+ +
+
+ + + diff --git a/src/assets/iconfont/iconfont.css b/src/assets/iconfont/iconfont.css new file mode 100644 index 0000000..1df74d1 --- /dev/null +++ b/src/assets/iconfont/iconfont.css @@ -0,0 +1,232 @@ +@font-face { + font-family: 'iconfont'; /* Project id 4533260 */ + src: url('iconfont.eot?t=1784185072587'); /* IE9 */ + src: + url('iconfont.eot?t=1784185072587#iefix') format('embedded-opentype'), + /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,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') + format('woff2'), + url('iconfont.woff?t=1784185072587') format('woff'), + url('iconfont.ttf?t=1784185072587') format('truetype'), + url('iconfont.svg?t=1784185072587#iconfont') format('svg'); +} + +.iconfont { + font-family: 'iconfont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-changguan1:before { + content: '\e87b'; +} + +.icon-deng-dianliang:before { + content: '\e7b9'; +} + +.icon-deng-guanbi:before { + content: '\e7ba'; +} + +.icon-shuaxin:before { + content: '\e878'; +} + +.icon-guanbi1:before { + content: '\e879'; +} + +.icon-tianjia1:before { + content: '\e81f'; +} + +.icon-qiandaoma:before { + content: '\e857'; +} + +.icon-rili1:before { + content: '\e856'; +} + +.icon-fenzutitle:before { + content: '\e84c'; +} + +.icon-chenggong:before { + content: '\e84d'; +} + +.icon-cuncaogao:before { + content: '\e84e'; +} + +.icon-tupian:before { + content: '\e84f'; +} + +.icon-weixinzhifu1:before { + content: '\e850'; +} + +.icon-shanchu:before { + content: '\e851'; +} + +.icon-qianbao:before { + content: '\e852'; +} + +.icon-nan:before { + content: '\e853'; +} + +.icon-jinbi:before { + content: '\e854'; +} + +.icon-nv:before { + content: '\e855'; +} + +.icon-fenxiang1:before { + content: '\e847'; +} + +.icon-xiugai:before { + content: '\e848'; +} + +.icon-bianji:before { + content: '\e849'; +} + +.icon-gengduo1:before { + content: '\e84a'; +} + +.icon-shang:before { + content: '\e84b'; +} + +.icon-tianjia:before { + content: '\e840'; +} + +.icon-gengduo:before { + content: '\e841'; +} + +.icon-dianhua:before { + content: '\e842'; +} + +.icon-chexiao:before { + content: '\e843'; +} + +.icon-weixin:before { + content: '\e844'; +} + +.icon-fenzu:before { + content: '\e845'; +} + +.icon-dianming:before { + content: '\e846'; +} + +.icon-taocan:before { + content: '\e7fc'; +} + +.icon-tejia:before { + content: '\e7da'; +} + +.icon-manjian:before { + content: '\e7db'; +} + +.icon-piao:before { + content: '\e83f'; +} + +.icon-gou:before { + content: '\e63d'; +} + +.icon-fenxiang:before { + content: '\e83e'; +} + +.icon-liulanliang:before { + content: '\e83c'; +} + +.icon-rili:before { + content: '\e83d'; +} + +.icon-zuo:before { + content: '\e83b'; +} + +.icon-xia:before { + content: '\e83a'; +} + +.icon-dingwei:before { + content: '\e82d'; +} + +.icon-guanbi:before { + content: '\e82e'; +} + +.icon-shoucang:before { + content: '\e82f'; +} + +.icon-shijian:before { + content: '\e830'; +} + +.icon-changguan:before { + content: '\e831'; +} + +.icon-weixuanzhong:before { + content: '\e832'; +} + +.icon-xuanze:before { + content: '\e833'; +} + +.icon-xuanze-fill:before { + content: '\e834'; +} + +.icon-xuanzhong:before { + content: '\e835'; +} + +.icon-weixinzhifu:before { + content: '\e836'; +} + +.icon-you:before { + content: '\e837'; +} + +.icon-lianxiwomen:before { + content: '\e838'; +} + +.icon-yue:before { + content: '\e839'; +} diff --git a/src/assets/iconfont/iconfont.eot b/src/assets/iconfont/iconfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..f4c88056538eaabec1048a8a0d1f099ae121ab94 GIT binary patch literal 16128 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 dLhCiC;ZM%YRA8) literal 0 HcmV?d00001 diff --git a/src/assets/iconfont/iconfont.js b/src/assets/iconfont/iconfont.js new file mode 100644 index 0000000..901bc13 --- /dev/null +++ b/src/assets/iconfont/iconfont.js @@ -0,0 +1,67 @@ +((window._iconfont_svg_string_4533260 = + ''), + ((a) => { + var c = (h = (h = document.getElementsByTagName('script'))[h.length - 1]).getAttribute( + 'data-injectcss', + ), + h = h.getAttribute('data-disable-injectsvg'); + if (!h) { + var l, + v, + o, + t, + i, + s = function (c, h) { + h.parentNode.insertBefore(c, h); + }; + if (c && !a.__iconfont__svg__cssinject__) { + a.__iconfont__svg__cssinject__ = !0; + try { + document.write( + '', + ); + } catch (c) { + console && console.log(c); + } + } + ((l = function () { + var c, + h = document.createElement('div'); + ((h.innerHTML = a._iconfont_svg_string_4533260), + (h = h.getElementsByTagName('svg')[0]) && + (h.setAttribute('aria-hidden', 'true'), + (h.style.position = 'absolute'), + (h.style.width = 0), + (h.style.height = 0), + (h.style.overflow = 'hidden'), + (h = h), + (c = document.body).firstChild ? s(h, c.firstChild) : c.appendChild(h))); + }), + document.addEventListener + ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState) + ? setTimeout(l, 0) + : ((v = function () { + (document.removeEventListener('DOMContentLoaded', v, !1), l()); + }), + document.addEventListener('DOMContentLoaded', v, !1)) + : document.attachEvent && + ((o = l), + (t = a.document), + (i = !1), + z(), + (t.onreadystatechange = function () { + 'complete' == t.readyState && ((t.onreadystatechange = null), m()); + }))); + } + function m() { + i || ((i = !0), o()); + } + function z() { + try { + t.documentElement.doScroll('left'); + } catch (c) { + return void setTimeout(z, 50); + } + m(); + } + })(window)); diff --git a/src/assets/iconfont/iconfont.json b/src/assets/iconfont/iconfont.json new file mode 100644 index 0000000..197c344 --- /dev/null +++ b/src/assets/iconfont/iconfont.json @@ -0,0 +1,380 @@ +{ + "id": "4533260", + "name": "改版-六个羽友", + "font_family": "iconfont", + "css_prefix_text": "icon-", + "description": "", + "glyphs": [ + { + "icon_id": "43518948", + "name": "场馆", + "font_class": "changguan1", + "unicode": "e87b", + "unicode_decimal": 59515 + }, + { + "icon_id": "31394058", + "name": "灯-点亮", + "font_class": "deng-dianliang", + "unicode": "e7b9", + "unicode_decimal": 59321 + }, + { + "icon_id": "31394059", + "name": "灯-关闭", + "font_class": "deng-guanbi", + "unicode": "e7ba", + "unicode_decimal": 59322 + }, + { + "icon_id": "43469992", + "name": "刷新", + "font_class": "shuaxin", + "unicode": "e878", + "unicode_decimal": 59512 + }, + { + "icon_id": "43469991", + "name": "关闭", + "font_class": "guanbi1", + "unicode": "e879", + "unicode_decimal": 59513 + }, + { + "icon_id": "39274830", + "name": "添加", + "font_class": "tianjia1", + "unicode": "e81f", + "unicode_decimal": 59423 + }, + { + "icon_id": "41007799", + "name": "签到码", + "font_class": "qiandaoma", + "unicode": "e857", + "unicode_decimal": 59479 + }, + { + "icon_id": "40996457", + "name": "日历", + "font_class": "rili1", + "unicode": "e856", + "unicode_decimal": 59478 + }, + { + "icon_id": "40820828", + "name": "分组title", + "font_class": "fenzutitle", + "unicode": "e84c", + "unicode_decimal": 59468 + }, + { + "icon_id": "40820822", + "name": "成功", + "font_class": "chenggong", + "unicode": "e84d", + "unicode_decimal": 59469 + }, + { + "icon_id": "40820826", + "name": "存草稿", + "font_class": "cuncaogao", + "unicode": "e84e", + "unicode_decimal": 59470 + }, + { + "icon_id": "40820824", + "name": "图片", + "font_class": "tupian", + "unicode": "e84f", + "unicode_decimal": 59471 + }, + { + "icon_id": "40820823", + "name": "微信支付", + "font_class": "weixinzhifu1", + "unicode": "e850", + "unicode_decimal": 59472 + }, + { + "icon_id": "40820821", + "name": "删除", + "font_class": "shanchu", + "unicode": "e851", + "unicode_decimal": 59473 + }, + { + "icon_id": "40820818", + "name": "钱包", + "font_class": "qianbao", + "unicode": "e852", + "unicode_decimal": 59474 + }, + { + "icon_id": "40820816", + "name": "男", + "font_class": "nan", + "unicode": "e853", + "unicode_decimal": 59475 + }, + { + "icon_id": "40820819", + "name": "金币", + "font_class": "jinbi", + "unicode": "e854", + "unicode_decimal": 59476 + }, + { + "icon_id": "40820817", + "name": "女", + "font_class": "nv", + "unicode": "e855", + "unicode_decimal": 59477 + }, + { + "icon_id": "40820832", + "name": "分享", + "font_class": "fenxiang1", + "unicode": "e847", + "unicode_decimal": 59463 + }, + { + "icon_id": "40820825", + "name": "修改", + "font_class": "xiugai", + "unicode": "e848", + "unicode_decimal": 59464 + }, + { + "icon_id": "40820830", + "name": "编辑", + "font_class": "bianji", + "unicode": "e849", + "unicode_decimal": 59465 + }, + { + "icon_id": "40820829", + "name": "更多1", + "font_class": "gengduo1", + "unicode": "e84a", + "unicode_decimal": 59466 + }, + { + "icon_id": "40820820", + "name": "上", + "font_class": "shang", + "unicode": "e84b", + "unicode_decimal": 59467 + }, + { + "icon_id": "40820837", + "name": "添加", + "font_class": "tianjia", + "unicode": "e840", + "unicode_decimal": 59456 + }, + { + "icon_id": "40820836", + "name": "更多", + "font_class": "gengduo", + "unicode": "e841", + "unicode_decimal": 59457 + }, + { + "icon_id": "40820835", + "name": "电话", + "font_class": "dianhua", + "unicode": "e842", + "unicode_decimal": 59458 + }, + { + "icon_id": "40820827", + "name": "撤销", + "font_class": "chexiao", + "unicode": "e843", + "unicode_decimal": 59459 + }, + { + "icon_id": "40820831", + "name": "微信", + "font_class": "weixin", + "unicode": "e844", + "unicode_decimal": 59460 + }, + { + "icon_id": "40820834", + "name": "分组", + "font_class": "fenzu", + "unicode": "e845", + "unicode_decimal": 59461 + }, + { + "icon_id": "40820833", + "name": "点名", + "font_class": "dianming", + "unicode": "e846", + "unicode_decimal": 59462 + }, + { + "icon_id": "36759285", + "name": "套餐", + "font_class": "taocan", + "unicode": "e7fc", + "unicode_decimal": 59388 + }, + { + "icon_id": "33120817", + "name": "特价", + "font_class": "tejia", + "unicode": "e7da", + "unicode_decimal": 59354 + }, + { + "icon_id": "33120818", + "name": "满减", + "font_class": "manjian", + "unicode": "e7db", + "unicode_decimal": 59355 + }, + { + "icon_id": "40351403", + "name": "票", + "font_class": "piao", + "unicode": "e83f", + "unicode_decimal": 59455 + }, + { + "icon_id": "848275", + "name": "勾", + "font_class": "gou", + "unicode": "e63d", + "unicode_decimal": 58941 + }, + { + "icon_id": "40248532", + "name": "分享", + "font_class": "fenxiang", + "unicode": "e83e", + "unicode_decimal": 59454 + }, + { + "icon_id": "40216674", + "name": "浏览量", + "font_class": "liulanliang", + "unicode": "e83c", + "unicode_decimal": 59452 + }, + { + "icon_id": "40216675", + "name": "日历", + "font_class": "rili", + "unicode": "e83d", + "unicode_decimal": 59453 + }, + { + "icon_id": "40191312", + "name": "左", + "font_class": "zuo", + "unicode": "e83b", + "unicode_decimal": 59451 + }, + { + "icon_id": "40191242", + "name": "下", + "font_class": "xia", + "unicode": "e83a", + "unicode_decimal": 59450 + }, + { + "icon_id": "40191226", + "name": "定位", + "font_class": "dingwei", + "unicode": "e82d", + "unicode_decimal": 59437 + }, + { + "icon_id": "40191227", + "name": "关闭", + "font_class": "guanbi", + "unicode": "e82e", + "unicode_decimal": 59438 + }, + { + "icon_id": "40191228", + "name": "收藏", + "font_class": "shoucang", + "unicode": "e82f", + "unicode_decimal": 59439 + }, + { + "icon_id": "40191229", + "name": "时间", + "font_class": "shijian", + "unicode": "e830", + "unicode_decimal": 59440 + }, + { + "icon_id": "40191230", + "name": "场馆", + "font_class": "changguan", + "unicode": "e831", + "unicode_decimal": 59441 + }, + { + "icon_id": "40191231", + "name": "未选中", + "font_class": "weixuanzhong", + "unicode": "e832", + "unicode_decimal": 59442 + }, + { + "icon_id": "40191232", + "name": "选择", + "font_class": "xuanze", + "unicode": "e833", + "unicode_decimal": 59443 + }, + { + "icon_id": "40191233", + "name": "选择-fill", + "font_class": "xuanze-fill", + "unicode": "e834", + "unicode_decimal": 59444 + }, + { + "icon_id": "40191234", + "name": "选中", + "font_class": "xuanzhong", + "unicode": "e835", + "unicode_decimal": 59445 + }, + { + "icon_id": "40191236", + "name": "微信支付", + "font_class": "weixinzhifu", + "unicode": "e836", + "unicode_decimal": 59446 + }, + { + "icon_id": "40191237", + "name": "右", + "font_class": "you", + "unicode": "e837", + "unicode_decimal": 59447 + }, + { + "icon_id": "40191238", + "name": "联系我们", + "font_class": "lianxiwomen", + "unicode": "e838", + "unicode_decimal": 59448 + }, + { + "icon_id": "40191239", + "name": "余额", + "font_class": "yue", + "unicode": "e839", + "unicode_decimal": 59449 + } + ] +} diff --git a/src/assets/iconfont/iconfont.svg b/src/assets/iconfont/iconfont.svg new file mode 100644 index 0000000..ab06c11 --- /dev/null +++ b/src/assets/iconfont/iconfont.svg @@ -0,0 +1,125 @@ + + + + Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/iconfont/iconfont.ttf b/src/assets/iconfont/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..857fa5d5a2a05caff50d88b7b3747c7ff695a631 GIT binary patch literal 15960 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 L`P1{`I?MbYoVM68 literal 0 HcmV?d00001 diff --git a/src/assets/iconfont/iconfont.woff b/src/assets/iconfont/iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..ce4c85cfbe0ba1cf4fc6fb37ada835a718dee9d1 GIT binary patch literal 9508 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 literal 0 HcmV?d00001 diff --git a/src/assets/iconfont/iconfont.woff2 b/src/assets/iconfont/iconfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..16c7b71b68e257ab921ca7d1b5a88f9669d9ad14 GIT binary patch literal 8084 zcmV;FA8X)uPew8T0RR9103Vb93jhEB06tg%03SvG0RR9100000000000000000000 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 literal 0 HcmV?d00001 diff --git a/src/assets/styles/index.less b/src/assets/styles/index.less index b5a78cc..05c6e52 100644 --- a/src/assets/styles/index.less +++ b/src/assets/styles/index.less @@ -55,3 +55,13 @@ a { ::-webkit-scrollbar-track { background: transparent; } + +.match-ellipsis-single { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.ant-layout .ant-layout-header { + padding-inline: 15px; +} diff --git a/src/hooks/useBasicLayout.ts b/src/hooks/useBasicLayout.ts index f0b511d..868035a 100644 --- a/src/hooks/useBasicLayout.ts +++ b/src/hooks/useBasicLayout.ts @@ -1,46 +1,99 @@ -import { h } from 'vue'; import { useRouter, useRoute } from 'vue-router'; -import { TrophyOutlined, WalletOutlined } from '@ant-design/icons-vue'; +import { routes } from '@/router/routes'; +import { generateMenu, type MenuItem } from '@/router/utils'; import { useBreadcrumb } from './useBreadcrumb'; +/** + * 基础布局管理 Hook + * + * @description + * 管理页面布局的核心逻辑。菜单、面包屑均由「路由表」派生,路由是唯一数据源: + * - 侧边栏菜单:generateMenu 根据路由的 meta.title / meta.icon 生成; + * - 菜单高亮 / 展开:根据当前路由匹配; + * - 面包屑:见 useBreadcrumb,取自 route.matched。 + */ export function useBasicLayout() { + // 路由实例,用于页面跳转 const router = useRouter(); + // 当前路由信息 const route = useRoute(); + // 获取面包屑数据 const { breadcrumbItems } = useBreadcrumb(); - const menuItems = [ - { - key: '/events', - icon: h(TrophyOutlined), - label: '我的赛事', - }, - // { TODO 本期先做隐藏 - // key: '/wallet', - // icon: h(WalletOutlined), - // label: '钱包管理', - // }, - ]; + /** + * 侧边栏菜单配置 + * 由主布局("/")的子路由生成,不再手写维护 + */ + const layoutChildren = routes.find((r) => r.path === '/' && r.children?.length)?.children ?? []; + const menuItems = generateMenu(layoutChildren); + /** + * 收集所有叶子菜单(可点击、可高亮的具体菜单项)的 key + * 父级 submenu 不参与 selected 高亮,只有叶子项才精确匹配当前路由 + */ + const leafMenuKeys = new Set(); + const collectLeafKeys = (items: MenuItem[]) => { + items.forEach((item) => { + if (item.children?.length) { + collectLeafKeys(item.children); + } else { + leafMenuKeys.add(item.key); + } + }); + }; + collectLeafKeys(menuItems); + + /** + * 获取当前激活的菜单 key(侧边栏高亮项) + * + * 优先级: + * 1. 当前路径命中某个叶子菜单 -> 高亮该菜单项 + * 2. 路由 meta.activeMenu 配置(详情页等路径不等于菜单 key 的场景) + * 3. 默认返回当前路由路径 + */ const getActiveMenuKey = () => { - const matchedRoutes = route.matched; - for (const r of matchedRoutes) { + if (leafMenuKeys.has(route.path)) { + return route.path; + } + for (const r of route.matched) { if (r.meta?.activeMenu) { return r.meta.activeMenu as string; } } - if (route.path.startsWith('/events')) return '/events'; - if (route.path.startsWith('/wallet')) return '/wallet'; return route.path; }; - const handleMenuClick = (info: any) => { + /** + * 获取需要展开的子菜单 keys + * 根据当前路径匹配所有「含子菜单且为当前路径祖先」的父级菜单 + */ + const getOpenKeys = () => { + return menuItems + .filter( + (item) => + item.children?.length && + (route.path === item.key || route.path.startsWith(`${item.key}/`)), + ) + .map((item) => item.key); + }; + + /** + * 菜单点击处理:跳转到对应路由 + */ + const handleMenuClick = (info: { key: string | number }) => { router.push(String(info.key)); }; return { + // 面包屑数据 breadcrumbItems, + // 菜单配置(由路由生成) menuItems, + // 获取激活菜单 key getActiveMenuKey, + // 获取展开菜单 keys + getOpenKeys, + // 菜单点击处理 handleMenuClick, }; } diff --git a/src/hooks/useBreadcrumb.ts b/src/hooks/useBreadcrumb.ts index ae55850..db5bd21 100644 --- a/src/hooks/useBreadcrumb.ts +++ b/src/hooks/useBreadcrumb.ts @@ -1,28 +1,39 @@ import { computed, h } from 'vue'; import { useRoute, useRouter } from 'vue-router'; +/** + * 面包屑管理 Hook + * + * @description + * 面包屑完全由当前路由派生:遍历 route.matched(命中的路由链,从父到子), + * 取每一层 meta.title 作为面包屑标题。层级关系写在路由表里(分组路由 + 子路由), + * 不再维护额外的菜单/映射表。 + * + * @returns breadcrumbs - 原始面包屑数据 + * @returns breadcrumbItems - 处理后的面包屑项(非末项渲染为可点击链接) + */ export function useBreadcrumb() { const route = useRoute(); const router = useRouter(); /** - * 根据当前路径和记录路径,计算拼接后的路径 + * 根据父级已拼接路径与当前路由记录的 path,计算该层的完整跳转路径 + * 兼容子路由使用相对路径或绝对路径两种写法 */ - const buildPath = (currentPath: string, recordPath: string): string => { + const buildPath = (parentPath: string, recordPath: string): string => { if (recordPath.startsWith('/')) { return recordPath; } - return currentPath ? `${currentPath}/${recordPath}`.replace(/\/+/g, '/') : `/${recordPath}`; + return `${parentPath}/${recordPath}`.replace(/\/+/g, '/'); }; const breadcrumbs = computed(() => { - const matched = route.matched; - const items: Array<{ title: string; path?: string }> = []; + const items: Array<{ title: string; path: string }> = []; let currentPath = ''; - for (const record of matched) { + for (const record of route.matched) { currentPath = buildPath(currentPath, record.path); - if (record.meta && record.meta.title) { + if (record.meta?.title) { items.push({ title: record.meta.title as string, path: currentPath, @@ -38,25 +49,19 @@ export function useBreadcrumb() { key: index, title: item.path && index !== breadcrumbs.value.length - 1 - ? h( + ? // 非末项:渲染为可点击链接 + h( 'a', { onClick: (e: Event) => { e.preventDefault(); - // 最保守方案:只有当前路径包含 /bracket/ 且目标路径是 /events/bracket 时才保留 query - // 也就是只有:/events/bracket/xxx → /events/bracket 时才保留 - const targetPath = item.path || '/'; - const isBracketChildPage = - route.path.includes('/bracket/') && targetPath === '/events/bracket'; - router.push({ - path: targetPath, - query: isBracketChildPage ? route.query : {}, - }); + router.push(item.path); }, }, item.title, ) - : item.title, + : // 末项:仅显示文本,表示当前所在位置 + item.title, })); }); diff --git a/src/layouts/BasicLayout.module.less b/src/layouts/BasicLayout.module.less index a3fc109..85d7741 100644 --- a/src/layouts/BasicLayout.module.less +++ b/src/layouts/BasicLayout.module.less @@ -1,57 +1,200 @@ .container { min-height: 100vh; + background: #f0f2f5; } .sider { - box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08); + background: #fff !important; + box-shadow: 2px 0 8px rgba(0, 0, 0, 0.06); + + :deep(.ant-menu) { + background: #fff; + border-right: 1px solid #f0f0f0; + } + + :deep(.ant-menu-item) { + margin: 0; + border-radius: 0; + color: #595959; + + &:hover { + background: #e6f7ff; + color: #1890ff; + } + } + + :deep(.ant-menu-item-selected) { + position: relative; + background: linear-gradient(90deg, #e6f7ff 0%, #bae7ff 100%) !important; + color: #1890ff !important; + font-weight: 500; + + // 左侧高亮指示条,标识当前选中的菜单项 + &::before { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 3px; + background: #1890ff; + } + } + + :deep(.ant-menu-submenu-title) { + margin: 0; + color: #595959; + + &:hover { + color: #1890ff; + } + } + + :deep(.ant-menu-submenu-selected > .ant-menu-submenu-title) { + color: #1890ff !important; + } } .logo { - height: 56px; + height: 64px; display: flex; align-items: center; - justify-content: center; + padding: 0 24px; overflow: hidden; - color: #fff; - background: rgba(255, 255, 255, 0.08); + color: #262626; + background: #fff; + border-bottom: 1px solid #f0f0f0; + gap: 12px; +} + +.logoIcon { + width: 32px; + height: 32px; + background: linear-gradient(135deg, #1890ff 0%, #722ed1 100%); + border-radius: 8px; + flex-shrink: 0; } .logoText { - font-size: 16px; + font-size: 18px; font-weight: 600; white-space: nowrap; + color: #262626; } .header { - background: #fff; - padding: 0 16px; + background: #ffffff !important; + padding: 0 24px; + display: flex; + align-items: center; + justify-content: space-between; + height: 64px; + border-bottom: 1px solid #f0f0f0; + + :deep(.ant-layout-header) { + background: #ffffff !important; + } +} + +.headerLeft { + display: flex; + align-items: center; + gap: 12px; +} + +.headerRight { display: flex; align-items: center; - box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); } .trigger { font-size: 18px; cursor: pointer; transition: color 0.3s; - padding: 0 12px; + padding: 8px; display: inline-flex; align-items: center; + color: #595959; + border-radius: 4px; &:hover { - color: #1677ff; + color: #1890ff; + background: #f5f5f5; } } -.content { - margin: 16px; - padding: 24px; - background: #fff; - border-radius: 8px; - min-height: 280px; +.refreshIcon { + font-size: 16px; + cursor: pointer; + padding: 8px; + display: inline-flex; + align-items: center; + color: #595959; + border-radius: 4px; + + &:hover { + color: #1890ff; + background: #f5f5f5; + } } -.footer { - text-align: center; - color: rgba(0, 0, 0, 0.45); +.breadcrumb { + margin-left: 12px; + color: #8c8c8c; + + :deep(.ant-breadcrumb-link) { + color: #8c8c8c; + + &:hover { + color: #1890ff; + } + } + + :deep(.ant-breadcrumb-last) { + color: #262626; + } +} + +.headerIcon { + font-size: 16px; + cursor: pointer; + color: #595959; + padding: 8px; + border-radius: 4px; + transition: all 0.3s; + + &:hover { + color: #1890ff; + background: #f5f5f5; + } +} + +.userInfo { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + padding: 6px 12px; + border-radius: 4px; + transition: background 0.3s; + + // &:hover { + // background: #f5f5f5; + // } +} + +.userName { + color: #262626; + font-size: 14px; +} + +.content { + margin: 0; + background: #f0f2f5; + min-height: calc(100vh - 64px); + overflow: auto; +} + +.pageContent { + padding: 15px; } diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index f01ba2a..211e2b3 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -1,69 +1,171 @@ import { computed, defineComponent, ref } from 'vue'; -import { useRouter, useRoute, RouterView } from 'vue-router'; -import { Layout, Menu } from 'ant-design-vue'; -import type { MenuProps } from 'ant-design-vue'; +import { Layout, Menu, Breadcrumb, Modal, Avatar, Space } from 'ant-design-vue'; +import { RouterView, useRouter } from 'vue-router'; import { - DashboardOutlined, - InfoCircleOutlined, MenuFoldOutlined, MenuUnfoldOutlined, + ReloadOutlined, + SearchOutlined, + BellOutlined, + FullscreenOutlined, + UserOutlined, } from '@ant-design/icons-vue'; +import { useBasicLayout } from '../hooks/useBasicLayout'; +import { auth } from '@/hooks/useAuth'; import styles from './BasicLayout.module.less'; -const { Header, Sider, Content, Footer } = Layout; +// 解构 Layout 组件 +const { Header, Sider, Content } = Layout; /** - * 基础布局:左侧导航 + 顶部栏 + 内容区 + 页脚 + * 基础布局组件 + * + * @description + * CPMS 运营平台的主布局结构,包含: + * - 左侧侧边栏:Logo + 导航菜单 + * - 顶部 Header:菜单折叠按钮 + 面包屑 + 用户信息 + * - 内容区域:路由视图渲染区域 + * + * @example + * ```typescript + * // 在路由中使用 + * { + * path: '/', + * component: BasicLayout, + * children: [...] + * } + * ``` */ export default defineComponent({ name: 'BasicLayout', setup() { - const route = useRoute(); + // 使用布局 Hook 获取菜单和面包屑数据 + const { breadcrumbItems, menuItems, getActiveMenuKey, getOpenKeys, handleMenuClick } = + useBasicLayout(); + + // 路由实例,用于退出登录后跳转到登录页 const router = useRouter(); + + /** + * 侧边栏折叠状态 + * true: 折叠状态(只显示图标) + * false: 展开状态(显示图标+文字) + */ const collapsed = ref(false); - const selectedKeys = computed(() => [route.path]); - - const menuItems: MenuProps['items'] = [ - { key: '/dashboard', icon: () => , label: '工作台' }, - { key: '/about', icon: () => , label: '关于' }, - ]; - - const handleMenuClick: MenuProps['onClick'] = ({ key }) => { - router.push(key as string); - }; - + /** + * 切换侧边栏折叠/展开状态 + */ const toggleCollapsed = () => { collapsed.value = !collapsed.value; }; + /** + * 退出登录:二次确认后跳转到登录页(不调用接口) + * - 点击用户名弹出确认弹框 + * - 确定 -> 跳转登录页 + * - 取消 -> 关闭弹框,不做任何处理 + */ + const handleLogout = () => { + Modal.confirm({ + title: '确认退出', + content: '确定要退出当前账号吗?', + okText: '确定', + cancelText: '取消', + onOk: () => { + // 清除本地登录态(不调用接口),否则路由守卫会把 /login 重定向回首页 + auth.logout(); + router.replace('/login'); + }, + }); + }; + return () => ( - + {/* 左侧侧边栏 */} + + {/* Logo 区域 */}
- {collapsed.value ? 'CPMS' : 'CPMS 运营平台'} +
+ {collapsed.value ? 'CPMS' : 'CPMS运营平台'}
+ + {/* 导航菜单 */} + {/* 右侧内容区域 */} -
- - {collapsed.value ? : } - + {/* 顶部 Header */} +
+
+ {/* 折叠/展开按钮 */} + + {collapsed.value ? : } + + + {/* 刷新按钮 */} + {/* + + */} + + {/* 面包屑导航 */} + {breadcrumbItems.value.length > 0 && ( + + {breadcrumbItems.value.map((item) => ( + {item.title} + ))} + + )} +
+ + {/* Header 右侧:用户信息 */} +
+ + {/* 搜索图标 */} + {/* + + */} + + {/* 通知图标 */} + {/* + + */} + + {/* 全屏图标 */} + {/* + + */} + + {/* 用户信息:点击弹出退出登录确认 */} +
+ } /> + 用户名 +
+
+
+ {/* 内容区域 */} - +
+ {/* 路由视图:根据当前路由渲染对应页面 */} + +
- -
CPMS 运营平台 ©{new Date().getFullYear()}
); diff --git a/src/main.ts b/src/main.ts index 2ed0b1f..ec0c72d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,7 @@ import 'ant-design-vue/dist/reset.css'; import App from './App'; import router from './router'; import './assets/styles/index.less'; +import './assets/iconfont/iconfont.css'; const app = createApp(App); diff --git a/src/router/index.ts b/src/router/index.ts index ae9e49e..1596db4 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,9 +1,9 @@ -import { createRouter, createWebHistory } from 'vue-router'; +import { createRouter, createWebHashHistory } from 'vue-router'; import { routes } from './routes'; import { auth } from '@/hooks/useAuth'; const router = createRouter({ - history: createWebHistory(import.meta.env.VITE_BASE_URL || '/'), + history: createWebHashHistory(import.meta.env.VITE_BASE_URL || '/'), routes, scrollBehavior: () => ({ left: 0, top: 0 }), }); diff --git a/src/router/routes.ts b/src/router/routes.ts index af168c7..cbf8ae8 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -1,40 +1,23 @@ import type { RouteRecordRaw } from 'vue-router'; +import { + BarChartOutlined, + UserOutlined, + StarOutlined, + FileTextOutlined, + NotificationOutlined, + BorderTopOutlined, + BoxPlotOutlined, + SafetyCertificateOutlined, +} from '@ant-design/icons-vue'; import { createRoute } from './utils'; -/** - * ====== 业务路由模块 ====== - * 实际项目中按模块拆分,如 eventsRoutes、walletRoutes 等, - * 然后在下方 routes 数组的布局 children 中引入。 - * 参考示例(嵌套路由): - * - * const eventsRoutes = { - * path: '/events', - * name: 'EventsModule', - * redirect: '/events/list', - * meta: { title: '我的赛事', activeMenu: '/events' }, - * children: [ - * createRoute('list', () => import('@/pages/events/list'), { title: '赛事列表' }), - * { - * path: 'bracket', - * name: 'BracketPage', - * component: () => import('@/pages/events/bracket'), - * meta: { title: '赛事详情' }, - * children: [ - * createRoute('player-management', () => import('@/pages/events/bracket/player-management'), { title: '选手管理' }), - * createRoute('match-result', () => import('@/pages/events/bracket/match-result'), { title: '比赛结果' }), - * ], - * }, - * ], - * }; - */ - export const routes: RouteRecordRaw[] = [ // ── 登录页(不经过布局)── { path: '/login', name: 'Login', component: () => import('@/pages/login'), - meta: { title: '登录' }, + meta: { title: '登录', hideInMenu: true }, }, // ── 主布局(需要登录)── @@ -42,17 +25,149 @@ export const routes: RouteRecordRaw[] = [ path: '/', component: () => import('@/layouts/BasicLayout'), children: [ - // 业务模块路由在此添加,例如:eventsRoutes, walletRoutes - + // 数据分析 createRoute('/dashboard', () => import('@/views/Dashboard'), { - title: '工作台', - icon: 'DashboardOutlined', + title: '数据分析', + icon: BarChartOutlined, }), + + // 场馆列表(分组) + { + path: '/venue', + name: 'Venue', + redirect: '/venue/list', + meta: { + title: '场馆列表', + icon: 'icon-changguan1', + activeMenu: '/venue', + }, + children: [ + createRoute('/venue/list', () => import('@/views/venue/list'), { + title: '馆客多', + }), + createRoute('/venue/records', () => import('@/views/venue/records'), { + title: '收录', + }), + ], + }, + + // C端用户列表 + createRoute('/users', () => import('@/views/Dashboard'), { + title: 'C端用户列表', + icon: UserOutlined, + }), + // 点评管理 + createRoute('/reviews', () => import('@/views/Dashboard'), { + title: '点评管理', + icon: StarOutlined, + }), + // 广告位管理 + createRoute('/ads', () => import('@/views/Dashboard'), { + title: '广告位管理', + icon: NotificationOutlined, + }), + // 资讯管理 + createRoute('/news', () => import('@/views/Dashboard'), { + title: '资讯管理', + icon: FileTextOutlined, + }), + // 申请入驻管理 + createRoute('/apply', () => import('@/views/Dashboard'), { + title: '申请入驻管理', + icon: UserOutlined, + }), + // 反馈管理 + createRoute('/feedback', () => import('@/views/Dashboard'), { + title: '反馈管理', + icon: BoxPlotOutlined, + }), + + // 活动管理(分组) + { + path: '/activity', + name: 'Activity', + redirect: '/activity/list', + meta: { title: '活动管理', icon: 'icon-rili', activeMenu: '/activity' }, + children: [ + createRoute('/activity/list', () => import('@/views/Dashboard'), { + title: '活动列表', + }), + createRoute('/activity/categories', () => import('@/views/Dashboard'), { + title: '活动分类', + }), + ], + }, + + // 场馆设置(分组) + { + path: '/venue-settings', + name: 'VenueSettings', + redirect: '/venue-settings/basic', + meta: { + title: '场馆设置', + icon: BorderTopOutlined, + activeMenu: '/venue-settings', + }, + children: [ + createRoute('/venue-settings/basic', () => import('@/views/Dashboard'), { + title: '基本设置', + }), + createRoute('/venue-settings/service', () => import('@/views/Dashboard'), { + title: '服务设置', + }), + ], + }, + + // 钱包管理(分组) + { + path: '/wallet', + name: 'Wallet', + redirect: '/wallet/records', + meta: { title: '钱包管理', icon: 'icon-qianbao', activeMenu: '/wallet' }, + children: [ + createRoute('/wallet/records', () => import('@/views/Dashboard'), { + title: '交易记录', + }), + createRoute('/wallet/withdraw', () => import('@/views/Dashboard'), { + title: '提现管理', + }), + createRoute('/wallet/recharge', () => import('@/views/Dashboard'), { + title: '充值管理', + }), + ], + }, + + // 系统管理(分组) + { + path: '/system', + name: 'System', + redirect: '/system/users', + meta: { + title: '系统管理', + icon: SafetyCertificateOutlined, + activeMenu: '/system', + }, + children: [ + createRoute('/system/users', () => import('@/views/Dashboard'), { + title: '用户管理', + }), + createRoute('/system/roles', () => import('@/views/Dashboard'), { + title: '角色管理', + }), + createRoute('/system/permissions', () => import('@/views/Dashboard'), { + title: '权限管理', + }), + createRoute('/system/logs', () => import('@/views/Dashboard'), { + title: '操作日志', + }), + ], + }, + + // 关于(不在侧边栏显示) createRoute('/about', () => import('@/views/About'), { title: '关于', - icon: 'InfoCircleOutlined', + hideInMenu: true, }), - // 默认重定向 { path: '/', redirect: '/dashboard' }, ], diff --git a/src/router/utils.ts b/src/router/utils.ts index 03dc5a2..e008d07 100644 --- a/src/router/utils.ts +++ b/src/router/utils.ts @@ -1,20 +1,25 @@ +import { h, type Component, type VNode } from 'vue'; import type { RouteRecordRaw } from 'vue-router'; /** 路由 meta 类型 */ export type AppMeta = { + /** 页面 / 菜单标题,同时用于面包屑 */ title: string; - icon?: string; + /** + * 菜单图标(仅一级菜单需要),支持两种写法: + * - iconfont 的 class 名,如 'icon-changguan1' + * - 组件,如 ant-design 图标 BarChartOutlined + */ + icon?: Component | string; + /** 是否在侧边栏菜单中隐藏(详情页等) */ hideInMenu?: boolean; + /** 高亮的菜单 key(路径不等于菜单 key 的场景,如详情页) */ activeMenu?: string; }; /** * 快速创建路由记录 * 根据路径自动生成 PascalCase 路由 name - * - * @example - * createRoute('list', () => import('@/pages/home'), { title: '赛事列表' }) - * // => { path: 'list', name: 'List', meta: {...}, component: ... } */ export function createRoute( path: string, @@ -38,3 +43,47 @@ export function createRoute( children, }; } + +/** 侧边栏菜单项(ant-design-vue Menu 的 items 结构) */ +export interface MenuItem { + key: string; + label: string; + icon?: VNode; + children?: MenuItem[]; +} + +/** + * 根据路由表生成侧边栏菜单 + * + * @description + * 菜单完全由路由派生,路由是「菜单 / 面包屑」唯一的数据源: + * - 仅收录带 meta.title 且未标记 hideInMenu 的路由; + * - 有子路由的生成子菜单(父级本身不跳转,点击展开); + * - 图标取自 meta.icon。 + * + * @param routes 需要遍历的路由数组(通常传入主布局的 children) + */ +export function generateMenu(routes: RouteRecordRaw[] = []): MenuItem[] { + const items: MenuItem[] = []; + + for (const route of routes) { + const meta = route.meta as AppMeta | undefined; + if (!meta?.title || meta.hideInMenu) { + continue; + } + + const children = generateMenu(route.children); + const item: MenuItem = { key: route.path, label: meta.title }; + if (meta.icon) { + // 字符串 -> iconfont 图标();组件 -> 直接渲染 + item.icon = + typeof meta.icon === 'string' ? h('i', { class: ['iconfont', meta.icon] }) : h(meta.icon); + } + if (children.length) { + item.children = children; + } + items.push(item); + } + + return items; +} diff --git a/src/types/index.ts b/src/types/index.ts index 9182e7d..cf58fa0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -27,7 +27,8 @@ export interface SelectOption { declare module 'vue-router' { interface RouteMeta { title?: string; - icon?: string; + /** 菜单图标:iconfont 的 class 名(字符串) 或 组件(如 antd 图标) */ + icon?: import('vue').Component | string; /** 是否需要登录 */ requiresAuth?: boolean; /** 是否在菜单中隐藏 */ diff --git a/src/views/Dashboard.module.less b/src/views/Dashboard.module.less deleted file mode 100644 index e816330..0000000 --- a/src/views/Dashboard.module.less +++ /dev/null @@ -1,27 +0,0 @@ -.container { - // 容器 -} - -.title { - margin-top: 0; - margin-bottom: 24px; - font-size: 20px; - font-weight: 600; -} - -.panel { - margin-top: 16px; - - ul { - margin: 12px 0 0; - padding-left: 20px; - line-height: 2; - } - - code { - padding: 2px 8px; - background: #f5f5f5; - border-radius: 4px; - font-size: 13px; - } -} diff --git a/src/views/Dashboard.tsx b/src/views/Dashboard.tsx deleted file mode 100644 index cf3c62a..0000000 --- a/src/views/Dashboard.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { defineComponent } from 'vue'; -import { Card, Col, Row, Statistic } from 'ant-design-vue'; -import styles from './Dashboard.module.less'; - -interface StatItem { - title: string; - value: number; - suffix: string; - precision?: number; -} - -/** - * 工作台 / 仪表盘 - */ -export default defineComponent({ - name: 'Dashboard', - setup() { - const stats: StatItem[] = [ - { title: '今日访问', value: 1280, suffix: '次' }, - { title: '活跃用户', value: 368, suffix: '人' }, - { title: '订单总数', value: 9920, suffix: '单' }, - { title: '处理率', value: 96.8, suffix: '%', precision: 1 }, - ]; - - return () => ( -
-

工作台

- - - {stats.map((item) => ( - - - - - - ))} - - - -

- 欢迎使用 CPMS 运营平台。这是一个基于 Vue 3 + Vite + TypeScript + Ant Design Vue - 搭建的中后台管理项目骨架,采用 TSX 写法,你可以在此基础上继续开发业务功能。 -

-
    -
  • - 开发命令:npm run dev -
  • -
  • - 构建(测试环境):npm run build:test -
  • -
  • - 构建(生产环境):npm run build:prod -
  • -
  • - 代码检查:npm run lint -
  • -
-
-
- ); - }, -}); diff --git a/src/views/Dashboard/components/AddVenueModal.tsx b/src/views/Dashboard/components/AddVenueModal.tsx new file mode 100644 index 0000000..abfc62b --- /dev/null +++ b/src/views/Dashboard/components/AddVenueModal.tsx @@ -0,0 +1,184 @@ +import { defineComponent, reactive, ref, watch } from 'vue'; +import { Modal, Form, Input, Select, message } from 'ant-design-vue'; +import type { Rule } from 'ant-design-vue/es/form'; +import { saveVenue, statusMap, type VenueSaveParams } from '../model'; + +interface AddVenueModalProps { + open: boolean; + onClose: () => void; + onSuccess?: () => void; +} + +/** + * 新增场馆弹框 + */ +export default defineComponent({ + name: 'AddVenueModal', + props: { + open: { + type: Boolean, + default: false, + }, + onClose: { + type: Function, + required: true, + }, + onSuccess: { + type: Function, + default: undefined, + }, + }, + setup(props: AddVenueModalProps) { + const labelCol = { span: 5 }; + const wrapperCol = { span: 18 }; + + // 表单实例 + const formRef = ref(); + // 提交中状态 + const submitting = ref(false); + + // 表单数据初始值 + const getInitialForm = (): VenueSaveParams => ({ + name: '', + type: '', + contact: '', + phone: '', + address: '', + status: 'active', + }); + const formState = reactive(getInitialForm()); + + // 校验规则 + const rules: Record = { + name: [{ required: true, message: '请输入场馆名称', trigger: 'blur' }], + type: [{ required: true, message: '请输入场馆类型', trigger: 'blur' }], + contact: [{ required: true, message: '请输入联系人', trigger: 'blur' }], + phone: [ + { required: true, message: '请输入联系电话', trigger: 'blur' }, + { + pattern: /^1[3-9]\d{9}$/, + message: '手机号格式不正确', + trigger: 'blur', + }, + ], + status: [{ required: true, message: '请选择状态', trigger: 'change' }], + }; + + // 打开时重置表单 + watch( + () => props.open, + (open) => { + if (open) { + Object.assign(formState, getInitialForm()); + formRef.value?.clearValidate?.(); + } + }, + ); + + /** 确定:校验 -> 提交 -> 成功回调 */ + const handleOk = async () => { + try { + await formRef.value?.validate(); + } catch { + // 校验不通过,直接返回 + return; + } + + submitting.value = true; + try { + await saveVenue({ ...formState }); + message.success('新增成功'); + props.onSuccess?.(); + props.onClose(); + } catch { + message.error('新增失败,请重试'); + } finally { + submitting.value = false; + } + }; + + return () => ( + props.onClose()} + > +
+ + { + formState.name = e.target.value; + }} + placeholder="请输入场馆名称" + /> + + + { + formState.type = e.target.value; + }} + placeholder="请输入场馆类型" + /> + + + { + formState.contact = e.target.value; + }} + placeholder="请输入联系人" + /> + + + { + formState.phone = e.target.value; + }} + placeholder="请输入联系电话" + /> + + + + + + { + formState.address = e.target.value; + }} + placeholder="请输入地址" + rows={3} + /> + +
+
+ ); + }, +}); diff --git a/src/views/Dashboard/index.module.less b/src/views/Dashboard/index.module.less new file mode 100644 index 0000000..2f71d60 --- /dev/null +++ b/src/views/Dashboard/index.module.less @@ -0,0 +1,86 @@ +.container { + display: flex; + flex-direction: column; + height: calc(100vh - 64px - 30px); +} + +.filterCard { + flex-shrink: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + margin-bottom: 16px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + padding: 20px 24px; + } +} + +.filterRow { + :global(.ant-form) { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + row-gap: 12px; + column-gap: 16px; + } + + :global(.ant-form-item) { + flex-shrink: 0; + margin-right: 0; + margin-bottom: 0; + } +} + +.tableCard { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + padding: 0; + } +} + +.tableBody { + flex: 1; + min-height: 0; + overflow: auto; +} + +.tableHeader { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 24px; + border-bottom: 1px solid #f0f0f0; +} + +.tableFooter { + flex-shrink: 0; + padding: 16px 24px; + border-top: 1px solid #f0f0f0; + display: flex; + justify-content: flex-end; +} + +.pagination { + display: flex; + align-items: center; + gap: 16px; +} + +.paginationText { + color: #595959; + font-size: 14px; +} diff --git a/src/views/Dashboard/index.tsx b/src/views/Dashboard/index.tsx new file mode 100644 index 0000000..b8ab966 --- /dev/null +++ b/src/views/Dashboard/index.tsx @@ -0,0 +1,247 @@ +import { defineComponent } from 'vue'; +import { + Card, + Table, + Input, + Select, + Button, + Space, + Tag, + Popconfirm, + Tooltip, + Pagination, + Form, +} from 'ant-design-vue'; +import { + SearchOutlined, + EditOutlined, + DeleteOutlined, + PlusOutlined, + EyeOutlined, +} from '@ant-design/icons-vue'; +import { useDashboardModel, type VenueItem } from './model'; +import AddVenueModal from './components/AddVenueModal'; +import styles from './index.module.less'; + +/** + * 数据分析 / 场馆列表 + */ +export default defineComponent({ + name: 'Dashboard', + setup() { + const { + tableData, + currentPage, + formRef, + formState, + statusMap, + addModalOpen, + openAddModal, + closeAddModal, + handleReset, + fetchVenueList, + } = useDashboardModel(); + + const columns = [ + { + title: '序号', + dataIndex: 'id', + key: 'id', + width: 100, + }, + { + title: '场馆名称', + dataIndex: 'name', + key: 'name', + width: 150, + }, + { + title: '场馆类型', + dataIndex: 'type', + key: 'type', + width: 120, + }, + { + title: '联系人', + dataIndex: 'contact', + key: 'contact', + width: 120, + }, + { + title: '联系电话', + dataIndex: 'phone', + key: 'phone', + width: 140, + }, + { + title: '地址', + dataIndex: 'address', + key: 'address', + // 开启文本溢出省略 + 悬浮 tooltip + customRender: ({ record }: { record: VenueItem }) => ( + +
{record.address}
+
+ ), + }, + { + title: '状态', + dataIndex: 'status', + key: 'status', + width: 100, + customRender: ({ record }: { record: VenueItem }) => { + const status = statusMap[record.status] || { + color: 'default', + text: '未知', + }; + return {status.text}; + }, + }, + { + title: '', + key: 'avatar', + width: 80, + }, + { + title: '操作', + key: 'action', + width: 230, + fixed: 'right' as const, + customRender: () => ( + + + {/* */} + + + + + + ), + }, + ]; + + return () => ( +
+ +
+
+ + { + formState.name = e.target.value; + }} + placeholder="请输入场馆名称" + prefix={} + style={{ width: '200px' }} + /> + + + { + formState.status = val; + }} + placeholder="请选择状态" + style={{ width: '140px' }} + allowClear={false} + > + {Object.entries(statusMap).map(([value, { text }]) => ( + + {text} + + ))} + + + + { + formState.contact = e.target.value; + }} + placeholder="请输入联系人" + style={{ width: '150px' }} + /> + + + { + formState.phone = e.target.value; + }} + placeholder="请输入联系电话" + style={{ width: '150px' }} + /> + + + + + + + +
+
+
+ + +
+ {/* 场馆列表 */} + +
+
+ + + +
+ { + currentPage.value = page; + }} + total={500} + showSizeChanger + showQuickJumper + showTotal={(total: number) => `共 ${total} 条`} + /> +
+ + + {/* 新增场馆弹框 */} + + + ); + }, +}); diff --git a/src/views/Dashboard/model/index.ts b/src/views/Dashboard/model/index.ts new file mode 100644 index 0000000..4d3b06d --- /dev/null +++ b/src/views/Dashboard/model/index.ts @@ -0,0 +1,2 @@ +export * from './useDashboardModel'; +export * from './services'; diff --git a/src/views/Dashboard/model/services.ts b/src/views/Dashboard/model/services.ts new file mode 100644 index 0000000..912f4ce --- /dev/null +++ b/src/views/Dashboard/model/services.ts @@ -0,0 +1,119 @@ +import { get, post } from '@/utils/request'; + +/** 场馆列表行数据 */ +export interface VenueItem { + key: string; + id: string; + name: string; + type: string; + contact: string; + status: string; + phone: string; + address: string; + createTime: string; +} + +/** 场馆状态映射:状态值 -> 颜色 / 文案 */ +export const statusMap: Record = { + active: { color: 'green', text: '正常' }, + inactive: { color: 'red', text: '停用' }, + pending: { color: 'orange', text: '待审' }, +}; + +/** 场馆列表查询参数 */ +export interface VenueListParams { + page: number; + size: number; + name?: string; + type?: string; + status?: string; + contact?: string; + phone?: string; +} + +const venueListApi = '/venue/page'; + +/** + * 场馆列表接口 + * @description 后端接口就绪后,在 useDashboardModel 中启用替换 mock 数据 + */ +export const getVenueList = (params: VenueListParams) => { + return get(venueListApi, params); +}; + +/** 新增场馆参数 */ +export interface VenueSaveParams { + name: string; + type: string; + contact: string; + phone: string; + address: string; + status: string; +} + +const venueSaveApi = '/venue/save'; + +/** 新增场馆接口 */ +export const saveVenue = (params: VenueSaveParams) => { + return post(venueSaveApi, params); +}; + +/** 临时 mock 数据(接口对接前占位展示) */ +export const mockVenueList: VenueItem[] = [ + { + key: '1', + id: 'V001', + name: '健身中心', + type: '健身馆', + contact: '张三', + status: 'active', + phone: '13999999999', + address: '北京市朝阳区xxx路xxx号', + createTime: '2024-01-15 10:30:00', + }, + { + key: '2', + id: 'V002', + name: '篮球公园', + type: '篮球馆', + contact: '李四', + status: 'active', + phone: '13999999999', + address: '上海市浦东新区xxx路xxx号', + createTime: '2024-01-16 14:20:00', + }, + { + key: '3', + id: 'V003', + name: '游泳馆', + type: '游泳馆', + contact: '王五', + status: 'inactive', + phone: '13999999999', + address: '广州市天河区xxx路xxx号', + createTime: '2024-01-17 09:15:00', + }, + { + key: '4', + id: 'V004', + name: '羽毛球馆', + type: '羽毛球馆', + contact: '马六', + status: 'active', + phone: '13999999999', + address: '深圳市南山区xxx路xxx号', + createTime: '2024-01-18 16:45:00', + }, + { + key: '5', + id: 'V005', + name: '网球中心', + type: '网球馆', + contact: '冯七', + status: 'pending', + phone: '13999999999', + address: + '杭州市西湖区xxx路xxx号杭州市西湖区xxx路xxx号杭州市西湖区xxx路xxx号杭州市西湖区xxx路xxx号11', + createTime: '2024-01-19 11:00:00', + }, +]; diff --git a/src/views/Dashboard/model/useDashboardModel.ts b/src/views/Dashboard/model/useDashboardModel.ts new file mode 100644 index 0000000..a032d5f --- /dev/null +++ b/src/views/Dashboard/model/useDashboardModel.ts @@ -0,0 +1,83 @@ +import { reactive, ref } from 'vue'; +import { getVenueList, mockVenueList, statusMap, type VenueItem } from './services'; + +/** 筛选表单字段 */ +export interface VenueFilterForm { + name: string; + type?: string; + status?: string; + contact: string; + phone: string; +} + +/** + * Dashboard(场馆列表)页面业务逻辑 + * + * @description + * 页面的状态、数据、事件处理都集中在这里,index.tsx 只负责渲染。 + */ +export function useDashboardModel() { + // 表格数据(暂用 mock,接口就绪后由 fetchVenueList 填充) + const tableData = ref(mockVenueList); + // 当前页码 + const currentPage = ref(1); + // 筛选表单实例 + const formRef = ref(); + // 筛选表单数据 + const formState = reactive({ + name: '', + type: undefined, + status: undefined, + contact: '', + phone: '', + }); + + // 新增场馆弹框显隐 + const addModalOpen = ref(false); + /** 打开新增弹框 */ + const openAddModal = () => { + addModalOpen.value = true; + }; + /** 关闭新增弹框 */ + const closeAddModal = () => { + addModalOpen.value = false; + }; + + /** 重置筛选表单 */ + const handleReset = () => { + formRef.value?.resetFields(); + Object.assign(formState, { + name: '', + type: undefined, + status: undefined, + contact: '', + phone: '', + }); + }; + + /** + * 查询场馆列表 + * @description 后端接口就绪后启用,替换默认的 mock 数据 + */ + const fetchVenueList = async () => { + const res: any = await getVenueList({ + page: currentPage.value, + size: 10, + ...formState, + }); + tableData.value = res?.data?.list ?? []; + }; + + return { + tableData, + currentPage, + formRef, + formState, + statusMap, + addModalOpen, + openAddModal, + closeAddModal, + handleReset, + fetchVenueList, + }; +} diff --git a/src/views/venue/list/index.module.less b/src/views/venue/list/index.module.less new file mode 100644 index 0000000..d8812ec --- /dev/null +++ b/src/views/venue/list/index.module.less @@ -0,0 +1,67 @@ +.container { + display: flex; + flex-direction: column; + height: calc(100vh - 64px - 30px); +} + +.filterCard { + flex-shrink: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + margin-bottom: 16px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + padding: 20px 24px; + } +} + +.filterRow { + :global(.ant-form) { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + row-gap: 12px; + column-gap: 16px; + } + + :global(.ant-form-item) { + flex-shrink: 0; + margin-right: 0; + margin-bottom: 0; + } +} + +.tableCard { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + padding: 0; + } +} + +.tableBody { + flex: 1; + min-height: 0; + overflow: auto; +} + +.tableFooter { + flex-shrink: 0; + padding: 16px 24px; + border-top: 1px solid #f0f0f0; + display: flex; + justify-content: flex-end; +} diff --git a/src/views/venue/list/index.tsx b/src/views/venue/list/index.tsx new file mode 100644 index 0000000..02a9fe2 --- /dev/null +++ b/src/views/venue/list/index.tsx @@ -0,0 +1,139 @@ +import { defineComponent } from 'vue'; +import { + Card, + Table, + Input, + Select, + Button, + Space, + Tag, + Popconfirm, + Pagination, + Form, +} from 'ant-design-vue'; +import { SearchOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons-vue'; +import { useVenueListModel, type VenueListItem } from './model'; +import styles from './index.module.less'; + +/** + * 馆客多 / 场馆列表 + */ +export default defineComponent({ + name: 'VenueList', + setup() { + const { tableData, currentPage, formRef, formState, statusMap, handleReset } = + useVenueListModel(); + + const columns = [ + { title: '序号', dataIndex: 'id', key: 'id', width: 100 }, + { title: '场馆名称', dataIndex: 'name', key: 'name', width: 160 }, + { title: '场馆类型', dataIndex: 'type', key: 'type', width: 140 }, + { title: '联系人', dataIndex: 'contact', key: 'contact', width: 120 }, + { title: '联系电话', dataIndex: 'phone', key: 'phone', width: 160 }, + { + title: '状态', + dataIndex: 'status', + key: 'status', + width: 100, + customRender: ({ record }: { record: VenueListItem }) => { + const status = statusMap[record.status] || { + color: 'default', + text: '未知', + }; + return {status.text}; + }, + }, + { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 180 }, + { + title: '操作', + key: 'action', + width: 230, + fixed: 'right' as const, + customRender: () => ( + + + + + + + + ), + }, + ]; + + return () => ( +
+ +
+
+ + { + formState.name = e.target.value; + }} + placeholder="请输入场馆名称" + prefix={} + style={{ width: '200px' }} + /> + + + + + + + + + + + +
+
+ + +
+
+ + +
+ { + currentPage.value = page; + }} + total={500} + showSizeChanger + showQuickJumper + showTotal={(total: number) => `共 ${total} 条`} + /> +
+ + + ); + }, +}); diff --git a/src/views/venue/list/model/index.ts b/src/views/venue/list/model/index.ts new file mode 100644 index 0000000..f523e80 --- /dev/null +++ b/src/views/venue/list/model/index.ts @@ -0,0 +1,2 @@ +export * from './useVenueListModel'; +export * from './services'; diff --git a/src/views/venue/list/model/services.ts b/src/views/venue/list/model/services.ts new file mode 100644 index 0000000..f14ad83 --- /dev/null +++ b/src/views/venue/list/model/services.ts @@ -0,0 +1,72 @@ +import { get } from '@/utils/request'; + +/** 场馆列表行数据 */ +export interface VenueListItem { + key: string; + id: string; + name: string; + type: string; + contact: string; + status: string; + phone: string; + createTime: string; +} + +/** 场馆状态映射:状态值 -> 颜色 / 文案 */ +export const statusMap: Record = { + active: { color: 'green', text: '正常' }, + inactive: { color: 'red', text: '停用' }, + pending: { color: 'orange', text: '待审' }, +}; + +/** 场馆列表查询参数 */ +export interface VenueListParams { + page: number; + size: number; + name?: string; + status?: string; +} + +const venueListApi = '/venue/list'; + +/** + * 馆客多-场馆列表接口 + * @description 后端接口就绪后,在 useVenueListModel 中启用替换 mock 数据 + */ +export const getVenueList = (params: VenueListParams) => { + return get(venueListApi, params); +}; + +/** 临时 mock 数据(接口对接前占位展示) */ +export const mockVenueList: VenueListItem[] = [ + { + key: '1', + id: 'V001', + name: '健身中心', + type: '健身馆', + contact: '张三', + status: 'active', + phone: '13999999999', + createTime: '2024-01-15 10:30:00', + }, + { + key: '2', + id: 'V002', + name: '篮球公园', + type: '篮球馆', + contact: '李四', + status: 'active', + phone: '13999999999', + createTime: '2024-01-16 14:20:00', + }, + { + key: '3', + id: 'V003', + name: '游泳馆', + type: '游泳馆', + contact: '王五', + status: 'inactive', + phone: '13999999999', + createTime: '2024-01-17 09:15:00', + }, +]; diff --git a/src/views/venue/list/model/useVenueListModel.ts b/src/views/venue/list/model/useVenueListModel.ts new file mode 100644 index 0000000..fc8ef63 --- /dev/null +++ b/src/views/venue/list/model/useVenueListModel.ts @@ -0,0 +1,54 @@ +import { reactive, ref } from 'vue'; +import { getVenueList, mockVenueList, statusMap, type VenueListItem } from './services'; + +/** 筛选表单字段 */ +export interface VenueListFilterForm { + name: string; + status?: string; +} + +/** + * 馆客多(场馆列表)页面业务逻辑 + */ +export function useVenueListModel() { + // 表格数据(暂用 mock,接口就绪后由 fetchList 填充) + const tableData = ref(mockVenueList); + // 当前页码 + const currentPage = ref(1); + // 筛选表单实例 + const formRef = ref(); + // 筛选表单数据 + const formState = reactive({ + name: '', + status: undefined, + }); + + /** 重置筛选表单 */ + const handleReset = () => { + formRef.value?.resetFields(); + Object.assign(formState, { name: '', status: undefined }); + }; + + /** + * 查询场馆列表 + * @description 后端接口就绪后启用,替换默认的 mock 数据 + */ + const fetchList = async () => { + const res: any = await getVenueList({ + page: currentPage.value, + size: 10, + ...formState, + }); + tableData.value = res?.data?.list ?? []; + }; + + return { + tableData, + currentPage, + formRef, + formState, + statusMap, + handleReset, + fetchList, + }; +} diff --git a/src/views/venue/records/index.module.less b/src/views/venue/records/index.module.less new file mode 100644 index 0000000..d8812ec --- /dev/null +++ b/src/views/venue/records/index.module.less @@ -0,0 +1,67 @@ +.container { + display: flex; + flex-direction: column; + height: calc(100vh - 64px - 30px); +} + +.filterCard { + flex-shrink: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + margin-bottom: 16px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + padding: 20px 24px; + } +} + +.filterRow { + :global(.ant-form) { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + row-gap: 12px; + column-gap: 16px; + } + + :global(.ant-form-item) { + flex-shrink: 0; + margin-right: 0; + margin-bottom: 0; + } +} + +.tableCard { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + background: #fff; + border: 1px solid #f0f0f0; + border-radius: 8px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); + + :global(.ant-card-body) { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + padding: 0; + } +} + +.tableBody { + flex: 1; + min-height: 0; + overflow: auto; +} + +.tableFooter { + flex-shrink: 0; + padding: 16px 24px; + border-top: 1px solid #f0f0f0; + display: flex; + justify-content: flex-end; +} diff --git a/src/views/venue/records/index.tsx b/src/views/venue/records/index.tsx new file mode 100644 index 0000000..56a291e --- /dev/null +++ b/src/views/venue/records/index.tsx @@ -0,0 +1,137 @@ +import { defineComponent } from 'vue'; +import { + Card, + Table, + Input, + Select, + Button, + Space, + Tag, + Popconfirm, + Pagination, + Form, +} from 'ant-design-vue'; +import { SearchOutlined, EyeOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue'; +import { useVenueRecordsModel, type VenueRecordItem } from './model'; +import styles from './index.module.less'; + +/** + * 收录 / 收录记录列表 + */ +export default defineComponent({ + name: 'VenueRecords', + setup() { + const { tableData, currentPage, formRef, formState, statusMap, handleReset } = + useVenueRecordsModel(); + + const columns = [ + { title: '序号', dataIndex: 'id', key: 'id', width: 100 }, + { title: '场馆名称', dataIndex: 'venueName', key: 'venueName', width: 180 }, + { title: '来源', dataIndex: 'source', key: 'source', width: 140 }, + { + title: '收录状态', + dataIndex: 'status', + key: 'status', + width: 120, + customRender: ({ record }: { record: VenueRecordItem }) => { + const status = statusMap[record.status] || { + color: 'default', + text: '未知', + }; + return {status.text}; + }, + }, + { title: '收录时间', dataIndex: 'recordTime', key: 'recordTime', width: 180 }, + { + title: '操作', + key: 'action', + width: 240, + fixed: 'right' as const, + customRender: () => ( + + + + + + + + ), + }, + ]; + + return () => ( +
+ +
+
+ + { + formState.venueName = e.target.value; + }} + placeholder="请输入场馆名称" + prefix={} + style={{ width: '200px' }} + /> + + + + + + + + + + + +
+
+ + +
+
+ + +
+ { + currentPage.value = page; + }} + total={500} + showSizeChanger + showQuickJumper + showTotal={(total: number) => `共 ${total} 条`} + /> +
+ + + ); + }, +}); diff --git a/src/views/venue/records/model/index.ts b/src/views/venue/records/model/index.ts new file mode 100644 index 0000000..7dd5fb0 --- /dev/null +++ b/src/views/venue/records/model/index.ts @@ -0,0 +1,2 @@ +export * from './useVenueRecordsModel'; +export * from './services'; diff --git a/src/views/venue/records/model/services.ts b/src/views/venue/records/model/services.ts new file mode 100644 index 0000000..08bbfab --- /dev/null +++ b/src/views/venue/records/model/services.ts @@ -0,0 +1,64 @@ +import { get } from '@/utils/request'; + +/** 收录记录行数据 */ +export interface VenueRecordItem { + key: string; + id: string; + venueName: string; + source: string; + status: string; + recordTime: string; +} + +/** 收录状态映射:状态值 -> 颜色 / 文案 */ +export const statusMap: Record = { + recorded: { color: 'green', text: '已收录' }, + reviewing: { color: 'orange', text: '审核中' }, + rejected: { color: 'red', text: '已驳回' }, +}; + +/** 收录记录查询参数 */ +export interface VenueRecordParams { + page: number; + size: number; + venueName?: string; + status?: string; +} + +const venueRecordApi = '/venue/records'; + +/** + * 收录记录接口 + * @description 后端接口就绪后,在 useVenueRecordsModel 中启用替换 mock 数据 + */ +export const getVenueRecords = (params: VenueRecordParams) => { + return get(venueRecordApi, params); +}; + +/** 临时 mock 数据(接口对接前占位展示) */ +export const mockVenueRecords: VenueRecordItem[] = [ + { + key: '1', + id: 'R001', + venueName: '健身中心', + source: '用户提交', + status: 'recorded', + recordTime: '2024-01-15 10:30:00', + }, + { + key: '2', + id: 'R002', + venueName: '篮球公园', + source: '平台采集', + status: 'reviewing', + recordTime: '2024-01-16 14:20:00', + }, + { + key: '3', + id: 'R003', + venueName: '游泳馆', + source: '用户提交', + status: 'rejected', + recordTime: '2024-01-17 09:15:00', + }, +]; diff --git a/src/views/venue/records/model/useVenueRecordsModel.ts b/src/views/venue/records/model/useVenueRecordsModel.ts new file mode 100644 index 0000000..b5b8b95 --- /dev/null +++ b/src/views/venue/records/model/useVenueRecordsModel.ts @@ -0,0 +1,54 @@ +import { reactive, ref } from 'vue'; +import { getVenueRecords, mockVenueRecords, statusMap, type VenueRecordItem } from './services'; + +/** 筛选表单字段 */ +export interface VenueRecordFilterForm { + venueName: string; + status?: string; +} + +/** + * 收录记录页面业务逻辑 + */ +export function useVenueRecordsModel() { + // 表格数据(暂用 mock,接口就绪后由 fetchList 填充) + const tableData = ref(mockVenueRecords); + // 当前页码 + const currentPage = ref(1); + // 筛选表单实例 + const formRef = ref(); + // 筛选表单数据 + const formState = reactive({ + venueName: '', + status: undefined, + }); + + /** 重置筛选表单 */ + const handleReset = () => { + formRef.value?.resetFields(); + Object.assign(formState, { venueName: '', status: undefined }); + }; + + /** + * 查询收录记录 + * @description 后端接口就绪后启用,替换默认的 mock 数据 + */ + const fetchList = async () => { + const res: any = await getVenueRecords({ + page: currentPage.value, + size: 10, + ...formState, + }); + tableData.value = res?.data?.list ?? []; + }; + + return { + tableData, + currentPage, + formRef, + formState, + statusMap, + handleReset, + fetchList, + }; +} diff --git a/vite.config.ts b/vite.config.ts index 21e6065..1dc21f3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -38,6 +38,7 @@ export default defineConfig(({ mode }) => { }, }, build: { + target: 'es2020', outDir: 'dist', sourcemap: mode !== 'production', chunkSizeWarningLimit: 1500, @@ -50,5 +51,10 @@ export default defineConfig(({ mode }) => { }, }, }, + optimizeDeps: { + esbuildOptions: { + target: 'es2020', + }, + }, }; });