release(custom): i
@@ -1,23 +1,26 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
types: [
|
types: [
|
||||||
{ value: 'feat', name:'feat: 新增功能' },
|
{ value: 'feat', name: 'feat: 新增功能' },
|
||||||
{ value: 'fix', name:'fix: 修复bug' },
|
{ value: 'fix', name: 'fix: 修复bug' },
|
||||||
{ value: 'docs', name:'docs: 文档变更' },
|
{ value: 'docs', name: 'docs: 文档变更' },
|
||||||
{ value: 'style', name:'style: 代码格式(不影响功能,例如空格、分号等格式修正)' },
|
{ value: 'style', name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)' },
|
||||||
{ value: 'refactor', name:'refactor: 代码重构(不包括 bug 修复、功能新增)' },
|
{ value: 'refactor', name: 'refactor: 代码重构(不包括 bug 修复、功能新增)' },
|
||||||
{ value: 'perf', name:'perf: 性能优化' },
|
{ value: 'perf', name: 'perf: 性能优化' },
|
||||||
{ value: 'test', name:'test: 添加、修改测试用例' },
|
{ value: 'test', name: 'test: 添加、修改测试用例' },
|
||||||
{ value: 'build', name:'build: 构建流程、外部依赖变更(如升级 npm 包、修改 脚手架 配置等)' },
|
{
|
||||||
{ value: 'ci', name:'ci: 修改 CI 配置、脚本' },
|
value: 'build',
|
||||||
{ value: 'chore', name:'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)' },
|
name: 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 脚手架 配置等)',
|
||||||
{ value: 'revert', name:'revert: 回滚 commit' },
|
},
|
||||||
{ value: 'wip', name:'wip: 开发中' },
|
{ value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
|
||||||
{ value: 'mod', name:'mod: 不确定分类的修改' },
|
{ value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)' },
|
||||||
{ value: 'release', name:'release: 发布' },
|
{ value: 'revert', name: 'revert: 回滚 commit' },
|
||||||
|
{ value: 'wip', name: 'wip: 开发中' },
|
||||||
|
{ value: 'mod', name: 'mod: 不确定分类的修改' },
|
||||||
|
{ value: 'release', name: 'release: 发布' },
|
||||||
],
|
],
|
||||||
scopes: [
|
scopes: [
|
||||||
['custom', '自定义'],
|
['custom', '自定义'],
|
||||||
['projects', '项目搭建'],
|
['projects', '项目搭建'],
|
||||||
['components', '组件相关'],
|
['components', '组件相关'],
|
||||||
['utils', 'utils 相关'],
|
['utils', 'utils 相关'],
|
||||||
['styles', '样式相关'],
|
['styles', '样式相关'],
|
||||||
@@ -26,7 +29,7 @@ module.exports = {
|
|||||||
].map(([value, description]) => {
|
].map(([value, description]) => {
|
||||||
return {
|
return {
|
||||||
value,
|
value,
|
||||||
name: `${value.padEnd(30)} (${description})`
|
name: `${value.padEnd(30)} (${description})`,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
messages: {
|
messages: {
|
||||||
@@ -37,9 +40,9 @@ module.exports = {
|
|||||||
body: '填写更加详细的变更描述(可选)。使用 "|" 换行:',
|
body: '填写更加详细的变更描述(可选)。使用 "|" 换行:',
|
||||||
breaking: '列举非兼容性重大的变更(可选):',
|
breaking: '列举非兼容性重大的变更(可选):',
|
||||||
footer: '列举出所有变更的 Issues Closed(可选)。 例如: #31, #34:',
|
footer: '列举出所有变更的 Issues Closed(可选)。 例如: #31, #34:',
|
||||||
confirmCommit: '确认提交?'
|
confirmCommit: '确认提交?',
|
||||||
},
|
},
|
||||||
allowBreakingChanges: ['feat', 'fix'],
|
allowBreakingChanges: ['feat', 'fix'],
|
||||||
subjectLimit: 100,
|
subjectLimit: 100,
|
||||||
breaklineChar: '|'
|
breaklineChar: '|',
|
||||||
}
|
}
|
||||||
|
|||||||
14
.env.test
@@ -1,7 +1,7 @@
|
|||||||
VITE_PUBLIC_PATH = '/'
|
VITE_PUBLIC_PATH = '/static/mer'
|
||||||
|
|
||||||
# 是否启用MOCK
|
# 是否启用MOCK
|
||||||
VITE_USE_MOCK = true
|
VITE_USE_MOCK = true
|
||||||
|
|
||||||
# base api
|
# base api
|
||||||
VITE_BASE_API = '/api'
|
VITE_BASE_API = 'https://test.wanzhuanyongcheng.cn/store'
|
||||||
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>
|
||||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<includedPredefinedLibrary name="Node.js Core" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/jsLinters/eslint.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EslintConfiguration">
|
||||||
|
<option name="fix-on-save" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/prettier.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PrettierConfiguration">
|
||||||
|
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.vscode/extensions.json
vendored
@@ -4,6 +4,6 @@
|
|||||||
"antfu.iconify",
|
"antfu.iconify",
|
||||||
"mikestead.dotenv",
|
"mikestead.dotenv",
|
||||||
"sdras.vue-vscode-snippets",
|
"sdras.vue-vscode-snippets",
|
||||||
"cipchk.cssrem",
|
"cipchk.cssrem"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Components from 'unplugin-vue-components/vite'
|
|||||||
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
|
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
|
||||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
|
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
|
||||||
import IconsResolver from 'unplugin-icons/resolver'
|
import IconsResolver from 'unplugin-icons/resolver'
|
||||||
|
import mkcert from 'vite-plugin-mkcert'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * unplugin-icons插件,自动引入iconify图标
|
* * unplugin-icons插件,自动引入iconify图标
|
||||||
@@ -43,4 +44,5 @@ export default [
|
|||||||
inject: 'body-last',
|
inject: 'body-last',
|
||||||
customDomId: '__CUSTOM_SVG_ICON__',
|
customDomId: '__CUSTOM_SVG_ICON__',
|
||||||
}),
|
}),
|
||||||
|
mkcert(),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
推荐阅读作者在掘金的文章:
|
推荐阅读作者在掘金的文章:
|
||||||
|
|
||||||
[保熟的UnoCSS使用指北,优雅使用antfu大佬的原子化CSS](https://juejin.cn/post/7142466784971456548)
|
[保熟的 UnoCSS 使用指北,优雅使用 antfu 大佬的原子化 CSS](https://juejin.cn/post/7142466784971456548)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
`<icon-[iconify图标名称]`
|
`<icon-[iconify图标名称]`
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<icon-ant-design:fullscreen-exit-outlined />
|
<icon-ant-design:fullscreen-exit-outlined />
|
||||||
<icon-ant-design:fullscreen-outlined />
|
<icon-ant-design:fullscreen-outlined />
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -37,4 +37,4 @@
|
|||||||
<TheIcon icon="logo" type="custom" />
|
<TheIcon icon="logo" type="custom" />
|
||||||
```
|
```
|
||||||
|
|
||||||
封装组件参看 src/components/icon
|
封装组件参看 src/components/icon
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## 安装pnpm
|
## 安装 pnpm
|
||||||
|
|
||||||
### 使用Corepack安装(推荐)
|
### 使用 Corepack 安装(推荐)
|
||||||
|
|
||||||
从 v16.13 开始,Node.js 发布了 Corepack 来管理包管理器。 这是一项实验性功能,需要通过运行如下脚本来启用它:
|
从 v16.13 开始,Node.js 发布了 Corepack 来管理包管理器。 这是一项实验性功能,需要通过运行如下脚本来启用它:
|
||||||
|
|
||||||
@@ -8,17 +8,19 @@
|
|||||||
npx corepack enable // 可能需要管理员权限
|
npx corepack enable // 可能需要管理员权限
|
||||||
```
|
```
|
||||||
|
|
||||||
这将自动在您的系统上安装 pnpm。 但是,它可能不是最新版本的 pnpm。 若要升级,请检查[最新的 pnpm 版本](https://github.com/pnpm/pnpm/releases/latest) 并运行,如 7.14.0
|
这将自动在您的系统上安装 pnpm。 但是,它可能不是最新版本的 pnpm。 若要升级,请检查[最新的 pnpm 版本](https://github.com/pnpm/pnpm/releases/latest) 并运行,如 7.14.0
|
||||||
|
|
||||||
```
|
```
|
||||||
corepack prepare pnpm@7.14.0 --activate
|
corepack prepare pnpm@7.14.0 --activate
|
||||||
```
|
```
|
||||||
|
|
||||||
如果是 Node.js v16.17 或者更新的版本,可以直接安装最新版本的 pnpm
|
如果是 Node.js v16.17 或者更新的版本,可以直接安装最新版本的 pnpm
|
||||||
|
|
||||||
```
|
```
|
||||||
corepack prepare pnpm@latest --activate
|
corepack prepare pnpm@latest --activate
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用npm安装
|
### 使用 npm 安装
|
||||||
|
|
||||||
```
|
```
|
||||||
npm i -g pnpm
|
npm i -g pnpm
|
||||||
@@ -29,4 +31,4 @@ npm i -g pnpm
|
|||||||
```
|
```
|
||||||
npm uninstall -g pnpm
|
npm uninstall -g pnpm
|
||||||
npm i -g pnpm
|
npm i -g pnpm
|
||||||
```
|
```
|
||||||
|
|||||||
34
package.json
@@ -11,7 +11,8 @@
|
|||||||
"lint:fix": "eslint --fix --ext .js,.vue .",
|
"lint:fix": "eslint --fix --ext .js,.vue .",
|
||||||
"lint:staged": "lint-staged",
|
"lint:staged": "lint-staged",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"lf": "npx prettier --write --end-of-line lf ."
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,vue}": [
|
"*.{js,vue}": [
|
||||||
@@ -31,28 +32,28 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@unocss/eslint-config": "^0.55.3",
|
"@unocss/eslint-config": "^0.55.7",
|
||||||
"@vueuse/core": "^10.4.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.5.0",
|
"axios": "^1.5.1",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.10",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"md-editor-v3": "^4.4.0",
|
"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-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.106",
|
"@iconify/json": "^2.2.126",
|
||||||
"@iconify/vue": "^4.1.1",
|
"@iconify/vue": "^4.1.1",
|
||||||
"@unocss/preset-rem-to-px": "^0.55.3",
|
"@unocss/preset-rem-to-px": "^0.55.7",
|
||||||
"@vitejs/plugin-vue": "^4.3.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",
|
||||||
@@ -64,15 +65,16 @@
|
|||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"lint-staged": "^14.0.1",
|
"lint-staged": "^14.0.1",
|
||||||
"naive-ui": "^2.34.4",
|
"naive-ui": "^2.35.0",
|
||||||
"rollup-plugin-visualizer": "^5.9.2",
|
"rollup-plugin-visualizer": "^5.9.2",
|
||||||
"sass": "^1.66.1",
|
"sass": "^1.69.0",
|
||||||
"unocss": "0.55.3",
|
"unocss": "0.55.3",
|
||||||
"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-mkcert": "^1.16.0",
|
||||||
"vite-plugin-mock": "2.9.6",
|
"vite-plugin-mock": "2.9.6",
|
||||||
"vite-plugin-svg-icons": "^2.0.1"
|
"vite-plugin-svg-icons": "^2.0.1"
|
||||||
}
|
}
|
||||||
|
|||||||
15687
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: 170 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 20 KiB |
@@ -3,4 +3,13 @@ import { request } from '@/utils'
|
|||||||
export default {
|
export default {
|
||||||
getUser: () => request.get('/user'),
|
getUser: () => request.get('/user'),
|
||||||
refreshToken: () => request.post('/auth/refreshToken', null, { noNeedTip: true }),
|
refreshToken: () => request.post('/auth/refreshToken', null, { noNeedTip: true }),
|
||||||
|
// 获取商家信息
|
||||||
|
getMerchantInfo: () => request.post('/info'),
|
||||||
|
// 上传图片
|
||||||
|
uploadImg: (data) =>
|
||||||
|
request.post('/upload', data, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 20 KiB |
@@ -21,7 +21,7 @@ import '@wangeditor/editor/dist/css/style.css' // 引入 css
|
|||||||
|
|
||||||
import { onBeforeUnmount, shallowRef, ref } from 'vue'
|
import { onBeforeUnmount, shallowRef, ref } from 'vue'
|
||||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||||
import { getToken } from '@/utils'
|
import api from '@/api'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
valueHtml: {
|
valueHtml: {
|
||||||
@@ -36,64 +36,40 @@ const editorRef = shallowRef()
|
|||||||
|
|
||||||
const _ref = ref(null)
|
const _ref = ref(null)
|
||||||
|
|
||||||
const Token = getToken()
|
|
||||||
|
|
||||||
const toolbarConfig = {}
|
const toolbarConfig = {}
|
||||||
|
|
||||||
const editorConfig = { placeholder: '请输入商品详情...', MENU_CONF: {} }
|
const editorConfig = { placeholder: '请输入商品详情...', MENU_CONF: {} }
|
||||||
|
|
||||||
const htmlValue = computed({
|
const htmlValue = computed({
|
||||||
get() {
|
get() {
|
||||||
console.log('get', props.valueHtml)
|
|
||||||
return props.valueHtml
|
return props.valueHtml
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
console.log('set', props.valueHtml)
|
|
||||||
emit('update:valueHtml', value)
|
emit('update:valueHtml', value)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
editorConfig.MENU_CONF['uploadImage'] = {
|
editorConfig.MENU_CONF['uploadImage'] = {
|
||||||
// 其他配置...
|
|
||||||
// 小于该值就插入 base64 格式(而不上传),默认为 0
|
|
||||||
fieldName: 'file',
|
|
||||||
server: '/store/upload',
|
|
||||||
allowedFileTypes: ['image/*'],
|
allowedFileTypes: ['image/*'],
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${Token}`,
|
|
||||||
},
|
|
||||||
base64LimitSize: 5 * 1024, // 5kb
|
base64LimitSize: 5 * 1024, // 5kb
|
||||||
// 超时时间,默认为 10 秒
|
// 超时时间,默认为 10 秒
|
||||||
timeout: 5 * 1000, // 5 秒
|
timeout: 5 * 1000, // 5 秒
|
||||||
// 自定义插入图片
|
|
||||||
customInsert(res, insertFn) {
|
async customUpload(file, insertFn) {
|
||||||
if (res.code === 200) {
|
await upFile(file, insertFn)
|
||||||
console.log(res)
|
|
||||||
$message.success('上传成功')
|
|
||||||
insertFn(res.data.data)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
editorConfig.MENU_CONF['uploadVideo'] = {
|
editorConfig.MENU_CONF['uploadVideo'] = {
|
||||||
server: '/store/upload',
|
|
||||||
fieldName: 'file',
|
|
||||||
allowedFileTypes: ['video/*'],
|
allowedFileTypes: ['video/*'],
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${Token}`,
|
|
||||||
},
|
|
||||||
// 单个文件上传成功之后
|
|
||||||
customInsert(res, insertFn) {
|
|
||||||
console.log(res)
|
|
||||||
|
|
||||||
// 如果成功了,就把视频的地址,插入到编辑器中
|
async customUpload(file, insertFn) {
|
||||||
insertFn(res.data.data)
|
await upFile(file, insertFn)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组件销毁时,也及时销毁编辑器
|
// 组件销毁时,也及时销毁编辑器
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
console.log('销毁')
|
|
||||||
const editor = editorRef.value
|
const editor = editorRef.value
|
||||||
if (editor == null) return
|
if (editor == null) return
|
||||||
editor.destroy()
|
editor.destroy()
|
||||||
@@ -105,6 +81,13 @@ const handleCreated = (editor) => {
|
|||||||
_ref.value.style.zIndex = 10
|
_ref.value.style.zIndex = 10
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const upFile = async (file, insertFn) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
const res = await api.uploadImg(formData)
|
||||||
|
insertFn(res.data.data)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-upload
|
<n-upload
|
||||||
v-model:file-list="List"
|
v-model:file-list="List"
|
||||||
action="/store/upload"
|
|
||||||
:headers="headers"
|
|
||||||
:max="max"
|
:max="max"
|
||||||
list-type="image-card"
|
list-type="image-card"
|
||||||
|
:custom-request="customRequest"
|
||||||
|
:multiple="multiple"
|
||||||
@before-upload="beforeUpload"
|
@before-upload="beforeUpload"
|
||||||
@finish="handleFinish"
|
|
||||||
@error="handleError"
|
@error="handleError"
|
||||||
>
|
>
|
||||||
点击上传
|
点击上传
|
||||||
@@ -14,9 +13,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { getToken } from '@/utils'
|
import api from '@/api'
|
||||||
|
|
||||||
const token = getToken()
|
|
||||||
|
|
||||||
const prop = defineProps({
|
const prop = defineProps({
|
||||||
list: {
|
list: {
|
||||||
@@ -27,14 +24,14 @@ const prop = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:list'])
|
const emit = defineEmits(['update:list'])
|
||||||
|
|
||||||
const headers = ref({
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
})
|
|
||||||
|
|
||||||
const List = computed({
|
const List = computed({
|
||||||
get() {
|
get() {
|
||||||
return prop.list
|
return prop.list
|
||||||
@@ -44,12 +41,6 @@ const List = computed({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleFinish = ({ file, event }) => {
|
|
||||||
const res = JSON.parse(event.target.response)
|
|
||||||
file.url = res.data.data
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleError = () => {
|
const handleError = () => {
|
||||||
$message.error('上传失败')
|
$message.error('上传失败')
|
||||||
}
|
}
|
||||||
@@ -62,6 +53,14 @@ const beforeUpload = (data) => {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customRequest = async ({ file, onFinish }) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file.file)
|
||||||
|
const res = await api.uploadImg(formData)
|
||||||
|
$message.success(res.msg)
|
||||||
|
onFinish(res.data.data)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ function handleMenuSelect(key, item) {
|
|||||||
left: 5px;
|
left: 5px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.n-menu-item-content--selected,
|
&.n-menu-item-content--selected,
|
||||||
&:hover {
|
&:hover {
|
||||||
&::before {
|
&::before {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ export function createPermissionGuard(router) {
|
|||||||
return { path: 'login', query: { ...to.query, redirect: to.path } }
|
return { path: 'login', query: { ...to.query, redirect: to.path } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 单点登录的情况 */
|
||||||
|
if (to.query.tk) return true
|
||||||
|
|
||||||
/** 有token的情况 */
|
/** 有token的情况 */
|
||||||
if (to.path === '/login') return { path: '/' }
|
if (to.path === '/login') return { path: '/' }
|
||||||
|
|
||||||
|
|||||||
@@ -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 || []
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { lStorage } from '@/utils'
|
import { lStorage } from '@/utils'
|
||||||
import api from '@/api'
|
|
||||||
|
|
||||||
const TOKEN_CODE = 'mer_token'
|
const TOKEN_CODE = 'mer_token'
|
||||||
const DURATION = 6 * 60 * 60
|
const DURATION = 6 * 60 * 60
|
||||||
@@ -17,17 +16,17 @@ export function removeToken() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function refreshAccessToken() {
|
export async function refreshAccessToken() {
|
||||||
const tokenItem = lStorage.getItem(TOKEN_CODE)
|
// const tokenItem = lStorage.getItem(TOKEN_CODE)
|
||||||
if (!tokenItem) {
|
// if (!tokenItem) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
const { time } = tokenItem
|
// const { time } = tokenItem
|
||||||
// token生成或者刷新后30分钟内不执行刷新
|
// // token生成或者刷新后30分钟内不执行刷新
|
||||||
if (new Date().getTime() - time <= 1000 * 60 * 30) return
|
// if (new Date().getTime() - time <= 1000 * 60 * 30) return
|
||||||
try {
|
// try {
|
||||||
const res = await api.refreshToken()
|
// const res = await api.refreshToken()
|
||||||
setToken(res.data.token)
|
// setToken(res.data.token)
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error(error)
|
// console.error(error)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,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)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { request } from '@/utils'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getGoodClass: (data) => request.post('/goods/class', data),
|
getGoodClass: (data) => request.post('/classify', data),
|
||||||
addGoods: (data) => request.post('/goods/edit', data),
|
addGoods: (data) => request.post('/goods/edit', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<Upload v-model:list="model.cover" />
|
<Upload v-model:list="model.cover" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="12" label="商品轮播图:" path="rotation">
|
<n-form-item-gi :span="12" label="商品轮播图:" path="rotation">
|
||||||
<Upload v-model:list="model.rotation" :max="5" />
|
<Upload v-model:list="model.rotation" :max="5" multiple />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="12" label="商品价格:" path="number">
|
<n-form-item-gi :span="12" label="商品价格:" path="number">
|
||||||
<n-input-number v-model:value="model.number" placeholder="输入商品价格" />
|
<n-input-number v-model:value="model.number" placeholder="输入商品价格" />
|
||||||
@@ -31,11 +31,12 @@
|
|||||||
<n-form-item-gi :span="12" label="商品库存:" path="stock">
|
<n-form-item-gi :span="12" label="商品库存:" path="stock">
|
||||||
<n-input-number v-model:value="model.stock" placeholder="输入商品库存" />
|
<n-input-number v-model:value="model.stock" placeholder="输入商品库存" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
|
|
||||||
<n-form-item-gi :span="12" label="商品简介:" path="profile">
|
<n-form-item-gi :span="12" label="商品简介:" path="profile">
|
||||||
<n-input v-model:value="model.profile" type="textarea" placeholder="输入商品简介" />
|
<n-input v-model:value="model.profile" type="textarea" placeholder="输入商品简介" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="12" label="上架状态:" path="state">
|
||||||
|
<n-switch v-model:value="model.state" :checked-value="1" :unchecked-value="2" />
|
||||||
|
</n-form-item-gi>
|
||||||
<n-form-item-gi :span="12" label="商品详情:" path="details">
|
<n-form-item-gi :span="12" label="商品详情:" path="details">
|
||||||
<Editor v-model:valueHtml="model.details" />
|
<Editor v-model:valueHtml="model.details" />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
@@ -67,6 +68,7 @@ const model = ref({
|
|||||||
stock: null,
|
stock: null,
|
||||||
number: null,
|
number: null,
|
||||||
market_num: null,
|
market_num: null,
|
||||||
|
state: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
|
|||||||
7
src/views/goods/class/api.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getGoodClass: (data) => request.post('/classify', data),
|
||||||
|
// 添加或修改
|
||||||
|
addGoodClass: (data) => request.post('/classify/edit', data),
|
||||||
|
}
|
||||||
171
src/views/goods/class/index.vue
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-button type="primary" @click="addClass(1)">添加商品分类</n-button>
|
||||||
|
<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="showModalTitle"
|
||||||
|
: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 label="商品分类:" :span="14" path="name">
|
||||||
|
<n-input v-model:value="model.name" placeholder="请输入商品分类" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi label="是否显示:" :span="14" path="status">
|
||||||
|
<n-switch v-model:value="model.status" :unchecked-value="2" :checked-value="1" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="14">
|
||||||
|
<div class="m-auto">
|
||||||
|
<n-button type="primary" @click="submit">提交</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.js'
|
||||||
|
import { NTag, NButton } from 'naive-ui'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const showModalTitle = ref('')
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
name: '',
|
||||||
|
status: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '分类名称',
|
||||||
|
key: 'name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否显示',
|
||||||
|
slot: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : 'warning',
|
||||||
|
bordered: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '显示' : '隐藏'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
size: 'small',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: () => {
|
||||||
|
addClass(2, row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '编辑',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入商品分类',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
get_data()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
get_data()
|
||||||
|
})
|
||||||
|
|
||||||
|
const get_data = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const res = await api.getGoodClass({
|
||||||
|
PageNum: pagination.value.page,
|
||||||
|
PageSize: pagination.value.pageSize,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const addClass = (e, row = {}) => {
|
||||||
|
showModalTitle.value = e === 1 ? '添加商品分类' : '编辑商品分类'
|
||||||
|
if (e === 2) model.value = { ...row }
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
const res = await api.addGoodClass(model.value)
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
formRef.value.restoreValidation()
|
||||||
|
model.value = {
|
||||||
|
name: '',
|
||||||
|
status: 2,
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
get_data()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -2,5 +2,5 @@ import { request } from '@/utils'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
getGoods: (data) => request.post('/goods', data),
|
getGoods: (data) => request.post('/goods', data),
|
||||||
getGoodClass: (data) => request.post('/goods/class', data),
|
getGoodClass: (data) => request.post('/classify', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { NButton, NEllipsis } from 'naive-ui'
|
import { NButton, NEllipsis, NImage, NSwitch } from 'naive-ui'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
|
import api1 from '../add/api'
|
||||||
import { useGoodsStore } from '@/store/modules/goods'
|
import { useGoodsStore } from '@/store/modules/goods'
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -31,12 +32,9 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'cover',
|
slot: 'cover',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('img', {
|
return h(NImage, {
|
||||||
|
width: '50',
|
||||||
src: row.cover,
|
src: row.cover,
|
||||||
style: {
|
|
||||||
width: '30px',
|
|
||||||
height: '30px',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -74,13 +72,34 @@ const columns = ref([
|
|||||||
key: 'stock',
|
key: 'stock',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '审核状态',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'status',
|
slot: 'status',
|
||||||
render(row) {
|
render(row) {
|
||||||
return h('span', row.status === 1 ? '已审核' : row.status === 2 ? '已拒绝' : '待审核')
|
return h('span', row.status === 1 ? '已审核' : row.status === 2 ? '已拒绝' : '待审核')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '是否上架',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'state',
|
||||||
|
render(row) {
|
||||||
|
return [
|
||||||
|
h(NSwitch, {
|
||||||
|
checkedValue: 1,
|
||||||
|
uncheckedValue: 2,
|
||||||
|
value: row.state,
|
||||||
|
onUpdateValue: async (val) => {
|
||||||
|
await api1.addGoods({
|
||||||
|
...row,
|
||||||
|
state: val,
|
||||||
|
})
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '备注',
|
title: '备注',
|
||||||
key: 'notes',
|
key: 'notes',
|
||||||
@@ -91,19 +110,17 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'action',
|
slot: 'action',
|
||||||
render(row) {
|
render(row) {
|
||||||
if (row.status === 1 || row.status === 2) {
|
return [
|
||||||
return [
|
h(
|
||||||
h(
|
NButton,
|
||||||
NButton,
|
{
|
||||||
{
|
type: 'primary',
|
||||||
type: 'primary',
|
size: 'small',
|
||||||
size: 'small',
|
onClick: () => toEdit(row),
|
||||||
onClick: () => toEdit(row),
|
},
|
||||||
},
|
() => '编辑'
|
||||||
() => '编辑'
|
),
|
||||||
),
|
]
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export default {
|
|||||||
path: '/goods',
|
path: '/goods',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/goods_list',
|
redirect: '/goods_list',
|
||||||
|
meta: {
|
||||||
|
title: '商品管理',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Goodslist',
|
name: 'Goodslist',
|
||||||
@@ -13,7 +18,17 @@ export default {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '商品列表',
|
title: '商品列表',
|
||||||
icon: 'mdi:account-multiple',
|
icon: 'mdi:account-multiple',
|
||||||
order: 10,
|
order: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Goodsclass',
|
||||||
|
path: 'goods_class',
|
||||||
|
component: () => import('./class/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '商品分类',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ import { useStorage } from '@vueuse/core'
|
|||||||
import bgImg from '@/assets/images/login_bg.webp'
|
import bgImg from '@/assets/images/login_bg.webp'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { addDynamicRoutes } from '@/router'
|
import { addDynamicRoutes } from '@/router'
|
||||||
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const title = import.meta.env.VITE_TITLE
|
const title = import.meta.env.VITE_TITLE
|
||||||
|
|
||||||
@@ -80,6 +83,26 @@ const loginInfo = ref({
|
|||||||
|
|
||||||
initLoginInfo()
|
initLoginInfo()
|
||||||
|
|
||||||
|
const easyLogin = async () => {
|
||||||
|
userStore.logout()
|
||||||
|
if (query.tk && query.type) {
|
||||||
|
console.log(query)
|
||||||
|
$message.success('登录成功')
|
||||||
|
setToken(query.tk)
|
||||||
|
window.localStorage.setItem('type', query.type)
|
||||||
|
await addDynamicRoutes()
|
||||||
|
if (query.redirect) {
|
||||||
|
const path = query.redirect
|
||||||
|
Reflect.deleteProperty(query, 'redirect')
|
||||||
|
router.push({ path, query })
|
||||||
|
} else {
|
||||||
|
router.push('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
easyLogin()
|
||||||
|
|
||||||
function initLoginInfo() {
|
function initLoginInfo() {
|
||||||
const localLoginInfo = lStorage.get('loginInfo')
|
const localLoginInfo = lStorage.get('loginInfo')
|
||||||
if (localLoginInfo) {
|
if (localLoginInfo) {
|
||||||
|
|||||||
@@ -1,6 +1,72 @@
|
|||||||
<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" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单佣金" tabular-nums>
|
||||||
|
<n-number-animation :from="0" :to="cardData.service" />
|
||||||
|
</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: '7%' }"
|
||||||
|
: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"
|
||||||
@@ -13,9 +79,55 @@
|
|||||||
|
|
||||||
<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 songs = ref([
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '待付款',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '待核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '已核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '已过期',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectOptions = ref([
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
label: '商品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '用户昵称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '手机号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '订单号',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '订单号',
|
title: '订单号',
|
||||||
@@ -28,15 +140,41 @@ 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: 'commission',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '订单状态',
|
title: '订单状态',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@@ -55,17 +193,33 @@ const columns = ref([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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() {
|
||||||
|
// // console.log(row)
|
||||||
|
// },
|
||||||
|
// },
|
||||||
])
|
])
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -88,18 +242,51 @@ 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
|
||||||
|
}
|
||||||
const res = await api.getOrder({
|
const res = await api.getOrder({
|
||||||
pageNum: pagination.value.page,
|
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
|
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)
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
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
src/views/order/index1/api.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getOrder: (data) => request.post('/order', data),
|
||||||
|
}
|
||||||
282
src/views/order/index1/index.vue
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
<template>
|
||||||
|
<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" />
|
||||||
|
</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: '7%' }"
|
||||||
|
: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
|
||||||
|
class="mt-5"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import api from './api'
|
||||||
|
import { NEllipsis } from 'naive-ui'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const songs = ref([
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '待付款',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '待核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '已核销',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 4,
|
||||||
|
label: '已过期',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectOptions = ref([
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
label: '商品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: '用户昵称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: '手机号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3,
|
||||||
|
label: '订单号',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'oid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户',
|
||||||
|
align: 'center',
|
||||||
|
key: 'user_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '手机号',
|
||||||
|
align: 'center',
|
||||||
|
key: 'phone',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'status',
|
||||||
|
render(row) {
|
||||||
|
switch (row.status) {
|
||||||
|
case 0:
|
||||||
|
return h('span', '待付款')
|
||||||
|
case 1:
|
||||||
|
return h('span', '待使用')
|
||||||
|
case 2:
|
||||||
|
return h('span', '已完成')
|
||||||
|
case 3:
|
||||||
|
return h('span', '已过期')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下单时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'add_time',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '核销时间',
|
||||||
|
align: 'center',
|
||||||
|
key: 'cancel_time',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '操作',
|
||||||
|
// align: 'center',
|
||||||
|
// slot: 'action',
|
||||||
|
// render() {
|
||||||
|
// // console.log(row)
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
onUpdatePageSize: (pageSize) => {
|
||||||
|
pagination.value.pageSize = pageSize
|
||||||
|
pagination.value.page = 1
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
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
|
||||||
|
}
|
||||||
|
const res = await api.getOrder({
|
||||||
|
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.number
|
||||||
|
cardData.value.service = res.data.commission
|
||||||
|
cardData.value.count = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
queryData.value = {
|
||||||
|
status: '',
|
||||||
|
time: null,
|
||||||
|
word: '',
|
||||||
|
selectKey: null,
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -8,17 +8,28 @@ export default {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '订单管理',
|
title: '订单管理',
|
||||||
icon: 'majesticons:compass-line',
|
icon: 'majesticons:compass-line',
|
||||||
order: 1,
|
order: 10,
|
||||||
// requireAuth: true,
|
|
||||||
// role: ['1'],
|
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'OrderList',
|
name: 'gyList',
|
||||||
path: 'order_list',
|
path: 'gy_list',
|
||||||
|
component: () => import('./index1/index.vue'),
|
||||||
|
meta: {
|
||||||
|
requireAuth: true,
|
||||||
|
role: ['1'],
|
||||||
|
title: '订单列表',
|
||||||
|
icon: 'material-symbols:auto-awesome-outline-rounded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dhList',
|
||||||
|
path: 'dh_list',
|
||||||
component: () => import('./index/index.vue'),
|
component: () => import('./index/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
requireAuth: true,
|
||||||
title: '订单列表',
|
title: '订单列表',
|
||||||
|
role: ['2'],
|
||||||
icon: 'material-symbols:auto-awesome-outline-rounded',
|
icon: 'material-symbols:auto-awesome-outline-rounded',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { request } from '@/utils'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getList: (data) => request.post('/order', data),
|
getList: (data) => request.post('/record', data),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <div> -->
|
|
||||||
<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" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<n-card ml-10 w-500>
|
||||||
|
<n-statistic label="订单服务费(积分)" tabular-nums>
|
||||||
|
<n-number-animation :from="0" :to="cardData.service" />
|
||||||
|
</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="8">
|
||||||
|
<div mt-10 flex items-center>
|
||||||
|
<span>积分渠道:</span>
|
||||||
|
<n-radio-group v-model:value="queryData.type">
|
||||||
|
<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>条件筛选:</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-10"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="data"
|
:data="data"
|
||||||
@@ -10,35 +61,48 @@
|
|||||||
remote
|
remote
|
||||||
/>
|
/>
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
<!-- </div> -->
|
|
||||||
</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 columns = ref([
|
|
||||||
|
const songs = ref([
|
||||||
{
|
{
|
||||||
title: 'ID',
|
label: '订单',
|
||||||
key: 'ID',
|
value: 1,
|
||||||
align: 'center',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商品名称',
|
label: '提现',
|
||||||
key: 'goods_name',
|
value: 2,
|
||||||
align: 'center',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户名称',
|
label: '增加(含驳回)',
|
||||||
key: 'user_name',
|
value: 3,
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '获取积分',
|
|
||||||
key: 'number',
|
|
||||||
align: 'center',
|
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const queryData = ref({
|
||||||
|
type: 1,
|
||||||
|
time: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const cardData = ref({
|
||||||
|
total: 0,
|
||||||
|
service: 0,
|
||||||
|
count: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
// watch(
|
||||||
|
// () => queryData.value.type,
|
||||||
|
// () => {
|
||||||
|
// getList()
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
|
||||||
|
const columns = ref([])
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
@@ -63,18 +127,137 @@ onMounted(() => {
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
switch (queryData.value.type) {
|
||||||
|
case 1:
|
||||||
|
columns.value = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
key: 'ID',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品名称',
|
||||||
|
align: 'center',
|
||||||
|
slot: 'goods_name',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NEllipsis,
|
||||||
|
{
|
||||||
|
style: 'max-width: 240px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => row.goods_name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商品数量',
|
||||||
|
key: 'count',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户名称',
|
||||||
|
key: 'user_name',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '上次留存积分',
|
||||||
|
key: 'balance',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '获取积分',
|
||||||
|
key: 'number',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '服务费',
|
||||||
|
key: 'commission',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
key: 'record_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
columns.value = [
|
||||||
|
{
|
||||||
|
title: '单号',
|
||||||
|
key: 'oid',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '上次留存积分',
|
||||||
|
key: 'balance',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '扣除积分',
|
||||||
|
key: 'record_number',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
key: 'record_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
columns.value = [
|
||||||
|
{
|
||||||
|
title: '单号',
|
||||||
|
key: 'oid',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '上次留存积分',
|
||||||
|
key: 'balance',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '获取积分',
|
||||||
|
key: 'record_number',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
key: 'record_time',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
const res = await api.getList({
|
const res = await api.getList({
|
||||||
pageNum: pagination.value.page,
|
pageNum: pagination.value.page,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
|
Type: queryData.value.type,
|
||||||
|
StartTime: queryData.value.time === null ? '' : queryData.value.time[0] || '',
|
||||||
|
EndTime: queryData.value.time === null ? '' : queryData.value.time[1] || '',
|
||||||
})
|
})
|
||||||
console.log(res)
|
|
||||||
data.value = res.data.data || []
|
data.value = res.data.data || []
|
||||||
pagination.value.itemCount = res.data.total
|
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 = {
|
||||||
|
type: 1,
|
||||||
|
time: null,
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -6,30 +6,32 @@ export default {
|
|||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/settlement_list',
|
redirect: '/settlement_list',
|
||||||
meta: {
|
meta: {
|
||||||
|
title: '积分管理',
|
||||||
requireAuth: true,
|
requireAuth: true,
|
||||||
order: 1,
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
role: ['2'],
|
role: ['2'],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'Settlementlist',
|
name: 'Jflist',
|
||||||
path: 'settlement_list',
|
path: 'jf_list',
|
||||||
component: () => import('./index/index.vue'),
|
component: () => import('./jf_list/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '积分明细',
|
title: '积分明细',
|
||||||
icon: 'mdi:account-multiple',
|
icon: 'mdi:account-multiple',
|
||||||
order: 10,
|
order: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: 'Jflist',
|
name: 'Txlist',
|
||||||
// path: 'jf_list',
|
path: 'tx_list',
|
||||||
// component: () => import('./jf_list/index.vue'),
|
component: () => import('./tx_list/index.vue'),
|
||||||
// meta: {
|
meta: {
|
||||||
// title: '积分列表',
|
title: '积分提现',
|
||||||
// icon: 'mdi:account-multiple',
|
icon: 'mdi:account-multiple',
|
||||||
// order: 10,
|
order: 10,
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/views/settlement/tx_list/api.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getList: (data) => request.post('/withdraw', data),
|
||||||
|
// 申请提现
|
||||||
|
apply: (data) => request.post('/withdraw/set', data),
|
||||||
|
}
|
||||||
194
src/views/settlement/tx_list/index.vue
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
<template>
|
||||||
|
<!-- <div> -->
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<div w-1200 flex items-center justify-between>
|
||||||
|
<n-card class="w-300">
|
||||||
|
<n-statistic label="可提现积分">
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:precision="2"
|
||||||
|
:from="0"
|
||||||
|
:to="userInfo.integral"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<div w-100 text-center text-25>/</div>
|
||||||
|
<n-card class="w-300">
|
||||||
|
<n-statistic label="兑换比例">
|
||||||
|
<n-number-animation ref="numberAnimationInstRef" :precision="2" :from="0" :to="100" />
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<div w-100 text-center text-25>=</div>
|
||||||
|
<n-card class="w-300">
|
||||||
|
<n-statistic label="CNY">
|
||||||
|
<n-number-animation
|
||||||
|
ref="numberAnimationInstRef"
|
||||||
|
:precision="2"
|
||||||
|
:from="0"
|
||||||
|
:to="userInfo.integral / 100"
|
||||||
|
/>
|
||||||
|
</n-statistic>
|
||||||
|
</n-card>
|
||||||
|
<div ml-10 flex flex-col items-center justify-center>
|
||||||
|
<n-input-number v-model:value="formData.integral" clearable placeholder="请输入提现积分" />
|
||||||
|
<n-button mt-10 w-full type="primary" @click="ok">立即提现</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-data-table
|
||||||
|
class="mt-10"
|
||||||
|
:loading="loading"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:bordered="false"
|
||||||
|
remote
|
||||||
|
/>
|
||||||
|
</CommonPage>
|
||||||
|
<!-- </div> -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import api from './api'
|
||||||
|
import comm from '@/api'
|
||||||
|
import { NTag, NImage } from 'naive-ui'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
key: 'ID',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '提现积分',
|
||||||
|
key: 'integral',
|
||||||
|
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: 'status',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: row.status === 1 ? 'success' : row.status === 2 ? 'error' : 'warning',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (row.status === 1 ? '已审核' : row.status === 2 ? '已拒绝' : '待审核'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '提现时间',
|
||||||
|
slot: 'add_time',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(
|
||||||
|
'span',
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: () => row.add_time,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打款截图',
|
||||||
|
slot: 'img',
|
||||||
|
render: (row) => {
|
||||||
|
return h(NImage, {
|
||||||
|
src: row.status_img,
|
||||||
|
width: '50',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
integral: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
onUpdatePageSize: (pageSize) => {
|
||||||
|
pagination.value.pageSize = pageSize
|
||||||
|
pagination.value.page = 1
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
|
||||||
|
const userInfo = ref({})
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await comm.getMerchantInfo()
|
||||||
|
userInfo.value = res.data.data
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await api.getList({
|
||||||
|
pageNum: pagination.value.page,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
} catch (error) {
|
||||||
|
$message.error(error.msg)
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const ok = async () => {
|
||||||
|
// if (formData.value.integral < 1000) return $message.warning('提现积分不能小于10000')
|
||||||
|
const res = await api.apply({
|
||||||
|
number: formData.value.integral,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
formData.value.integral = null
|
||||||
|
getList()
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
15
src/views/sys/api.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { request } from '@/utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getList: (data) => request.post('/staff/list', data),
|
||||||
|
// 查找用户
|
||||||
|
findUser: (data) => request.post('/find/user', data),
|
||||||
|
// 绑定核销人员
|
||||||
|
bindUser: (data) => request.post('/staff/user/set', data),
|
||||||
|
// 获取商家信息
|
||||||
|
getMerchantInfo: () => request.post('/info'),
|
||||||
|
// 更新商家信息
|
||||||
|
updateMerchantInfo: (data) => request.post('/edit', data),
|
||||||
|
// 取消核销人员
|
||||||
|
delVerifyUser: (data) => request.post('/staff/user/delete', data),
|
||||||
|
}
|
||||||
237
src/views/sys/index/index.vue
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
<script setup>
|
||||||
|
import api from '../api'
|
||||||
|
import Upload from '@/components/Upload.vue'
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getInfo()
|
||||||
|
})
|
||||||
|
|
||||||
|
const infoData = ref({})
|
||||||
|
|
||||||
|
const model = ref({})
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入店铺名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
head_photo: {
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: '请输入上传店铺封面图',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
bank: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入银行名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
bank_card: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入银行卡号',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
bank_name: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入账户名称',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
bank_user: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入法定代表人',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
img: {
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: '请输入上传店铺轮播图',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入店铺详细地址',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
lt: {
|
||||||
|
required: true,
|
||||||
|
message: '请查找店铺经纬度',
|
||||||
|
},
|
||||||
|
week: {
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: '请选择营业日期',
|
||||||
|
},
|
||||||
|
week_start: {
|
||||||
|
required: true,
|
||||||
|
message: '请选择营业开始时间',
|
||||||
|
},
|
||||||
|
week_end: {
|
||||||
|
required: true,
|
||||||
|
message: '请选择营业结束时间',
|
||||||
|
},
|
||||||
|
mobile: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入店铺手机号',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const days = ref([
|
||||||
|
{ label: '周一', value: '1' },
|
||||||
|
{ label: '周二', value: '2' },
|
||||||
|
{ label: '周三', value: '3' },
|
||||||
|
{ label: '周四', value: '4' },
|
||||||
|
{ label: '周五', value: '5' },
|
||||||
|
{ label: '周六', value: '6' },
|
||||||
|
{ label: '周日', value: '7' },
|
||||||
|
])
|
||||||
|
|
||||||
|
const getInfo = async () => {
|
||||||
|
const res = await api.getMerchantInfo()
|
||||||
|
infoData.value = res.data.data
|
||||||
|
console.log((!res.data.data.week_start && 1) || '00:00:00')
|
||||||
|
model.value = {
|
||||||
|
...res.data.data,
|
||||||
|
head_photo: [{ url: res.data.data.head_photo, status: 'finished', id: 1 }],
|
||||||
|
img: res.data.data.img
|
||||||
|
.split(',')
|
||||||
|
.map((item, index) => ({ url: item, status: 'finished', id: index })),
|
||||||
|
lt: `${res.data.data.lat},${res.data.data.lon}`,
|
||||||
|
week: res.data.data.week.length === 0 ? [] : res.data.data.week.split(','),
|
||||||
|
week_start: res.data.data.week_start.length === 0 ? '00:00:00' : res.data.data.week_start,
|
||||||
|
week_end: res.data.data.week_end.length === 0 ? '00:00:00' : res.data.data.week_end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中位置触发该函数
|
||||||
|
window.addEventListener('message', (res) => {
|
||||||
|
model.value.lt = `${res.data?.latlng?.lat},${res.data?.latlng?.lng}`
|
||||||
|
model.value.lat = res.data?.latlng?.lat
|
||||||
|
model.value.lon = res.data.latlng?.lng
|
||||||
|
showModal.value = false
|
||||||
|
})
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
const data = {
|
||||||
|
...model.value,
|
||||||
|
head_photo: model.value.head_photo[0].url,
|
||||||
|
img: model.value.img.map((item) => item.url).join(','),
|
||||||
|
lat: model.value.lat.toString(),
|
||||||
|
lon: model.value.lon.toString(),
|
||||||
|
week: model.value.week.join(','),
|
||||||
|
}
|
||||||
|
delete data.lt
|
||||||
|
const res = await api.updateMerchantInfo(data)
|
||||||
|
$message.success(res.msg)
|
||||||
|
getInfo()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-tabs type="line" animated>
|
||||||
|
<n-tab-pane name="1" tab="基本信息">
|
||||||
|
<div>商户名称: {{ infoData.name }}</div>
|
||||||
|
<div>负责人手机号码: {{ infoData.phone }}</div>
|
||||||
|
<div>商户类型: {{ infoData.bType === 1 ? '供应商' : '兑换商' }}</div>
|
||||||
|
<!-- <div>经营类目: {{ infoData.scope }}</div> -->
|
||||||
|
<div>入驻时间: {{ infoData.add_time }}</div>
|
||||||
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="2" tab="店铺信息">
|
||||||
|
<!-- {{ model }} -->
|
||||||
|
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
|
||||||
|
<n-grid :cols="24" :x-gap="24">
|
||||||
|
<n-form-item-gi :span="24" label="店铺封面图:" path="head_photo">
|
||||||
|
<Upload v-model:list="model.head_photo" :max="1" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="24" label="店铺轮播图:" path="img">
|
||||||
|
<Upload v-model:list="model.img" :max="5" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="店铺号码:" path="mobile">
|
||||||
|
<n-input v-model:value="model.mobile" placeholder="请输入店铺号码" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="法定代表人:" path="bank_user">
|
||||||
|
<n-input v-model:value="model.bank_user" placeholder="请输入法定代表人" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="账户名称:" path="bank_name">
|
||||||
|
<n-input v-model:value="model.bank_name" placeholder="请输入账户名称" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="开户银行:" path="bank">
|
||||||
|
<n-input v-model:value="model.bank" placeholder="请输入开户银行" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="银行卡号:" path="bank_card">
|
||||||
|
<n-input v-model:value="model.bank_card" placeholder="请输入银行卡号" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="营业日期:" path="week">
|
||||||
|
<n-select v-model:value="model.week" multiple :options="days" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="营业开始时间:" path="week_start">
|
||||||
|
<n-time-picker
|
||||||
|
v-model:formatted-value="model.week_start"
|
||||||
|
value-format="HH:mm:ss"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="营业结束时间:" path="week_end">
|
||||||
|
<n-time-picker
|
||||||
|
v-model:formatted-value="model.week_end"
|
||||||
|
value-format="HH:mm:ss"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="店铺名称:" path="name">
|
||||||
|
<n-input v-model:value="model.name" placeholder="请输入店铺名称" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="店铺详细地址:" path="address">
|
||||||
|
<n-input v-model:value="model.address" placeholder="请输入店铺详细地址" />
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15" label="店铺经纬度:" path="lt">
|
||||||
|
<n-input-group>
|
||||||
|
<n-input
|
||||||
|
v-model:value="model.lt"
|
||||||
|
placeholder="请查找店铺经纬度"
|
||||||
|
:style="{ width: '100%' }"
|
||||||
|
/>
|
||||||
|
<n-button type="primary" @click="showModal = true">查找位置</n-button>
|
||||||
|
</n-input-group>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi :span="15">
|
||||||
|
<div class="m-auto">
|
||||||
|
<n-button type="primary" w-100 @click="submit">提交</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
</n-grid>
|
||||||
|
</n-form>
|
||||||
|
</n-tab-pane>
|
||||||
|
<!-- <n-tab-pane name="3" tab="功能信息">开发中</n-tab-pane> -->
|
||||||
|
</n-tabs>
|
||||||
|
<!-- h5地图 -->
|
||||||
|
<n-modal v-if="showModal" v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: 600px; height: 600px"
|
||||||
|
title="查找地图位置"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
src="https://apis.map.qq.com/tools/locpicker?type=1&key=S3GBZ-WR26O-IXNW2-SXBOD-LZXV6-WAFNO&referer=myapp"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
frameborder="0"
|
||||||
|
></iframe>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</CommonPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
35
src/views/sys/route.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: '商户设置',
|
||||||
|
path: '/sys',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/sys_info',
|
||||||
|
meta: {
|
||||||
|
title: '商户设置',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'SysInfo',
|
||||||
|
path: 'sys_info',
|
||||||
|
component: () => import('./index/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '商户信息',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SysVerify',
|
||||||
|
path: 'sys_verify',
|
||||||
|
component: () => import('./verify/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '核销人员',
|
||||||
|
icon: 'mdi:account-multiple',
|
||||||
|
order: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
242
src/views/sys/verify/index.vue
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
<script setup>
|
||||||
|
import api from '../api.js'
|
||||||
|
import { NAvatar, NButton, NPopconfirm } from 'naive-ui'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
title: '头像',
|
||||||
|
slot: 'avatarUrl',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
return h(NAvatar, { src: row.avatarUrl, round: true, size: 50 })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '昵称',
|
||||||
|
key: 'nickName',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '手机号',
|
||||||
|
key: 'phone',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
slot: 'action',
|
||||||
|
align: 'center',
|
||||||
|
render: (row) => {
|
||||||
|
console.log(row)
|
||||||
|
return [
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
size: 'small',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: () => {
|
||||||
|
addUser(2, row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '编辑',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
NPopconfirm,
|
||||||
|
{
|
||||||
|
onPositiveClick: () => {
|
||||||
|
delVerifyUser(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '删除无法撤销,请谨慎!',
|
||||||
|
trigger: () =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
class: 'ml-10',
|
||||||
|
size: 'small',
|
||||||
|
type: 'error',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '删除',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const data = ref([])
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
const showModalTitle = ref('')
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
onChange: (page) => {
|
||||||
|
pagination.value.page = page
|
||||||
|
get_list()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
get_list()
|
||||||
|
})
|
||||||
|
|
||||||
|
const get_list = async () => {
|
||||||
|
loading.value = true
|
||||||
|
const res = await api.getList({
|
||||||
|
PageNum: pagination.value.page,
|
||||||
|
PageSize: pagination.value.pageSize,
|
||||||
|
})
|
||||||
|
data.value = res.data.data || []
|
||||||
|
pagination.value.itemCount = res.data.total
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const addUser = (type, row = {}) => {
|
||||||
|
showModalTitle.value = type === 1 ? '添加核销人员' : '编辑核销人员'
|
||||||
|
if (type === 2) {
|
||||||
|
model.value = {
|
||||||
|
inputValue: row.phone,
|
||||||
|
id: row.uid,
|
||||||
|
url: row.avatarUrl,
|
||||||
|
name: row.nickName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const model = ref({
|
||||||
|
inputValue: '',
|
||||||
|
url: '',
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
const res = await api.findUser({
|
||||||
|
phone: model.value.inputValue,
|
||||||
|
})
|
||||||
|
model.value = {
|
||||||
|
...model.value,
|
||||||
|
id: res.data.data.uid,
|
||||||
|
url: res.data.data.avatarUrl,
|
||||||
|
name: res.data.data.nickName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
if (!model.value.id) return $message.error('请绑定核销人员')
|
||||||
|
const res = await api.bindUser({
|
||||||
|
uid: model.value.id,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
model.value = {
|
||||||
|
inputValue: '',
|
||||||
|
url: '',
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
get_list()
|
||||||
|
}
|
||||||
|
|
||||||
|
const delVerifyUser = async (row) => {
|
||||||
|
const res = await api.delVerifyUser({
|
||||||
|
uid: row.uid,
|
||||||
|
})
|
||||||
|
$message.success(res.msg)
|
||||||
|
get_list()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CommonPage show-footer :title="$route.title">
|
||||||
|
<n-button type="primary" @click="addUser(1)">添加核销人员</n-button>
|
||||||
|
<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: 600px"
|
||||||
|
:title="showModalTitle"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-form ref="formRef" :model="model" label-placement="left">
|
||||||
|
<n-grid :cols="1" :x-gap="24">
|
||||||
|
<n-form-item-gi class="flex items-center" label="查找用户" :span="20">
|
||||||
|
<n-input-group>
|
||||||
|
<n-input
|
||||||
|
v-model:value="model.inputValue"
|
||||||
|
placeholder="请输入用户手机号"
|
||||||
|
:style="{ width: '90%' }"
|
||||||
|
/>
|
||||||
|
<n-button type="primary" ghost @click="search">搜索</n-button>
|
||||||
|
</n-input-group>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi class="flex items-center" label="绑定用户" :span="12">
|
||||||
|
<div v-if="model.url !== '' && model.id !== null" class="text-center">
|
||||||
|
<img class="h-100 w-100 border rounded-5" :src="model.url || ''" />
|
||||||
|
<div>{{ model.name }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="checkBox">+</div>
|
||||||
|
</n-form-item-gi>
|
||||||
|
<n-form-item-gi>
|
||||||
|
<div m-auto>
|
||||||
|
<n-button type="primary" @click="submit">提交</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>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.checkBox {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: rgb(250, 250, 252);
|
||||||
|
border: 1px dashed rgb(224, 224, 230);
|
||||||
|
border-radius: 3px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100px;
|
||||||
|
font-size: 30px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px dashed #18a058;
|
||||||
|
transition: 1s all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -22,13 +22,18 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'ID',
|
key: 'ID',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '昵称',
|
||||||
|
align: 'center',
|
||||||
|
key: 'nickName',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '头像',
|
title: '头像',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
slot: 'avatar',
|
slot: 'avatarUrl',
|
||||||
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',
|
||||||
@@ -52,14 +57,14 @@ const columns = ref([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
key: 'pulse',
|
key: 'pulse',
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: '操作',
|
// title: '操作',
|
||||||
align: 'center',
|
// align: 'center',
|
||||||
slot: 'action',
|
// slot: 'action',
|
||||||
render(row) {
|
// render(row) {
|
||||||
console.log(row)
|
// console.log(row)
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
])
|
])
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -8,51 +8,16 @@
|
|||||||
<p text-16>Hello, {{ userStore.name }}</p>
|
<p text-16>Hello, {{ userStore.name }}</p>
|
||||||
<p mt-5 text-12 op-60>今天又是元气满满的一天</p>
|
<p mt-5 text-12 op-60>今天又是元气满满的一天</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div ml-auto flex items-center>
|
|
||||||
<n-statistic label="待办" :value="4">
|
|
||||||
<template #suffix>/ 10</template>
|
|
||||||
</n-statistic>
|
|
||||||
<n-statistic label="Stars" ml-80 w-100>
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin">
|
|
||||||
<img alt="stars" src="https://badgen.net/github/stars/zclzone/vue-naive-admin" />
|
|
||||||
</a>
|
|
||||||
</n-statistic>
|
|
||||||
<n-statistic label="Forks" ml-80 w-100>
|
|
||||||
<a href="https://github.com/zclzone/vue-naive-admin">
|
|
||||||
<img alt="forks" src="https://badgen.net/github/forks/zclzone/vue-naive-admin" />
|
|
||||||
</a>
|
|
||||||
</n-statistic>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
<!-- <Map /> -->
|
||||||
<!-- <n-card title="项目" size="small" :segmented="true" mt-15 rounded-10>
|
|
||||||
<template #header-extra>
|
|
||||||
<n-button text type="primary">更多</n-button>
|
|
||||||
</template>
|
|
||||||
<div flex flex-wrap justify-between>
|
|
||||||
<n-card
|
|
||||||
v-for="i in 10"
|
|
||||||
:key="i"
|
|
||||||
class="mb-10 mt-10 w-300 flex-shrink-0 cursor-pointer"
|
|
||||||
hover:card-shadow
|
|
||||||
title="Vue Naive Admin"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
<p op-60>一个基于 Vue3.0、Vite、Naive UI 的轻量级后台管理模板</p>
|
|
||||||
</n-card>
|
|
||||||
<div h-0 w-300></div>
|
|
||||||
<div h-0 w-300></div>
|
|
||||||
<div h-0 w-300></div>
|
|
||||||
<div h-0 w-300></div>
|
|
||||||
</div>
|
|
||||||
</n-card> -->
|
|
||||||
</div>
|
</div>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
|
// import Map from '@/components/Map.vue'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
plugins: createVitePlugins(viteEnv, isBuild),
|
plugins: createVitePlugins(viteEnv, isBuild),
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
|
https: false,
|
||||||
port: VITE_PORT,
|
port: VITE_PORT,
|
||||||
open: false,
|
open: false,
|
||||||
proxy: VITE_USE_PROXY
|
proxy: VITE_USE_PROXY
|
||||||
|
|||||||