【更新】前端依赖大升级,业务代码等多处优化调整,完全去掉以往this.xxx等语法。

pull/189/MERGE
小诺 2023-12-31 13:06:54 +08:00 committed by 俞宝山
parent a216d0ccff
commit 4f9de9fc9a
164 changed files with 3284 additions and 3242 deletions

View File

@ -19,70 +19,70 @@
"dependencies": { "dependencies": {
"@amap/amap-jsapi-loader": "1.0.1", "@amap/amap-jsapi-loader": "1.0.1",
"@ant-design/colors": "7.0.0", "@ant-design/colors": "7.0.0",
"@ant-design/icons-vue": "6.1.0", "@ant-design/icons-vue": "7.0.1",
"@antv/g2plot": "2.4.28", "@antv/g2plot": "2.4.31",
"@chenfengyuan/vue-qrcode": "2.0.0", "@chenfengyuan/vue-qrcode": "2.0.0",
"@highlightjs/vue-plugin": "2.1.0", "@highlightjs/vue-plugin": "2.1.0",
"@tinymce/tinymce-vue": "5.0.0", "@tinymce/tinymce-vue": "5.1.1",
"@vue-office/docx": "1.2.0", "@vue-office/docx": "1.3.2",
"@vue-office/excel": "1.2.0", "@vue-office/excel": "1.4.7",
"@vue-office/pdf": "1.2.0", "@vue-office/pdf": "1.5.5",
"ant-design-vue": "3.2.14", "ant-design-vue": "3.2.14",
"axios": "1.1.3", "axios": "1.6.2",
"cropperjs": "1.5.12", "cropperjs": "1.6.1",
"dayjs": "1.11.7", "dayjs": "1.11.10",
"echarts": "5.4.0", "echarts": "5.4.3",
"echarts-stat": "1.2.0", "echarts-stat": "1.2.0",
"enquire.js": "2.1.6", "enquire.js": "2.1.6",
"event-source-polyfill": "1.0.31", "event-source-polyfill": "1.0.31",
"fuse.js": "6.6.2", "fuse.js": "7.0.0",
"highlight.js": "11.6.0", "highlight.js": "11.9.0",
"hotkeys-js": "3.10.1", "hotkeys-js": "3.12.2",
"js-pinyin": "0.1.9", "js-pinyin": "0.2.5",
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "2.0.33", "pinia": "2.1.7",
"qs": "6.11.1", "qs": "6.11.2",
"screenfull": "6.0.2", "screenfull": "6.0.2",
"sm-crypto": "0.3.11", "sm-crypto": "0.3.13",
"snowflake-id": "1.1.0", "snowflake-id": "1.1.0",
"sortablejs": "1.15.0", "sortablejs": "1.15.1",
"tinymce": "6.2.0", "tinymce": "6.8.1",
"vue": "3.2.44", "vue": "3.3.10",
"vue-cropper": "1.0.5", "vue-cropper": "1.1.1",
"vue-demi": "0.13.11", "vue-demi": "0.13.11",
"vue-i18n": "9.2.2", "vue-i18n": "9.8.0",
"vue-router": "4.1.6", "vue-router": "4.2.5",
"vue3-colorpicker": "2.0.4", "vue3-colorpicker": "2.2.3",
"vue3-tree-org": "4.2.2", "vue3-tree-org": "4.2.2",
"vuedraggable-es": "4.1.1" "vuedraggable-es": "4.1.1"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "0.29.4", "@antfu/eslint-config": "0.29.4",
"@babel/eslint-parser": "7.19.1", "@babel/eslint-parser": "7.19.1",
"@vitejs/plugin-legacy": "3.0.2", "@vitejs/plugin-legacy": "5.2.0",
"@vitejs/plugin-vue": "4.1.0", "@vitejs/plugin-vue": "4.5.2",
"@vitejs/plugin-vue-jsx": "3.0.1", "@vitejs/plugin-vue-jsx": "3.1.0",
"@vue/compiler-sfc": "3.2.47", "@vue/compiler-sfc": "3.3.10",
"@vue/eslint-config-standard": "8.0.1", "@vue/eslint-config-standard": "8.0.1",
"antd-less-to-css-variable": "1.0.5", "antd-less-to-css-variable": "1.0.5",
"autoprefixer": "10.4.13", "autoprefixer": "10.4.16",
"eslint": "8.26.0", "eslint": "8.55.0",
"eslint-config-prettier": "8.5.0", "eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "4.2.1", "eslint-plugin-prettier": "5.0.1",
"eslint-plugin-vue": "9.7.0", "eslint-plugin-vue": "9.7.0",
"less": "4.1.3", "less": "4.1.3",
"postcss": "8.4.21", "postcss": "8.4.32",
"prettier": "2.8.7", "prettier": "3.1.0",
"rollup-plugin-visualizer": "5.8.3", "rollup-plugin-visualizer": "5.10.0",
"tailwindcss": "3.2.7", "tailwindcss": "3.3.6",
"typescript": "4.9.5", "typescript": "5.3.3",
"unplugin-auto-import": "0.15.2", "unplugin-auto-import": "0.17.2",
"unplugin-vue-components": "0.24.1", "unplugin-vue-components": "0.26.0",
"vite": "4.2.1", "vite": "5.0.6",
"vite-plugin-compression": "0.5.1", "vite-plugin-compression": "0.5.1",
"vite-plugin-vue-setup-extend": "0.4.0", "vite-plugin-vue-setup-extend": "0.4.0",
"vue-eslint-parser": "9.1.0" "vue-eslint-parser": "9.3.2"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/auth/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/auth/` + url, ...arg)
/** /**
* 绘画 * 绘画
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/auth/third/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/auth/third/` + url, ...arg)
/** /**
* 三方登录 * 三方登录
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/auth/third/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/auth/third/` + url, ...arg)
/** /**
* 三方用户 * 三方用户
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/biz/dict/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/biz/dict/` + url, ...arg)
/** /**
* 字典 * 字典
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/biz/org/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/biz/org/` + url, ...arg)
/** /**
* 机构 * 机构
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/biz/position/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/biz/position/` + url, ...arg)
/** /**
* 岗位 * 岗位
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/biz/user/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/biz/user/` + url, ...arg)
/** /**
* 人员接口api * 人员接口api
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/config/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/config/` + url, ...arg)
/** /**
* 配置 * 配置
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/dict/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/dict/` + url, ...arg)
/** /**
* 字典 * 字典
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/email/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/email/` + url, ...arg)
/** /**
* 邮件 * 邮件
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/file/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/file/` + url, ...arg)
/** /**
* 文件 * 文件
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/job/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/job/` + url, ...arg)
/** /**
* 定时任务 * 定时任务
* *
@ -22,10 +22,6 @@ export default {
jobPage(data) { jobPage(data) {
return request('page', data, 'get') return request('page', data, 'get')
}, },
// 获取定时任务列表
jobList(data) {
return request('list', data, 'get')
},
// 提交表单 edit为true时为编辑默认为新增 // 提交表单 edit为true时为编辑默认为新增
submitForm(data, edit = false) { submitForm(data, edit = false) {
return request(edit ? 'edit' : 'add', data) return request(edit ? 'edit' : 'add', data)

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/log/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/log/` + url, ...arg)
/** /**
* 日志 * 日志
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/message/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/message/` + url, ...arg)
/** /**
* 站内信 * 站内信
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/monitor/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/monitor/` + url, ...arg)
/** /**
* 监控 * 监控
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/dev/sms/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/dev/sms/` + url, ...arg)
/** /**
* 短信 * 短信
* *

View File

@ -1,6 +1,6 @@
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/gen/basic/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/gen/basic/` + url, ...arg)
export default { export default {
// 获取代码生成基础分页 // 获取代码生成基础分页

View File

@ -1,6 +1,6 @@
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/gen/config/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/gen/config/` + url, ...arg)
export default { export default {
// 获取代码生成详情配置列表 // 获取代码生成详情配置列表

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/mobile/button/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/mobile/button/` + url, ...arg)
/** /**
* 按钮 * 按钮
* *

View File

@ -13,10 +13,6 @@ export default {
mobileMenuTree(data) { mobileMenuTree(data) {
return request('tree', data, 'get') return request('tree', data, 'get')
}, },
// 获取移动端菜单列表
mobileMenuList(data) {
return request('list', data, 'get')
},
// 提交移动端菜单表单 edit为true时为编辑默认为新增 // 提交移动端菜单表单 edit为true时为编辑默认为新增
mobileMenuSubmitForm(data, edit = false) { mobileMenuSubmitForm(data, edit = false) {
return request(edit ? 'edit' : 'add', data) return request(edit ? 'edit' : 'add', data)

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/mobile/module/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/mobile/module/` + url, ...arg)
/** /**
* 类别 * 类别
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/index/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/index/` + url, ...arg)
/** /**
* 系统首页控制器 * 系统首页控制器
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/org/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/org/` + url, ...arg)
/** /**
* 机构 * 机构
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/position/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/position/` + url, ...arg)
/** /**
* 职位 * 职位
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/button/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/button/` + url, ...arg)
/** /**
* 按钮 * 按钮
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/field/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/field/` + url, ...arg)
/** /**
* 字段 * 字段
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/menu/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/menu/` + url, ...arg)
/** /**
* 菜单 * 菜单
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/module/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/module/` + url, ...arg)
/** /**
* 模块 * 模块
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/role/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/role/` + url, ...arg)
/** /**
* 角色 * 角色
* *
@ -22,10 +22,6 @@ export default {
rolePage(data) { rolePage(data) {
return request('page', data, 'get') return request('page', data, 'get')
}, },
// 获取角色列表
roleList(data) {
return request('list', data, 'get')
},
// 提交表单 edit为true时为编辑默认为新增 // 提交表单 edit为true时为编辑默认为新增
submitForm(data, edit = false) { submitForm(data, edit = false) {
return request(edit ? 'edit' : 'add', data) return request(edit ? 'edit' : 'add', data)

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/user/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/user/` + url, ...arg)
/** /**
* 用户接口api * 用户接口api
* *

View File

@ -10,7 +10,7 @@
*/ */
import { baseRequest } from '@/utils/request' import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/userCenter/${url}`, ...arg) const request = (url, ...arg) => baseRequest(`/sys/userCenter/` + url, ...arg)
/** /**
* 用户个人控制器 * 用户个人控制器
* *

View File

@ -0,0 +1,103 @@
export const getYear = () => {
let v = []
let y = new Date().getFullYear()
for (let i = 0; i < 11; i++) {
v.push(y + i)
}
return v
}
export const data = {
second: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
minute: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
hour: [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23'
],
day: [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31'
],
month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
week: [
{
value: '1',
label: '周日'
},
{
value: '2',
label: '周一'
},
{
value: '3',
label: '周二'
},
{
value: '4',
label: '周三'
},
{
value: '5',
label: '周四'
},
{
value: '6',
label: '周五'
},
{
value: '7',
label: '周六'
}
],
year: getYear()
}

View File

@ -405,18 +405,10 @@
</template> </template>
<script setup name="XnCron"> <script setup name="XnCron">
import { data, getYear } from './data.js'
const activeKey = ref('1') const activeKey = ref('1')
const type = ref('0')
const defaultValue = ref('') const defaultValue = ref('')
const modalVisible = ref(false) const modalVisible = ref(false)
const getYear = () => {
let v = []
let y = new Date().getFullYear()
for (let i = 0; i < 11; i++) {
v.push(y + i)
}
return v
}
const dateValue = ref({ const dateValue = ref({
second: { second: {
type: '0', type: '0',
@ -504,101 +496,6 @@
appoint: [] appoint: []
} }
}) })
const data = {
second: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
minute: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
hour: [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23'
],
day: [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31'
],
month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
week: [
{
value: '1',
label: '周日'
},
{
value: '2',
label: '周一'
},
{
value: '3',
label: '周二'
},
{
value: '4',
label: '周三'
},
{
value: '5',
label: '周四'
},
{
value: '6',
label: '周五'
},
{
value: '7',
label: '周六'
}
],
year: getYear()
}
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -610,111 +507,62 @@
default: () => [] default: () => []
} }
}) })
const value_second = computed(() => { const setRules = (v) => {
let v = dateValue.value.second switch (v.type) {
if (v.type === '0') { case '0':
return '*' return '*'
} else if (v.type === '1') { case '1':
return v.range.start + '-' + v.range.end return v.range.start + '-' + v.range.end
} else if (v.type === '2') { case '2':
return v.loop.start + '/' + v.loop.end return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') { case '3':
return v.appoint.length > 0 ? v.appoint.join(',') : '*' return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else { case '4':
return 'L'
case '5':
return '?'
default:
return '*' return '*'
} }
}
const value_second = computed(() => {
let v = dateValue.value.second
return setRules(v)
}) })
const value_minute = computed(() => { const value_minute = computed(() => {
let v = dateValue.value.minute let v = dateValue.value.minute
if (v.type === '0') { return setRules(v)
return '*'
} else if (v.type === '1') {
return v.range.start + '-' + v.range.end
} else if (v.type === '2') {
return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') {
return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else {
return '*'
}
}) })
const value_hour = computed(() => { const value_hour = computed(() => {
let v = dateValue.value.hour let v = dateValue.value.hour
if (v.type === '0') { return setRules(v)
return '*'
} else if (v.type === '1') {
return v.range.start + '-' + v.range.end
} else if (v.type === '2') {
return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') {
return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else {
return '*'
}
}) })
const value_day = computed(() => { const value_day = computed(() => {
let v = dateValue.value.day let v = dateValue.value.day
if (v.type === '0') { return setRules(v)
return '*'
} else if (v.type === '1') {
return v.range.start + '-' + v.range.end
} else if (v.type === '2') {
return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') {
return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else if (v.type === '4') {
return 'L'
} else if (v.type === '5') {
return '?'
} else {
return '*'
}
}) })
const value_month = computed(() => { const value_month = computed(() => {
let v = dateValue.value.month let v = dateValue.value.month
if (v.type === '0') { return setRules(v)
return '*'
} else if (v.type === '1') {
return v.range.start + '-' + v.range.end
} else if (v.type === '2') {
return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') {
return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else {
return '*'
}
}) })
const value_week = computed(() => { const value_week = computed(() => {
let v = dateValue.value.week let v = dateValue.value.week
if (v.type === '0') { return setRules(v)
return '*'
} else if (v.type === '1') {
return v.range.start + '-' + v.range.end
} else if (v.type === '2') {
return v.loop.end + '#' + v.loop.start
} else if (v.type === '3') {
return v.appoint.length > 0 ? v.appoint.join(',') : '*'
} else if (v.type === '4') {
return v.last + 'L'
} else if (v.type === '5') {
return '?'
} else {
return '*'
}
}) })
const value_year = computed(() => { const value_year = computed(() => {
let v = dateValue.value.year let v = dateValue.value.year
if (v.type === '-1') { switch (v.type) {
case '-1':
return '' return ''
} else if (v.type === '0') { case '0':
return '*' return '*'
} else if (v.type === '1') { case '1':
return v.range.start + '-' + v.range.end return v.range.start + '-' + v.range.end
} else if (v.type === '2') { case '2':
return v.loop.start + '/' + v.loop.end return v.loop.start + '/' + v.loop.end
} else if (v.type === '3') { case '3':
return v.appoint.length > 0 ? v.appoint.join(',') : '' return v.appoint.length > 0 ? v.appoint.join(',') : ''
} else { default:
return '' return ''
} }
}) })

View File

@ -2,7 +2,7 @@
<a-modal <a-modal
:class="['my-modal', modalClass, simpleClass]" :class="['my-modal', modalClass, simpleClass]"
:visible="visible" :visible="visible"
v-bind="$props" v-bind="props"
:width="modalWidth" :width="modalWidth"
:wrap-class-name="wrapClassName + fullscreenClass" :wrap-class-name="wrapClassName + fullscreenClass"
@cancel="handleCancel" @cancel="handleCancel"
@ -27,24 +27,23 @@
<slot name="insertFooter"></slot> <slot name="insertFooter"></slot>
<slot name="footer"> <slot name="footer">
<a-button @click="handleCancel"> <a-button @click="handleCancel">
{{ $props.cancelText || '取消' }} {{ props.cancelText || '取消' }}
</a-button> </a-button>
<slot name="centerFooter"></slot> <slot name="centerFooter"></slot>
<a-button type="primary" @click="handleOk" :loading="loading"> <a-button type="primary" @click="handleOk" :loading="loading">
{{ $props.okText || '确定' }} {{ props.okText || '确定' }}
</a-button> </a-button>
</slot> </slot>
<slot name="appendFooter"></slot> <slot name="appendFooter"></slot>
</template> </template>
</a-modal> </a-modal>
</template> </template>
<script> <script setup>
import props from './props.js' import mixinProps from './props.js'
import { useSlots } from 'vue'
export default { const slots = useSlots()
name: 'DragModal', const props = defineProps({
mixins: [props], ...mixinProps,
props: {
// //
modalClass: { modalClass: {
type: String, type: String,
@ -92,218 +91,194 @@
type: Boolean, type: Boolean,
default: undefined default: undefined
} }
}, })
emits: ['ok', 'close', 'fullscreen'], const emit = defineEmits(['ok', 'close', 'fullscreen'])
data() { const modalWidth = ref('')
return { const contain = ref(null)
modalWidth: '',
contain: null,
// //
header: null, const header = ref(null)
modalContent: null, const modalContent = ref(null)
mouseDownX: 0, const mouseDownX = ref(0)
mouseDownY: 0, const mouseDownY = ref(0)
deltaX: 0, const deltaX = ref(0)
deltaY: 0, const deltaY = ref(0)
sumX: 0, const sumX = ref(0)
sumY: 0, const sumY = ref(0)
onmousedown: false, const onmousedown = ref(false)
// //
modalBody: null, const modalBody = ref(null)
myBody: null, const myBody = ref(null)
prevModalWidth: 0, const prevModalWidth = ref(0)
prevModalHeight: 0, const prevModalHeight = ref(0)
prevBodyWidth: 0, const prevBodyWidth = ref(0)
prevBodyHeight: 0, const prevBodyHeight = ref(0)
startX: 0, const startX = ref(0)
startY: 0, const startY = ref(0)
// //
fullscreenClass: '', const fullscreenClass = ref('')
fullscreenStatus: false const fullscreenStatus = ref(false)
} const slotKeys = computed(() => {
}, return Object.keys(slots)
computed: { })
slotKeys() { const simpleClass = computed(() => {
return Object.keys(this.$slots)
},
simpleClass() {
return Math.random().toString(36).substring(2) return Math.random().toString(36).substring(2)
}
},
watch: {
visible() {
this.$nextTick(() => {
this.initialEvent(this.visible)
}) })
}, onMounted(() => {
fullscreenStatus() { nextTick(() => {
this.fullscreenClass = this.fullscreenStatus ? ' full-modal' : '' initialEvent(props.visible)
}
},
mounted() {
this.$nextTick(() => {
this.initialEvent(this.visible)
}) })
}, })
created() {}, watch(
beforeUnmount() { () => props.visible,
this.removeMove() (newValue) => {
document.removeEventListener('mouseup', this.removeUp, false) nextTick(() => {
this.removeResize() initialEvent(props.visible)
document.removeEventListener('mouseup', this.removeResize) })
}, }
methods: { )
changeWidth(width) { watch(
this.modalWidth = width () => fullscreenStatus.value,
}, (newValue) => {
handleFullScreen(e) { fullscreenClass.value = fullscreenStatus.value ? ' full-modal' : ''
}
)
onBeforeUnmount(() => {
removeMove()
document.removeEventListener('mouseup', removeUp, false)
removeResize()
document.removeEventListener('mouseup', removeResize)
})
const changeWidth = (width) => {
modalWidth.value = width
}
const handleFullScreen = (e) => {
e?.stopPropagation() e?.stopPropagation()
e?.preventDefault() e?.preventDefault()
this.fullscreenStatus = !this.fullscreenStatus fullscreenStatus.value = !fullscreenStatus.value
this.$emit('fullscreen', e) emit('fullscreen', e)
}, }
handleOk(e) { const handleOk = (e) => {
this.reset() reset()
this.$emit('ok', e) emit('ok', e)
}, }
handleCancel(e) { const handleCancel = (e) => {
const classList = e.target?.classList const classList = e.target?.classList
// //
if (classList.contains('ant-modal-close-x') || classList.contains('ant-space-item')) { if (classList.contains('ant-modal-close-x') || classList.contains('ant-space-item')) {
return return
} }
this.reset() reset()
this.$emit('close', e) emit('close', e)
},
reset() {
//
this.mouseDownX = 0
this.mouseDownY = 0
this.deltaX = 0
this.deltaY = 0
this.sumX = 0
this.sumY = 0
//
this.prevModalWidth = 0
this.prevModalHeight = 0
this.prevBodyWidth = 0
this.prevBodyHeight = 0
this.startX = 0
this.startY = 0
//
this.fullscreenStatus = false
},
initialEvent(visible) {
// console.log('--------- ')
// console.log('simpleClass===>', this.simpleClass)
// console.log('document===>', document)
if (visible) {
this.reset()
//
document.removeEventListener('mouseup', this.removeUp, false)
this.contain = document.getElementsByClassName(this.simpleClass)[0]
// console.log('-contain:', this.contain)
this.changeWidth(this.$props.width)
if (this.$props.drag === true) {
this.header = this.contain.getElementsByClassName('ant-modal-header')[0]
this.modalContent = this.contain.getElementsByClassName('ant-modal-content')[0]
this.header.style.cursor = 'all-scroll'
this.modalContent.style.left = 0
this.modalContent.style.transform = 'translate(0px,0px)'
// console.log('-header:', this.header)
// console.log('-modalContent:', this.modalContent)
//
// this.contain.onmousedown = (event) => {
this.header.onmousedown = (event) => {
this.onmousedown = true
this.mouseDownX = event.pageX
this.mouseDownY = event.pageY
document.body.onselectstart = () => false
document.addEventListener('mousemove', this.handleMove, false)
} }
document.addEventListener('mouseup', this.removeUp, false) const reset = () => {
//
mouseDownX.value = 0
mouseDownY.value = 0
deltaX.value = 0
deltaY.value = 0
sumX.value = 0
sumY.value = 0
//
prevModalWidth.value = 0
prevModalHeight.value = 0
prevBodyWidth.value = 0
prevBodyHeight.value = 0
startX.value = 0
startY.value = 0
//
fullscreenStatus.value = false
}
const initialEvent = (visible) => {
if (visible) {
reset()
//
document.removeEventListener('mouseup', removeUp, false)
contain.value = document.getElementsByClassName(simpleClass.value)[0]
changeWidth(props.width)
if (props.drag === true) {
header.value = contain.value.getElementsByClassName('ant-modal-header')[0]
modalContent.value = contain.value.getElementsByClassName('ant-modal-content')[0]
header.value.style.cursor = 'all-scroll'
modalContent.value.style.left = 0
modalContent.value.style.transform = 'translate(0px,0px)'
//
header.value.onmousedown = (event) => {
onmousedown.value = true
mouseDownX.value = event.pageX
mouseDownY.value = event.pageY
document.body.onselectstart = () => false
document.addEventListener('mousemove', handleMove, false)
}
document.addEventListener('mouseup', removeUp, false)
} }
if (this.$props.resize === true) { if (props.resize === true) {
this.modalBody = this.contain.getElementsByClassName('ant-modal-content')[0] modalBody.value = contain.value.getElementsByClassName('ant-modal-content')[0]
this.myBody = this.contain.getElementsByClassName('ant-modal-body')[0] myBody.value = contain.value.getElementsByClassName('ant-modal-body')[0]
this.modalBody.style.overflow = 'hidden' modalBody.value.style.overflow = 'hidden'
this.modalBody.style.resize = 'both' modalBody.value.style.resize = 'both'
this.myBody.style.overflow = 'auto' myBody.value.style.overflow = 'auto'
this.myBody.style.height = 'auto' myBody.value.style.height = 'auto'
// console.log('-modalBody:', this.modalBody)
// console.log('-myBody:', this.myBody)
// //
this.modalBody.onmousedown = (event) => { modalBody.value.onmousedown = (event) => {
event.preventDefault() event.preventDefault()
const rect = this.modalBody.getBoundingClientRect() const rect = modalBody.value.getBoundingClientRect()
const rightBorder = rect.x + rect.width - 17 const rightBorder = rect.x + rect.width - 17
const bottomBorder = rect.y + rect.height - 17 const bottomBorder = rect.y + rect.height - 17
// console.log('rightBorder:' + rightBorder, 'clientX:' + event.clientX)
// console.log('bottomBorder:' + bottomBorder, 'clientY:' + event.clientY)
if (event.clientX >= rightBorder && event.clientY >= bottomBorder) { if (event.clientX >= rightBorder && event.clientY >= bottomBorder) {
this.prevModalWidth = this.modalBody.offsetWidth prevModalWidth.value = modalBody.value.offsetWidth
this.prevModalHeight = this.modalBody.offsetHeight prevModalHeight.value = modalBody.value.offsetHeight
this.prevBodyWidth = this.myBody.offsetWidth prevBodyWidth.value = myBody.value.offsetWidth
this.prevBodyHeight = this.myBody.offsetHeight prevBodyHeight.value = myBody.value.offsetHeight
this.startX = event.clientX startX.value = event.clientX
this.startY = event.clientY startY.value = event.clientY
document.addEventListener('mousemove', handleResize)
document.addEventListener('mousemove', this.handleResize)
} }
document.addEventListener('mouseup', this.removeResize) document.addEventListener('mouseup', removeResize)
} }
} }
} }
}, }
handleMove(event) { const handleMove = (event) => {
if (this.fullscreenStatus) { if (fullscreenStatus.value) {
return return
} }
const delta1X = event.pageX - this.mouseDownX const delta1X = event.pageX - mouseDownX.value
const delta1Y = event.pageY - this.mouseDownY const delta1Y = event.pageY - mouseDownY.value
this.deltaX = delta1X deltaX.value = delta1X
this.deltaY = delta1Y deltaY.value = delta1Y
// console.log('delta1X:' + delta1X, 'sumX:' + this.sumX, 'delta1Y:' + delta1Y, 'sumY:' + this.sumY) modalContent.value.style.transform = `translate(${delta1X + sumX.value}px, ${delta1Y + sumY.value}px)`
this.modalContent.style.transform = `translate(${delta1X + this.sumX}px, ${delta1Y + this.sumY}px)` }
}, const removeMove = () => {
removeMove() { document.removeEventListener('mousemove', handleMove, false)
document.removeEventListener('mousemove', this.handleMove, false) }
}, const removeUp = (event) => {
removeUp(event) {
document.body.onselectstart = () => true document.body.onselectstart = () => true
if (this.onmousedown && !(event.pageX === this.mouseDownX && event.pageY === this.mouseDownY)) { if (onmousedown.value && !(event.pageX === mouseDownX.value && event.pageY === mouseDownY.value)) {
this.onmousedown = false onmousedown.value = false
this.sumX = this.sumX + this.deltaX sumX.value = sumX.value + deltaX.value
this.sumY = this.sumY + this.deltaY sumY.value = sumY.value + deltaY.value
// console.log('sumX:' + this.sumX, 'sumY:' + this.sumY)
} }
this.removeMove() removeMove()
// this.checkMove() }
}, const handleResize = (event) => {
handleResize(event) { if (fullscreenStatus.value) {
if (this.fullscreenStatus) {
return return
} }
const diffX = event.clientX - this.startX const diffX = event.clientX - startX.value
const diffY = event.clientY - this.startY const diffY = event.clientY - startY.value
const minWidth = 180 const minWidth = 180
const minHeight = 0 const minHeight = 0
if (prevBodyWidth.value + diffX > minWidth) {
if (this.prevBodyWidth + diffX > minWidth) { changeWidth(prevModalWidth.value + diffX + 'px')
this.changeWidth(this.prevModalWidth + diffX + 'px')
// this.myBody.style.width = this.prevBodyWidth + diffX + 'px'
} }
if (this.prevBodyHeight + diffY > minHeight) { if (prevBodyHeight.value + diffY > minHeight) {
// this.modalBody.style.height = this.prevModalHeight + diffY + 'px' myBody.value.style.height = prevBodyHeight.value + diffY + 'px'
this.myBody.style.height = this.prevBodyHeight + diffY + 'px'
}
},
removeResize() {
document.removeEventListener('mousemove', this.handleResize)
} }
} }
const removeResize = () => {
document.removeEventListener('mousemove', handleResize)
} }
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -8,12 +8,7 @@
```javascript ```javascript
import Ellipsis from '@/components/Ellipsis' import Ellipsis from '@/components/Ellipsis'
// vue3 不需要利用compoents去注册组件引入后可直接使用
export default {
components: {
Ellipsis
}
}
``` ```

View File

@ -1,13 +1,14 @@
<script lang="jsx"> <template>
<ellipsis />
</template>
<script setup>
import { h } from 'vue'
import Tooltip from 'ant-design-vue/es/tooltip' import Tooltip from 'ant-design-vue/es/tooltip'
import { cutStrByFullLength, getStrFullLength } from './util' import { cutStrByFullLength, getStrFullLength } from './util'
import { useSlots } from 'vue'
const slots = useSlots()
export default { const props = defineProps({
name: 'Ellipsis',
components: {
Tooltip
},
props: {
prefixCls: { prefixCls: {
type: String, type: String,
default: 'ant-pro-ellipsis' default: 'ant-pro-ellipsis'
@ -27,24 +28,21 @@
type: Boolean, type: Boolean,
default: false default: false
} }
}, })
methods: {
getStrDom(str, fullLength) { const str = slots
return <span>{cutStrByFullLength(str, this.length) + (fullLength > this.length ? '...' : '')}</span>
},
getTooltip(fullStr, fullLength) {
return <Tooltip title={fullStr}>{this.getStrDom(fullStr, fullLength)}</Tooltip>
}
},
render() {
const { tooltip, length } = this.$props
const str = this.$slots
.default() .default()
.map((vNode) => vNode.children) .map((vNode) => vNode.children)
.join('') .join('')
const fullLength = getStrFullLength(str) const fullLength = getStrFullLength(str)
const strDom = tooltip && fullLength > length ? this.getTooltip(str, fullLength) : this.getStrDom(str, fullLength) const showStr = cutStrByFullLength(str, props.length) + (fullLength > props.length ? '...' : '')
return strDom
} // 使h
const ellipsis = () => {
return props.tooltip && fullLength > props.length
? h(Tooltip, { title: str }, { default: () => showStr })
: // default: () => xxx
h('span', showStr)
} }
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="baiduMap" :style="{height: `${height}px`}"> <div class="baiduMap" :style="{ height: `${height}px` }">
<div :id="`container-${mid}`" style="width: 100%; height: 100%">地图资源加载中...</div> <div :id="`container-${mid}`" style="width: 100%; height: 100%">地图资源加载中...</div>
</div> </div>
</template> </template>
@ -25,6 +25,7 @@
}, },
plugins: { plugins: {
type: Array, type: Array,
// eslint-disable-next-line vue/require-valid-default-prop
default: ['BMap.ScaleControl', 'BMap.ZoomControl', 'BMap.LocationControl', 'BMap.NavigationControl3D'] default: ['BMap.ScaleControl', 'BMap.ZoomControl', 'BMap.LocationControl', 'BMap.NavigationControl3D']
}, },
viewMode: { viewMode: {

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="gaodeMap" :style="{height: `${height}px`}"> <div class="gaodeMap" :style="{ height: `${height}px` }">
<div :id="`container-${mid}`" style="width: 100%; height: 100%">地图资源加载中...</div> <div :id="`container-${mid}`" style="width: 100%; height: 100%">地图资源加载中...</div>
</div> </div>
</template> </template>
@ -26,6 +26,7 @@
}, },
plugins: { plugins: {
type: Array, type: Array,
// eslint-disable-next-line vue/require-valid-default-prop
default: ['AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation', 'AMap.MarkerCluster'] default: ['AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation', 'AMap.MarkerCluster']
}, },
viewMode: { viewMode: {

View File

@ -36,69 +36,71 @@
</a-tabs> </a-tabs>
</a-modal> </a-modal>
</template> </template>
<script setup>
<script>
import config from '@/assets/icons/mobile' import config from '@/assets/icons/mobile'
export default { const visible = ref(false)
data() { const iconData = ref([])
return { const modelValue = ref('')
visible: false, const activeKey = ref('default')
iconData: [], const iconItemDefault = ref('default')
modelValue: '',
activeKey: 'default', onMounted(() => {
iconItemDefault: 'default' iconData.value.push(...config.icons)
} })
},
mounted() {
this.iconData.push(...config.icons)
},
methods: {
// //
showIconModal(value) { const showIconModal = (value) => {
this.visible = true visible.value = true
this.defaultSetting(value) defaultSetting(value)
}, }
//
defineExpose({
showIconModal
})
// //
defaultSetting(value) { const defaultSetting = (value) => {
if (value) { if (value) {
this.modelValue = value modelValue.value = value
// //
if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) { if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) {
this.activeKey = 'default' activeKey.value = 'default'
if (value.indexOf('-two-tone') > -1) { if (value.indexOf('-two-tone') > -1) {
this.iconItemDefault = 'twotone' iconItemDefault.value = 'twotone'
} else if (value.indexOf('-filled') > -1) { } else if (value.indexOf('-filled') > -1) {
this.iconItemDefault = 'filled' iconItemDefault.value = 'filled'
} }
} else if (value.indexOf('-extend') > -1) { } else if (value.indexOf('-extend') > -1) {
// //
this.activeKey = 'extend' activeKey.value = 'extend'
// , // ,
// this.iconItemDefault = 'json' // this.iconItemDefault = 'json'
} }
} }
}, }
// //
paneChange(e) { const paneChange = (e) => {
if (e.indexOf('default') === -1) { if (e.indexOf('default') === -1) {
this.iconItemDefault = 'default' iconItemDefault.value = 'default'
} }
}, }
// icon // icon
radioGroupChange(e) { const radioGroupChange = (e) => {
this.iconItemDefault = e.target.value iconItemDefault.value = e.target.value
}, }
const emit = defineEmits(['iconCallBack'])
// //
selectIcon(value) { const selectIcon = (value) => {
this.defaultValue = value visible.value = false
this.visible = false
// eslint-disable-next-line vue/require-explicit-emits // eslint-disable-next-line vue/require-explicit-emits
this.$emit('iconCallBack', this.defaultValue) emit('iconCallBack', value)
},
onCancel() {
this.visible = false
}
} }
const onCancel = () => {
visible.value = false
} }
</script> </script>

View File

@ -36,69 +36,72 @@
</a-tabs> </a-tabs>
</a-modal> </a-modal>
</template> </template>
<script setup>
<script>
import config from '@/config/iconSelect' import config from '@/config/iconSelect'
export default { const visible = ref(false)
data() { const iconData = ref([])
return { const modelValue = ref('')
visible: false, const activeKey = ref('default')
iconData: [], const iconItemDefault = ref('default')
modelValue: '',
activeKey: 'default', onMounted(() => {
iconItemDefault: 'default' iconData.value.push(...config.icons)
} })
},
mounted() {
this.iconData.push(...config.icons)
},
methods: {
// //
showIconModal(value) { const showIconModal = (value) => {
this.visible = true visible.value = true
this.defaultSetting(value) defaultSetting(value)
}, }
//
defineExpose({
showIconModal
})
// //
defaultSetting(value) { const defaultSetting = (value) => {
if (value) { if (value) {
this.modelValue = value modelValue.value = value
// //
if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) { if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) {
this.activeKey = 'default' activeKey.value = 'default'
if (value.indexOf('-two-tone') > -1) { if (value.indexOf('-two-tone') > -1) {
this.iconItemDefault = 'twotone' iconItemDefault.value = 'twotone'
} else if (value.indexOf('-filled') > -1) { } else if (value.indexOf('-filled') > -1) {
this.iconItemDefault = 'filled' iconItemDefault.value = 'filled'
} }
} else if (value.indexOf('-extend') > -1) { } else if (value.indexOf('-extend') > -1) {
// //
this.activeKey = 'extend' activeKey.value = 'extend'
// , // ,
// this.iconItemDefault = 'json' // this.iconItemDefault = 'json'
} }
} }
}, }
// //
paneChange(e) { const paneChange = (e) => {
if (e.indexOf('default') === -1) { if (e.indexOf('default') === -1) {
this.iconItemDefault = 'default' iconItemDefault.value = 'default'
} }
}, }
// icon // icon
radioGroupChange(e) { const radioGroupChange = (e) => {
this.iconItemDefault = e.target.value iconItemDefault.value = e.target.value
}, }
const emit = defineEmits(['iconCallBack'])
// //
selectIcon(value) { const selectIcon = (value) => {
this.defaultValue = value visible.value = false
this.visible = false
// eslint-disable-next-line vue/require-explicit-emits // eslint-disable-next-line vue/require-explicit-emits
this.$emit('iconCallBack', this.defaultValue) emit('iconCallBack', value)
},
onCancel() {
this.visible = false
}
} }
const onCancel = () => {
visible.value = false
} }
</script> </script>

View File

@ -13,29 +13,23 @@ iconSelector
```vue ```vue
<template> <template>
<div> <div>
<a-button type="primary" @click="$refs.iconselector.showModal(iconValue)">选择</a-button> <a-button type="primary" @click="openIcon(iconValue)">选择</a-button>
<icon-selector ref="iconselector" @callBack="iconCallBack"/> <icon-selector ref="iconselector" @iconCallBack="iconCallBack" />
</div> </div>
</template> </template>
<script> <script setup>
import iconSelector from '@/components/Selector/iconSelector.vue' const iconselector = ref() // 绑定ref="iconselector"
export default { // 打开icon选择器
name: 'YourView', const openIcon = (iconValue) => {
components: { iconselector.value.showIconModal(iconValue)
iconSelector
},
data () {
return {
} }
}, // 选择后回调
methods: { const iconCallBack = (value) => {
iconCallBack (icon) { console.log('iconCallBack Icon', value)
console.log('iconCallBack Icon', icon)
} }
}
}
</script> </script>
``` ```

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="org-table"> <div class="org-table">
<a-table <a-table
ref="table" ref="tableRef"
size="small" size="small"
:columns="commons" :columns="commons"
:data-source="tableData" :data-source="tableData"
@ -143,7 +143,7 @@
} }
] ]
// ref // ref
const table = ref() const tableRef = ref()
// ref // ref
const selectedTable = ref() const selectedTable = ref()
const tableRecordNum = ref() const tableRecordNum = ref()

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="pos-table"> <div class="pos-table">
<a-table <a-table
ref="table" ref="tableRef"
size="small" size="small"
:columns="commons" :columns="commons"
:data-source="tableData" :data-source="tableData"
@ -143,7 +143,7 @@
} }
] ]
// ref // ref
const table = ref() const tableRef = ref()
// ref // ref
const selectedTable = ref() const selectedTable = ref()
const tableRecordNum = ref() const tableRecordNum = ref()

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="role-table"> <div class="role-table">
<a-table <a-table
ref="table" ref="tableRef"
size="small" size="small"
:columns="commons" :columns="commons"
:data-source="tableData" :data-source="tableData"
@ -143,7 +143,7 @@
} }
] ]
// ref // ref
const table = ref() const tableRef = ref()
// ref // ref
const selectedTable = ref() const selectedTable = ref()
const tableRecordNum = ref() const tableRecordNum = ref()
@ -192,10 +192,13 @@
} }
}) })
// //
// eslint-disable-next-line vue/no-setup-props-destructure
const radioModel = props.radioModel const radioModel = props.radioModel
// //
// eslint-disable-next-line vue/no-setup-props-destructure
const dataIsConverterFlw = props.dataIsConverterFlw const dataIsConverterFlw = props.dataIsConverterFlw
// //
// eslint-disable-next-line vue/no-setup-props-destructure
const roleGlobal = props.roleGlobal const roleGlobal = props.roleGlobal
// //
const current = ref(0) // const current = ref(0) //

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="user-table"> <div class="user-table">
<a-table <a-table
ref="table" ref="tableRef"
size="small" size="small"
:columns="commons" :columns="commons"
:data-source="tableData" :data-source="tableData"
@ -143,7 +143,7 @@
} }
] ]
// ref // ref
const table = ref() const tableRef = ref()
// ref // ref
const selectedTable = ref() const selectedTable = ref()
const tableRecordNum = ref() const tableRecordNum = ref()

View File

@ -39,16 +39,10 @@
switch (arguments.length) { switch (arguments.length) {
case 1: case 1:
return parseInt(Math.random() * minNum + 1, 10) return parseInt(Math.random() * minNum + 1, 10)
// eslint-disable-next-line no-unreachable
break
case 2: case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10) return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10)
// eslint-disable-next-line no-unreachable
break
default: default:
return 0 return 0
// eslint-disable-next-line no-unreachable
break
} }
} }
</script> </script>

View File

@ -21,7 +21,7 @@ Table 重封装组件说明
<template> <template>
<s-table <s-table
ref="table" ref="tableRef"
:rowKey="(record) => record.data.id" :rowKey="(record) => record.data.id"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
@ -99,44 +99,36 @@ export default {
```vue ```vue
<template> <template>
<s-table <s-table ref="tableRef" :columns="columns" :data="loadData" :alert="false" bordered :row-key="(record) => record.id">
ref="table" <!-- #operator 插槽可以放入一些关于表格的操作,比如新增数据。 -->
:columns="columns" <template #operator class="table-operator">
:data="loadData" <a-space>
> <a-button type="primary" @click="">
<span slot="action" slot-scope="text, record"> <template #icon><plus-outlined /></template>
<a>编辑</a> 新增
<a-divider type="vertical"/> </a-button>
<a-dropdown> </a-space>
<a class="ant-dropdown-link"> </template>
更多 <a-icon type="down"/> <!-- #bodyCell 放入column表格列需要显示的数据可以通过判断进行一个自定义显示 -->
</a> <template #bodyCell="{ column, record }">
<a-menu slot="overlay"> <template >
<a-menu-item> <a-avatar style="width: 25px; height: 25px" />
<a href="javascript:;">1st menu item</a> </template>
</a-menu-item> <template v-if="column.dataIndex === 'status'">
<a-menu-item> <!-- 进行自定义显示内容 -->
<a href="javascript:;">2nd menu item</a> </template>
</a-menu-item> <!-- column.dataIndex === 'action' 时,可以进行编辑删除等关于这行数据的一个操作,操作内容可进行自定义 -->
<a-menu-item> <template v-if="column.dataIndex === 'action'">
<a href="javascript:;">3rd menu item</a> <a @click="">编辑</a>
</a-menu-item> </template>
</a-menu> </template>
</a-dropdown>
</span>
</s-table> </s-table>
</template> </template>
<script> <script setup>
import STable from '@/components/table/' import STable from '@/components/table/'
const tableRef = ref() //一定要进行一个表格的ref绑定
export default { const columns = ref([
components: {
STable,
},
data() {
return {
columns: [
{ {
title: '规则编号', title: '规则编号',
dataIndex: 'no', dataIndex: 'no',
@ -162,31 +154,25 @@ export default {
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}, },
], ])
// 查询条件参数 const queryParam = ref({})
queryParam: {}, // 加载按钮数据
// 加载数据方法 必须为 Promise 对象 const loadData = (parameter) => {
loadData: (parameter) => {
return this.$http.get('/service', { return this.$http.get('/service', {
params: Object.assign(parameter, this.queryParam), params: Object.assign(parameter, queryParam.value),
}).then((res) => { }).then((res) => {
return res.result return res.result
}) })
}, }
} const edit = (row) => {
},
methods: {
edit(row) {
// axios 发送数据到后端 修改数据成功后 // axios 发送数据到后端 修改数据成功后
// 调用 refresh() 重新加载列表数据 // 调用 refresh() 重新加载列表数据
// 这里 setTimeout 模拟发起请求的网络延迟.. // 这里 setTimeout 模拟发起请求的网络延迟..
setTimeout(() => { setTimeout(() => {
this.$refs.table.refresh() // refresh() 不传参默认值 false 不刷新到分页第一页 tableRef.value.refresh() // refresh() 不传参默认值 false 不刷新到分页第一页
}, 1500) }, 1500)
}, }
},
}
</script> </script>
``` ```
@ -195,9 +181,9 @@ export default {
内置方法 内置方法
---- ----
通过 `this.$refs.table` 调用 通过 `声明的ref去调用 ==> tableRef.value` 调用
`this.$refs.table.refresh(true)` 刷新列表 (用户新增/修改数据后,重载列表数据) `tableRef.value.refresh(true)` 刷新列表 (用户新增/修改数据后,重载列表数据)
> 注意:要调用 `refresh(bool)` 需要给表格组件设定 `ref` > 注意:要调用 `refresh(bool)` 需要给表格组件设定 `ref`
> >
@ -233,38 +219,82 @@ alert: {
> >
> 文档中的结构有可能由于组件 bug 进行修正而改动。实际修改请以当时最新版本为准 > 文档中的结构有可能由于组件 bug 进行修正而改动。实际修改请以当时最新版本为准
修改 `@/components/table/index.js`156 行起 修改 `@/components/table/index.js`348 行起
```javascript ```javascript
result.then(r => { const data = reactive({
this.localPagination = this.showPagination && Object.assign({}, this.localPagination, { needTotalList: [],
current: r.pageNo, // 返回结果中的当前分页数 localLoading: false,
total: r.totalCount, // 返回结果中的总记录数 localDataSource: [],
showSizeChanger: this.showSizeChanger, localPagination: Object.assign({}, props.pagination),
pageSize: (pagination && pagination.pageSize) || isFullscreen: false,
this.localPagination.pageSize customSize: props.compSize,
}) || false columnsSetting: [],
// 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页 localSettings: {
if (r.data.length === 0 && this.showPagination && this.localPagination.current > 1) { rowClassName: props.rowClassName,
this.localPagination.current-- rowClassNameSwitch: Boolean(props.rowClassName)
this.loadData() }
})
// 这里的 data.xxx 是之前声明的
// 在 loadData() 方法中去获取后端数据,进行一个数据的加载更新
result.then((r) => {
if (r == null) {
data.localLoading = false
return return
} }
data.localPagination =
(props.showPagination &&
Object.assign({}, data.localPagination, {
current: r.current, // pageNo, // 返回结果中的当前分页数
total: r.total, // totalRows, // 返回结果中的总记录数
showSizeChanger: props.showSizeChanger,
pageSizeOptions: props.pageSizeOptions,
showTotal: (total, range) => {
return `${range[0]}-${range[1]} 共 ${total} 条 `
},
pageSize: (pagination && pagination.pageSize) || data.localPagination.pageSize
})) ||
false
// 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小 // 后端数据records为null保存修复
if (r.records == null) {
r.records = []
}
// 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
if (r.records.length === 0 && props.showPagination && data.localPagination.current > 1) {
data.localPagination.current--
loadData()
return
}
// 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能 // 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能
try { try {
if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.pageNo * this.localPagination.pageSize))) { /*
this.localPagination.hideOnSinglePage = true if ((['auto', true].includes(props.showPagination) && r.total <= (r.pages * data.localPagination.size))) {
data.localPagination.hideOnSinglePage = true
}
*/
if (!props.showPagination) {
data.localPagination.hideOnSinglePage = true
} }
} catch (e) { } catch (e) {
this.localPagination = false data.localPagination = false
} }
console.log('loadData -> this.localPagination', this.localPagination) // 返回结果中的数组数据
this.localDataSource = r.data // 返回结果中的数组数据 if (props.showPagination === false) {
this.localLoading = false // 既然配置了不分页,那么我们这里接收到肯定是数组
data.localDataSource = []
if (r instanceof Array) {
data.localDataSource = r
}
} else {
data.localDataSource = r.records
}
data.localLoading = false
getTableProps() // 获取到后端返回的数据后需要调用一下获取table的props的方法去刷新table
}) })
``` ```
返回 JSON 例子: 返回 JSON 例子:
@ -336,4 +366,4 @@ result.then(r => {
更新时间 更新时间
---- ----
该文档最后更新于: 2019-06-23 PM 17:19 该文档最后更新于: 2023-12-27 PM 16:45

View File

@ -22,76 +22,70 @@
</div> </div>
</div> </div>
</template> </template>
<script setup>
<script> import Draggable from 'vuedraggable-es'
import draggable from 'vuedraggable-es' const emit = defineEmits(['columnChange'])
const props = defineProps({
export default {
components: {
draggable
},
props: {
columns: { columns: {
type: Array, type: Array,
default: () => [] default: () => []
} }
}, })
data() {
return { const indeterminate = ref(false)
indeterminate: false, const checkAll = ref(true)
checkAll: true, const columnsSetting = ref([])
columnsSetting: [], const originColumns = ref()
originColumns: []
} onMounted(() => {
}, columnsSetting.value = props.columns.map((value) => {
mounted() { if (value.checked === undefined) {
this.columnsSetting = this.columns.map((value) => {
if (value.checked == undefined) {
return { return {
...value, ...value,
checked: true checked: true
} }
} else return value } else return value
}) })
// originColumns // originColumns
this.originColumns = this.columnsSetting.map((value) => ({ ...value })) originColumns.value = columnsSetting.value.map((value) => ({ ...value }))
// //
const notCheckedList = this.columnsSetting.filter((value) => !value.checked) const notCheckedList = columnsSetting.value.filter((value) => !value.checked)
if (notCheckedList.length) this.checkAll = false if (notCheckedList.length) checkAll.value = false
}, })
methods: {
reset() { const reset = () => {
this.columnsSetting = this.originColumns.map((value) => ({ ...value })) columnsSetting.value = originColumns.value.map((value) => ({ ...value }))
this.indeterminate = false indeterminate.value = false
const checkedList = this.columnsSetting.filter((value) => value.checked) const checkedList = columnsSetting.value.filter((value) => value.checked)
this.checkAll = checkedList.length === this.columnsSetting.length checkAll.value = checkedList.length === columnsSetting.value.length
this.emitColumnChange() emitColumnChange()
}, }
onChange() {
const checkedList = this.columnsSetting.filter((value) => value.checked) const onChange = () => {
this.indeterminate = Boolean(checkedList.length) && checkedList.length < this.columnsSetting.length const checkedList = columnsSetting.value.filter((value) => value.checked)
this.checkAll = checkedList.length === this.columnsSetting.length indeterminate.value = Boolean(checkedList.length) && checkedList.length < columnsSetting.value.length
this.emitColumnChange() checkAll.value = checkedList.length === columnsSetting.value.length
}, emitColumnChange()
onCheckAllChange(e) { }
//
const onCheckAllChange = (e) => {
e.preventDefault() e.preventDefault()
const val = e.target.checked const val = e.target.checked
Object.assign(this, {
indeterminate: false, indeterminate.value = false
checkAll: val, checkAll.value = val
columnsSetting: this.columns.map((value) => ({ columnsSetting.value = props.columns.map((value) => ({
...value, ...value,
checked: val checked: val
})) }))
}) emitColumnChange()
this.emitColumnChange() }
},
emitColumnChange() { const emitColumnChange = () => {
// eslint-disable-next-line vue/require-explicit-emits // eslint-disable-next-line vue/require-explicit-emits
this.$emit('columnChange', this.columnsSetting) emit('columnChange', columnsSetting.value)
}
}
} }
</script> </script>
<style lang="less" scoped></style>

View File

@ -1,36 +1,128 @@
<script lang="jsx"> <template>
<div className="table-wrapper">
<div className="s-table-tool">
<div className="s-table-tool-left">
<!-- 插槽操作按钮 -->
<slot name="operator"></slot>
</div>
<!-- 斑马纹 -->
<div className="layout-items-center s-table-tool-right">
<div className="layout-items-center ml-4" v-show="props.toolConfig.striped">
<a-checkbox :checked="data.localSettings.rowClassNameSwitch" @change="changeRowClass"> </a-checkbox>
</div>
<span v-for="item in tool">
<!-- 刷新 -->
<a-tooltip
v-if="item.name === 'refresh' && props.toolConfig.refresh"
:title="item.title"
class="s-tool-item"
@click="refresh"
>
<component class="icons" :is="item.icon"></component>
</a-tooltip>
<!-- 列展示 -->
<a-popover
v-if="item.isPopover && item.name === 'columnSetting' && props.toolConfig.columnSetting"
trigger="click"
placement="topLeft"
overlayClassName="s-table-column-settings"
arrow-point-at-center
>
<template #content>
<columnSetting :columns="props.columns" @columnChange="columnChange" />
</template>
<a-tooltip :title="item.title" class="s-tool-item">
<component class="icons" :is="item.icon"></component>
</a-tooltip>
</a-popover>
<!-- 密度 -->
<a-dropdown trigger="click" v-if="item.isDropdown && item.name == 'height' && props.toolConfig.height">
<template #overlay>
<a-menu selectable :selectedKeys="[data.customSize]" @click="changeHeight">
<a-menu-item key="default">默认</a-menu-item>
<a-menu-item key="middle">中等</a-menu-item>
<a-menu-item key="small">紧凑</a-menu-item>
</a-menu>
</template>
<a-tooltip :title="item.title" class="s-tool-item">
<component class="icons" :is="item.icon"></component>
</a-tooltip>
</a-dropdown>
</span>
</div>
</div>
<!-- 统计列数据 -->
<a-alert showIcon class="mb-4" v-if="props.alert">
<template #message>
<div>
<span className="mr-3">
已选择:{{ ' ' }}
<a className="font-6">
{{
props.rowSelection && props.rowSelection.selectedRowKeys ? props.rowSelection.selectedRowKeys.length : 0
}}
</a>
</span>
<span className="mr-3" v-for="item in data.needTotalList">
{{ item.title }} 总计{{ ' ' }}
<a className="font-6">{{ !item.customRender ? item.total : item.customRender(item.total) }}</a>
</span>
<a
v-show="
props.rowSelection && props.rowSelection.selectedRowKeys && props.rowSelection.selectedRowKeys.length > 0
"
className="ml-6"
@click="
rowClear(
typeof props.alert === 'boolean' && props.alert
? clearSelected()
: props.alert.clear && typeof props.alert.clear === 'function'
? props.alert.clear()
: null
)
"
>
{{ ' ' }}
清空{{ ' ' }}
</a>
</div>
</template>
</a-alert>
<!-- 表格 -->
<a-table
v-bind="{ ...renderTableProps, ...data.localSettings }"
@change="loadData"
:row-key="(record) => record.id"
@expand="
(expanded, record) => {
emit('expand', expanded, record)
}
"
>
<template #[item]="scope" v-for="item in renderSlots">
<slot :name="item" :scope="scope" v-bind="scope || {}"></slot>
</template>
</a-table>
</div>
</template>
<script setup>
import './index.less'
import { tableProps } from 'ant-design-vue/es/table/Table.js' import { tableProps } from 'ant-design-vue/es/table/Table.js'
import { get } from 'lodash-es'
import draggable from 'vuedraggable-es'
import columnSetting from './columnSetting.vue' import columnSetting from './columnSetting.vue'
import './index.less' import './index.less'
import i18n from '@/locales'
const { t } = i18n.global import { useSlots } from 'vue'
import { useRoute } from 'vue-router'
const slots = useSlots()
const route = useRoute()
const emit = defineEmits(['expand'])
const renderSlots = Object.keys(slots)
export default { const props = defineProps(
name: 'STable', Object.assign({}, tableProps(), {
components: {
draggable,
columnSetting
},
data() {
return {
needTotalList: [],
localLoading: false,
localDataSource: [],
localPagination: Object.assign({}, this.pagination),
isFullscreen: false,
customSize: this.compSize,
columnsSetting: [],
localSettings: {
rowClassName: this.rowClassName,
rowClassNameSwitch: Boolean(this.rowClassName)
}
}
},
// eslint-disable-next-line vue/order-in-components
props: Object.assign({}, tableProps(), {
rowKey: { rowKey: {
type: [String, Function], type: [String, Function],
default: 'key' default: 'key'
@ -97,82 +189,161 @@
striped: false striped: false
}) })
} }
}),
watch: {
pageNum(val) {
Object.assign(this.localPagination, {
current: val
}) })
}, )
size(val) {
Object.assign(this.localPagination, { const data = reactive({
size: val needTotalList: [],
}) localLoading: false,
}, localDataSource: [],
showSizeChanger(val) { localPagination: Object.assign({}, props.pagination),
Object.assign(this.localPagination, { isFullscreen: false,
showSizeChanger: val customSize: props.compSize,
}) columnsSetting: [],
}, localSettings: {
columns(v) { rowClassName: props.rowClassName,
this.columnsSetting = v rowClassNameSwitch: Boolean(props.rowClassName)
} }
})
watch(
() => props.pageNum,
(newVal) => {
Object.assign(data.localPagination, {
current: newVal
})
}
)
watch(
() => props.size,
(newVal) => {
Object.assign(data.localPagination, {
size: newVal
})
}
)
watch(
() => props.showSizeChanger,
(newVal) => {
Object.assign(data.localPagination, {
showSizeChanger: newVal
})
}
)
watch(
() => props.columns,
(newVal) => {
data.columnsSetting = newVal
}
)
// props
const renderTableProps = ref([])
//
const tool = [
{
name: 'refresh',
icon: 'sync-outlined',
title: '刷新'
}, },
created() { {
const { current } = this.$route.params name: 'height',
const localPageNum = (current && parseInt(current)) || this.pageNum icon: 'column-height-outlined',
this.localPagination = title: '密度',
(['auto', true].includes(this.showPagination) && isDropdown: true
Object.assign({}, this.localPagination, { },
{
name: 'columnSetting',
icon: 'setting-outlined',
title: '列设置',
isPopover: true,
visible: false
}
]
//
const refresh = (bool = false) => {
bool &&
(data.localPagination = Object.assign(
{},
{
current: 1,
pageSize: data.localPagination.pageSize
}
))
loadData()
getTableProps()
}
//
const changeRowClass = (value) => {
const val = value.target.checked
data.localSettings.rowClassNameSwitch = val
const evenClass = val ? (_record, index) => (index % 2 === 1 ? 'table-striped' : null) : props.rowClassName
data.localSettings.rowClassName = evenClass
}
//
const changeHeight = (v) => {
data.customSize = v.key
getTableProps()
}
//
const columnChange = (val) => {
data.columnsSetting = val
getTableProps()
}
//
const rowClear = (callback) => {
callback
clearSelected()
}
//
const init = () => {
const { current } = route.params
const localPageNum = (current && parseInt(current)) || props.pageNum
data.localPagination =
(['auto', true].includes(props.showPagination) &&
Object.assign({}, data.localPagination, {
current: localPageNum, current: localPageNum,
pageSize: this.size, //this.compSize, size// pageSize: props.size, //props.compSize, size//
showSizeChanger: this.showSizeChanger, showSizeChanger: props.showSizeChanger,
defaultPageSize: this.defaultPageSize, defaultPageSize: props.defaultPageSize,
pageSizeOptions: this.pageSizeOptions, pageSizeOptions: props.pageSizeOptions,
showTotal: (total, range) => { showTotal: (total, range) => {
return `${range[0]}-${range[1]}${total}` return `${range[0]}-${range[1]}${total}`
} }
})) || })) ||
false false
this.needTotalList = this.initTotalList(this.columns) data.needTotalList = initTotalList(props.columns)
this.loadData() data.columnsSetting = props.columns
this.columnsSetting = this.columns loadData()
/*.map((c) => {
const tt = c.title
if (typeof tt === 'string') {
c.title = () => t(tt)
} }
return c const initTotalList = (columns) => {
})*/ const totalList = []
}, columns &&
methods: { columns instanceof Array &&
// true, columns.forEach((column) => {
refresh(bool = false) { if (column.needTotal) {
bool && totalList.push({
(this.localPagination = Object.assign( ...column,
{}, total: 0
{ })
current: 1, }
pageSize: this.localPagination.pageSize })
return totalList
} }
))
this.loadData()
},
// //
loadData(pagination, filters, sorter) { const loadData = (pagination, filters, sorter) => {
this.localLoading = true data.localLoading = true
const parameter = Object.assign( const parameter = Object.assign(
{ {
current: current:
(pagination && pagination.current) || (pagination && pagination.current) || (props.showPagination && data.localPagination.current) || props.pageNum,
(this.showPagination && this.localPagination.current) ||
this.pageNum,
// 使size // 使size
size: size:
(pagination && pagination.pageSize) || (pagination && pagination.pageSize) ||
(this.showPagination && this.localPagination.pageSize) || (props.showPagination && data.localPagination.pageSize) ||
this.pageSize || props.pageSize ||
this.localPagination.pageSize data.localPagination.pageSize
}, },
(sorter && (sorter &&
sorter.field && { sorter.field && {
@ -188,85 +359,158 @@
...filters ...filters
} }
) )
const result = this.data(parameter) const result = props.data(parameter)
if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') { if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
result.then((r) => { result.then((r) => {
if (r == null) { if (r == null) {
this.localLoading = false data.localLoading = false
return return
} }
this.localPagination = data.localPagination =
(this.showPagination && (props.showPagination &&
Object.assign({}, this.localPagination, { Object.assign({}, data.localPagination, {
current: r.current, // pageNo, // current: r.current, // pageNo, //
total: r.total, // totalRows, // total: r.total, // totalRows, //
showSizeChanger: this.showSizeChanger, showSizeChanger: props.showSizeChanger,
pageSizeOptions: this.pageSizeOptions, pageSizeOptions: props.pageSizeOptions,
showTotal: (total, range) => { showTotal: (total, range) => {
return `${range[0]}-${range[1]}${total}` return `${range[0]}-${range[1]}${total}`
}, },
pageSize: (pagination && pagination.pageSize) || this.localPagination.pageSize pageSize: (pagination && pagination.pageSize) || data.localPagination.pageSize
})) || })) ||
false false
// recordsnull // recordsnull
if (r.records == null) { if (r.records == null) {
r.records = [] r.records = []
} }
// 0 , // 0 ,
if (r.records.length === 0 && this.showPagination && this.localPagination.current > 1) { if (r.records.length === 0 && props.showPagination && data.localPagination.current > 1) {
this.localPagination.current-- data.localPagination.current--
this.loadData() loadData()
return return
} }
// table // table
try { try {
/* /*
if ((['auto', true].includes(this.showPagination) && r.total <= (r.pages * this.localPagination.size))) { if ((['auto', true].includes(props.showPagination) && r.total <= (r.pages * data.localPagination.size))) {
this.localPagination.hideOnSinglePage = true data.localPagination.hideOnSinglePage = true
} }
*/ */
if (!this.showPagination) { if (!props.showPagination) {
this.localPagination.hideOnSinglePage = true data.localPagination.hideOnSinglePage = true
} }
} catch (e) { } catch (e) {
this.localPagination = false data.localPagination = false
} }
// //
if (this.showPagination === false) { if (props.showPagination === false) {
// //
this.localDataSource = [] data.localDataSource = []
if (r instanceof Array) { if (r instanceof Array) {
this.localDataSource = r data.localDataSource = r
} }
} else { } else {
this.localDataSource = r.records data.localDataSource = r.records
} }
this.localLoading = false data.localLoading = false
getTableProps()
}) })
} }
},
initTotalList(columns) {
const totalList = []
columns &&
columns instanceof Array &&
columns.forEach((column) => {
if (column.needTotal) {
totalList.push({
...column,
total: 0
})
} }
// props
const getTableProps = () => {
let renderProps = {}
const localKeys = Object.keys(data)
Object.keys(tableProps()).forEach((k) => {
const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
if (localKeys.includes(localKey)) {
renderProps[k] = data[localKey]
return renderProps[k]
}
if (k === 'rowSelection') {
if (props.rowSelection) {
// 使alert rowSelection
renderProps[k] = {
...props.rowSelection,
onChange: (selectedRowKeys, selectedRows) => {
updateSelect(selectedRowKeys, selectedRows)
typeof props[k].onChange !== 'undefined' && props[k].onChange(selectedRowKeys, selectedRows)
}
}
return renderProps[k]
} else if (!props.rowSelection) {
// rowSelection
renderProps[k] = null
return renderProps[k]
}
}
if (k === 'customRow') {
if (props.lineSelection && props.rowSelection) {
// customRow
renderProps[k] = (record, index) => {
return {
...(typeof props.customRow !== 'undefined' && props.customRow(record, index)),
onClick: (event) => {
// onClick
typeof data[k] !== 'undefined' &&
typeof data[k](record, index).onClick !== 'undefined' &&
data[k](record, index).onClick(event)
// disabled
const rowDisabled =
typeof props.rowSelection.getCheckboxProps !== 'undefined' &&
props.rowSelection.getCheckboxProps(record).disabled
if (rowDisabled) return
//
const classList = event.target?.classList
if (!classList.contains('ant-table-cell')) return
const key = (typeof props.rowKey === 'function' && props.rowKey(record)) || props.rowKey || index
let selectedRows = props.rowSelection.selectedRows
let selectedRowKeys = props.rowSelection.selectedRowKeys
const rowType = props.rowSelection?.type || 'checkbox'
if (rowType === 'radio' || props.rowSelection.selectedRowKeys === undefined) {
selectedRowKeys = [key]
selectedRows = [record]
} else if (!props.rowSelection.selectedRowKeys?.includes(key)) {
selectedRowKeys.push(key)
selectedRows.push(record)
} else {
const index = props.rowSelection.selectedRowKeys?.findIndex((itemKey) => itemKey === key)
selectedRows.splice(index, 1)
selectedRowKeys.splice(index, 1)
}
updateSelect(selectedRowKeys, selectedRows)
}
}
}
return renderProps[k]
}
}
data[k] && (renderProps[k] = data[k])
//
renderProps = {
...renderProps,
bordered: props.bordered,
size: data.customSize, // sizea-tablecompSize
columns: data.columnsSetting.filter((value) => value.checked === undefined || value.checked)
}
return renderProps[k]
}) })
return totalList renderTableProps.value = renderProps
}, }
// total // total
updateSelect(selectedRowKeys, selectedRows) { const updateSelect = (selectedRowKeys, selectedRows) => {
if (this.rowSelection) { if (props.rowSelection) {
this.rowSelection.selectedRows = selectedRows // eslint-disable-next-line vue/no-mutating-props
this.rowSelection.selectedRowKeys = selectedRowKeys props.rowSelection.selectedRows = selectedRows
// eslint-disable-next-line vue/no-mutating-props
props.rowSelection.selectedRowKeys = selectedRowKeys
getTableProps()
} }
const list = this.needTotalList const list = data.needTotalList
this.needTotalList = list.map((item) => { data.needTotalList = list.map((item) => {
return { return {
...item, ...item,
total: selectedRows.reduce((sum, val) => { total: selectedRows.reduce((sum, val) => {
@ -275,290 +519,26 @@
}, 0) }, 0)
} }
}) })
}, }
// table // table
clearSelected() { const clearSelected = () => {
if (this.rowSelection) { if (props.rowSelection) {
this.rowSelection.onChange([], []) props.rowSelection.onChange([], [])
this.updateSelect([], []) updateSelect([], [])
getTableProps()
}
} }
},
// //
clearRefreshSelected(bool = false) { const clearRefreshSelected = (bool = false) => {
this.refresh(bool) refresh(bool)
this.clearSelected() clearSelected()
},
// table 使 clear
renderClear(callback) {
if (this.rowSelection && this.rowSelection.selectedRowKeys && this.rowSelection.selectedRowKeys.length > 0) {
return (
<a
className="ml-6"
onClick={() => {
callback()
this.clearSelected()
}}>
{' '}
清空{' '}
</a>
)
} else {
return null
} }
}, //
renderAlert() { defineExpose({
// clearRefreshSelected,
const needTotalItems = this.needTotalList.map((item) => { refresh
return (
<span className="mr-3">
{item.title} 总计{' '}
<a className="font-6">{!item.customRender ? item.total : item.customRender(item.total)}</a>
</span>
)
}) })
// alert onMounted(() => {
if (alert) { init()
const showAlert =
(typeof this.alert === 'object' &&
this.alert !== null &&
this.alert.show &&
typeof this.rowSelection.selectedRowKeys !== 'undefined') ||
this.alert
if (showAlert) {
//
const clearItem =
typeof this.alert === 'boolean' && this.alert
? this.renderClear(this.clearSelected)
: this.alert.clear && typeof this.alert.clear === 'function'
? this.renderClear(this.alert.clear)
: null
const message = (
<div>
<span className="mr-3">
已选择:{' '}
<a className="font-6">
{this.rowSelection && this.rowSelection.selectedRowKeys
? this.rowSelection.selectedRowKeys.length
: 0}
</a>
</span>
{needTotalItems}
{clearItem}
</div>
)
return <a-alert showIcon class="mb-4" message={message} />
}
}
},
columnChange(val) {
this.columnsSetting = val
},
renderHeader() {
let tools = [
{
name: 'refresh',
icon: <sync-outlined class="ml-4" />,
title: '刷新',
onClick: () => {
this.refresh()
}
},
{
name: 'height',
icon: <column-height-outlined />,
title: '密度',
isDropdown: true,
menu: () => {
const onClick = ({ key }) => {
this.customSize = key
}
return (
<a-menu onClick={onClick} selectable selectedKeys={[this.customSize]}>
<a-menu-item key="default">默认</a-menu-item>
<a-menu-item key="middle">中等</a-menu-item>
<a-menu-item key="small">紧凑</a-menu-item>
</a-menu>
)
},
onClick: () => {}
},
{
name: 'columnSetting',
icon: <setting-outlined />,
title: '列设置',
isPopover: true,
visible: false,
menu: () => {
return <columnSetting columns={this.columns} onColumnChange={this.columnChange} />
},
onClick: () => {}
}
]
if (this.extraTool.length) {
tools = tools.concat(this.extraTool)
}
//
const changeRowClass = (value) => {
const val = value.target.checked
this.localSettings.rowClassNameSwitch = val
const evenClass = val ? (_record, index) => (index % 2 === 1 ? 'table-striped' : null) : this.rowClassName
this.localSettings.rowClassName = evenClass
}
return (
<div className="s-table-tool">
<div className="s-table-tool-left">{this.$slots.operator && this.$slots.operator()}</div>
<div className="layout-items-center s-table-tool-right">
{this.toolConfig.striped ? (
<div className="layout-items-center ml-4">
<a-checkbox checked={this.localSettings.rowClassNameSwitch} onChange={changeRowClass}>
斑马纹
</a-checkbox>
</div>
) : null}
{tools.map((tool) => {
if (!this.toolConfig[tool.name]) {
return null
}
const tooltipEle = (
<a-tooltip title={tool.title} class="s-tool-item" onClick={tool.onClick}>
{tool.icon}
</a-tooltip>
)
if (tool.isPopover) {
return (
<a-popover
trigger={'click'}
placement="topLeft"
overlayClassName="s-table-column-settings"
arrow-point-at-center
content={tool.menu()}>
{tooltipEle}
</a-popover>
)
}
if (tool.isDropdown) {
return (
<a-dropdown trigger={['click']} overlay={tool.menu()}>
{tooltipEle}
</a-dropdown>
)
}
return tooltipEle
})}
</div>
</div>
)
}
},
render() {
let props = {}
const localKeys = Object.keys(this.$data)
Object.keys(tableProps()).forEach((k) => {
const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
if (localKeys.includes(localKey)) {
props[k] = this[localKey]
return props[k]
}
if (k === 'rowSelection') {
if (this.rowSelection) {
// 使alert rowSelection
props[k] = {
...this.rowSelection,
onChange: (selectedRowKeys, selectedRows) => {
this.updateSelect(selectedRowKeys, selectedRows)
typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
}
}
return props[k]
} else if (!this.rowSelection) {
// rowSelection
props[k] = null
return props[k]
}
}
if (k === 'customRow') {
if (this.lineSelection && this.rowSelection) {
// customRow
props[k] = (record, index) => {
return {
...(typeof this.customRow !== 'undefined' && this.customRow(record, index)),
onClick: (event) => {
// onClick
typeof this[k] !== 'undefined' &&
typeof this[k](record, index).onClick !== 'undefined' &&
this[k](record, index).onClick(event)
// disabled
const rowDisabled =
typeof this.rowSelection.getCheckboxProps !== 'undefined' &&
this.rowSelection.getCheckboxProps(record).disabled
if (rowDisabled) return
//
const classList = event.target?.classList
if (!classList.contains('ant-table-cell')) return
const key = (typeof this.rowKey === 'function' && this.rowKey(record)) || this.rowKey || index
let selectedRows = this.rowSelection.selectedRows
let selectedRowKeys = this.rowSelection.selectedRowKeys
const rowType = this.rowSelection?.type || 'checkbox'
if (rowType === 'radio' || this.rowSelection.selectedRowKeys === undefined) {
selectedRowKeys = [key]
selectedRows = [record]
} else if (!this.rowSelection.selectedRowKeys?.includes(key)) {
selectedRowKeys.push(key)
selectedRows.push(record)
} else {
const index = this.rowSelection.selectedRowKeys?.findIndex((itemKey) => itemKey === key)
selectedRows.splice(index, 1)
selectedRowKeys.splice(index, 1)
}
this.updateSelect(selectedRowKeys, selectedRows)
typeof this.rowSelection.onChange !== 'undefined' &&
this.rowSelection.onChange(selectedRowKeys, selectedRows)
}
}
}
return props[k]
}
}
this[k] && (props[k] = this[k])
//
props = {
...props,
size: this.customSize, // sizea-tablecompSize
columns: this.columnsSetting.filter((value) => value.checked === undefined || value.checked)
}
// 使scroll使
if (!props.scroll) {
props.scroll = { x: 1000 }
//
if (props.columns && props.columns.length > 10) {
props.scroll = { x: 1200 }
}
}
return props[k]
}) })
const table = (
<a-table
{...props}
{...this.localSettings}
v-slots={this.$slots}
onChange={this.loadData}
onExpand={(expanded, record) => {
this.$emit('expand', expanded, record)
}}
/>
)
return (
<div className="table-wrapper">
{this.renderHeader()}
{this.renderAlert()}
{table}
</div>
)
}
}
</script> </script>

View File

@ -8,7 +8,7 @@
<a-tag color="orange">{{ item.title }}</a-tag> <a-tag color="orange">{{ item.title }}</a-tag>
</template> </template>
<template #actions> <template #actions>
<template v-for="{ key, label, icon, color } in props.actions"> <template v-for="{ key, label, icon, color } in props.actions" :key="key">
<a-tooltip :title="label"> <a-tooltip :title="label">
<component :is="icon" @click="doAction(key, item)" :style="{ color: color }" /> <component :is="icon" @click="doAction(key, item)" :style="{ color: color }" />
</a-tooltip> </a-tooltip>
@ -22,9 +22,11 @@
<span class="xn-card-meta-title">{{ item.subTitle }}</span> <span class="xn-card-meta-title">{{ item.subTitle }}</span>
</template> </template>
<template #description> <template #description>
<div v-if="item.contents" v-for="content in item.contents"> <div v-if="item.contents">
<div v-for="content in item.contents" :key="content.value">
<span>{{ content.label }}{{ content.value }}</span> <span>{{ content.label }}{{ content.value }}</span>
</div> </div>
</div>
</template> </template>
</a-card-meta> </a-card-meta>
</a-card> </a-card>

View File

@ -3,86 +3,80 @@
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<script setup>
<script> const props = defineProps({
export default {
name: 'XnContextMenu',
props: {
target: null, target: null,
show: Boolean show: Boolean
},
data() {
return {
triggerShowFn: () => {},
triggerHideFn: () => {},
x: null,
y: null,
style: {},
binded: false
}
},
watch: {
show(show) {
if (show) {
this.bindHideEvents()
} else {
this.unbindHideEvents()
}
},
target(target) {
this.bindEvents()
}
},
mounted() {
this.bindEvents()
},
methods: {
//
bindEvents() {
this.$nextTick(() => {
if (!this.target || this.binded) return
this.triggerShowFn = this.contextMenuHandler.bind(this)
this.target.addEventListener('contextmenu', this.triggerShowFn)
this.binded = true
}) })
},
// const x = ref(null)
unbindEvents() { const y = ref(null)
if (!this.target) return const style = ref({})
this.target.removeEventListener('contextmenu', this.triggerShowFn) const binded = ref(false)
}, const emit = defineEmits(['update:show', 'get-context-menu'])
// show
watch(
() => props.show,
(newValue) => {
newValue ? bindHideEvents() : unbindHideEvents()
}
)
watch(
() => props.target,
(newValue) => {
bindEvents()
}
)
//
const bindEvents = (e) => {
nextTick(() => {
if (!props.target || binded.value) return
props.target.addEventListener('contextmenu', contextMenuHandler)
binded.value = true
})
}
// //
bindHideEvents() { const bindHideEvents = () => {
this.triggerHideFn = this.clickDocumentHandler.bind(this) document.addEventListener('mousedown', clickDocumentHandler)
document.addEventListener('mousedown', this.triggerHideFn) document.addEventListener('mousewheel', clickDocumentHandler)
document.addEventListener('mousewheel', this.triggerHideFn) }
},
// //
unbindHideEvents() { const unbindHideEvents = () => {
document.removeEventListener('mousedown', this.triggerHideFn) document.removeEventListener('mousedown', clickDocumentHandler)
document.removeEventListener('mousewheel', this.triggerHideFn) document.removeEventListener('mousewheel', clickDocumentHandler)
}, }
// //
clickDocumentHandler(e) { const clickDocumentHandler = () => {
this.$emit('update:show', false) emit('update:show', false)
}, }
// //
contextMenuHandler(e) { const contextMenuHandler = (e) => {
this.x = e.clientX x.value = e.clientX
this.y = e.clientY y.value = e.clientY
this.layout() layout()
this.$emit('update:show', true) emit('update:show', true)
this.$emit('get-context-menu', e) emit('get-context-menu', e)
e.preventDefault() e.preventDefault()
}, }
// //
layout() { const layout = () => {
this.style = { style.value = {
left: this.x + 'px', left: x.value + 'px',
top: this.y + 'px', top: y.value + 'px',
display: 'block' display: 'block'
} }
} }
}
//
const unbindEvents = () => {
if (!props.target) return
props.target.removeEventListener('contextmenu', contextMenuHandler)
} }
</script> </script>

View File

@ -4,44 +4,50 @@
<slot :name="slotKey" /> <slot :name="slotKey" />
</template> </template>
</a-modal> </a-modal>
<a-drawer v-else :visible="visible" v-bind="$attrs" :footer-style="{ textAlign: 'right' }"> <a-drawer v-else :visible="visible" v-bind="$attrs" @close="cancel" :footer-style="{ textAlign: 'right' }">
<template v-for="slotKey in slotKeys" #[slotKey]> <template v-for="slotKey in slotKeys" #[slotKey]>
<slot :name="slotKey" /> <slot :name="slotKey" />
</template> </template>
</a-drawer> </a-drawer>
</template> </template>
<script> <script setup>
import { mapState } from 'pinia' import { useSlots } from 'vue'
import { globalStore } from '@/store' const slots = useSlots()
const FormContainerTypeEnum = { import { globalStore } from '@/store'
DRAWER: 'drawer', const store = globalStore()
MODAL: 'modal' const props = defineProps({
}
export default {
name: 'XnFormContainer',
inheritAttrs: false,
props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false,
required: true required: true
} }
}, })
computed: {
...mapState(globalStore, ['formStyle']), const FormContainerTypeEnum = {
slotKeys() { DRAWER: 'drawer',
return Object.keys(this.$slots) MODAL: 'modal'
},
isModal() {
return FormContainerTypeEnum.MODAL === this.formStyle
}
},
methods: {
cancel() {
this.$emit('close')
}
} }
const formStyle = computed(() => {
return store.formStyle
})
const slotKeys = computed(() => {
return Object.keys(slots)
})
const isModal = computed(() => {
return FormContainerTypeEnum.MODAL === formStyle.value
})
const emit = defineEmits(['close'])
const cancel = () => {
emit('close')
}
</script>
<script>
//
export default {
inheritAttrs: false
} }
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<!-- 本组件这兄弟写的很好 请参照https://blog.csdn.net/weixin_41897680/article/details/124925222--> <!-- 本组件这兄弟写的很好 请参照https://blog.csdn.net/weixin_41897680/article/details/124925222-->
<div class="hljs-container" :codetype="props.language"> <div class="hljs-container" :codetype="props.language">
<highlightjs :language="props.language" :autodetect="!props.language" :code="props.code"></highlightjs> <highlightjs :language="props.language" :autodetect="!props.language" :code="props.code" />
</div> </div>
</template> </template>
@ -54,8 +54,8 @@
}*/ }*/
/** 滚动条 */ /** 滚动条 */
:deep(.hljs,.hljs-container) { :deep(.hljs, .hljs-container) {
max-height: 300px!important; max-height: 300px !important;
overflow-x: auto; overflow-x: auto;
} }

View File

@ -37,46 +37,50 @@ const app = createApp(App)
app.use(vueEsign) app.use(vueEsign)
// 局部 // 局部
import vueEsign from 'vue-esign' import vueEsign from 'vue-esign'
components: { vueEsign } // vue3 中只需需引入组件就可以使用无需注册
``` ```
2. 页面中使用 2. 页面中使用
**必须设置 `ref` ,用来调用组件的两个内置方法 `reset()``generate()`** // 在组件中使用 ref="esign"
**在script中必须设置 `const esign = ref()` ,用来调用组件的两个内置方法 `reset()``generate()`**
无需给组件设置 `style` 的宽高,如果画布的 `width`属性值没超出父元素的样式宽度则该组件的样式宽度就是画布宽度超出的话组件样式宽度则是父元素的100% 所以只需设置好父元素的宽度即可; 无需给组件设置 `style` 的宽高,如果画布的 `width`属性值没超出父元素的样式宽度则该组件的样式宽度就是画布宽度超出的话组件样式宽度则是父元素的100% 所以只需设置好父元素的宽度即可;
```html ```html
<!-- vue2 -->
<vue-esign ref="esign" :width="800" :height="300" :isCrop="isCrop" :lineWidth="lineWidth" :lineColor="lineColor" :bgColor.sync="bgColor" />
<!-- vue3 --> <!-- vue3 -->
<vue-esign ref="esign" :width="800" :height="300" :isCrop="isCrop" :lineWidth="lineWidth" :lineColor="lineColor" v-model:bgColor="bgColor" /> <vue-esign ref="esign" :width="800" :height="300" :isCrop="isCrop" :lineWidth="lineWidth" :lineColor="lineColor" v-model:bgColor="bgColor" :quality="1"/>
<!-- isClearBgColor为false时不必再给bgColor加sync修饰符或v-model --> <!-- isClearBgColor为false时不必再给bgColor加sync修饰符或v-model -->
<button @click="handleReset">清空画板</button> <a-button type="primary" @click="handleGenerate">预览</a-button>
<button @click="handleGenerate">生成图片</button> <a-button @click="handleReset">清屏</a-button>
``` ```
```js
data () { ```vue
return { <script setup>
lineWidth: 6, const esign = ref(false) // 相当于$ref
lineColor: '#000000',
bgColor: '', // 这里const相当于vue2中的data()
resultImg: '', const resultImg = ref('')
isCrop: false const isCrop = ref(false)
const lineWidth = ref(6)
const lineColor = ref('#000000')
const bgColor = ref('')
const handleReset = () => {
esign.value.reset()
resultImg.value = ''
} }
}, const handleGenerate = () => {
methods: { esign.value
handleReset () { .generate()
this.$refs.esign.reset() .then((res) => {
}, resultImg.value = res
handleGenerate () { })
this.$refs.esign.generate().then(res => { .catch(() => {
this.resultImg = res message.warning('无任何签字') // 画布没有签字时会执行这里 'Not Signned'
}).catch(err => {
alert(err) // 画布没有签字时会执行这里 'Not Signned'
}) })
} }
} </script>
```
3. 说明 3. 说明
| 属性 | 类型 | 默认值 | 说明 | | 属性 | 类型 | 默认值 | 说明 |
@ -95,7 +99,7 @@ methods: {
**清空画布** **清空画布**
```js ```js
this.$refs.esign.reset() esign.value.reset()
``` ```
**生成图片** **生成图片**
@ -103,7 +107,7 @@ this.$refs.esign.reset()
```js ```js
// 可选配置参数 在未设置format或quality属性时可在生成图片时配置 例如: {format:'image/jpeg', quality: 0.5} // 可选配置参数 在未设置format或quality属性时可在生成图片时配置 例如: {format:'image/jpeg', quality: 0.5}
// this.$refs.esign.generate({format:'image/jpeg', quality: 0.5}) // this.$refs.esign.generate({format:'image/jpeg', quality: 0.5})
this.$refs.esign.generate().then(res => { esign.value.generate().then(res => {
console.log(res) // base64图片 console.log(res) // base64图片
}).catch(err => { }).catch(err => {
alert(err) // 画布没有签字时会执行这里 'Not Signned' alert(err) // 画布没有签字时会执行这里 'Not Signned'

View File

@ -1,7 +1,3 @@
<!--
本插件来源于https://github.com/JaimeCheng/vue-esign#readme
因为集成进来跟我的Vue版本不一致打包出问题所以集成源码方式感谢作者的源码
-->
<template> <template>
<canvas <canvas
ref="canvas" ref="canvas"
@ -14,9 +10,11 @@
></canvas> ></canvas>
</template> </template>
<script> <script setup>
export default { const canvas = ref()
props: { const emit = defineEmits(['update:bgColor'])
const props = defineProps({
width: { width: {
type: Number, type: Number,
default: 800 default: 800
@ -53,225 +51,222 @@
type: Number, type: Number,
default: 1 default: 1
} }
}, })
data() {
return { const hasDrew = ref(false)
hasDrew: false, const resultImg = ref('')
resultImg: '', const points = ref([])
points: [], const canvasTxt = ref(null)
canvasTxt: null, const startX = ref(0)
startX: 0, const startY = ref(0)
startY: 0, const isDrawing = ref(false)
isDrawing: false, const sratio = ref(1)
sratio: 1
} const ratio = computed(() => {
}, return props.height / props.width
computed: { })
ratio() { const stageInfo = computed(() => {
return this.height / this.width return canvas.value.getBoundingClientRect()
}, })
stageInfo() { const myBg = computed(() => {
return this.$refs.canvas.getBoundingClientRect() return props.bgColor ? props.bgColor : 'rgba(255, 255, 255, 0)'
}, })
myBg() {
return this.bgColor ? this.bgColor : 'rgba(255, 255, 255, 0)' watch(myBg, (newVal) => {
} canvas.value.style.background = newVal
}, })
watch: {
myBg: function (newVal) { onBeforeMount(() => {
this.$refs.canvas.style.background = newVal window.addEventListener('resize', $_resizeHandler)
} })
}, onBeforeUnmount(() => {
beforeMount() { window.removeEventListener('resize', $_resizeHandler)
window.addEventListener('resize', this.$_resizeHandler) })
},
// eslint-disable-next-line vue/no-deprecated-destroyed-lifecycle onMounted(() => {
beforeDestroy() { canvas.value.height = props.height
window.removeEventListener('resize', this.$_resizeHandler) canvas.value.width = props.width
}, canvas.value.style.background = myBg.value
mounted() { $_resizeHandler()
const canvas = this.$refs.canvas
canvas.height = this.height
canvas.width = this.width
canvas.style.background = this.myBg
this.$_resizeHandler()
// //
document.onmouseup = () => { document.onmouseup = () => {
this.isDrawing = false isDrawing.value = false
} }
}, })
methods: {
$_resizeHandler() { const $_resizeHandler = () => {
const canvas = this.$refs.canvas canvas.value.style.width = props.width + 'px'
canvas.style.width = this.width + 'px' const realw = parseFloat(window.getComputedStyle(canvas.value).width)
const realw = parseFloat(window.getComputedStyle(canvas).width) canvas.value.style.height = ratio.value * realw + 'px'
canvas.style.height = this.ratio * realw + 'px' canvasTxt.value = canvas.value.getContext('2d', { willReadFrequently: true })
this.canvasTxt = canvas.getContext('2d') canvasTxt.value.scale(Number(sratio.value), Number(sratio.value))
this.canvasTxt.scale(Number(this.sratio), Number(this.sratio)) sratio.value = realw / props.width
this.sratio = realw / this.width canvasTxt.value.scale(1 / sratio.value, 1 / sratio.value)
this.canvasTxt.scale(1 / this.sratio, 1 / this.sratio) }
},
// pc // pc
mouseDown(e) { const mouseDown = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
this.isDrawing = true isDrawing.value = true
this.hasDrew = true hasDrew.value = true
let obj = { let obj = {
x: e.offsetX, x: e.offsetX,
y: e.offsetY y: e.offsetY
} }
this.drawStart(obj) drawStart(obj)
}, }
mouseMove(e) { const mouseMove = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
if (this.isDrawing) { if (isDrawing.value) {
let obj = { let obj = {
x: e.offsetX, x: e.offsetX,
y: e.offsetY y: e.offsetY
} }
this.drawMove(obj) drawMove(obj)
} }
}, }
mouseUp(e) { const mouseUp = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
let obj = { let obj = {
x: e.offsetX, x: e.offsetX,
y: e.offsetY y: e.offsetY
} }
this.drawEnd(obj) drawEnd(obj)
this.isDrawing = false isDrawing.value = false
}, }
// mobile // mobile
touchStart(e) { const touchStart = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
this.hasDrew = true hasDrew.value = true
if (e.touches.length === 1) { if (e.touches.length === 1) {
let obj = { let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left, x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
} }
this.drawStart(obj) drawStart(obj)
} }
}, }
touchMove(e) { const touchMove = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
if (e.touches.length === 1) { if (e.touches.length === 1) {
let obj = { let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left, x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
} }
this.drawMove(obj) drawMove(obj)
} }
}, }
touchEnd(e) { const touchEnd = (e) => {
e = e || event e = e || event
e.preventDefault() e.preventDefault()
if (e.touches.length === 1) { if (e.touches.length === 1) {
let obj = { let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left, x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
}
drawEnd(obj)
} }
this.drawEnd(obj)
} }
},
// //
drawStart(obj) { const drawStart = (obj) => {
this.startX = obj.x startX.value = obj.x
this.startY = obj.y startY.value = obj.y
this.canvasTxt.beginPath() canvasTxt.value.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY) canvasTxt.value.moveTo(startX.value, startY.value)
this.canvasTxt.lineTo(obj.x, obj.y) canvasTxt.value.lineTo(obj.x, obj.y)
this.canvasTxt.lineCap = 'round' canvasTxt.value.lineCap = 'round'
this.canvasTxt.lineJoin = 'round' canvasTxt.value.lineJoin = 'round'
this.canvasTxt.lineWidth = this.lineWidth * this.sratio canvasTxt.value.lineWidth = props.lineWidth * sratio.value
this.canvasTxt.stroke() canvasTxt.value.stroke()
this.canvasTxt.closePath() canvasTxt.value.closePath()
this.points.push(obj) points.value.push(obj)
}, }
drawMove(obj) { const drawMove = (obj) => {
this.canvasTxt.beginPath() canvasTxt.value.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY) canvasTxt.value.moveTo(startX.value, startY.value)
this.canvasTxt.lineTo(obj.x, obj.y) canvasTxt.value.lineTo(obj.x, obj.y)
this.canvasTxt.strokeStyle = this.lineColor canvasTxt.value.strokeStyle = props.lineColor
this.canvasTxt.lineWidth = this.lineWidth * this.sratio canvasTxt.value.lineWidth = props.lineWidth * sratio.value
this.canvasTxt.lineCap = 'round' canvasTxt.value.lineCap = 'round'
this.canvasTxt.lineJoin = 'round' canvasTxt.value.lineJoin = 'round'
this.canvasTxt.stroke() canvasTxt.value.stroke()
this.canvasTxt.closePath() canvasTxt.value.closePath()
this.startY = obj.y startY.value = obj.y
this.startX = obj.x startX.value = obj.x
this.points.push(obj) points.value.push(obj)
}, }
drawEnd(obj) { const drawEnd = (obj) => {
this.canvasTxt.beginPath() canvasTxt.value.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY) canvasTxt.value.moveTo(startX.value, startY.value)
this.canvasTxt.lineTo(obj.x, obj.y) canvasTxt.value.lineTo(obj.x, obj.y)
this.canvasTxt.lineCap = 'round' canvasTxt.value.lineCap = 'round'
this.canvasTxt.lineJoin = 'round' canvasTxt.value.lineJoin = 'round'
this.canvasTxt.stroke() canvasTxt.value.stroke()
this.canvasTxt.closePath() canvasTxt.value.closePath()
this.points.push(obj) points.value.push(obj)
this.points.push({ x: -1, y: -1 }) points.value.push({ x: -1, y: -1 })
}, }
// //
generate(options) { const generate = (options) => {
let imgFormat = options && options.format ? options.format : this.format let imgFormat = options && options.format ? options.format : props.format
let imgQuality = options && options.quality ? options.quality : this.quality let imgQuality = options && options.quality ? options.quality : props.quality
const pm = new Promise((resolve, reject) => { const pm = new Promise((resolve, reject) => {
if (!this.hasDrew) { if (!hasDrew.value) {
reject(`Warning: Not Signned!`) reject(`Warning: Not Signned!`)
return return
} }
var resImgData = this.canvasTxt.getImageData(0, 0, this.$refs.canvas.width, this.$refs.canvas.height) var resImgData = canvasTxt.value.getImageData(0, 0, canvas.value.width, canvas.value.height)
this.canvasTxt.globalCompositeOperation = 'destination-over' canvasTxt.value.globalCompositeOperation = 'destination-over'
this.canvasTxt.fillStyle = this.myBg canvasTxt.value.fillStyle = myBg.value
this.canvasTxt.fillRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height) canvasTxt.value.fillRect(0, 0, canvas.value.width, canvas.value.height)
this.resultImg = this.$refs.canvas.toDataURL(imgFormat, imgQuality) resultImg.value = canvas.value.toDataURL(imgFormat, imgQuality)
var resultImg = this.resultImg var resultImgData = resultImg.value
this.canvasTxt.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height) canvasTxt.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
this.canvasTxt.putImageData(resImgData, 0, 0) canvasTxt.value.putImageData(resImgData, 0, 0)
this.canvasTxt.globalCompositeOperation = 'source-over' canvasTxt.value.globalCompositeOperation = 'source-over'
if (this.isCrop) { if (props.isCrop) {
const crop_area = this.getCropArea(resImgData.data) const crop_area = getCropArea(resImgData.data)
var crop_canvas = document.createElement('canvas') var crop_canvas = document.createElement('canvas')
const crop_ctx = crop_canvas.getContext('2d') const crop_ctx = crop_canvas.getContext('2d', { willReadFrequently: true })
crop_canvas.width = crop_area[2] - crop_area[0] crop_canvas.width = crop_area[2] - crop_area[0]
crop_canvas.height = crop_area[3] - crop_area[1] crop_canvas.height = crop_area[3] - crop_area[1]
const crop_imgData = this.canvasTxt.getImageData(...crop_area) const crop_imgData = canvasTxt.value.getImageData(...crop_area)
crop_ctx.globalCompositeOperation = 'destination-over' crop_ctx.globalCompositeOperation = 'destination-over'
crop_ctx.putImageData(crop_imgData, 0, 0) crop_ctx.putImageData(crop_imgData, 0, 0)
crop_ctx.fillStyle = this.myBg crop_ctx.fillStyle = myBg.value
crop_ctx.fillRect(0, 0, crop_canvas.width, crop_canvas.height) crop_ctx.fillRect(0, 0, crop_canvas.width, crop_canvas.height)
resultImg = crop_canvas.toDataURL(imgFormat, imgQuality) resultImgData = crop_canvas.toDataURL(imgFormat, imgQuality)
crop_canvas = null crop_canvas = null
} }
resolve(resultImg) resolve(resultImgData)
}) })
return pm return pm
},
reset() {
this.canvasTxt.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
if (this.isClearBgColor) {
this.$emit('update:bgColor', '')
this.$refs.canvas.style.background = 'rgba(255, 255, 255, 0)'
} }
this.points = [] const reset = () => {
this.hasDrew = false canvasTxt.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
this.resultImg = '' if (props.isClearBgColor) {
}, emit('update:bgColor', '')
getCropArea(imgData) { canvas.value.style.background = 'rgba(255, 255, 255, 0)'
var topX = this.$refs.canvas.width }
var btmX = 0 points.value = []
var topY = this.$refs.canvas.height hasDrew.value = false
var btnY = 0 resultImg.value = ''
for (var i = 0; i < this.$refs.canvas.width; i++) { }
for (var j = 0; j < this.$refs.canvas.height; j++) { const getCropArea = (imgData) => {
var pos = (i + this.$refs.canvas.width * j) * 4 let topX = canvas.value.width
let btmX = 0
let topY = canvas.value.height
let btnY = 0
for (let i = 0; i < canvas.value.width; i++) {
for (let j = 0; j < canvas.value.height; j++) {
let pos = (i + canvas.value.width * j) * 4
if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) { if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) {
btnY = Math.max(j, btnY) btnY = Math.max(j, btnY)
btmX = Math.max(i, btmX) btmX = Math.max(i, btmX)
@ -284,13 +279,14 @@
btmX++ btmX++
topY++ topY++
btnY++ btnY++
const data = [topX, topY, btmX, btnY] return [topX, topY, btmX, btnY]
return data
}
}
} }
// 使
defineExpose({
generate,
reset
})
</script> </script>
<style scoped> <style scoped>
canvas { canvas {
max-width: 100%; max-width: 100%;

View File

@ -8,8 +8,6 @@
* 5.不可二次分发开源参与同类竞品如有想法可联系团队xiaonuobase@qq.com商议合作 * 5.不可二次分发开源参与同类竞品如有想法可联系团队xiaonuobase@qq.com商议合作
* 6.若您的项目无法满足以上几点需要更多功能代码获取Snowy商业授权许可请在官网购买授权地址为 https://www.xiaonuo.vip * 6.若您的项目无法满足以上几点需要更多功能代码获取Snowy商业授权许可请在官网购买授权地址为 https://www.xiaonuo.vip
*/ */
import { defineAsyncComponent } from 'vue'
/** /**
* 图标选择器基础数据 * 图标选择器基础数据
* 推荐前往https://icones.js.org下载图标的Vue文件然后放在src/assets/icons文件夹里面 * 推荐前往https://icones.js.org下载图标的Vue文件然后放在src/assets/icons文件夹里面

View File

@ -1,49 +1,53 @@
<template> <template>
<div v-show="$route.meta.type === 'iframe'" class="iframe-pages"> <div v-show="route.meta.type === 'iframe'" class="iframe-pages">
<div></div>
<iframe <iframe
v-for="item in iframeList" v-for="item in iframeList"
v-show="$route.meta.url === item.meta.url" v-show="route.meta.url === item.meta.url"
:key="item.meta.url" :key="item.meta.url"
:src="item.meta.url" :src="item.meta.url"
frameborder="0" frameborder="0"
></iframe> ></iframe>
</div> </div>
</template> </template>
<script setup>
<script> import { useRoute, useRouter } from 'vue-router'
import { mapState, mapActions } from 'pinia'
import { iframeStore, globalStore } from '@/store' import { iframeStore, globalStore } from '@/store'
const iStore = iframeStore()
const store = globalStore()
const route = useRoute()
const router = useRouter()
export default { const iframeList = computed(() => {
data() { return iStore.iframeList
return {} })
},
computed: { const isMobile = computed(() => {
...mapState(iframeStore, ['iframeList']), return store.isMobile
...mapState(globalStore, ['isMobile', 'layoutTags']) })
}, const layoutTags = computed(() => {
watch: { return store.layoutTags
$route(e) { })
this.push(e)
} watch(route, () => {
}, push(router.currentRoute.value)
created() { })
this.push(this.$route) onBeforeMount(() => {
}, push(router.currentRoute.value)
mounted() {}, })
methods: {
...mapActions(iframeStore, ['setIframeList', 'pushIframeList', 'clearIframeList']), const setIframeList = iStore.setIframeList
push(route) { const pushIframeList = iStore.pushIframeList
const clearIframeList = iStore.clearIframeList
const push = (route) => {
if (route.meta.type === 'iframe') { if (route.meta.type === 'iframe') {
if (this.isMobile || !this.layoutTags) { if (isMobile || !layoutTags) {
this.setIframeList(route) setIframeList(route)
} else { } else {
this.pushIframeList(route) pushIframeList(route)
}
} else if (this.isMobile || !this.layoutTags) {
this.clearIframeList()
}
} }
} else if (isMobile || !layoutTags) {
clearIframeList()
} }
} }
</script> </script>

View File

@ -33,7 +33,7 @@
</a-form-item> </a-form-item>
<a-form-item label="查收情况:" name="receiveInfoList"> <a-form-item label="查收情况:" name="receiveInfoList">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:alert="false" :alert="false"
@ -146,7 +146,7 @@
Object.assign(message, data) Object.assign(message, data)
formData.value = message formData.value = message
receiveInfoList.value = data.receiveInfoList receiveInfoList.value = data.receiveInfoList
table.value.refresh(true) tableRef.value.refresh(true)
}) })
unreadMessageNum.value = Math.max(unreadMessageNum.value - 1, 0) unreadMessageNum.value = Math.max(unreadMessageNum.value - 1, 0)
} }
@ -161,7 +161,7 @@
const formRef = ref() const formRef = ref()
const receiveInfoList = ref([]) const receiveInfoList = ref([])
const formData = ref({}) const formData = ref({})
const table = ref() const tableRef = ref()
const columns = [ const columns = [
{ {
title: '姓名', title: '姓名',

View File

@ -97,6 +97,7 @@
moduleBackColor.value moduleBackColor.value
? moduleMenu.classList.add('module-menu-color') ? moduleMenu.classList.add('module-menu-color')
: moduleMenu.classList.remove('module-menu-color') : moduleMenu.classList.remove('module-menu-color')
// eslint-disable-next-line no-empty
} catch (err) {} } catch (err) {}
setSelectedKeys() setSelectedKeys()
} }

View File

@ -53,7 +53,7 @@
/> />
</div> </div>
<a-divider /> <a-divider />
<a-form ref="form" class="text-right"> <a-form ref="formRef" class="text-right">
<a-form-item label="模块坞"> <a-form-item label="模块坞">
<a-switch :checked="moduleUnfoldOpen" @change="toggleState('moduleUnfoldOpen')" /> <a-switch :checked="moduleUnfoldOpen" @change="toggleState('moduleUnfoldOpen')" />
</a-form-item> </a-form-item>
@ -86,14 +86,12 @@
</div> </div>
</div> </div>
</template> </template>
<script setup>
<script>
import { colorList } from '@/config/settingConfig' import { colorList } from '@/config/settingConfig'
import { ThemeModeEnum } from '@/utils/enum' import { ThemeModeEnum } from '@/utils/enum'
import { globalStore } from '@/store' import { globalStore } from '@/store'
import { mapState, mapStores } from 'pinia'
import tool from '@/utils/tool' import tool from '@/utils/tool'
const store = globalStore()
const toolDataNameMap = { const toolDataNameMap = {
menuIsCollapse: 'MENU_COLLAPSE', menuIsCollapse: 'MENU_COLLAPSE',
sideUniqueOpen: 'SIDE_UNIQUE_OPEN', sideUniqueOpen: 'SIDE_UNIQUE_OPEN',
@ -103,10 +101,7 @@
topHeaderThemeColorSpread: 'TOP_HEADER_THEME_COLOR_SPREAD', topHeaderThemeColorSpread: 'TOP_HEADER_THEME_COLOR_SPREAD',
moduleUnfoldOpen: 'MODULE_UNFOLD_OPEN' moduleUnfoldOpen: 'MODULE_UNFOLD_OPEN'
} }
export default defineComponent({ const sideStyleList = ref([
data() {
return {
sideStyleList: [
{ {
tips: '暗色主题风格', tips: '暗色主题风格',
value: ThemeModeEnum.DARK, value: ThemeModeEnum.DARK,
@ -122,8 +117,9 @@
value: ThemeModeEnum.REAL_DARK, value: ThemeModeEnum.REAL_DARK,
style: 'snowy-setting-checkbox-item-realdark' style: 'snowy-setting-checkbox-item-realdark'
} }
], ])
layoutList: [
const layoutList = ref([
{ {
tips: '经典', tips: '经典',
value: 'classical', value: 'classical',
@ -134,8 +130,9 @@
value: 'doublerow', value: 'doublerow',
style: 'snowy-setting-layout-menu-doublerow' style: 'snowy-setting-layout-menu-doublerow'
} }
], ])
xnFormStyleOptions: [
const xnFormStyleOptions = ref([
{ {
label: '抽屉', label: '抽屉',
value: 'drawer' value: 'drawer'
@ -144,68 +141,81 @@
label: '对话框', label: '对话框',
value: 'modal' value: 'modal'
} }
],
colorList
}
},
computed: {
...mapStores(globalStore),
...mapState(globalStore, [
'theme',
'themeColor',
'layout',
'menuIsCollapse',
'sideUniqueOpen',
'layoutTagsOpen',
'breadcrumbOpen',
'moduleUnfoldOpen',
'topHeaderThemeColorOpen',
'topHeaderThemeColorSpread',
'formStyle'
]) ])
},
mounted() {}, const theme = computed(() => {
methods: { return store.theme
changeTopHanderThemeColorOpen() { })
this.toggleState('topHeaderThemeColorOpen') const themeColor = computed(() => {
if (!this.topHeaderThemeColorOpen) { return store.themeColor
this.globalStore.topHeaderThemeColorSpread = false })
const layout = computed(() => {
return store.layout
})
const menuIsCollapse = computed(() => {
return store.menuIsCollapse
})
const sideUniqueOpen = computed(() => {
return store.sideUniqueOpen
})
const layoutTagsOpen = computed(() => {
return store.layoutTagsOpen
})
const breadcrumbOpen = computed(() => {
return store.breadcrumbOpen
})
const moduleUnfoldOpen = computed(() => {
return store.moduleUnfoldOpen
})
const topHeaderThemeColorOpen = computed(() => {
return store.topHeaderThemeColorOpen
})
const topHeaderThemeColorSpread = computed(() => {
return store.topHeaderThemeColorSpread
})
const formStyle = computed(() => {
return store.formStyle
})
const changeTopHanderThemeColorOpen = () => {
toggleState('topHeaderThemeColorOpen')
if (!topHeaderThemeColorOpen) {
store.topHeaderThemeColorSpread = false
tool.data.set('SNOWY_TOP_HEADER_THEME_COLOR_SPREAD', false) tool.data.set('SNOWY_TOP_HEADER_THEME_COLOR_SPREAD', false)
} }
}, }
changeTopHanderThemeColorSpread() {
this.toggleState('topHeaderThemeColorSpread') const changeTopHanderThemeColorSpread = () => {
}, toggleState('topHeaderThemeColorSpread')
toggleState(stateName) { }
this.globalStore.toggleConfig(stateName) const toggleState = (stateName) => {
store.toggleConfig(stateName)
const toolDataName = toolDataNameMap[stateName] const toolDataName = toolDataNameMap[stateName]
tool.data.set(`SNOWY_${toolDataName}`, this.globalStore[stateName]) tool.data.set(`SNOWY_${toolDataName}`, store[stateName])
}, }
// //
setSideStyle(value) { const setSideStyle = (value) => {
this.globalStore.setTheme(value) store.setTheme(value)
tool.data.set('SNOWY_THEME', value) tool.data.set('SNOWY_THEME', value)
}, }
// //
layoutStyle(value) { const layoutStyle = (value) => {
this.globalStore.setLayout(value) store.setLayout(value)
tool.data.set('SNOWY_LAYOUT', value) tool.data.set('SNOWY_LAYOUT', value)
}, }
// //
tagColor(value) { const tagColor = (value) => {
tool.data.set('SNOWY_THEME_COLOR', value) tool.data.set('SNOWY_THEME_COLOR', value)
this.globalStore.setThemeColor(value) store.setThemeColor(value)
}, }
// //
formStyleChange(value) { const formStyleChange = (value) => {
tool.data.set('SNOWY_FORM_STYLE', value) tool.data.set('SNOWY_FORM_STYLE', value)
this.globalStore.setFormStyle(value) store.setFormStyle(value)
} }
}
})
</script> </script>
<style type="less" scoped> <style lang="less" scoped>
.snowy-setting-checkbox { .snowy-setting-checkbox {
display: flex; display: flex;
margin-bottom: 20px; margin-bottom: 20px;

View File

@ -16,18 +16,15 @@
</a-menu> </a-menu>
</a-drawer> </a-drawer>
</template> </template>
<script setup>
<script>
import NavMenu from './NavMenu.vue' import NavMenu from './NavMenu.vue'
import { globalStore } from '@/store' import { globalStore } from '@/store'
import { mapState } from 'pinia' import { useRouter } from 'vue-router'
export default { const router = useRouter()
components: { const store = globalStore()
NavMenu
}, const vDrag = (el) => {
directives: {
drag(el) {
const oDiv = el // const oDiv = el //
let firstTime = '' let firstTime = ''
let lastTime = '' let lastTime = ''
@ -65,39 +62,37 @@
return false return false
} }
} }
},
data() { const visible = ref(false)
return { const menu = ref([])
visible: false,
menu: [] const sysBaseConfig = computed(() => {
} return store.sysBaseConfig
}, })
computed: {
...mapState(globalStore, ['sysBaseConfig']) onBeforeMount(() => {
}, const menus = router.getMenu()
created() { menu.value = filterUrl(menus)
const menu = this.$router.getMenu() })
this.menu = this.filterUrl(menu)
}, const showMobileNav = (e) => {
methods: {
showMobileNav(e) {
const isdrag = e.currentTarget.getAttribute('drag-flag') const isdrag = e.currentTarget.getAttribute('drag-flag')
this.visible = true visible.value = true
if (isdrag === 'true') { if (isdrag === 'true') {
return false return false
} else { } else {
this.visible = true visible.value = true
}
} }
},
// //
onSelect(obj) { const onSelect = (obj) => {
const pathLength = obj.keyPath.length const pathLength = obj.keyPath.length
const path = obj.keyPath[pathLength - 1] const path = obj.keyPath[pathLength - 1]
this.$router.push({ path }) router.push({ path })
this.visible = false visible.value = false
}, }
// //
filterUrl(map) { const filterUrl = (map) => {
map.forEach((item, index) => { map.forEach((item, index) => {
item.meta = item.meta ? item.meta : {} item.meta = item.meta ? item.meta : {}
// //
@ -105,19 +100,16 @@
map.splice(index, 1) map.splice(index, 1)
} }
// http // http
// eslint-disable-next-line eqeqeq if (item.meta.type === 'iframe') {
if (item.meta.type == 'iframe') {
item.path = `/i/${item.name}` item.path = `/i/${item.name}`
} }
// //
if (item.children && item.children.length > 0) { if (item.children && item.children.length > 0) {
item.children = this.filterUrl(item.children) item.children = filterUrl(item.children)
} }
}) })
return map return map
} }
}
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -58,242 +58,245 @@
</div> </div>
</template> </template>
<script> <script setup>
import tool from '@/utils/tool'
import XnContextMenu from '@/components/XnContextMenu/index.vue' import XnContextMenu from '@/components/XnContextMenu/index.vue'
import { globalStore, iframeStore, keepAliveStore, viewTagsStore } from '@/store' import { globalStore, iframeStore, keepAliveStore, viewTagsStore } from '@/store'
import { mapState, mapActions } from 'pinia'
import routerUtil from '@/utils/routerUtil' import routerUtil from '@/utils/routerUtil'
import { useRoute, useRouter } from 'vue-router'
import { watch } from 'vue'
export default { const route = useRoute()
name: 'Tags', const router = useRouter()
components: { XnContextMenu }, const store = globalStore()
props: {}, const kStore = keepAliveStore()
data() { const iStore = iframeStore()
return { const vStore = viewTagsStore()
// tagList: [],
activeKey: this.$route.fullPath, const activeKey = ref()
maxTabs: 20, const maxTabs = ref(20)
contextMenuTarget: null, const contextMenuTarget = ref(null)
contextMenuVisible: false, const contextMenuVisible = ref(false)
currentContextMenuTabIndex: 0 const currentContextMenuTabIndex = ref(0)
}
}, const viewTags = computed(() => {
computed: { return vStore.viewTags
...mapState(viewTagsStore, ['viewTags']), })
...mapState(globalStore, ['layoutTagsOpen']),
tagList() { const layoutTagsOpen = computed(() => {
return this.viewTags return store.layoutTagsOpen
} })
},
watch: { const tagList = computed(() => {
$route(to) { return viewTags.value
this.addViewTags(to) })
},
layoutTagsOpen() { watch(route, (to) => {
this.closeOtherCacheTabs() addViewTags(to)
} activeKey.value = to.fullPath
}, })
created() { watch(layoutTagsOpen, () => {
const module = this.$router.getMenu() // closeOtherCacheTabs()
const indexMenu = routerUtil.getIndexMenu(module).path })
// eslint-disable-next-line eqeqeq
const dashboardRoute = this.treeFind(module, (node) => node.path === indexMenu) onMounted(() => {
if (dashboardRoute) {
dashboardRoute.fullPath = dashboardRoute.path
this.addViewTags(dashboardRoute)
this.addViewTags(this.$route)
}
},
mounted() {
const tabNavList = document.querySelector('.ant-tabs-nav-list') const tabNavList = document.querySelector('.ant-tabs-nav-list')
if (tabNavList) { if (tabNavList) {
this.contextMenuTarget = tabNavList contextMenuTarget.value = tabNavList
} }
}, })
methods: { // tag
...mapActions(viewTagsStore, ['addViewTags', 'pushViewTags', 'removeViewTags']), const addViewTags = (to) => {
...mapActions(iframeStore, ['addIframe', 'removeIframeList', 'refreshIframe']), activeKey.value = to.fullPath
...mapActions(keepAliveStore, ['pushKeepLive', 'removeKeepLive', 'setRouteShow']), if (to.name && !to.meta.fullpage) {
handleTabContextMenu(evt) { vStore.pushViewTags(to)
evt.preventDefault() kStore.pushKeepLive(to.name)
let target = evt.target
// "使"
while (!target.classList.contains('ant-tabs-tab')) {
if (target.classList.contains('ant-tabs')) {
this.currentContextMenuTabIndex = 0
return
} }
target = target.parentNode if (tagList.value.length - 1 > maxTabs.value) {
const firstTag = tagList.value[1]
vStore.removeViewTags(firstTag)
} }
const tabList = document.querySelectorAll('.ant-tabs-nav-list .ant-tabs-tab')
this.currentContextMenuTabIndex = Array.from(tabList).findIndex((tab) => tab === target)
},
onTabClick(tab) {
this.$router.push(tab)
},
getCurrentTag() {
return this.tagList[this.currentContextMenuTabIndex]
},
onTabRemove(tabKey, action) {
if (action === 'remove') {
const tag = this.tagList.find((tag) => tag.fullPath === tabKey)
this.closeSelectedTag(tag)
} }
},
//
onTabUp(e) {
//
if (e.which === 2) {
this.handleTabContextMenu(e)
this.closeTabs()
}
},
getTabWrapEl() {
return document.querySelector('.ant-tabs-nav-wrap')
},
scrollLeft() {
const wrapEl = this.getTabWrapEl()
if (wrapEl) {
const event = new WheelEvent('wheel', { deltaX: 0, deltaY: -100 })
wrapEl.dispatchEvent(event)
}
},
scrollRight() {
const wrapEl = this.getTabWrapEl()
if (wrapEl) {
const event = new WheelEvent('wheel', { deltaX: 0, deltaY: 100 })
wrapEl.dispatchEvent(event)
}
},
// //
treeFind(tree, func) { const treeFind = (tree, func) => {
for (const data of tree) { for (const data of tree) {
if (func(data)) return data if (func(data)) return data
if (data.children) { if (data.children) {
const res = this.treeFind(data.children, func) const res = treeFind(data.children, func)
if (res) return res if (res) return res
} }
} }
return null return null
},
// tag
addViewTags(route) {
this.activeKey = route.fullPath
if (route.name && !route.meta.fullpage) {
this.pushViewTags(route)
this.pushKeepLive(route.name)
} }
if (this.tagList.length - 1 > this.maxTabs) {
const firstTag = this.tagList[1] const getCurrentTag = () => {
this.removeViewTags(firstTag) return tagList.value[currentContextMenuTabIndex.value]
} }
},
// tag // tag
isActive(route) { const isActive = (to) => {
return route.path === this.$route.path return to.path === route.path
}, }
// tag // tag
closeSelectedTag(tag, autoPushLatestView = true) { const closeSelectedTag = (tag, autoPushLatestView = true) => {
this.removeViewTags(tag) vStore.removeViewTags(tag)
this.removeIframeList(tag) iStore.removeIframeList(tag)
this.removeKeepLive(tag.name) kStore.removeKeepLive(tag.name)
if (autoPushLatestView && this.isActive(tag)) { if (autoPushLatestView && isActive(tag)) {
const latestView = this.tagList.slice(-1)[0] const latestView = tagList.value.slice(-1)[0]
if (latestView) { if (latestView) {
this.$router.push(latestView) router.push(latestView)
} else { } else {
this.$router.push('/') router.push('/')
}
} }
} }
},
// TAB // TAB
refreshTab() { const refreshTab = () => {
this.contextMenuVisible = false contextMenuVisible.value = false
const nowTag = this.getCurrentTag() const nowTag = getCurrentTag()
// //
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
if (this.$route.fullPath !== nowTag.fullPath) { if (route.fullPath !== nowTag.fullPath) {
this.$router.push({ router.push({
path: nowTag.fullPath, path: nowTag.fullPath,
query: nowTag.query query: nowTag.query
}) })
} }
this.refreshIframe(nowTag) iStore.refreshIframe(nowTag)
setTimeout(() => { setTimeout(() => {
this.removeKeepLive(nowTag.name) kStore.removeKeepLive(nowTag.name)
this.setRouteShow(false) kStore.setRouteShow(false)
this.$nextTick(() => { nextTick(() => {
this.pushKeepLive(nowTag.name) kStore.pushKeepLive(nowTag.name)
this.setRouteShow(true) kStore.setRouteShow(true)
}) })
}, 0) }, 0)
},
// TAB
closeTabs() {
this.contextMenuVisible = false
const nowTag = this.getCurrentTag()
if (!nowTag.meta.affix) {
this.closeSelectedTag(nowTag)
} }
},
// TAB
const closeTabs = () => {
contextMenuVisible.value = false
const nowTag = getCurrentTag()
if (!nowTag.meta.affix) {
closeSelectedTag(nowTag)
}
}
// TAB // TAB
closeOtherTabs() { const closeOtherTabs = () => {
this.contextMenuVisible = false contextMenuVisible.value = false
const nowTag = this.getCurrentTag() const nowTag = getCurrentTag()
// //
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
if (this.$route.fullPath !== nowTag.fullPath) { if (route.fullPath !== nowTag.fullPath) {
this.$router.push({ router.push({
path: nowTag.fullPath, path: nowTag.fullPath,
query: nowTag.query query: nowTag.query
}) })
} }
const tags = [...this.tagList] const tags = [...tagList.value]
tags.forEach((tag) => { tags.forEach((tag) => {
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
if ((tag.meta && tag.meta.affix) || nowTag.fullPath === tag.fullPath) { if ((tag.meta && tag.meta.affix) || nowTag.fullPath === tag.fullPath) {
return true return true
} else { } else {
this.closeSelectedTag(tag, false) closeSelectedTag(tag, false)
} }
}) })
}, }
// //
closeOtherCacheTabs() { const closeOtherCacheTabs = () => {
const tags = [...this.tagList] const tags = [...tagList]
tags.forEach((tag) => { tags.forEach((tag) => {
this.closeSelectedTag(tag, false) closeSelectedTag(tag, false)
}) })
}, }
// TAB // TAB
maximize() { const maximize = () => {
this.contextMenuVisible = false contextMenuVisible.value = false
const nowTag = this.getCurrentTag() const nowTag = getCurrentTag()
// //
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
if (this.$route.fullPath !== nowTag.fullPath) { if (route.fullPath !== nowTag.fullPath) {
this.$router.push({ router.push({
path: nowTag.fullPath, path: nowTag.fullPath,
query: nowTag.query query: nowTag.query
}) })
} }
document.getElementById('app').classList.add('main-maximize') document.getElementById('app').classList.add('main-maximize')
}, }
// //
openWindow() { const openWindow = () => {
this.contextMenuVisible = false contextMenuVisible.value = false
const nowTag = this.getCurrentTag() const nowTag = getCurrentTag()
const url = nowTag.href || '/' const url = nowTag.path || '/'
if (!nowTag.meta.affix) { if (!nowTag.meta.affix) {
this.closeSelectedTag(nowTag) closeSelectedTag(nowTag)
} }
window.open(url) window.open(url)
} }
const handleTabContextMenu = (evt) => {
evt.preventDefault()
let target = evt.target
// "使"
while (!target.classList.contains('ant-tabs-tab')) {
if (target.classList.contains('ant-tabs')) {
currentContextMenuTabIndex.value = 0
return
}
target = target.parentNode
}
const tabList = document.querySelectorAll('.ant-tabs-nav-list .ant-tabs-tab')
currentContextMenuTabIndex.value = Array.from(tabList).findIndex((tab) => tab === target)
}
const module = router.getMenu()
const indexMenu = routerUtil.getIndexMenu(module).path
// eslint-disable-next-line eqeqeq
const dashboardRoute = treeFind(module, (node) => node.path === indexMenu)
if (dashboardRoute) {
dashboardRoute.fullPath = dashboardRoute.path
addViewTags(dashboardRoute)
addViewTags(route)
}
const onTabRemove = (tabKey, action) => {
if (action === 'remove') {
const tag = tagList.value.find((tag) => tag.fullPath === tabKey)
closeSelectedTag(tag)
}
}
const onTabClick = (tab) => {
router.push(tab)
}
//
const onTabUp = (e) => {
//
if (e.which === 2) {
handleTabContextMenu(e)
closeTabs()
}
}
const getTabWrapEl = () => {
return document.querySelector('.ant-tabs-nav-wrap')
}
const scrollLeft = () => {
const wrapEl = getTabWrapEl()
if (wrapEl) {
const event = new WheelEvent('wheel', { deltaX: 0, deltaY: -100 })
wrapEl.dispatchEvent(event)
}
}
const scrollRight = () => {
const wrapEl = getTabWrapEl()
if (wrapEl) {
const event = new WheelEvent('wheel', { deltaX: 0, deltaY: 100 })
wrapEl.dispatchEvent(event)
} }
} }
</script> </script>
<style lang="less"> <style lang="less">
.snowy-admin-tabs { .snowy-admin-tabs {
&.ant-tabs { &.ant-tabs {
@ -316,7 +319,9 @@
background: none; background: none;
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
transition: background-color 0.3s, color 0.3s; transition:
background-color 0.3s,
color 0.3s;
padding: 0 16px; padding: 0 16px;
border-radius: 0; border-radius: 0;
border: none; border: none;

View File

@ -15,27 +15,22 @@
</div> </div>
</div> </div>
</template> </template>
<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'
<script> const route = useRoute()
export default { const breadList = ref([])
data() {
return { watch(route, () => {
breadList: [] getBreadcrumb()
} })
},
watch: { onBeforeMount(() => {
$route() { getBreadcrumb()
this.getBreadcrumb() })
}
}, const getBreadcrumb = () => {
created() { breadList.value = route.meta.breadcrumb
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
const matched = this.$route.meta.breadcrumb
this.breadList = matched
}
}
} }
</script> </script>

View File

@ -53,9 +53,9 @@
<Tags v-if="!isMobile && layoutTagsOpen" /> <Tags v-if="!isMobile && layoutTagsOpen" />
<a-layout-content class="main-content-wrapper"> <a-layout-content class="main-content-wrapper">
<div id="admin-ui-main" class="admin-ui-main"> <div id="admin-ui-main" class="admin-ui-main">
<router-view v-slot="{ Component }" :key="route.fullPath"> <router-view v-slot="{ Component }">
<keep-alive :include="keepLiveRoute"> <keep-alive :include="kStore.keepLiveRoute">
<component :is="Component" :key="route.name" v-if="routeShow" /> <component :is="Component" v-if="kStore.routeShow" :key="route.name" />
</keep-alive> </keep-alive>
</router-view> </router-view>
<iframe-view /> <iframe-view />
@ -149,12 +149,12 @@
</div> </div>
</div> </div>
<!-- 多标签 --> <!-- 多标签 -->
<Tags v-if="!isMobile && layoutTagsOpen"></Tags> <Tags v-if="!isMobile && layoutTagsOpen" />
<a-layout-content class="main-content-wrapper"> <a-layout-content class="main-content-wrapper">
<div id="admin-ui-main" class="admin-ui-main"> <div id="admin-ui-main" class="admin-ui-main">
<router-view v-slot="{ Component }" :key="route.fullPath"> <router-view v-slot="{ Component }">
<keep-alive :include="keepLiveRoute"> <keep-alive :include="kStore.keepLiveRoute">
<component :is="Component" v-if="routeShow" :key="route.name" /> <component :is="Component" v-if="kStore.routeShow" :key="route.name" />
</keep-alive> </keep-alive>
</router-view> </router-view>
<iframe-view /> <iframe-view />
@ -215,6 +215,10 @@
return store.theme return store.theme
}) })
const layoutTagsOpen = computed(() => { const layoutTagsOpen = computed(() => {
// keepAlive
if (!store.layoutTagsOpen) {
kStore.keepLiveRoute = []
}
return store.layoutTagsOpen return store.layoutTagsOpen
}) })
const breadcrumbOpen = computed(() => { const breadcrumbOpen = computed(() => {
@ -235,12 +239,6 @@
const module = computed(() => { const module = computed(() => {
return store.module return store.module
}) })
const keepLiveRoute = computed(() => {
return kStore.keepLiveRoute
})
const routeShow = computed(() => {
return kStore.routeShow
})
const sideTheme = computed(() => { const sideTheme = computed(() => {
return theme.value === ThemeModeEnum.REAL_DARK ? ThemeModeEnum.DARK : theme.value return theme.value === ThemeModeEnum.REAL_DARK ? ThemeModeEnum.DARK : theme.value
}) })
@ -355,6 +353,7 @@
topHeaderThemeColorSpread.value topHeaderThemeColorSpread.value
? headerLogin.classList.add('snowy-header-logo-primary-color') ? headerLogin.classList.add('snowy-header-logo-primary-color')
: headerLogin.classList.remove('snowy-header-logo-primary-color') : headerLogin.classList.remove('snowy-header-logo-primary-color')
// eslint-disable-next-line no-empty
} catch (e) {} } catch (e) {}
// //
if (layout.value === 'doublerow') { if (layout.value === 'doublerow') {
@ -363,6 +362,7 @@
topHeaderThemeColorSpread.value topHeaderThemeColorSpread.value
? snowyDoublerowSideTop.classList.add('snowy-doublerow-side-top-primary-color') ? snowyDoublerowSideTop.classList.add('snowy-doublerow-side-top-primary-color')
: snowyDoublerowSideTop.classList.remove('snowy-doublerow-side-top-primary-color') : snowyDoublerowSideTop.classList.remove('snowy-doublerow-side-top-primary-color')
// eslint-disable-next-line no-empty
} catch (e) {} } catch (e) {}
} }
} }

View File

@ -1,3 +1,3 @@
<template> <template>
<a-result status="403" title="403" sub-title="访"> </a-result> <a-result status="403" title="403" sub-title="访" />
</template> </template>

View File

@ -6,16 +6,13 @@
</template> </template>
</a-result> </a-result>
</template> </template>
<script setup>
<script> import { useRouter } from 'vue-router'
export default { const router = useRouter()
methods: { const gohome = () => {
gohome() {
location.href = '/' location.href = '/'
},
goback() {
this.$router.go(-1)
}
} }
const goback = () => {
router.go(-1)
} }
</script> </script>

View File

@ -20,7 +20,7 @@ export default {
searchKey: 'Search Key', searchKey: 'Search Key',
imports: 'Import', imports: 'Import',
more: 'More', more: 'More',
export: 'Export', export: 'Export'
}, },
model: { model: {
user: 'user', user: 'user',

View File

@ -22,7 +22,7 @@ export default {
searchKey: '关键词', searchKey: '关键词',
imports: '导入', imports: '导入',
more: '更多', more: '更多',
export: '导出', export: '导出'
}, },
model: { model: {
user: '用户', user: '用户',

View File

@ -109,7 +109,7 @@ router.beforeEach(async (to, from, next) => {
apiMenu[0] = cloneDeep(userRoutes.module[0]) apiMenu[0] = cloneDeep(userRoutes.module[0])
} }
const childrenApiMenu = apiMenu[0].children const childrenApiMenu = apiMenu[0].children
apiMenu[0].children = [...childrenApiMenu ? childrenApiMenu : [], ...userRoutes.menu] apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
let menuRouter = filterAsyncRouter(apiMenu) let menuRouter = filterAsyncRouter(apiMenu)
menuRouter = flatAsyncRoutes(menuRouter) menuRouter = flatAsyncRoutes(menuRouter)
menuRouter.forEach((item) => { menuRouter.forEach((item) => {
@ -148,7 +148,7 @@ router.getMenu = () => {
apiMenu[0] = cloneDeep(userRoutes.module[0]) apiMenu[0] = cloneDeep(userRoutes.module[0])
} }
const childrenApiMenu = apiMenu[0].children const childrenApiMenu = apiMenu[0].children
apiMenu[0].children = [...childrenApiMenu ? childrenApiMenu : [], ...userRoutes.menu] apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
return filterUrl(apiMenu) return filterUrl(apiMenu)
} }

View File

@ -30,77 +30,132 @@ const getCacheConfig = (value) => {
/** /**
* deprecated 请使用 useGlobalStore * deprecated 请使用 useGlobalStore
*/ */
export const globalStore = defineStore({ export const globalStore = defineStore('global', () => {
id: 'global', // 利用Vue3组合式APIref()定义state的属性
state: () => ({ // function() 定义actions
// computed 定义getters
// 定义state
// 移动端布局 // 移动端布局
isMobile: false, const isMobile = ref(false)
// 布局 // 布局
layout: getCacheConfig('SNOWY_LAYOUT'), const layout = ref(getCacheConfig('SNOWY_LAYOUT'))
// 菜单是否折叠 toggle // 菜单是否折叠 toggle
menuIsCollapse: getCacheConfig('SNOWY_MENU_COLLAPSE'), const menuIsCollapse = ref(getCacheConfig('SNOWY_MENU_COLLAPSE'))
// 侧边菜单是否排他展开 // 侧边菜单是否排他展开
sideUniqueOpen: getCacheConfig('SNOWY_SIDE_UNIQUE_OPEN'), const sideUniqueOpen = ref(getCacheConfig('SNOWY_SIDE_UNIQUE_OPEN'))
// 多标签栏 // 多标签栏
layoutTagsOpen: getCacheConfig('SNOWY_LAYOUT_TAGS_OPEN'), const layoutTagsOpen = ref(getCacheConfig('SNOWY_LAYOUT_TAGS_OPEN'))
// 是否展示面包屑 // 是否展示面包屑
breadcrumbOpen: getCacheConfig('SNOWY_BREADCRUMD_OPEN'), const breadcrumbOpen = ref(getCacheConfig('SNOWY_BREADCRUMD_OPEN'))
// 顶栏是否应用主题色 // 顶栏是否应用主题色
topHeaderThemeColorOpen: getCacheConfig('SNOWY_TOP_HEADER_THEME_COLOR_OPEN'), const topHeaderThemeColorOpen = ref(getCacheConfig('SNOWY_TOP_HEADER_THEME_COLOR_OPEN'))
// 顶栏主题色通栏 // 顶栏主题色通栏
topHeaderThemeColorSpread: getCacheConfig('SNOWY_TOP_HEADER_THEME_COLOR_SPREAD'), const topHeaderThemeColorSpread = ref(getCacheConfig('SNOWY_TOP_HEADER_THEME_COLOR_SPREAD'))
// 模块坞 // 模块坞
moduleUnfoldOpen: getCacheConfig('SNOWY_MODULE_UNFOLD_OPEN'), const moduleUnfoldOpen = ref(getCacheConfig('SNOWY_MODULE_UNFOLD_OPEN'))
// 主题 // 主题
theme: getCacheConfig('SNOWY_THEME'), const theme = ref(getCacheConfig('SNOWY_THEME'))
// 主题颜色 // 主题颜色
themeColor: toolDataGet('SNOWY_THEME_COLOR') || config.COLOR, const themeColor = ref(toolDataGet('SNOWY_THEME_COLOR') || config.COLOR)
// 整体表单风格 // 整体表单风格
formStyle: getCacheConfig('SNOWY_FORM_STYLE'), const formStyle = ref(getCacheConfig('SNOWY_FORM_STYLE'))
// 用户信息 // 用户信息
userInfo: toolDataGet('USER_INFO') || {}, const userInfo = ref(toolDataGet('USER_INFO') || {})
// 系统配置 // 系统配置
sysBaseConfig: toolDataGet('SNOWY_SYS_BASE_CONFIG') || config.SYS_BASE_CONFIG, const sysBaseConfig = ref(toolDataGet('SNOWY_SYS_BASE_CONFIG') || config.SYS_BASE_CONFIG)
// 默认应用 // 默认应用
module: getCacheConfig('SNOWY_MENU_MODULE_ID') const module = ref(getCacheConfig('SNOWY_MENU_MODULE_ID'))
}),
getters: {}, // 定义action
actions: { const setIsMobile = (key) => {
setIsMobile(key) { isMobile.value = key
this.isMobile = key
},
setLayout(key) {
this.layout = key
},
setTheme(key) {
this.theme = key
const closeMessage = message.loading(`加载中...`)
changeColor(this.themeColor, key).then(closeMessage)
},
setThemeColor(key) {
this.themeColor = key
const closeMessage = message.loading(`加载中...`)
changeColor(key, this.theme).then(closeMessage)
},
initTheme() {
const closeMessage = message.loading(`加载中...`)
changeColor(this.themeColor, this.theme).then(closeMessage)
},
toggleConfig(key) {
this[key] = !this[key]
},
setFormStyle(key) {
this.formStyle = key
},
setUserInfo(key) {
this.userInfo = key
},
setSysBaseConfig(key) {
this.sysBaseConfig = key
},
setModule(key) {
this.module = key
} }
const setLayout = (key) => {
layout.value = key
}
const setTheme = (key) => {
theme.value = key
const closeMessage = message.loading(`加载中...`)
changeColor(themeColor.value, key).then(closeMessage)
}
const setThemeColor = (key) => {
themeColor.value = key
const closeMessage = message.loading(`加载中...`)
changeColor(key, theme.value).then(closeMessage)
}
const initTheme = () => {
const closeMessage = message.loading(`加载中...`)
changeColor(themeColor.value, theme.value).then(closeMessage)
}
const toggleConfig = (key) => {
switch (key) {
case 'menuIsCollapse':
menuIsCollapse.value = !menuIsCollapse.value
break
case 'topHeaderThemeColorSpread':
topHeaderThemeColorSpread.value = !topHeaderThemeColorSpread.value
break
case 'sideUniqueOpen':
sideUniqueOpen.value = !sideUniqueOpen.value
break
case 'layoutTagsOpen':
layoutTagsOpen.value = !layoutTagsOpen.value
break
case 'breadcrumbOpen':
breadcrumbOpen.value = !breadcrumbOpen.value
break
case 'topHeaderThemeColorOpen':
topHeaderThemeColorOpen.value = !topHeaderThemeColorOpen.value
topHeaderThemeColorSpread.value = topHeaderThemeColorOpen.value
? topHeaderThemeColorSpread.value
: topHeaderThemeColorOpen.value
break
case 'moduleUnfoldOpen':
moduleUnfoldOpen.value = !moduleUnfoldOpen.value
break
}
}
const setFormStyle = (key) => {
formStyle.value = key
}
const setUserInfo = (key) => {
userInfo.value = key
}
const setSysBaseConfig = (key) => {
sysBaseConfig.value = key
}
const setModule = (key) => {
module.value = key
}
return {
isMobile,
layout,
menuIsCollapse,
sideUniqueOpen,
layoutTagsOpen,
breadcrumbOpen,
topHeaderThemeColorOpen,
topHeaderThemeColorSpread,
moduleUnfoldOpen,
theme,
themeColor,
formStyle,
userInfo,
sysBaseConfig,
module,
setIsMobile,
setLayout,
setTheme,
setThemeColor,
initTheme,
toggleConfig,
setFormStyle,
setUserInfo,
setSysBaseConfig,
setModule
} }
}) })

View File

@ -10,32 +10,30 @@
*/ */
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
export const iframeStore = defineStore({ export const iframeStore = defineStore('iframe', () => {
id: 'iframe', // 定义state
state: () => ({ const iframeList = ref([])
iframeList: [] const setIframeList = (route) => {
}), iframeList.value = []
getters: {}, iframeList.value.push(route)
actions: {
setIframeList(route) {
this.iframeList = []
this.iframeList.push(route)
},
pushIframeList(route) {
const target = this.iframeList.find((item) => item.path === route.path)
if (!target) {
this.iframeList.push(route)
} }
},
removeIframeList(route) { // 定义action
this.iframeList.forEach((item, index) => { const pushIframeList = (route) => {
const target = iframeList.value.find((item) => item.path === route.path)
if (!target) {
iframeList.value.push(route)
}
}
const removeIframeList = (route) => {
iframeList.value.forEach((item, index) => {
if (item.path === route.path) { if (item.path === route.path) {
this.iframeList.splice(index, 1) iframeList.value.splice(index, 1)
} }
}) })
}, }
refreshIframe(route) { const refreshIframe = (route) => {
this.iframeList.forEach((item) => { iframeList.value.forEach((item) => {
if (item.path === route.path) { if (item.path === route.path) {
const url = route.meta.url const url = route.meta.url
item.meta.url = '' item.meta.url = ''
@ -44,9 +42,17 @@ export const iframeStore = defineStore({
}, 200) }, 200)
} }
}) })
},
clearIframeList() {
this.iframeList = []
} }
const clearIframeList = () => {
iframeList.value = []
}
return {
iframeList,
setIframeList,
pushIframeList,
removeIframeList,
refreshIframe,
clearIframeList
} }
}) })

View File

@ -10,37 +10,46 @@
*/ */
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
export const keepAliveStore = defineStore({ export const keepAliveStore = defineStore('keepAlive', () => {
id: 'keepAlive', // 定义state
state: () => ({ const keepLiveRoute = ref([])
keepLiveRoute: [], const routeKey = ref(null)
routeKey: null, const routeShow = ref(true)
routeShow: true
}), // 定义action
getters: {}, const pushKeepLive = (component) => {
actions: { if (!keepLiveRoute.value.includes(component)) {
pushKeepLive(component) { keepLiveRoute.value.push(component)
if (!this.keepLiveRoute.includes(component)) {
this.keepLiveRoute.push(component)
} }
}, }
removeKeepLive(component) { const removeKeepLive = (component) => {
const index = this.keepLiveRoute.indexOf(component) const index = keepLiveRoute.value.indexOf(component)
if (index !== -1) { if (index !== -1) {
this.keepLiveRoute.splice(index, 1) keepLiveRoute.value.splice(index, 1)
} }
},
clearKeepLive() {
this.keepLiveRoute = []
},
setRouteKey(key) {
this.routeKey = key
},
setRouteShow(key) {
this.routeShow = key
},
setRouteKeyAction(key) {
this.setRouteKey(key)
} }
const clearKeepLive = () => {
keepLiveRoute.value = []
}
const setRouteKey = (key) => {
routeKey.value = key
}
const setRouteShow = (key) => {
routeShow.value = key
}
const setRouteKeyAction = (key) => {
setRouteKey(key)
}
return {
keepLiveRoute,
routeKey,
routeShow,
pushKeepLive,
removeKeepLive,
clearKeepLive,
setRouteKey,
setRouteShow,
setRouteKeyAction
} }
}) })

View File

@ -1,26 +1,24 @@
import '@/utils/objects' import '@/utils/objects'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
export const searchStore = defineStore({ export const searchStore = defineStore('search', () => {
id: 'search', // 定义state
state: () => ({ const pool = ref([])
active: false, const hotkey = ref({
hotkey: {
open: 's', open: 's',
close: 'esc' close: 'esc'
}, })
pool: [] const active = ref(false)
}),
getters: {}, // 定义action
actions: { const toggleActive = () => {
toggleActive() { active.value = !active.value
this.active = !this.active }
}, const setActive = (val) => {
setActive(active) { active.value = val
this.active = active }
}, const init = (menu) => {
init(menu) { const poolList = []
const pool = []
const getFullName = function (meta) { const getFullName = function (meta) {
if (meta.breadcrumb) { if (meta.breadcrumb) {
let list = [] let list = []
@ -37,7 +35,7 @@ export const searchStore = defineStore({
if (m.children) { if (m.children) {
push(m.children) push(m.children)
} else if (m.children === null) { } else if (m.children === null) {
pool.push({ poolList.push({
icon: m.meta.icon, icon: m.meta.icon,
path: m.path, path: m.path,
fullPath: m.path, fullPath: m.path,
@ -51,7 +49,15 @@ export const searchStore = defineStore({
}) })
} }
push(menu) push(menu)
this.pool = pool pool.value = poolList
} }
return {
pool,
hotkey,
active,
toggleActive,
setActive,
init
} }
}) })

View File

@ -10,51 +10,59 @@
*/ */
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
export const viewTagsStore = defineStore({ export const viewTagsStore = defineStore('viewTags', () => {
id: 'viewTags', // 定义state
state: () => ({ const viewTags = ref([])
viewTags: []
}), // 定义action
getters: {}, const pushViewTags = (route) => {
actions: { const target = viewTags.value.find((item) => item.path === route.path)
pushViewTags(route) {
const target = this.viewTags.find((item) => item.path === route.path)
const isName = route.name const isName = route.name
if (!target && isName) { if (!target && isName) {
this.viewTags.push(route) viewTags.value.push(route)
} }
if (target) { if (target) {
this.viewTags.forEach((item) => { viewTags.value.forEach((item, index) => {
if (item.path === route.path) { if (item.path === route.path) {
Object.assign(item, route) viewTags.value[index] = { ...route, ...item }
// Object.assign(item, route)
} }
}) })
} }
}, }
removeViewTags(route) { const removeViewTags = (route) => {
this.viewTags.forEach((item, index) => { viewTags.value.forEach((item, index) => {
if (item.fullPath === route.fullPath) { if (item.fullPath === route.fullPath) {
this.viewTags.splice(index, 1) viewTags.value.splice(index, 1)
} }
}) })
}, }
updateViewTags(route) { const updateViewTags = (route) => {
this.viewTags.forEach((item) => { viewTags.value.forEach((item, index) => {
if (item.fullPath == route.fullPath) { if (item.fullPath === route.fullPath) {
Object.assign(item, route) viewTags.value[index] = { ...route, ...item }
// Object.assign(item, route)
} }
}) })
}, }
updateViewTagsTitle(title = '') { const updateViewTagsTitle = (title = '') => {
const nowFullPath = location.hash.substring(1) const nowFullPath = location.hash.substring(1)
this.viewTags.forEach((item) => { viewTags.value.forEach((item) => {
if (item.fullPath == nowFullPath) { if (item.fullPath === nowFullPath) {
item.meta.title = title item.meta.title = title
} }
}) })
},
clearViewTags() {
this.viewTags = []
} }
const clearViewTags = () => {
viewTags.value = []
}
return {
viewTags,
pushViewTags,
removeViewTags,
updateViewTags,
updateViewTagsTitle,
clearViewTags
} }
}) })

View File

@ -21,7 +21,7 @@ export default {
RgbToHex(a, b, c) { RgbToHex(a, b, c) {
const hexs = [a.toString(16), b.toString(16), c.toString(16)] const hexs = [a.toString(16), b.toString(16), c.toString(16)]
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}` if (hexs[i].length === 1) hexs[i] = `0${hexs[i]}`
} }
return `#${hexs.join('')}` return `#${hexs.join('')}`
}, },

View File

@ -57,13 +57,11 @@ export const watermark = {
if (wmInstance) { if (wmInstance) {
// 避免一直触发 // 避免一直触发
// observer.disconnect(); // observer.disconnect();
// console.log('水印属性修改了');
wmInstance.setAttribute('style', styleStr) wmInstance.setAttribute('style', styleStr)
} else { } else {
/* 此处根据用户登录状态,判断是否终止监听,避免用户退出后登录页面仍然有水印 */ /* 此处根据用户登录状态,判断是否终止监听,避免用户退出后登录页面仍然有水印 */
if (tool.data.get('TOKEN')) { if (tool.data.get('TOKEN')) {
//标签被移除,重新添加标签 //标签被移除,重新添加标签
// console.log('水印标签被移除了');
document.body.appendChild(watermark) document.body.appendChild(watermark)
} else { } else {
observer.disconnect() observer.disconnect()

View File

@ -26,7 +26,6 @@
import loginApi from '@/api/auth/loginApi' import loginApi from '@/api/auth/loginApi'
import userCenterApi from '@/api/sys/userCenterApi' import userCenterApi from '@/api/sys/userCenterApi'
import dictApi from '@/api/dev/dictApi' import dictApi from '@/api/dev/dictApi'
import { onMounted } from 'vue'
onMounted(() => { onMounted(() => {
// url // url

View File

@ -97,48 +97,37 @@
</div> </div>
</div> </div>
</template> </template>
<script setup>
<script>
import loginApi from '@/api/auth/loginApi' import loginApi from '@/api/auth/loginApi'
import phoneLoginForm from './phoneLoginForm.vue' import PhoneLoginForm from './phoneLoginForm.vue'
import threeLogin from './threeLogin.vue' import ThreeLogin from './threeLogin.vue'
import smCrypto from '@/utils/smCrypto' import smCrypto from '@/utils/smCrypto'
import { required } from '@/utils/formRules' import { required } from '@/utils/formRules'
import { afterLogin } from './util' import { afterLogin } from './util'
import config from '@/config' import configData from '@/config'
import configApi from '@/api/dev/configApi' import configApi from '@/api/dev/configApi'
import tool from '@/utils/tool' import tool from '@/utils/tool'
import { globalStore, iframeStore, keepAliveStore, viewTagsStore } from '@/store' import { globalStore, iframeStore, keepAliveStore, viewTagsStore } from '@/store'
import { mapActions, mapState } from 'pinia' const { proxy } = getCurrentInstance()
export default { const activeKey = ref('userAccount')
name: 'Login', const captchaOpen = ref(configData.SYS_BASE_CONFIG.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN)
components: { const validCodeBase64 = ref('')
phoneLoginForm, const loading = ref(false)
threeLogin
}, const ruleForm = reactive({
data() {
return {
activeKey: 'userAccount',
captchaOpen: config.SYS_BASE_CONFIG.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN,
validCodeBase64: '',
ruleForm: {
account: 'superAdmin', account: 'superAdmin',
password: '123456', password: '123456',
validCode: '', validCode: '',
validCodeReqNo: '', validCodeReqNo: '',
autologin: false autologin: false
}, })
rules: {
account: [required(this.$t('login.accountError'), 'blur')], const rules = reactive({
password: [required(this.$t('login.PWError'), 'blur')] account: [required(proxy.$t('login.accountError'), 'blur')],
}, password: [required(proxy.$t('login.PWError'), 'blur')]
loading: false, })
config: { const lang = ref([
lang: tool.data.get('APP_LANG') || this.$CONFIG.LANG,
theme: tool.data.get('APP_THEME') || 'default'
},
lang: [
{ {
name: '简体中文', name: '简体中文',
value: 'zh-cn' value: 'zh-cn'
@ -147,90 +136,106 @@
name: 'English', name: 'English',
value: 'en' value: 'en'
} }
] ])
} const config = ref({
}, lang: tool.data.get('APP_LANG') || proxy.$CONFIG.LANG,
computed: { theme: tool.data.get('APP_THEME') || 'default'
...mapState(globalStore, ['sysBaseConfig']), })
},
watch: { const store = globalStore()
'config.theme': function (val) { const kStore = keepAliveStore()
document.body.setAttribute('data-theme', val) const iStore = iframeStore()
}, const vStore = viewTagsStore()
'config.lang': function (val) {
this.$i18n.locale = val const setSysBaseConfig = store.setSysBaseConfig
tool.data.set('APP_LANG', val) const clearKeepLive = kStore.clearKeepLive
} const clearIframeList = iStore.clearIframeList
}, const clearViewTags = vStore.clearViewTags
created() {
this.clearViewTags() const sysBaseConfig = computed(() => {
this.clearKeepLive() return store.sysBaseConfig
this.clearIframeList() })
},
mounted() { onMounted(() => {
let formData = ref(config.SYS_BASE_CONFIG) let formData = ref(configData.SYS_BASE_CONFIG)
configApi.configSysBaseList().then((data) => { configApi.configSysBaseList().then((data) => {
if (data) { if (data) {
data.forEach((item) => { data.forEach((item) => {
formData.value[item.configKey] = item.configValue formData.value[item.configKey] = item.configValue
}) })
this.captchaOpen = formData.value.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN captchaOpen.value = formData.value.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN
tool.data.set('SNOWY_SYS_BASE_CONFIG', formData.value) tool.data.set('SNOWY_SYS_BASE_CONFIG', formData.value)
this.setSysBaseConfig(formData.value) setSysBaseConfig(formData.value)
this.refreshSwitch() refreshSwitch()
} }
}) })
}, })
methods: {
...mapActions(keepAliveStore, ['clearKeepLive']), onBeforeMount(() => {
...mapActions(viewTagsStore, ['clearViewTags']), clearViewTags()
...mapActions(iframeStore, ['clearIframeList']), clearKeepLive()
...mapActions(globalStore, ['setSysBaseConfig']), clearIframeList()
})
//
watch(
() => config.value.lang,
(newValue) => {
proxy.$i18n.locale = newValue
tool.data.set('APP_LANG', newValue)
}
)
//
watch(
() => config.value.theme,
(newValue) => {
document.body.setAttribute('data-theme', newValue)
}
)
// //
refreshSwitch() { const refreshSwitch = () => {
// //
if (this.captchaOpen === 'true') { if (captchaOpen.value === 'true') {
// //
this.loginCaptcha() loginCaptcha()
// //
this.rules.validCode = [required(this.$t('login.validError'), 'blur')] rules.validCode = [required(proxy.$t('login.validError'), 'blur')]
} }
}, }
// //
loginCaptcha() { const loginCaptcha = () => {
loginApi.getPicCaptcha().then((data) => { loginApi.getPicCaptcha().then((data) => {
this.validCodeBase64 = data.validCodeBase64 validCodeBase64.value = data.validCodeBase64
this.ruleForm.validCodeReqNo = data.validCodeReqNo ruleForm.validCodeReqNo = data.validCodeReqNo
}) })
}, }
// //
async login() { const loginForm = ref()
this.$refs.loginForm.validate().then(async () => { const login = async () => {
this.loading = true loginForm.value.validate().then(async () => {
loading.value = true
const loginData = { const loginData = {
account: this.ruleForm.account, account: ruleForm.account,
// SM2使hash // SM2使hash
password: smCrypto.doSm2Encrypt(this.ruleForm.password), password: smCrypto.doSm2Encrypt(ruleForm.password),
validCode: this.ruleForm.validCode, validCode: ruleForm.validCode,
validCodeReqNo: this.ruleForm.validCodeReqNo validCodeReqNo: ruleForm.validCodeReqNo
} }
// token // token
try { try {
const loginToken = await loginApi.login(loginData) const loginToken = await loginApi.login(loginData)
afterLogin(loginToken) afterLogin(loginToken)
} catch (err) { } catch (err) {
this.loading = false loading.value = false
this.loginCaptcha() loginCaptcha()
} }
}) })
},
configLang(key) {
this.config.lang = key
}
} }
const configLang = (key) => {
config.value.lang = key
} }
</script> </script>
<style lang="less"> <style lang="less">
@import 'login'; @import 'login';
</style> </style>

View File

@ -22,7 +22,7 @@ export const afterLogin = async (loginToken) => {
// 重置系统默认应用 // 重置系统默认应用
tool.data.set('SNOWY_MENU_MODULE_ID', menu[0].id) tool.data.set('SNOWY_MENU_MODULE_ID', menu[0].id)
message.success('登录成功') message.success('登录成功')
if (!!tool.data.get('LAST_VIEWS_PATH')) { if (tool.data.get('LAST_VIEWS_PATH')) {
// 如果有缓存,将其登录跳转到最后访问的路由 // 如果有缓存,将其登录跳转到最后访问的路由
indexMenu = tool.data.get('LAST_VIEWS_PATH') indexMenu = tool.data.get('LAST_VIEWS_PATH')
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<s-table ref="table" :columns="columns" :data="loadDataB" :alert="false" bordered :row-key="(record) => record.id"> <s-table ref="tableRef" :columns="columns" :data="loadDataB" :alert="false" bordered :row-key="(record) => record.id">
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'avatar'"> <template v-if="column.dataIndex === 'avatar'">
<a-avatar :src="record.avatar" style="width: 25px; height: 25px" /> <a-avatar :src="record.avatar" style="width: 25px; height: 25px" />
@ -18,13 +18,13 @@
</template> </template>
</template> </template>
</s-table> </s-table>
<token-info-list ref="tokenInfoList" @successful="table.refresh()" /> <token-info-list ref="tokenInfoList" @successful="tableRef.refresh()" />
</template> </template>
<script setup name="monitorBTab"> <script setup name="monitorBTab">
import monitorApi from '@/api/auth/monitorApi' import monitorApi from '@/api/auth/monitorApi'
import TokenInfoList from './tokenInfoList.vue' import TokenInfoList from './tokenInfoList.vue'
const table = ref(null) const tableRef = ref(null)
const tokenInfoList = ref() const tokenInfoList = ref()
const columns = [ const columns = [
{ {
@ -83,7 +83,7 @@
} }
] ]
monitorApi.monitorBExit(params).then(() => { monitorApi.monitorBExit(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
} }
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<s-table ref="table" :columns="columns" :data="loadDataC" :alert="false" bordered :row-key="(record) => record.id"> <s-table ref="tableRef" :columns="columns" :data="loadDataC" :alert="false" bordered :row-key="(record) => record.id">
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'avatar'"> <template v-if="column.dataIndex === 'avatar'">
<a-avatar :src="record.avatar" style="width: 25px; height: 25px" /> <a-avatar :src="record.avatar" style="width: 25px; height: 25px" />
@ -18,13 +18,13 @@
</template> </template>
</template> </template>
</s-table> </s-table>
<token-info-list ref="tokenInfoList" @successful="table.refresh()" /> <token-info-list ref="tokenInfoList" @successful="tableRef.refresh()" />
</template> </template>
<script setup name="monitorCTab"> <script setup name="monitorCTab">
import monitorApi from '@/api/auth/monitorApi' import monitorApi from '@/api/auth/monitorApi'
import TokenInfoList from './tokenInfoList.vue' import TokenInfoList from './tokenInfoList.vue'
const table = ref(null) const tableRef = ref(null)
const tokenInfoList = ref() const tokenInfoList = ref()
const columns = [ const columns = [
{ {
@ -83,7 +83,7 @@
} }
] ]
monitorApi.monitorCExit(params).then(() => { monitorApi.monitorCExit(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
} }
</script> </script>

View File

@ -13,8 +13,8 @@
</template> </template>
<script setup name="authMonitor"> <script setup name="authMonitor">
import analyse from './analyse.vue' import Analyse from './analyse.vue'
import monitorBTab from './bTab.vue' import MonitorBTab from './bTab.vue'
import monitorCTab from './cTab.vue' import MonitorCTab from './cTab.vue'
const activeKey = ref('1') const activeKey = ref('1')
</script> </script>

View File

@ -1,11 +1,5 @@
<template> <template>
<xn-form-container <xn-form-container title="令牌列表" :width="650" :visible="visible" :destroy-on-close="true" @close="onClose">
title="令牌列表"
:width="650"
:visible="visible"
:destroy-on-close="true"
@close="onClose"
>
<a-button <a-button
danger danger
style="margin-bottom: 10px" style="margin-bottom: 10px"
@ -104,7 +98,7 @@
// //
const loadData = ref([]) const loadData = ref([])
// //
let visible = $ref(false) const visible = ref(false)
// //
const selectedRowKeys = ref([]) const selectedRowKeys = ref([])
const exitLoading = ref(false) const exitLoading = ref(false)
@ -116,13 +110,13 @@
const onOpen = (tokenInfoList, type) => { const onOpen = (tokenInfoList, type) => {
monitorType.value = type monitorType.value = type
loadData.value = cloneDeep(tokenInfoList) loadData.value = cloneDeep(tokenInfoList)
visible = true visible.value = true
} }
// //
const onClose = () => { const onClose = () => {
loadData.value = [] loadData.value = []
monitorType.value = '' monitorType.value = ''
visible = false visible.value = false
} }
// //
const rowSelection = { const rowSelection = {

View File

@ -14,7 +14,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="6"> <a-col :span="6">
<a-button type="primary" @click="table.refresh(true)"></a-button> <a-button type="primary" @click="tableRef.refresh(true)"></a-button>
<a-button style="margin: 0 8px" @click="reset"></a-button> <a-button style="margin: 0 8px" @click="reset"></a-button>
</a-col> </a-col>
</a-row> </a-row>
@ -22,7 +22,7 @@
</a-card> </a-card>
<a-card :bordered="false"> <a-card :bordered="false">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:alert="false" :alert="false"
@ -45,9 +45,9 @@
<script setup name="authThird"> <script setup name="authThird">
import thirdApi from '@/api/auth/thirdApi' import thirdApi from '@/api/auth/thirdApi'
import tool from '@/utils/tool' import tool from '@/utils/tool'
let searchFormState = reactive({}) const searchFormState = ref({})
const searchFormRef = ref() const searchFormRef = ref()
const table = ref() const tableRef = ref()
const toolConfig = { refresh: true, height: true, columnSetting: false, striped: false } const toolConfig = { refresh: true, height: true, columnSetting: false, striped: false }
const columns = [ const columns = [
{ {
@ -83,14 +83,14 @@
} }
] ]
const loadData = (parameter) => { const loadData = (parameter) => {
return thirdApi.thirdPage(Object.assign(parameter, searchFormState)).then((res) => { return thirdApi.thirdPage(Object.assign(parameter, searchFormState.value)).then((res) => {
return res return res
}) })
} }
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields(); searchFormRef.value.resetFields();
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const categoryOptions = tool.dictList('THIRD_CATEGORY') const categoryOptions = tool.dictList('THIRD_CATEGORY')

View File

@ -27,7 +27,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
查询 查询
</a-button> </a-button>
@ -41,7 +41,7 @@
</a-card> </a-card>
<a-card :bordered="false" style="margin-bottom: 10px"> <a-card :bordered="false" style="margin-bottom: 10px">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -95,7 +95,7 @@
}) })
} }
// tableDOM // tableDOM
const table = ref(null) const tableRef = ref(null)
const formRef = ref() const formRef = ref()
const cardLoading = ref(true) const cardLoading = ref(true)
const searchFormRef = ref() const searchFormRef = ref()
@ -136,7 +136,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const loadTreeData = () => { const loadTreeData = () => {
@ -166,11 +166,11 @@
delete searchFormState.value.parentId delete searchFormState.value.parentId
columns.splice(2, 1) columns.splice(2, 1)
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const formSuccessful = () => { const formSuccessful = () => {
table.value.refresh() tableRef.value.refresh()
refreshStoreDict() refreshStoreDict()
} }
// store // store

View File

@ -72,7 +72,7 @@
// emit // emit
const emit = defineEmits({ successful: null }) const emit = defineEmits({ successful: null })
// //
let visible = $ref(false) const visible = ref(false)
let UserSelectorPlus = ref() let UserSelectorPlus = ref()
const formRef = ref() const formRef = ref()
// //
@ -83,7 +83,7 @@
// //
const onOpen = (record, parentId) => { const onOpen = (record, parentId) => {
visible = true visible.value = true
formData.value = { formData.value = {
sortCode: 99 sortCode: 99
} }
@ -112,7 +112,7 @@
} }
// //
const onClose = () => { const onClose = () => {
visible = false visible.value = false
} }
// //
const formRules = { const formRules = {
@ -152,7 +152,7 @@
bizOrgApi bizOrgApi
.submitForm(formData.value, formData.value.id) .submitForm(formData.value, formData.value.id)
.then(() => { .then(() => {
visible = false visible.value = false
emit('successful') emit('successful')
}) })
.finally(() => { .finally(() => {

View File

@ -23,7 +23,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
查询 查询
</a-button> </a-button>
@ -37,7 +37,7 @@
</a-card> </a-card>
<a-card :bordered="false"> <a-card :bordered="false">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -51,7 +51,7 @@
<a-space> <a-space>
<a-button <a-button
type="primary" type="primary"
@click="form.onOpen(undefined, searchFormState.parentId)" @click="formRef.onOpen(undefined, searchFormState.parentId)"
v-if="hasPerm('bizOrgAdd')" v-if="hasPerm('bizOrgAdd')"
> >
<template #icon><plus-outlined /></template> <template #icon><plus-outlined /></template>
@ -69,7 +69,7 @@
{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }} {{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
</template> </template>
<template v-if="column.dataIndex === 'action'"> <template v-if="column.dataIndex === 'action'">
<a @click="form.onOpen(record)" v-if="hasPerm('bizOrgEdit')"></a> <a @click="formRef.onOpen(record)" v-if="hasPerm('bizOrgEdit')"></a>
<a-divider type="vertical" v-if="hasPerm(['bizOrgEdit', 'bizOrgDelete'], 'and')" /> <a-divider type="vertical" v-if="hasPerm(['bizOrgEdit', 'bizOrgDelete'], 'and')" />
<a-popconfirm title="删除此机构与下级机构吗?" @confirm="removeOrg(record)"> <a-popconfirm title="删除此机构与下级机构吗?" @confirm="removeOrg(record)">
<a-button type="link" danger size="small" v-if="hasPerm('bizOrgDelete')"></a-button> <a-button type="link" danger size="small" v-if="hasPerm('bizOrgDelete')"></a-button>
@ -80,7 +80,7 @@
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
<Form ref="form" @successful="table.refresh()" /> <Form ref="formRef" @successful="tableRef.refresh()" />
</template> </template>
<script setup name="bizOrg"> <script setup name="bizOrg">
@ -129,8 +129,8 @@
} }
const toolConfig = { refresh: true, height: true, columnSetting: true } const toolConfig = { refresh: true, height: true, columnSetting: true }
// tableDOM // tableDOM
const table = ref(null) const tableRef = ref(null)
const form = ref() const formRef = ref()
const searchFormRef = ref() const searchFormRef = ref()
const searchFormState = ref({}) const searchFormState = ref({})
// //
@ -150,7 +150,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const loadTreeData = () => { const loadTreeData = () => {
@ -188,7 +188,7 @@
} else { } else {
delete searchFormState.value.parentId delete searchFormState.value.parentId
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const removeOrg = (record) => { const removeOrg = (record) => {
@ -198,13 +198,13 @@
} }
] ]
bizOrgApi.orgDelete(params).then(() => { bizOrgApi.orgDelete(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
} }
// //
const deleteBatchOrg = (params) => { const deleteBatchOrg = (params) => {
bizOrgApi.orgDelete(params).then(() => { bizOrgApi.orgDelete(params).then(() => {
table.value.clearRefreshSelected() tableRef.value.clearRefreshSelected()
}) })
} }
</script> </script>

View File

@ -23,7 +23,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
查询 查询
</a-button> </a-button>
@ -37,7 +37,7 @@
</a-card> </a-card>
<a-card :bordered="false"> <a-card :bordered="false">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -80,7 +80,7 @@
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
<Form ref="formRef" @successful="table.refresh(true)" /> <Form ref="formRef" @successful="tableRef.refresh(true)" />
</template> </template>
<script setup name="bizPosition"> <script setup name="bizPosition">
@ -129,7 +129,7 @@
} }
const toolConfig = { refresh: true, height: true, columnSetting: true } const toolConfig = { refresh: true, height: true, columnSetting: true }
// tableDOM // tableDOM
const table = ref(null) const tableRef = ref(null)
const formRef = ref() const formRef = ref()
const searchFormRef = ref() const searchFormRef = ref()
const searchFormState = ref({}) const searchFormState = ref({})
@ -149,7 +149,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
bizOrgApi bizOrgApi
@ -185,7 +185,7 @@
} else { } else {
delete searchFormState.value.orgId delete searchFormState.value.orgId
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const removeOrg = (record) => { const removeOrg = (record) => {
@ -195,13 +195,13 @@
} }
] ]
bizPositionApi.positionDelete(params).then(() => { bizPositionApi.positionDelete(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
} }
// //
const deleteBatchPosition = (params) => { const deleteBatchPosition = (params) => {
bizPositionApi.positionDelete(params).then(() => { bizPositionApi.positionDelete(params).then(() => {
table.value.clearRefreshSelected() tableRef.value.clearRefreshSelected()
}) })
} }
</script> </script>

View File

@ -35,7 +35,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
{{ $t('common.searchButton') }} {{ $t('common.searchButton') }}
</a-button> </a-button>
@ -49,7 +49,7 @@
</a-card> </a-card>
<a-card :bordered="false"> <a-card :bordered="false">
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -140,7 +140,7 @@
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
<Form ref="formRef" @successful="table.refresh()" /> <Form ref="formRef" @successful="tableRef.refresh()" />
<role-selector-plus <role-selector-plus
ref="RoleSelectorPlusRef" ref="RoleSelectorPlusRef"
:org-tree-api="selectorApiFunction.orgTreeApi" :org-tree-api="selectorApiFunction.orgTreeApi"
@ -216,7 +216,7 @@
const searchFormRef = ref() const searchFormRef = ref()
const defaultExpandedKeys = ref([]) const defaultExpandedKeys = ref([])
const searchFormState = ref({}) const searchFormState = ref({})
const table = ref(null) const tableRef = ref(null)
const treeData = ref([]) const treeData = ref([])
const selectedRowKeys = ref([]) const selectedRowKeys = ref([])
const treeFieldNames = { children: 'children', title: 'name', key: 'id' } const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
@ -234,7 +234,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
bizOrgApi bizOrgApi
@ -284,7 +284,7 @@
} else { } else {
delete searchFormState.value.orgId delete searchFormState.value.orgId
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const editStatus = (record) => { const editStatus = (record) => {
@ -293,7 +293,7 @@
bizUserApi bizUserApi
.userDisableUser(record) .userDisableUser(record)
.then(() => { .then(() => {
table.value.refresh() tableRef.value.refresh()
}) })
.finally(() => { .finally(() => {
loading.value = false loading.value = false
@ -302,7 +302,7 @@
bizUserApi bizUserApi
.userEnableUser(record) .userEnableUser(record)
.then(() => { .then(() => {
table.value.refresh() tableRef.value.refresh()
}) })
.finally(() => { .finally(() => {
loading.value = false loading.value = false
@ -317,7 +317,7 @@
} }
] ]
bizUserApi.userDelete(params).then(() => { bizUserApi.userDelete(params).then(() => {
table.value.refresh() tableRef.value.refresh()
}) })
} }
// //
@ -348,13 +348,13 @@
const exportBatchUser = (params) => { const exportBatchUser = (params) => {
bizUserApi.userExport(params).then((res) => { bizUserApi.userExport(params).then((res) => {
downloadUtil.resultDownload(res) downloadUtil.resultDownload(res)
table.value.clearSelected() tableRef.value.clearSelected()
}) })
} }
// //
const deleteBatchUser = (params) => { const deleteBatchUser = (params) => {
bizUserApi.userDelete(params).then(() => { bizUserApi.userDelete(params).then(() => {
table.value.clearRefreshSelected() tableRef.value.clearRefreshSelected()
}) })
} }
// //

View File

@ -13,8 +13,8 @@
</template> </template>
<script setup name="emailConfig"> <script setup name="emailConfig">
import localEmailForm from './localEmailForm.vue' import LocalEmailForm from './localEmailForm.vue'
import aliyunEmailForm from './aliyunEmailForm.vue' import AliyunEmailForm from './aliyunEmailForm.vue'
import tencentEmailForm from './tencentEmailForm.vue' import TencentEmailForm from './tencentEmailForm.vue'
const activeKey = ref('localEmail') const activeKey = ref('localEmail')
</script> </script>

View File

@ -16,9 +16,9 @@
</template> </template>
<script setup name="fileConfig"> <script setup name="fileConfig">
import localFileForm from './localFileForm.vue' import LocalFileForm from './localFileForm.vue'
import aliyunFileForm from './aliyunFileForm.vue' import AliyunFileForm from './aliyunFileForm.vue'
import tencentFileForm from './tencentFileForm.vue' import TencentFileForm from './tencentFileForm.vue'
import minioFileForm from './minioFileForm.vue' import MinioFileForm from './minioFileForm.vue'
const activeKey = ref('localFile') const activeKey = ref('localFile')
</script> </script>

View File

@ -35,7 +35,7 @@
import { required } from '@/utils/formRules' import { required } from '@/utils/formRules'
import configApi from '@/api/dev/configApi' import configApi from '@/api/dev/configApi'
// //
let visible = $ref(false) const visible = ref(false)
const emit = defineEmits({ successful: null }) const emit = defineEmits({ successful: null })
const formRef = ref() const formRef = ref()
// //
@ -44,7 +44,7 @@
// //
const onOpen = (record) => { const onOpen = (record) => {
visible = true visible.value = true
formData.value = { formData.value = {
sortCode: 99 sortCode: 99
} }
@ -55,7 +55,7 @@
// //
const onClose = () => { const onClose = () => {
formRef.value.resetFields() formRef.value.resetFields()
visible = false visible.value = false
} }
// //
const formRules = { const formRules = {

View File

@ -1,6 +1,6 @@
<template> <template>
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:alert="false" :alert="false"
@ -10,7 +10,7 @@
> >
<template #operator class="table-operator"> <template #operator class="table-operator">
<a-space> <a-space>
<a-button type="primary" @click="form.onOpen()"> <a-button type="primary" @click="formRef.onOpen()">
<template #icon> <template #icon>
<plus-outlined /> <plus-outlined />
</template> </template>
@ -21,14 +21,14 @@
placeholder="请输入关键字" placeholder="请输入关键字"
enter-button enter-button
allowClear allowClear
@search="table.refresh(true)" @search="tableRef.refresh(true)"
/> />
</a-space> </a-space>
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-space> <a-space>
<a @click="form.onOpen(record)"></a> <a @click="formRef.onOpen(record)"></a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-popconfirm title="确定要删除此配置吗?" @confirm="deleteConfig(record)"> <a-popconfirm title="确定要删除此配置吗?" @confirm="deleteConfig(record)">
<a-button type="link" danger size="small">删除</a-button> <a-button type="link" danger size="small">删除</a-button>
@ -37,16 +37,15 @@
</template> </template>
</template> </template>
</s-table> </s-table>
<Form ref="form" @successful="table.refresh(true)" /> <Form ref="formRef" @successful="tableRef.refresh(true)" />
</template> </template>
<script setup name="sysModule"> <script setup name="sysModule">
import Form from './form.vue' import Form from './form.vue'
import configApi from '@/api/dev/configApi' import configApi from '@/api/dev/configApi'
let searchFormState = reactive({}) const searchFormState = ref({})
const formRef = ref() const formRef = ref()
const table = ref() const tableRef = ref()
let form = ref()
const toolConfig = { refresh: true, height: true, columnSetting: false, striped: false } const toolConfig = { refresh: true, height: true, columnSetting: false, striped: false }
const columns = [ const columns = [
{ {
@ -77,7 +76,7 @@
} }
] ]
const loadData = (parameter) => { const loadData = (parameter) => {
return configApi.configPage(Object.assign(parameter, searchFormState)).then((res) => { return configApi.configPage(Object.assign(parameter, searchFormState.value)).then((res) => {
return res return res
}) })
} }
@ -89,7 +88,7 @@
} }
] ]
configApi.configDelete(params).then(() => { configApi.configDelete(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
} }
</script> </script>

View File

@ -10,7 +10,7 @@
</template> </template>
<script setup name="smsConfig"> <script setup name="smsConfig">
import aliyunSmsForm from './aliyunSmsForm.vue' import AliyunSmsForm from './aliyunSmsForm.vue'
import tencentSmsForm from './tencentSmsForm.vue' import TencentSmsForm from './tencentSmsForm.vue'
const activeKey = ref('aliyunSms') const activeKey = ref('aliyunSms')
</script> </script>

View File

@ -102,7 +102,7 @@
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import configApi from '@/api/dev/configApi' import configApi from '@/api/dev/configApi'
import tool from '@/utils/tool' import tool from '@/utils/tool'
import menuTreeSelect from '@/components/TreeSelect/menuTreeSelect.vue' import MenuTreeSelect from '@/components/TreeSelect/menuTreeSelect.vue'
// emit // emit
const emit = defineEmits({ successful: null }) const emit = defineEmits({ successful: null })

View File

@ -10,7 +10,7 @@
</template> </template>
<script setup name="thirdConfig"> <script setup name="thirdConfig">
import wechatThirdForm from './wechatThirdForm.vue' import WechatThirdForm from './wechatThirdForm.vue'
import giteeThirdForm from './giteeThirdForm.vue' import GiteeThirdForm from './giteeThirdForm.vue'
const activeKey = ref('wechatThird') const activeKey = ref('wechatThird')
</script> </script>

View File

@ -20,7 +20,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="$refs.table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
查询 查询
</a-button> </a-button>
@ -33,7 +33,7 @@
</a-form> </a-form>
<a-divider class="m-3 mx-0" /> <a-divider class="m-3 mx-0" />
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -42,7 +42,7 @@
:row-key="(record) => record.id" :row-key="(record) => record.id"
> >
<template #operator class="table-operator"> <template #operator class="table-operator">
<a-button type="primary" @click="form.onOpen(undefined, 'BIZ', searchFormState.parentId)"> <a-button type="primary" @click="formRef.onOpen(undefined, 'BIZ', searchFormState.parentId)">
<template #icon><plus-outlined /></template> <template #icon><plus-outlined /></template>
新增 新增
</a-button> </a-button>
@ -53,7 +53,7 @@
<a-tag color="green" v-else></a-tag> <a-tag color="green" v-else></a-tag>
</template> </template>
<template v-if="column.dataIndex === 'action'"> <template v-if="column.dataIndex === 'action'">
<a @click="form.onOpen(record, 'BIZ')">编辑</a> <a @click="formRef.onOpen(record, 'BIZ')">编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-popconfirm title="删除此字典与下级字典吗?" @confirm="remove(record)"> <a-popconfirm title="删除此字典与下级字典吗?" @confirm="remove(record)">
<a-button type="link" danger size="small">删除</a-button> <a-button type="link" danger size="small">删除</a-button>
@ -63,14 +63,14 @@
</s-table> </s-table>
</a-col> </a-col>
</a-row> </a-row>
<Form ref="form" @successful="formSuccessful()" /> <Form ref="formRef" @successful="formSuccessful()" />
</template> </template>
<script setup> <script setup>
import { Empty } from 'ant-design-vue' import { Empty } from 'ant-design-vue'
import dictApi from '@/api/dev/dictApi' import dictApi from '@/api/dev/dictApi'
import Form from './form.vue' import Form from './form.vue'
const { proxy } = getCurrentInstance() import tool from '@/utils/tool'
const columns = [ const columns = [
{ {
title: '字典名称', title: '字典名称',
@ -94,10 +94,10 @@
} }
] ]
// tableDOM // tableDOM
const table = ref(null) const tableRef = ref(null)
const form = ref() const formRef = ref()
const searchFormRef = ref() const searchFormRef = ref()
let searchFormState = reactive({}) const searchFormState = ref({})
// //
let defaultExpandedKeys = ref([]) let defaultExpandedKeys = ref([])
const treeData = ref([]) const treeData = ref([])
@ -109,9 +109,9 @@
const loadData = (parameter) => { const loadData = (parameter) => {
loadTreeData() loadTreeData()
parameter.category = 'BIZ' parameter.category = 'BIZ'
return dictApi.dictPage(Object.assign(parameter, searchFormState)).then((data) => { return dictApi.dictPage(Object.assign(parameter, searchFormState.value)).then((data) => {
if (data.records) { if (data.records) {
if (searchFormState.parentId) { if (searchFormState.value.parentId) {
let dataArray = [] let dataArray = []
data.records.forEach((item) => { data.records.forEach((item) => {
const obj = data.records.find((f) => f.id === item.parentId) const obj = data.records.find((f) => f.id === item.parentId)
@ -135,7 +135,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const loadTreeData = () => { const loadTreeData = () => {
@ -151,7 +151,7 @@
// //
const treeSelect = (selectedKeys) => { const treeSelect = (selectedKeys) => {
if (selectedKeys && selectedKeys.length > 0) { if (selectedKeys && selectedKeys.length > 0) {
searchFormState.parentId = selectedKeys.toString() searchFormState.value.parentId = selectedKeys.toString()
if (!columns.find((f) => f.title === '层级')) { if (!columns.find((f) => f.title === '层级')) {
columns.splice(2, 0, { columns.splice(2, 0, {
title: '层级', title: '层级',
@ -160,10 +160,10 @@
}) })
} }
} else { } else {
delete searchFormState.parentId delete searchFormState.value.parentId
columns.splice(2, 1) columns.splice(2, 1)
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const remove = (record) => { const remove = (record) => {
@ -173,19 +173,19 @@
} }
] ]
dictApi.dictDelete(params).then(() => { dictApi.dictDelete(params).then(() => {
table.value.refresh(true) tableRef.value.refresh(true)
}) })
refreshStoreDict() refreshStoreDict()
} }
// //
const formSuccessful = () => { const formSuccessful = () => {
table.value.refresh() tableRef.value.refresh()
refreshStoreDict() refreshStoreDict()
} }
// store // store
const refreshStoreDict = () => { const refreshStoreDict = () => {
dictApi.dictTree().then((res) => { dictApi.dictTree().then((res) => {
proxy.$TOOL.data.set('DICT_TYPE_TREE_DATA', res) tool.data.set('DICT_TYPE_TREE_DATA', res)
}) })
} }
</script> </script>

View File

@ -54,7 +54,7 @@
// emit // emit
const emit = defineEmits({ successful: null }) const emit = defineEmits({ successful: null })
// //
let visible = $ref(false) const visible = ref(false)
const formRef = ref() const formRef = ref()
// //
let formData = ref({}) let formData = ref({})
@ -65,7 +65,7 @@
// //
const onOpen = (record, type, parentId) => { const onOpen = (record, type, parentId) => {
visible = true visible.value = true
formData.value = { formData.value = {
sortCode: 99, sortCode: 99,
category: type category: type
@ -94,7 +94,7 @@
} }
// //
const onClose = () => { const onClose = () => {
visible = false visible.value = false
} }
// //
const formRules = { const formRules = {
@ -112,7 +112,7 @@
const onSubmit = () => { const onSubmit = () => {
formRef.value.validate().then(() => { formRef.value.validate().then(() => {
dictApi.submitForm(formData.value, formData.value.id).then(() => { dictApi.submitForm(formData.value, formData.value.id).then(() => {
visible = false visible.value = false
emit('successful') emit('successful')
}) })
}) })

View File

@ -20,7 +20,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-button type="primary" @click="$refs.table.refresh(true)"> <a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template> <template #icon><SearchOutlined /></template>
查询 查询
</a-button> </a-button>
@ -33,7 +33,7 @@
</a-form> </a-form>
<a-divider class="m-3 mx-0" /> <a-divider class="m-3 mx-0" />
<s-table <s-table
ref="table" ref="tableRef"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:expand-row-by-click="true" :expand-row-by-click="true"
@ -42,7 +42,7 @@
:row-key="(record) => record.id" :row-key="(record) => record.id"
> >
<template #operator class="table-operator"> <template #operator class="table-operator">
<a-button type="primary" @click="form.onOpen(undefined, 'FRM', searchFormState.parentId)"> <a-button type="primary" @click="formRef.onOpen(undefined, 'FRM', searchFormState.parentId)">
<template #icon><plus-outlined /></template> <template #icon><plus-outlined /></template>
新增 新增
</a-button> </a-button>
@ -53,21 +53,21 @@
<a-tag color="green" v-else></a-tag> <a-tag color="green" v-else></a-tag>
</template> </template>
<template v-if="column.dataIndex === 'action'"> <template v-if="column.dataIndex === 'action'">
<a @click="form.onOpen(record, 'FRM')">编辑</a> <a @click="formRef.onOpen(record, 'FRM')">编辑</a>
</template> </template>
</template> </template>
</s-table> </s-table>
</a-col> </a-col>
</a-row> </a-row>
<Form ref="form" @successful="formSuccessful()" /> <Form ref="formRef" @successful="formSuccessful()" />
</template> </template>
<script setup> <script setup>
import { Empty } from 'ant-design-vue' import { Empty } from 'ant-design-vue'
import dictApi from '@/api/dev/dictApi' import dictApi from '@/api/dev/dictApi'
import Form from './form.vue' import Form from './form.vue'
const { proxy } = getCurrentInstance() import tool from '@/utils/tool'
let searchFormState = reactive({}) const searchFormState = ref({})
const columns = [ const columns = [
{ {
title: '字典名称', title: '字典名称',
@ -91,11 +91,11 @@
} }
] ]
// tableDOM // tableDOM
const table = ref(null) const tableRef = ref(null)
const form = ref() const formRef = ref()
const searchFormRef = ref() const searchFormRef = ref()
// //
let defaultExpandedKeys = ref([]) const defaultExpandedKeys = ref([])
const treeData = ref([]) const treeData = ref([])
// treeNode title,key,children // treeNode title,key,children
const treeFieldNames = { children: 'children', title: 'dictLabel', key: 'id' } const treeFieldNames = { children: 'children', title: 'dictLabel', key: 'id' }
@ -105,9 +105,9 @@
const loadData = (parameter) => { const loadData = (parameter) => {
loadTreeData() loadTreeData()
parameter.category = 'FRM' parameter.category = 'FRM'
return dictApi.dictPage(Object.assign(parameter, searchFormState)).then((data) => { return dictApi.dictPage(Object.assign(parameter, searchFormState.value)).then((data) => {
if (data.records) { if (data.records) {
if (searchFormState.parentId) { if (searchFormState.value.parentId) {
let dataArray = [] let dataArray = []
data.records.forEach((item) => { data.records.forEach((item) => {
const obj = data.records.find((f) => f.id === item.parentId) const obj = data.records.find((f) => f.id === item.parentId)
@ -131,7 +131,7 @@
// //
const reset = () => { const reset = () => {
searchFormRef.value.resetFields() searchFormRef.value.resetFields()
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const loadTreeData = () => { const loadTreeData = () => {
@ -147,7 +147,7 @@
// //
const treeSelect = (selectedKeys) => { const treeSelect = (selectedKeys) => {
if (selectedKeys && selectedKeys.length > 0) { if (selectedKeys && selectedKeys.length > 0) {
searchFormState.parentId = selectedKeys.toString() searchFormState.value.parentId = selectedKeys.toString()
if (!columns.find((f) => f.title === '层级')) { if (!columns.find((f) => f.title === '层级')) {
columns.splice(2, 0, { columns.splice(2, 0, {
title: '层级', title: '层级',
@ -156,20 +156,20 @@
}) })
} }
} else { } else {
delete searchFormState.parentId delete searchFormState.value.parentId
columns.splice(2, 1) columns.splice(2, 1)
} }
table.value.refresh(true) tableRef.value.refresh(true)
} }
// //
const formSuccessful = () => { const formSuccessful = () => {
table.value.refresh() tableRef.value.refresh()
refreshStoreDict() refreshStoreDict()
} }
// store // store
const refreshStoreDict = () => { const refreshStoreDict = () => {
dictApi.dictTree().then((res) => { dictApi.dictTree().then((res) => {
proxy.$TOOL.data.set('DICT_TYPE_TREE_DATA', res) tool.data.set('DICT_TYPE_TREE_DATA', res)
}) })
} }
</script> </script>

Some files were not shown because too many files have changed in this diff Show More