Merge branch 'client_sync' into v2

# Conflicts:
#	packages/ui/certd-client/CHANGELOG.md
#	packages/ui/certd-client/package.json
#	packages/ui/certd-client/src/api/tools.ts
#	packages/ui/certd-client/src/components/index.ts
#	packages/ui/certd-client/src/main.ts
#	packages/ui/certd-client/src/plugin/fast-crud/index.tsx
#	packages/ui/certd-client/src/plugin/index.ts
#	packages/ui/certd-client/src/router/source/framework.ts
#	packages/ui/certd-client/src/store/modules/page.ts
#	packages/ui/certd-client/src/style/common.less
#	packages/ui/certd-client/src/utils/util.env.ts
#	packages/ui/certd-client/src/views/crud/form/independent/index.vue
#	packages/ui/certd-client/src/views/framework/register/index.vue
#	packages/ui/certd-client/vite.config.ts
pull/68/head
xiaojunnuo 2023-10-27 11:54:38 +08:00
commit e7704171f7
483 changed files with 7737 additions and 5075 deletions

View File

@ -0,0 +1,463 @@
/** @type {import('dependency-cruiser').IConfiguration} */
module.exports = {
forbidden: [
/* rules from the 'recommended' preset: */
{
name: 'no-circular',
severity: 'warn',
comment:
'This dependency is part of a circular relationship. You might want to revise ' +
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
from: {},
to: {
circular: true
}
},
{
name: 'no-orphans',
comment:
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
"add an exception for it in your dependency-cruiser configuration. By default " +
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
severity: 'warn',
from: {
orphan: true,
pathNot: [
'(^|/)\\.[^/]+\\.(js|cjs|mjs|ts|json)$', // dot files
'\\.d\\.ts$', // TypeScript declaration files
'(^|/)tsconfig\\.json$', // TypeScript config
'(^|/)(babel|webpack)\\.config\\.(js|cjs|mjs|ts|json)$' // other configs
]
},
to: {},
},
{
name: 'no-deprecated-core',
comment:
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
"bound to exist - node doesn't deprecate lightly.",
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'core'
],
path: [
'^(v8\/tools\/codemap)$',
'^(v8\/tools\/consarray)$',
'^(v8\/tools\/csvparser)$',
'^(v8\/tools\/logreader)$',
'^(v8\/tools\/profile_view)$',
'^(v8\/tools\/profile)$',
'^(v8\/tools\/SourceMap)$',
'^(v8\/tools\/splaytree)$',
'^(v8\/tools\/tickprocessor-driver)$',
'^(v8\/tools\/tickprocessor)$',
'^(node-inspect\/lib\/_inspect)$',
'^(node-inspect\/lib\/internal\/inspect_client)$',
'^(node-inspect\/lib\/internal\/inspect_repl)$',
'^(async_hooks)$',
'^(punycode)$',
'^(domain)$',
'^(constants)$',
'^(sys)$',
'^(_linklist)$',
'^(_stream_wrap)$'
],
}
},
{
name: 'not-to-deprecated',
comment:
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
'version of that module, or find an alternative. Deprecated modules are a security risk.',
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'deprecated'
]
}
},
{
name: 'no-non-package-json',
severity: 'error',
comment:
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
"available on live with an non-guaranteed version. Fix it by adding the package to the dependencies " +
"in your package.json.",
from: {},
to: {
dependencyTypes: [
'npm-no-pkg',
'npm-unknown'
]
}
},
{
name: 'not-to-unresolvable',
comment:
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
'module: add it to your package.json. In all other cases you likely already know what to do.',
severity: 'error',
from: {},
to: {
couldNotResolve: true
}
},
{
name: 'no-duplicate-dep-types',
comment:
"Likely this module depends on an external ('npm') package that occurs more than once " +
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
"maintenance problems later on.",
severity: 'warn',
from: {},
to: {
moreThanOneDependencyType: true,
// as it's pretty common to have a type import be a type only import
// _and_ (e.g.) a devDependency - don't consider type-only dependency
// types for this rule
dependencyTypesNot: ["type-only"]
}
},
/* rules you might want to tweak for your specific situation: */
{
name: 'not-to-test',
comment:
"This module depends on code within a folder that should only contain tests. As tests don't " +
"implement functionality this is odd. Either you're writing a test outside the test folder " +
"or there's something in the test folder that isn't a test.",
severity: 'error',
from: {
pathNot: '^(tests)'
},
to: {
path: '^(tests)'
}
},
{
name: 'not-to-spec',
comment:
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
severity: 'error',
from: {},
to: {
path: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
}
},
{
name: 'not-to-dev-dep',
severity: 'error',
comment:
"This module depends on an npm package from the 'devDependencies' section of your " +
'package.json. It looks like something that ships to production, though. To prevent problems ' +
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
'section of your package.json. If this module is development only - add it to the ' +
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
from: {
path: '^(src)',
pathNot: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
},
to: {
dependencyTypes: [
'npm-dev'
]
}
},
{
name: 'optional-deps-used',
severity: 'info',
comment:
"This module depends on an npm package that is declared as an optional dependency " +
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
"If you're using an optional dependency here by design - add an exception to your" +
"dependency-cruiser configuration.",
from: {},
to: {
dependencyTypes: [
'npm-optional'
]
}
},
{
name: 'peer-deps-used',
comment:
"This module depends on an npm package that is declared as a peer dependency " +
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
"add an exception to your dependency-cruiser configuration.",
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'npm-peer'
]
}
}
],
options: {
/* conditions specifying which files not to follow further when encountered:
- path: a regular expression to match
- dependencyTypes: see https://github.com/sverweij/dependency-cruiser/blob/master/doc/rules-reference.md#dependencytypes-and-dependencytypesnot
for a complete list
*/
doNotFollow: {
path: 'node_modules'
},
/* conditions specifying which dependencies to exclude
- path: a regular expression to match
- dynamic: a boolean indicating whether to ignore dynamic (true) or static (false) dependencies.
leave out if you want to exclude neither (recommended!)
*/
// exclude : {
// path: '',
// dynamic: true
// },
/* pattern specifying which files to include (regular expression)
dependency-cruiser will skip everything not matching this pattern
*/
// includeOnly : '',
/* dependency-cruiser will include modules matching against the focus
regular expression in its output, as well as their neighbours (direct
dependencies and dependents)
*/
// focus : '',
/* list of module systems to cruise */
// moduleSystems: ['amd', 'cjs', 'es6', 'tsd'],
/* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/develop/'
to open it on your online repo or `vscode://file/${process.cwd()}/` to
open it in visual studio code),
*/
// prefix: '',
/* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation
true: also detect dependencies that only exist before typescript-to-javascript compilation
"specify": for each dependency identify whether it only exists before compilation or also after
*/
tsPreCompilationDeps: true,
/*
list of extensions to scan that aren't javascript or compile-to-javascript.
Empty by default. Only put extensions in here that you want to take into
account that are _not_ parsable.
*/
// extraExtensionsToScan: [".json", ".jpg", ".png", ".svg", ".webp"],
/* if true combines the package.jsons found from the module up to the base
folder the cruise is initiated from. Useful for how (some) mono-repos
manage dependencies & dependency definitions.
*/
// combinedDependencies: false,
/* if true leave symlinks untouched, otherwise use the realpath */
// preserveSymlinks: false,
/* TypeScript project file ('tsconfig.json') to use for
(1) compilation and
(2) resolution (e.g. with the paths property)
The (optional) fileName attribute specifies which file to take (relative to
dependency-cruiser's current working directory). When not provided
defaults to './tsconfig.json'.
*/
tsConfig: {
fileName: 'tsconfig.json'
},
/* Webpack configuration to use to get resolve options from.
The (optional) fileName attribute specifies which file to take (relative
to dependency-cruiser's current working directory. When not provided defaults
to './webpack.conf.js'.
The (optional) `env` and `args` attributes contain the parameters to be passed if
your webpack config is a function and takes them (see webpack documentation
for details)
*/
// webpackConfig: {
// fileName: './webpack.config.js',
// env: {},
// args: {},
// },
/* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use
for compilation (and whatever other naughty things babel plugins do to
source code). This feature is well tested and usable, but might change
behavior a bit over time (e.g. more precise results for used module
systems) without dependency-cruiser getting a major version bump.
*/
// babelConfig: {
// fileName: './.babelrc'
// },
/* List of strings you have in use in addition to cjs/ es6 requires
& imports to declare module dependencies. Use this e.g. if you've
re-declared require, use a require-wrapper or use window.require as
a hack.
*/
// exoticRequireStrings: [],
/* options to pass on to enhanced-resolve, the package dependency-cruiser
uses to resolve module references to disk. You can set most of these
options in a webpack.conf.js - this section is here for those
projects that don't have a separate webpack config file.
Note: settings in webpack.conf.js override the ones specified here.
*/
enhancedResolveOptions: {
/* List of strings to consider as 'exports' fields in package.json. Use
['exports'] when you use packages that use such a field and your environment
supports it (e.g. node ^12.19 || >=14.7 or recent versions of webpack).
If you have an `exportsFields` attribute in your webpack config, that one
will have precedence over the one specified here.
*/
exportsFields: ["exports"],
/* List of conditions to check for in the exports field. e.g. use ['imports']
if you're only interested in exposed es6 modules, ['require'] for commonjs,
or all conditions at once `(['import', 'require', 'node', 'default']`)
if anything goes for you. Only works when the 'exportsFields' array is
non-empty.
If you have a 'conditionNames' attribute in your webpack config, that one will
have precedence over the one specified here.
*/
conditionNames: ["import", "require", "node", "default"],
/*
The extensions, by default are the same as the ones dependency-cruiser
can access (run `npx depcruise --info` to see which ones that are in
_your_ environment. If that list is larger than what you need (e.g.
it contains .js, .jsx, .ts, .tsx, .cts, .mts - but you don't use
TypeScript you can pass just the extensions you actually use (e.g.
[".js", ".jsx"]). This can speed up the most expensive step in
dependency cruising (module resolution) quite a bit.
*/
// extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"],
/*
If your TypeScript project makes use of types specified in 'types'
fields in package.jsons of external dependencies, specify "types"
in addition to "main" in here, so enhanced-resolve (the resolver
dependency-cruiser uses) knows to also look there. You can also do
this if you're not sure, but still use TypeScript. In a future version
of dependency-cruiser this will likely become the default.
*/
mainFields: ["main", "types"],
},
reporterOptions: {
dot: {
/* pattern of modules that can be consolidated in the detailed
graphical dependency graph. The default pattern in this configuration
collapses everything in node_modules to one folder deep so you see
the external modules, but not the innards your app depends upon.
*/
collapsePattern: 'node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/master/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
don't worry - dependency-cruiser will fall back to the default one.
*/
// theme: {
// graph: {
// /* use splines: "ortho" for straight lines. Be aware though
// graphviz might take a long time calculating ortho(gonal)
// routings.
// */
// splines: "true"
// },
// modules: [
// {
// criteria: { matchesFocus: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesFocus: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { matchesReaches: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesReaches: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { source: "^src/model" },
// attributes: { fillcolor: "#ccccff" }
// },
// {
// criteria: { source: "^src/view" },
// attributes: { fillcolor: "#ccffcc" }
// },
// ],
// dependencies: [
// {
// criteria: { "rules[0].severity": "error" },
// attributes: { fontcolor: "red", color: "red" }
// },
// {
// criteria: { "rules[0].severity": "warn" },
// attributes: { fontcolor: "orange", color: "orange" }
// },
// {
// criteria: { "rules[0].severity": "info" },
// attributes: { fontcolor: "blue", color: "blue" }
// },
// {
// criteria: { resolved: "^src/model" },
// attributes: { color: "#0000ff77" }
// },
// {
// criteria: { resolved: "^src/view" },
// attributes: { color: "#00770077" }
// }
// ]
// }
},
archi: {
/* pattern of modules that can be consolidated in the high level
graphical dependency graph. If you use the high level graphical
dependency graph reporter (`archi`) you probably want to tweak
this collapsePattern to your situation.
*/
collapsePattern: '^(packages|src|lib|app|bin|test(s?)|spec(s?))/[^/]+|node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/master/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
for 'archi' dependency-cruiser will use the one specified in the
dot section (see above), if any, and otherwise use the default one.
*/
// theme: {
// },
},
"text": {
"highlightFocused": true
},
}
}
};
// generated: dependency-cruiser@12.11.0 on 2023-03-24T14:11:38.647Z

View File

@ -16,14 +16,10 @@ module.exports = {
tsx: true
}
},
extends: [
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"prettier"
],
extends: ["plugin:vue/vue3-recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "prettier"],
rules: {
//"max-len": [0, 200, 2, { ignoreUrls: true }],
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",

View File

@ -34,3 +34,4 @@ https://github.com/fast-crud/fs-server-js

View File

@ -6,109 +6,118 @@
"dev": "vite",
"dev:pm": "vite --mode pm",
"dev:force": "vite --force",
"debug": "vite --mode debug",
"debug": "vite --mode debug --open",
"debug:pm": "vite --mode debugpm",
"debug:force": "vite --force --mode debug",
"build": "vite build ",
"build": "npm run tsc && vite build ",
"serve": "vite preview",
"preview": "vite preview",
"pretty-quick": "pretty-quick",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
"upgrade": "yarn upgrade-interactive --latest",
"tsc": "vue-tsc --noEmit --skipLibCheck"
"tsc": "vue-tsc --noEmit --skipLibCheck",
"circle:check": "pnpm dependency-cruise --validate --output-type err-html -f dependency-report.html src",
"afterPubPush": "git add . && git commit -m \"build: publish success\" && git push"
},
"author": "Greper",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^6.0.1",
"@certd/acme-client": "^1.1.6",
"@fast-crud/fast-crud": "^1.14.4",
"@fast-crud/fast-extends": "^1.14.4",
"@fast-crud/ui-antdv": "^1.14.4",
"@fast-crud/ui-interface": "^1.14.4",
"@iconify/iconify": "^3.0.1",
"@iconify/json": "^2.1.151",
"@ant-design/colors": "^7.0.0",
"@ant-design/icons-vue": "^6.1.0",
"@aws-sdk/client-s3": "^3.383.0",
"@aws-sdk/s3-request-presigner": "^3.383.0",
"@fast-crud/fast-crud": "^1.18.3",
"@fast-crud/fast-extends": "^1.18.3",
"@fast-crud/ui-antdv": "^1.18.3",
"@fast-crud/ui-interface": "^1.18.3",
"@iconify/iconify": "^3.1.1",
"@iconify/json": "^2.2.98",
"@purge-icons/generated": "^0.9.0",
"@soerenmartius/vue3-clipboard": "^0.1.2",
"ant-design-vue": "^3.2.15",
"axios": "^1.2.1",
"ant-design-vue": "^3.2.20",
"axios": "^1.3.4",
"axios-mock-adapter": "^1.21.2",
"base64-js": "^1.5.1",
"better-scroll": "^2.5.0",
"china-division": "^2.4.0",
"core-js": "^3.26.1",
"cos-js-sdk-v5": "^1.4.15-beta.0",
"better-scroll": "^2.5.1",
"china-division": "^2.6.1",
"core-js": "^3.32.0",
"cos-js-sdk-v5": "^1.4.19",
"cropperjs": "^1.5.13",
"dayjs": "^1.11.7",
"deepdash-es": "5.3.5",
"highlight.js": "^11.7.0",
"dayjs": "^1.11.9",
"highlight.js": "^11.8.0",
"humanize-duration": "^3.27.3",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",
"mitt": "^3.0.1",
"nanoid": "^4.0.0",
"nprogress": "^0.2.0",
"object-assign": "^4.1.1",
"pinia": "2.0.28",
"pinia": "2.1.6",
"qiniu-js": "^3.4.1",
"sortablejs": "^1.14.0",
"vue": "^3.2.45",
"sortablejs": "^1.15.0",
"vue": "^3.3.4",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.5",
"vuedraggable": "^4.0.1"
"vue-router": "^4.2.4",
"vuedraggable": "^2.24.3"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.3",
"@rollup/plugin-node-resolve": "^15.1.0",
"@types/chai": "^4.3.5",
"@types/lodash-es": "^4.17.8",
"@certd/pipeline": "^1.1.6",
"@rollup/plugin-commonjs": "^23.0.4",
"@rollup/plugin-node-resolve": "^15.0.1",
"@types/chai": "^4.3.4",
"@types/lodash-es": "^4.17.7",
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.15",
"@typescript-eslint/eslint-plugin": "^5.46.1",
"@typescript-eslint/parser": "^5.46.1",
"@vitejs/plugin-legacy": "^3.0.1",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/compiler-sfc": "^3.2.45",
"@vue/eslint-config-typescript": "^11.0.2",
"@vue/test-utils": "^2.2.6",
"@types/node": "^20.4.7",
"@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"@vitejs/plugin-legacy": "^4.1.1",
"@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/compiler-sfc": "^3.3.4",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/test-utils": "^2.4.1",
"autoprefixer": "^10.4.14",
"caller-path": "^4.0.0",
"chai": "^4.3.7",
"eslint": "8.29.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.26.0",
"dependency-cruiser": "^13.1.1",
"dot": "^1.1.3",
"eslint": "8.46.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-import": "^2.28.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.1",
"eslint-plugin-vue": "^9.8.0",
"esno": "^0.16.3",
"husky": "^8.0.2",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.16.1",
"esno": "^0.17.0",
"husky": "^8.0.3",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"lint-staged": "^13.1.0",
"postcss": "^8.4.23",
"prettier": "2.8.1",
"less-loader": "^11.1.3",
"lint-staged": "^13.2.3",
"postcss": "^8.4.27",
"prettier": "3.0.1",
"pretty-quick": "^3.1.3",
"rimraf": "^3.0.2",
"rollup": "^3.7.4",
"rollup-plugin-visualizer": "^5.8.2",
"stylelint": "^14.16.0",
"stylelint-config-prettier": "^9.0.4",
"stylelint-order": "^5.0.0",
"tailwindcss": "^3.3.2",
"rimraf": "^5.0.1",
"rollup": "^3.27.2",
"rollup-plugin-visualizer": "^5.9.2",
"stylelint": "^15.10.2",
"stylelint-config-prettier": "^9.0.5",
"stylelint-order": "^6.0.3",
"tailwindcss": "^3.3.3.3",
"terser": "^5.19.2",
"ts-node": "^10.9.1",
"typescript": "4.9.4",
"vite": "^4.0.1",
"typescript": "5.1.6",
"unplugin-vue-define-options": "^1.3.14",
"vite": "^4.4.8",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.9.2",
"vite-plugin-theme": "^0.8.1",
"vue-eslint-parser": "^9.1.0",
"vue-tsc": "^0.40.13"
"vite-plugin-theme": "^0.8.6",
"vite-plugin-windicss": "^1.9.0",
"vue-eslint-parser": "^9.3.1",
"vue-tsc": "^1.8.8",
"windicss": "^3.5.6"
},
"husky": {
"hooks": {

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -0,0 +1,6 @@
name,mobile
张三,18603040102
李四,18603040103
王五,18603040104
赵六,18603040105
田七,18603040106
1 name mobile
2 张三 18603040102
3 李四 18603040103
4 王五 18603040104
5 赵六 18603040105
6 田七 18603040106

View File

@ -4,10 +4,10 @@
</a-config-provider>
</template>
<script>
<script lang="ts">
import zhCN from "ant-design-vue/es/locale/zh_CN";
import enUS from "ant-design-vue/es/locale/en_US";
import { provide, ref, nextTick } from "vue";
import { provide, ref, nextTick, getCurrentInstance } from "vue";
import { usePageStore } from "/src/store/modules/page";
import { useResourceStore } from "/src/store/modules/resource";
import { useSettingStore } from "/@/store/modules/settings";
@ -16,7 +16,7 @@ import "dayjs/locale/en";
import dayjs from "dayjs";
export default {
name: "App",
setup() {
setup(props: any, ctx: any) {
//
const routerEnabled = ref(true);
const locale = ref(zhCN);
@ -25,7 +25,7 @@ export default {
await nextTick();
routerEnabled.value = true;
}
function localeChanged(value) {
function localeChanged(value: any) {
console.log("locale changed:", value);
if (value === "zh-cn") {
locale.value = zhCN;

View File

@ -49,13 +49,14 @@ export function responseError(data = {}, msg = "请求失败", code = 500) {
* @param {Error} error
*/
export function errorLog(error: any) {
if (error?.response?.data?.message) {
error.message = error?.response?.data?.message;
}
// 打印到控制台
console.error("errorLog", error);
let message = error.message;
if (error.response?.data?.message) {
message = error.response.data.message;
}
// 显示提示
uiContext.get().notification.error({ message: error.message });
uiContext.get().notification.error({ message });
}
/**

View File

@ -1,15 +1,18 @@
<template>
<pre class="fs-highlight hljs" v-html="highlightHTML"></pre>
<pre class="fs-highlight hljs" v-html="highlightHTMLRef"></pre>
</template>
<script>
<script lang="ts">
//
// https://highlightjs.org/usage/
// http://highlightjs.readthedocs.io/en/latest/api.html#configure-options
import highlight from "highlight.js";
import { ref, watch } from "vue";
import { defineComponent, Ref } from "vue";
import "../highlight-styles/github-gist.css";
import htmlFormat from "./libs/htmlFormat";
export default {
//@ts-ignore
import htmlFormat from "./libs/htmlFormat.js";
export default defineComponent({
name: "FsHighlight",
props: {
code: {
@ -28,34 +31,31 @@ export default {
default: ""
}
},
data() {
setup(props: any, ctx: any) {
const highlightHTMLRef: Ref = ref("");
watch(
() => {
return props.code;
},
() => {
doHighlight();
},
{
immediate: true
}
);
function doHighlight() {
const code = props.formatHtml ? htmlFormat(props.code) : props.code;
highlightHTMLRef.value = (highlight as any).highlightAuto(code, [props.lang, "html", "javascript", "json", "css", "scss", "less"]).value;
}
return {
highlightHTML: ""
highlightHTMLRef,
doHighlight
};
},
watch: {
code() {
this.highlight();
}
},
mounted() {
this.highlight();
},
methods: {
highlight() {
const code = this.formatHtml ? htmlFormat(this.code) : this.code;
this.highlightHTML = highlight.highlightAuto(code, [
this.lang,
"html",
"javascript",
"json",
"css",
"scss",
"less"
]).value;
}
}
};
});
</script>
<style lang="less">

View File

@ -1,56 +0,0 @@
<template>
<div class="fs-contentmenu-list" @click="rowClick">
<div
v-for="item in menulist"
:key="item.value"
:data-value="item.value"
class="fs-contentmenu-item"
flex="cross:center main:center"
>
<d2-icon v-if="item.icon" :name="item.icon" />
<div class="fs-contentmenu-item-title" flex-box="1">
{{ item.title }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "FsContextmenuList",
props: {
menulist: {
type: Array,
default: () => []
}
},
methods: {
rowClick(event) {
let target = event.target;
while (!target.dataset.value) {
target = target.parentNode;
}
this.$emit("rowClick", target.dataset.value);
}
}
};
</script>
<style lang="less">
.fs-contentmenu-list {
.fs-contentmenu-item {
padding: 8px 20px 8px 15px;
margin: 0;
font-size: 14px;
color: #606266;
cursor: pointer;
&:hover {
background: #ecf5ff;
color: #66b1ff;
}
.fs-contentmenu-item-title {
margin-left: 10px;
}
}
}
</style>

View File

@ -1,68 +0,0 @@
<template>
<div v-show="flag" class="fs-contextmenu" :style="style">
<slot />
</div>
</template>
<script>
export default {
name: "FsContextmenu",
props: {
visible: {
type: Boolean,
default: false
},
x: {
type: Number,
default: 0
},
y: {
type: Number,
default: 0
}
},
computed: {
flag: {
get() {
if (this.visible) {
// [ ]
window.addEventListener("mousedown", this.watchContextmenu);
}
return this.visible;
},
set(newVal) {
this.$emit("update:visible", newVal);
}
},
style() {
return {
left: this.x + "px",
top: this.y + "px",
display: this.visible ? "block" : "none "
};
}
},
mounted() {
// body
document.querySelector("body").appendChild(this.$el);
},
methods: {
watchContextmenu(event) {
if (!this.$el.contains(event.target) || event.button !== 0) this.flag = false;
window.removeEventListener("mousedown", this.watchContextmenu);
}
}
};
</script>
<style>
.fs-contextmenu {
position: absolute;
padding: 5px 0;
z-index: 2018;
background: #fff;
border: 1px solid #cfd7e5;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>

View File

@ -22,7 +22,7 @@
</a-dropdown>
</template>
<script>
<script lang="ts">
import i18n from "../../../i18n";
import { computed, inject } from "vue";
import _ from "lodash-es";
@ -30,8 +30,8 @@ export default {
name: "FsLocale",
setup() {
const languages = computed(() => {
const map = i18n.global.messages?.value || {};
const list = [];
const map: any = i18n.global.messages?.value || {};
const list: any = [];
_.forEach(map, (item, key) => {
list.push({
key,
@ -44,9 +44,9 @@ export default {
return i18n.global.locale.value;
});
const routerReload = inject("fn:router.reload");
const localeChanged = inject("fn:locale.changed");
const changeLocale = (change) => {
const routerReload: any = inject("fn:router.reload");
const localeChanged: any = inject("fn:locale.changed");
const changeLocale = (change: any) => {
i18n.global.locale.value = change.key;
routerReload();
localeChanged(change.key);

View File

@ -1,14 +1,13 @@
import { useRoute, useRouter } from "vue-router";
import { ref, watch, onMounted, onUnmounted, resolveComponent, nextTick, defineComponent } from "vue";
import getEachDeep from "deepdash-es/getEachDeep";
import _ from "lodash-es";
import BScroll from "better-scroll";
import "./index.less";
const eachDeep = getEachDeep(_);
import { utils } from "@fast-crud/fast-crud";
function useBetterScroll(enabled = true) {
let bsRef = ref(null);
let asideMenuRef = ref();
const bsRef = ref(null);
const asideMenuRef = ref();
let onOpenChange = () => {};
if (enabled) {
@ -71,7 +70,7 @@ export default defineComponent({
scroll: {}
},
setup(props, ctx) {
async function open(path) {
async function open(path: any) {
if (path == null) {
return;
}
@ -90,23 +89,24 @@ export default defineComponent({
console.error("导航失败", e);
}
}
function onSelect(item) {
function onSelect(item: any) {
open(item.key);
}
const FsIcon = resolveComponent("FsIcon");
const fsIcon = resolveComponent("FsIcon");
const buildMenus = (children) => {
const slots = [];
const buildMenus = (children: any) => {
const slots: any = [];
if (children == null) {
return slots;
}
for (let sub of children) {
const title = () => {
for (const sub of children) {
const title: any = () => {
if (sub?.meta?.icon) {
// @ts-ignore
return (
<div class={"menu-item-title"}>
<FsIcon class={"anticon"} icon={sub.meta.icon} />
<fsIcon class={"anticon"} icon={sub.meta.icon} />
<span>{sub.title}</span>
</div>
);
@ -147,16 +147,16 @@ export default defineComponent({
const route = useRoute();
const router = useRouter();
function openSelectedParents(fullPath) {
function openSelectedParents(fullPath: any) {
if (!props.expandSelected) {
return;
}
if (props.menus == null) {
return;
}
const keys = [];
const keys: any = [];
let changed = false;
eachDeep(props.menus, (value, key, parent, context) => {
utils.deepdash.forEachDeep(props.menus, (value: any, key: any, parent: any, context: any) => {
if (value == null) {
return;
}
@ -170,7 +170,7 @@ export default defineComponent({
}
});
if (keys.length > 0) {
for (let key of keys) {
for (const key of keys) {
if (openKeys.value.indexOf(key) === -1) {
openKeys.value.push(key);
changed = true;
@ -180,7 +180,7 @@ export default defineComponent({
return changed;
}
const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll);
const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll as any);
watch(
() => {

View File

@ -5,7 +5,7 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
export default defineComponent({
@ -23,7 +23,7 @@ export default defineComponent({
{ immediate: true }
);
const middle = "/fast-crud/fs-admin-antdv/tree/main/src/views";
function goSource(prefix) {
function goSource(prefix: any) {
const path = router.currentRoute.value.fullPath;
window.open(prefix + middle + path + "/index.vue");
}

View File

@ -2,22 +2,8 @@
<div class="fs-multiple-page-control-group">
<div class="fs-multiple-page-control-content">
<div class="fs-multiple-page-control-content-inner">
<a-tabs
class="fs-multiple-page-control fs-multiple-page-sort"
:active-key="page.getCurrent"
type="editable-card"
hide-add
@tabClick="handleClick"
@edit="handleTabEdit"
@contextmenu="handleContextmenu"
>
<a-tab-pane
v-for="item in page.getOpened"
:key="item.fullPath"
:tab="item.meta?.title || '未命名'"
:name="item.fullPath"
:closable="isTabClosable(item)"
/>
<a-tabs class="fs-multiple-page-control fs-multiple-page-sort" :active-key="page.getCurrent" type="editable-card" hide-add @tabClick="handleClick" @edit="handleTabEdit">
<a-tab-pane v-for="item in page.getOpened" :key="item.fullPath" :tab="item.meta?.title || '未命名'" :name="item.fullPath" :closable="isTabClosable(item)" />
</a-tabs>
<!-- <fs-contextmenu v-model:visible="contextmenuFlag" :x="contentmenuX" :y="contentmenuY">-->
<!-- <fs-contextmenu-list-->
@ -33,7 +19,7 @@
<span class="iconify" data-icon="ion:close-circle" data-inline="false"></span>
<template #icon><DownOutlined /></template>
<template #overlay>
<a-menu @click="(command) => handleControlItemClick(command)">
<a-menu @click="(command:any) => handleControlItemClick(command)">
<a-menu-item key="left">
<fs-icon name="arrow-left" class="fs-mr-10" />
关闭左侧
@ -57,8 +43,7 @@
</div>
</template>
<script>
import Sortable from "sortablejs";
<script lang="ts">
import { usePageStore } from "../../../store/modules/page";
import { computed } from "vue";
export default {
@ -119,14 +104,14 @@ export default {
* @description 计算某个标签页是否可关闭
* @param {Object} page 其中一个标签页
*/
isTabClosable(page) {
isTabClosable(page: any) {
return page.name !== "index";
},
/**
* @description 右键菜单功能点击
* @param {Object} event 事件
*/
handleContextmenu(event) {
handleContextmenu(event: any) {
let target = event.target;
// fix https://github.com/fs-projects/fs-admin/issues/54
let flag = false;
@ -148,7 +133,7 @@ export default {
* @description 右键菜单的 row-click 事件
* @param {String} command 事件类型
*/
contextmenuClick(command) {
contextmenuClick(command: any) {
this.handleControlItemClick(command, this.tagName);
},
/**
@ -156,7 +141,7 @@ export default {
* @param {String} command 事件类型
* @param {String} tagName tab 名称
*/
handleControlItemClick(command, tagName = null) {
handleControlItemClick(command: any, tagName: any = null) {
//if (tagName) this.contextmenuFlag = false;
const params = { pageSelect: tagName };
switch (command.key) {
@ -182,9 +167,9 @@ export default {
* @param {object} tab 标签
* @param {object} event 事件
*/
handleClick(tab) {
handleClick(tab: any) {
// tag
const page = this.page.getOpened.find((page) => page.fullPath === tab);
const page = this.page.getOpened.find((page: any) => page.fullPath === tab);
if (page) {
const { name, params, query } = page;
this.$router.push({ name, params, query });
@ -194,12 +179,12 @@ export default {
* @description 点击 tab 上的删除按钮触发这里
* @param {String} tagName tab 名称
*/
handleTabEdit(tagName, action) {
handleTabEdit(tagName: any, action: any) {
if (action === "remove") {
this.close({ tagName });
}
}
}
} as any
};
</script>
<style lang="less">
@ -217,6 +202,11 @@ export default {
}
//antdv
.fs-multiple-page-control-group {
.ant-tabs-tab-remove {
display: flex;
justify-content: center;
align-items: center;
}
.ant-tabs-bar {
margin: 0;
border-bottom: 1px solid #f0f0f0;

View File

@ -14,7 +14,7 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, ref } from "vue";
const colorListDefine = [
{
@ -60,7 +60,7 @@ export default defineComponent({
emits: ["change"],
setup(props, ctx) {
const colorList = ref(colorListDefine);
function changeColor(color) {
function changeColor(color: any) {
ctx.emit("change", color);
}
return {

View File

@ -1,23 +1,13 @@
<template>
<div class="fs-theme" @click="show()">
<fs-iconify icon="ion:sparkles-outline" />
<a-drawer
v-model:visible="visible"
title="主题设置"
placement="right"
width="350px"
:closable="false"
@after-visible-change="afterVisibleChange"
>
<fs-theme-color-picker
:primary-color="setting.getTheme.primaryColor"
@change="setting.setPrimaryColor"
></fs-theme-color-picker>
<a-drawer v-model:visible="visible" title="主题设置" placement="right" width="350px" :closable="false" @after-visible-change="afterVisibleChange">
<fs-theme-color-picker :primary-color="setting.getTheme.primaryColor" @change="setting.setPrimaryColor"></fs-theme-color-picker>
</a-drawer>
</div>
</template>
<script>
<script lang="ts">
import { ref, defineComponent } from "vue";
import FsThemeColorPicker from "./color-picker.vue";
import { useSettingStore } from "/@/store/modules/settings";

View File

@ -10,7 +10,7 @@
</template>
</a-dropdown>
</template>
<script>
<script lang="ts">
import { defineComponent } from "vue";
import { useUserStore } from "/src/store/modules/user";
import { Modal } from "ant-design-vue";

View File

@ -58,7 +58,7 @@
</a-layout>
</template>
<script>
<script lang="ts">
import { computed, onErrorCaptured, ref } from "vue";
import FsMenu from "./components/menu/index.jsx";
import FsLocale from "./components/locale/index.vue";
@ -152,6 +152,11 @@ export default {
background: #f6f6f6;
display: flex;
justify-content: space-between;
> div {
height: auto;
padding: 5px;
}
}
.header-buttons {
display: flex;

View File

@ -25,7 +25,7 @@
</div>
</div>
</template>
<script>
<script lang="ts">
export default {
name: "LayoutOutside"
};
@ -75,7 +75,10 @@ export default {
.top {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.header {
height: 44px;
line-height: 44px;

View File

@ -2,15 +2,19 @@ import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.less";
import "./style/common.less";
import i18n from "./i18n";
import store from "./store";
import components from "./components";
import plugin from "./plugin/";
// 正式项目请删除mock避免影响性能
//import "./mock";
// @ts-ignore
const app = createApp(App);
// 尽量
app.use(Antd);
app.use(router);
app.use(i18n);

View File

@ -1,5 +1,5 @@
import _ from "lodash-es";
function copyList(originList, newList, options, parentId) {
function copyList(originList: any, newList: any, options: any, parentId?: any) {
for (const item of originList) {
const newItem = { ...item, parentId };
newItem.id = ++options.idGenerator;
@ -11,7 +11,7 @@ function copyList(originList, newList, options, parentId) {
}
}
function delById(req, list) {
function delById(req: any, list: any) {
for (let i = 0; i < list.length; i++) {
const item = list[i];
console.log("remove i", i, req, req.params.id, item.id);
@ -26,27 +26,38 @@ function delById(req, list) {
}
}
function findById(id, list) {
function findById(id: any, list: any) {
for (const item of list) {
if (item.id === id) {
return item;
}
if (item.children != null && item.children.length > 0) {
const sub = findById(id, item.children);
const sub: any = findById(id, item.children);
if (sub != null) {
return sub;
}
}
}
}
export default {
function findByIds(ids: any[], list: any) {
const res = [];
for (const id of ids) {
const item = findById(id, list);
if (item != null) {
res.push(item);
}
}
console.log("findbyids", res, ids);
return res;
}
const mockUtil: any = {
findById,
buildMock(options) {
buildMock(options: any) {
const name = options.name;
if (options.copyTimes == null) {
options.copyTimes = 29;
}
const list = [];
const list: any = [];
for (let i = 0; i < options.copyTimes; i++) {
copyList(options.list, list, options);
}
@ -55,7 +66,7 @@ export default {
{
path: "/mock/" + name + "/page",
method: "get",
handle(req) {
handle(req: any) {
let data = [...list];
let limit = 20;
let offset = 0;
@ -65,9 +76,10 @@ export default {
item.lazy = false;
}
}
let orderProp, orderAsc;
let orderProp: any, orderAsc: any;
if (req && req.body) {
const { page, query, sort } = req.body;
const { page, sort } = req.body;
let query = req.body.query;
if (page.limit != null) {
limit = parseInt(page.limit);
}
@ -76,9 +88,9 @@ export default {
}
orderProp = sort.prop;
orderAsc = sort.asc;
query = query || {};
if (Object.keys(query).length > 0) {
data = list.filter((item) => {
data = list.filter((item: any) => {
let allFound = true; // 是否所有条件都符合
for (const key in query) {
// 判定某一个条件
@ -169,16 +181,10 @@ export default {
{
path: "/mock/" + name + "/get",
method: "get",
handle(req) {
handle(req: any) {
let id = req.params.id;
id = parseInt(id);
let current = null;
for (const item of list) {
if (item.id === id) {
current = item;
break;
}
}
const current = findById(req.body.id, list);
return {
code: 0,
msg: "success",
@ -186,10 +192,23 @@ export default {
};
}
},
{
path: "/mock/" + name + "/byIds",
method: "post",
handle(req: any) {
const ids = req.body.ids;
const res = findByIds(ids, list);
return {
code: 0,
msg: "success",
data: res
};
}
},
{
path: "/mock/" + name + "/add",
method: "post",
handle(req) {
handle(req: any) {
req.body.id = ++options.idGenerator;
list.unshift(req.body);
return {
@ -202,7 +221,7 @@ export default {
{
path: "/mock/" + name + "/update",
method: "post",
handle(req) {
handle(req: any): any {
const item = findById(req.body.id, list);
if (item) {
_.mergeWith(item, req.body, (objValue, srcValue) => {
@ -225,7 +244,7 @@ export default {
{
path: "/mock/" + name + "/delete",
method: "post",
handle(req) {
handle(req: any): any {
delById(req, list);
return {
code: 0,
@ -237,7 +256,7 @@ export default {
{
path: "/mock/" + name + "/batchDelete",
method: "post",
handle(req) {
handle(req: any): any {
const ids = req.body.ids;
for (let i = list.length - 1; i >= 0; i--) {
const item = list[i];
@ -255,7 +274,7 @@ export default {
{
path: "/mock/" + name + "/delete",
method: "post",
handle(req) {
handle(req: any): any {
delById(req, list);
return {
code: 0,
@ -267,7 +286,7 @@ export default {
{
path: "/mock/" + name + "/all",
method: "post",
handle(req) {
handle(req: any): any {
return {
code: 0,
msg: "success",
@ -278,3 +297,5 @@ export default {
];
}
};
export default mockUtil;

View File

@ -1,11 +1,13 @@
import cascaderData from "./cascader-data";
// @ts-ignore
import pcaDataLittle from "./pca-data-little";
// @ts-ignore
import { TreeNodesLazyLoader, getPcaData } from "./pcas-data";
import _ from "lodash-es";
const openStatus = [
{ value: "1", label: "打开", color: "success",icon:"ion:radio-button-on" },
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
{ value: "2", label: "停止", color: "cyan" },
{ value: "0", label: "关闭", color: "red",icon:"ion:radio-button-off" }
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
];
const moreOpenStatus = [
@ -20,11 +22,25 @@ const textStatus = [
{ id: "0", text: "关闭", color: "red" }
];
export function GetTreeChildrenByParentId(parentId) {
let manyStatus = [
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
{ value: "2", label: "停止", color: "cyan" },
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
];
for (let i = 0; i < 2; i++) {
manyStatus = manyStatus.concat(_.cloneDeep(manyStatus));
}
let idIndex = 0;
for (const item of manyStatus) {
idIndex++;
item.value = idIndex + "";
}
export function GetTreeChildrenByParentId(parentId: any) {
return TreeNodesLazyLoader.getChildren(parentId);
}
export function GetNodesByValues(values) {
export function GetNodesByValues(values: any) {
return TreeNodesLazyLoader.getNodesByValues(values);
}
@ -51,6 +67,17 @@ export default [
};
}
},
{
path: "/mock/dicts/ManyOpenStatusEnum",
method: "get",
handle() {
return {
code: 0,
msg: "success",
data: manyStatus
};
}
},
{
path: "/mock/dicts/moreOpenStatusEnum",
method: "get",
@ -99,7 +126,7 @@ export default [
{
path: "/mock/tree/GetTreeChildrenByParentId",
method: "get",
async handle({ params }) {
async handle({ params }: any) {
const list = await GetTreeChildrenByParentId(params.parentId);
return {
code: 0,
@ -111,7 +138,7 @@ export default [
{
path: "/mock/tree/GetNodesByValues",
method: "get",
async handle({ params }) {
async handle({ params }: any) {
const list = await GetNodesByValues(params.values);
return {
code: 0,

View File

@ -1,16 +1,18 @@
import _ from "lodash-es";
export async function getPcasData() {
// @ts-ignore
const pcasData = () => import("china-division/dist/pcas-code.json");
const ret = await pcasData();
return ret.default;
}
export async function getPcaData() {
// @ts-ignore
const pcaData = () => import("china-division/dist/pca-code.json");
const ret = await pcaData();
return ret.default;
}
export const TreeNodesLazyLoader = {
getNodesByValues(values) {
getNodesByValues(values: any) {
console.log("getNodesByValues", values);
if (!(values instanceof Array)) {
values = [values];
@ -28,20 +30,20 @@ export const TreeNodesLazyLoader = {
return nodes;
});
},
getNode(list, value) {
getNode(list: any, value: any) {
for (const item of list) {
if (item.code === value) {
return item;
}
if (item.children && item.children.length > 0) {
const found = this.getNode(item.children, value);
const found: any = this.getNode(item.children, value);
if (found) {
return found;
}
}
}
},
getChildren(parent) {
getChildren(parent: any) {
return getPcasData().then((data) => {
const list = this.getChildrenByParent(parent, data);
if (list == null) {
@ -50,7 +52,7 @@ export const TreeNodesLazyLoader = {
return this.cloneAndDeleteChildren(list);
});
},
getChildrenByParent(parentId, tree) {
getChildrenByParent(parentId: any, tree: any) {
if (!parentId) {
// 取第一级
return tree;
@ -61,7 +63,7 @@ export const TreeNodesLazyLoader = {
}
if (node.children && node.children.length > 0) {
// 递归查找
const list = this.getChildrenByParent(parentId, node.children);
const list: any = this.getChildrenByParent(parentId, node.children);
if (list) {
return list;
}
@ -69,10 +71,10 @@ export const TreeNodesLazyLoader = {
}
}
},
cloneAndDeleteChildren(list) {
cloneAndDeleteChildren(list: any) {
const newList = [];
for (const node of list) {
const newNode = {};
const newNode: any = {};
Object.assign(newNode, node);
if (newNode.children == null || newNode.children.length === 0) {
newNode.isLeaf = true;

View File

@ -1,12 +1,15 @@
import { mock } from "../api/service";
import * as tools from "../api/tools";
import _ from "lodash-es";
const commonMocks = import.meta.globEager("./common/mock.*.js");
const apiMocks = import.meta.globEager("../api/modules/*.mock.ts");
const viewMocks = import.meta.globEager("../views/**/mock.js");
// @ts-ignore
const commonMocks: any = import.meta.glob("./common/mock.*.[j|t]s", { eager: true });
// @ts-ignore
const apiMocks: any = import.meta.glob("../api/modules/*.mock.ts", { eager: true });
// @ts-ignore
const viewMocks: any = import.meta.glob("../views/**/mock.[j|t]s", { eager: true });
const list = [];
_.forEach(commonMocks, (value) => {
const list: any = [];
_.forEach(commonMocks, (value: any) => {
list.push(value.default);
});
_.forEach(apiMocks, (value) => {
@ -16,9 +19,9 @@ _.forEach(viewMocks, (value) => {
list.push(value.default);
});
list.forEach((apiFile) => {
list.forEach((apiFile: any) => {
for (const item of apiFile) {
mock.onAny(new RegExp(item.path)).reply(async (config) => {
mock.onAny(new RegExp(item.path)).reply(async (config: any) => {
console.log("------------fake request start -------------");
console.log("request:", config);
const data = config.data ? JSON.parse(config.data) : {};

View File

@ -1,12 +1,14 @@
import { request, requestForMock } from "/src/api/service";
import { ColumnCompositionProps, CrudOptions, FastCrud, setLogger, useColumns, UseCrudProps, useTypes } from "@fast-crud/fast-crud";
import { ColumnCompositionProps, CrudOptions, FastCrud, PageQuery, PageRes, setLogger, TransformResProps, useColumns, UseCrudProps, UserPageQuery, useTypes, useUi } from "@fast-crud/fast-crud";
import "@fast-crud/fast-crud/dist/style.css";
import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExtendsUploader } from "@fast-crud/fast-extends";
import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExtendsUploader, FsUploaderS3SignedUrlType } from "@fast-crud/fast-extends";
import "@fast-crud/fast-extends/dist/style.css";
import UiAntdv from "@fast-crud/ui-antdv";
import _ from "lodash-es";
import { useCrudPermission } from "../permission";
import { App } from "vue";
import { GetSignedUrl } from "/@/views/crud/component/uploader/s3/api";
import { notification } from "ant-design-vue";
function install(app: App, options: any = {}) {
app.use(UiAntdv);
@ -14,7 +16,7 @@ function install(app: App, options: any = {}) {
setLogger({ level: "info" });
app.use(FastCrud, {
i18n: options.i18n,
async dictRequest({ url }) {
async dictRequest({ url }: any) {
if (url && url.startsWith("/mock")) {
//如果是crud开头的dict请求视为mock
return await requestForMock({ url, method: "post" });
@ -23,16 +25,33 @@ function install(app: App, options: any = {}) {
},
/**
* useCrud
* @param contextuseCrud
* @param propsuseCrud
*/
commonOptions(context: UseCrudProps) {
const crudBinding = context.expose?.crudBinding;
commonOptions(props: UseCrudProps): CrudOptions {
const crudBinding = props.crudExpose?.crudBinding;
const opts: CrudOptions = {
table: {
size: "small",
pagination: false,
onResizeColumn: (w: any, col: any) => {
crudBinding.value.table.columnsMap[col.key].width = w;
onResizeColumn: (w: number, col: any) => {
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
crudBinding.value.table.columnsMap[col.key].width = w;
}
},
conditionalRender: {
match(scope) {
//不能用 !scope.value 否则switch组件设置为关之后就消失了
const { value, key } = scope;
return !value && key != "_index" && value != false;
},
render() {
return "-";
}
}
},
toolbar: {
export: {
fileType: "excel"
}
},
rowHandle: {
@ -48,7 +67,7 @@ function install(app: App, options: any = {}) {
}
},
request: {
transformQuery: ({ page, form, sort }) => {
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
const limit = page.pageSize;
const currentPage = page.currentPage ?? 1;
const offset = limit * (currentPage - 1);
@ -64,7 +83,7 @@ function install(app: App, options: any = {}) {
sort
};
},
transformRes: ({ res }) => {
transformRes: ({ res }: TransformResProps): PageRes => {
const pageSize = res.limit;
let currentPage = res.offset / pageSize;
if (res.offset % pageSize === 0) {
@ -82,6 +101,13 @@ function install(app: App, options: any = {}) {
width: "120px"
}
},
async afterSubmit({ mode }) {
if (mode === "add") {
notification.success({ message: "添加成功" });
} else if (mode === "edit") {
notification.success({ message: "保存成功" });
}
},
wrapperCol: {
span: null
}
@ -89,7 +115,8 @@ function install(app: App, options: any = {}) {
};
// 从 useCrud({permission}) 里获取permission参数去设置各个按钮的权限
const crudPermission = useCrudPermission({ permission: context.permission });
const permission = props.context?.permission || null;
const crudPermission = useCrudPermission({ permission });
return crudPermission.merge(opts);
}
});
@ -101,28 +128,28 @@ function install(app: App, options: any = {}) {
// @ts-ignore
defaultType: "cos",
cos: {
keepName: true,
domain: "https://d2p-demo-1251260344.cos.ap-guangzhou.myqcloud.com",
bucket: "d2p-demo-1251260344",
region: "ap-guangzhou",
secretId: "", //
secretKey: "", // 传了secretKey 和secretId 代表使用本地签名模式(不安全,生产环境不推荐)
getAuthorization(custom) {
async getAuthorization(custom: any) {
// 不传secretKey代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
return request({
const ret = request({
url: "http://www.docmirror.cn:7070/api/upload/cos/getAuthorization",
method: "get"
}).then((ret: any) => {
// 返回结构如下
// ret.data:{
// TmpSecretId,
// TmpSecretKey,
// XCosSecurityToken,
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
// }
return ret;
});
// 返回结构要求如下
// ret.data:{
// TmpSecretId,
// TmpSecretKey,
// XCosSecurityToken,
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
// }
return ret;
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
@ -134,6 +161,7 @@ function install(app: App, options: any = {}) {
region: "oss-cn-shenzhen",
accessKeyId: "",
accessKeySecret: "",
keepName: true,
async getAuthorization(custom: any, context: any) {
// 不传accessKeySecret代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
const ret = await request({
@ -147,33 +175,62 @@ function install(app: App, options: any = {}) {
// sdk配置
secure: true // 默认为非https上传,为了安全设置为true
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
}
},
qiniu: {
keepName: true,
bucket: "d2p-demo",
async getToken(options) {
async getToken(options: any) {
const ret = await request({
url: "http://www.docmirror.cn:7070/api/upload/qiniu/getToken",
method: "get"
});
return ret; // {token:xxx,expires:xxx}
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
},
domain: "http://d2p.file.handsfree.work/"
},
s3: {
keepName: true,
//同时也支持minio
bucket: "fast-crud",
sdkOpts: {
s3ForcePathStyle: true,
signatureVersion: "v4",
region: "us-east-1",
forcePathStyle: true,
//minio与s3完全适配
endpoint: "https://play.min.io",
credentials: {
//不建议在客户端使用secretAccessKey来上传
accessKeyId: "Q3AM3UQ867SPQQA43P2F", //访问登录名
secretAccessKey: "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" //访问密码
}
},
//预签名配置,向后端获取上传的预签名连接
async getSignedUrl(bucket: string, key: string, options: any, type: FsUploaderS3SignedUrlType) {
return await GetSignedUrl(bucket, key, type);
},
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
}
},
form: {
keepName: true,
action: "http://www.docmirror.cn:7070/api/upload/form/upload",
name: "file",
withCredentials: false,
uploadRequest: async ({ action, file, onProgress }) => {
uploadRequest: async ({ action, file, onProgress }: any) => {
// @ts-ignore
const data = new FormData();
data.append("file", file);
@ -190,7 +247,7 @@ function install(app: App, options: any = {}) {
}
});
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后的结果处理, 此处应返回格式为{url:xxx}
return {
url: "http://www.docmirror.cn:7070" + ret,
@ -203,14 +260,23 @@ function install(app: App, options: any = {}) {
//安装editor
app.use(FsExtendsEditor, {
//编辑器的公共配置
wangEditor: {}
wangEditor: {
editorConfig: {
MENU_CONF: {}
},
toolbarConfig: {}
}
});
app.use(FsExtendsJson);
app.use(FsExtendsTime);
app.use(FsExtendsCopyable);
const { addTypes, getType } = useTypes();
//此处演示修改官方字段类型
const textType = getType("text");
textType.search.autoSearchTrigger = "change"; //修改官方的字段类型,设置为文本变化就触发查询
// 此处演示自定义字段类型
const { addTypes } = useTypes();
addTypes({
time2: {
//如果与官方字段类型同名,将会覆盖官方的字段类型

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
import "./iconify";
import "./iconfont";
import FastCrud from "./fast-crud/index";
import FastCrud from "./fast-crud";
import permission from "./permission";
import { App } from "vue";
function install(app: App, options: any = {}) {

View File

@ -1,9 +1,11 @@
import permission from "./permission";
import permission from "./permission.js";
import permissionUtil from "../util.permission";
const install = function (app) {
const install = function (app: any) {
app.directive("permission", permission);
app.config.globalProperties.$hasPermissions = permissionUtil.hasPermissions;
};
permission.install = install;
export default permission;
export default {
install,
...permission
};

View File

@ -1,6 +1,6 @@
import permissionUtil from "../util.permission";
export default {
mounted(el, binding, vnode) {
mounted(el: any, binding: any, vnode: any) {
const { value } = binding;
const hasPermission = permissionUtil.hasPermissions(value);

View File

@ -1,4 +1,4 @@
import permissionDirective from "./directive/index";
import permissionDirective from "./directive/index.js";
import { registerRouterHook } from "./hook";
import util from "./util.permission";
export * from "./use-crud-permission";
@ -11,7 +11,7 @@ export function usePermission() {
}
export default {
install(app) {
install(app: any) {
// 开启权限模块
// 注册v-permission指令, 用于控制按钮权限
app.use(permissionDirective);

View File

@ -21,7 +21,7 @@ interface PermissionState {
* @param permissionList
* @returns {*}
*/
function formatPermissions(menuTree: Array<any>, permissionList = []) {
function formatPermissions(menuTree: Array<any>, permissionList: any[] = []) {
if (menuTree == null) {
menuTree = [];
}
@ -44,17 +44,19 @@ export const usePermissionStore = defineStore({
inited: false
}),
getters: {
// @ts-ignore
getPermissions() {
// @ts-ignore
return this.permissions;
},
// @ts-ignore
isInited() {
// @ts-ignore
return this.inited;
}
},
actions: {
init({ permissions }) {
init({ permissions }: any) {
this.permissions = permissions;
this.inited = true;
},
@ -62,7 +64,7 @@ export const usePermissionStore = defineStore({
this.permissions = [];
this.inited = false;
},
resolve(resourceTree) {
resolve(resourceTree: any) {
const permissions = formatPermissions(resourceTree);
this.init({ permissions });

View File

@ -1,17 +1,29 @@
import { usePermission } from "/@/plugin/permission";
import _ from "lodash-es";
export type UseCrudPermissionExtraProps = {
hasActionPermission: (action: string) => boolean;
};
export type UseCrudPermissionExtra = (props: UseCrudPermissionExtraProps) => any;
export type UseCrudPermissionCompProps = {
prefix: string;
extra?: UseCrudPermissionExtra;
[key: string]: any;
};
export type UseCrudPermissionProps = {
permission: string | UseCrudPermissionCompProps;
};
/**
*
* @param permission {prefix,extra}
*/
export function useCrudPermission({ permission }) {
export function useCrudPermission({ permission }: UseCrudPermissionProps) {
const { hasPermissions } = usePermission();
const prefix = permission instanceof Object ? permission.prefix : permission;
//根据权限显示按钮
function hasActionPermission(action) {
function hasActionPermission(action: string) {
if (!prefix) {
return true;
}
@ -50,7 +62,7 @@ export function useCrudPermission({ permission }) {
);
}
function merge(userOptions) {
function merge(userOptions: any) {
const permissionOptions = buildCrudPermission();
_.merge(permissionOptions, userOptions);
return permissionOptions;

View File

@ -14,11 +14,11 @@ const util = {
}
const permissionStore = usePermissionStore();
const userPermissionList = permissionStore.getPermissions;
return userPermissionList.some((permission) => {
return userPermissionList.some((permission: any) => {
return need.includes(permission);
});
},
requirePermissions: (value) => {
requirePermissions: (value: any) => {
if (!util.hasPermissions(value)) {
message.error("对不起,您没有权限执行此操作");
throw new NoPermissionError();

View File

@ -49,7 +49,7 @@ router.beforeEach(async (to, from, next) => {
}
});
router.afterEach((to) => {
router.afterEach((to: any) => {
// 进度条
NProgress.done();
// 多页控制 打开新的页面

View File

@ -3,11 +3,10 @@ import _ from "lodash-es";
import { outsideResource } from "./source/outside";
import { headerResource } from "./source/header";
import { frameworkResource } from "./source/framework";
// @ts-ignore
const modules = import.meta.glob("/src/views/**/*.vue");
let index = 0;
function transformOneResource(resource) {
function transformOneResource(resource: any, parent: any) {
let menu: any = null;
if (resource.meta == null) {
resource.meta = {};
@ -22,58 +21,58 @@ function transformOneResource(resource) {
} else {
menu = _.cloneDeep(resource);
delete menu.component;
}
let route;
if (resource.type !== "menu") {
if (resource.path == null || resource.path.startsWith("https://") || resource.path.startsWith("http://")) {
//没有route
route = null;
if (menu.path?.startsWith("/")) {
menu.fullPath = menu.path;
} else {
route = _.cloneDeep(resource);
if (route.component && typeof route.component === "string") {
const path = "/src/views" + route.component;
route.component = modules[path];
}
if (route.component == null) {
route.component = LayoutPass;
}
menu.fullPath = (parent?.fullPath || "") + "/" + menu.path;
}
}
let route;
if (meta.isRoute === false || resource.path == null || resource.path.startsWith("https://") || resource.path.startsWith("http://")) {
//没有route
route = null;
} else {
route = _.cloneDeep(resource);
if (route.component && typeof route.component === "string") {
const path = "/src/views" + route.component;
route.component = modules[path];
}
if (route.component == null) {
route.component = LayoutPass;
}
if (route?.meta?.cache !== false) {
if (route.meta == null) {
route.meta = {};
}
route.meta.cache = true;
}
}
if (resource.children) {
const { menus, routes } = buildMenusAndRouters(resource.children, resource);
if (menu) {
menu.children = menus;
}
if (route) {
route.children = routes;
}
}
return {
menu,
route
};
}
export const buildMenusAndRouters = (resources) => {
export const buildMenusAndRouters = (resources: any, parent: any = null) => {
const routes: Array<any> = [];
const menus: Array<any> = [];
for (const item of resources) {
const { menu, route } = transformOneResource(item);
let menuChildren;
let routeChildren;
if (item.children) {
if (item.children.length > 0) {
const ret = buildMenusAndRouters(item.children);
menuChildren = ret.menus;
routeChildren = ret.routes;
}
}
const { menu, route } = transformOneResource(item, parent);
if (menu) {
menus.push(menu);
menu.children = menuChildren;
}
if (route) {
if (route?.meta?.cache !== false) {
if (route.meta == null) {
route.meta = {};
}
route.meta.cache = true;
}
routes.push(route);
route.children = routeChildren;
}
}
@ -84,7 +83,7 @@ export const buildMenusAndRouters = (resources) => {
};
};
function setIndex(menus) {
function setIndex(menus: any) {
for (const menu of menus) {
menu.index = "index_" + index;
index++;
@ -94,7 +93,7 @@ function setIndex(menus) {
}
}
function findMenus(menus, condition) {
function findMenus(menus: any, condition: any) {
const list: any = [];
for (const menu of menus) {
if (condition(menu)) {
@ -110,8 +109,8 @@ function findMenus(menus, condition) {
return list;
}
function filterMenus(menus, condition) {
const list = menus.filter((item) => {
function filterMenus(menus: any, condition: any) {
const list = menus.filter((item: any) => {
return condition(item);
});
@ -123,7 +122,7 @@ function filterMenus(menus, condition) {
return list;
}
function flatChildren(list, children) {
function flatChildren(list: any, children: any) {
for (const child of children) {
list.push(child);
if (child.children && child.children.length > 0) {
@ -132,7 +131,7 @@ function flatChildren(list, children) {
child.children = null;
}
}
function flatSubRouters(routers) {
function flatSubRouters(routers: any) {
for (const router of routers) {
const children: Array<any> = [];
if (router.children && router.children.length > 0) {
@ -148,7 +147,7 @@ const outsideRet = buildMenusAndRouters(outsideResource);
const headerRet = buildMenusAndRouters(headerResource);
const outsideRoutes = outsideRet.routes;
const frameworkRoutes = flatSubRouters(frameworkRet.routes);
const frameworkRoutes = frameworkRet.routes;
const routes = [...outsideRoutes, ...frameworkRoutes];
const frameworkMenus = frameworkRet.menus;
const headerMenus = headerRet.menus;

View File

@ -8,6 +8,15 @@ export const crudResources = [
icon: "ion:apps-sharp"
},
children: [
{
title: "debug",
name: "debug",
path: "/crud/debug",
component: "/crud/debug/index.vue",
meta: {
isMenu: false
}
},
{
title: "基本特性",
name: "basis",
@ -18,11 +27,17 @@ export const crudResources = [
},
children: [
{
title: "HelloWorld",
title: "FirstDemo",
name: "FsCrudFirst",
path: "/crud/basis/first",
component: "/crud/basis/first/index.vue"
},
{
title: "HelloWorld",
name: "FsCrudHelloWorld",
path: "/crud/basis/helloworld",
component: "/crud/basis/helloworld/index.vue"
},
{
title: "动态计算",
name: "BasisCompute",
@ -59,6 +74,12 @@ export const crudResources = [
path: "/crud/basis/layout-custom",
component: "/crud/basis/layout-custom/index.vue"
},
{
title: "自定义组件",
name: "BasisCustom",
path: "/crud/basis/custom",
component: "/crud/basis/custom/index.vue"
},
{
title: "列设置",
name: "BasisColumnsSet",
@ -70,6 +91,12 @@ export const crudResources = [
name: "BasisColumnMergePlugin",
path: "/crud/basis/column-merge-plugin",
component: "/crud/basis/column-merge-plugin/index.vue"
},
{
title: "ResetCrudOptions",
name: "BasisReset",
path: "/crud/basis/reset",
component: "/crud/basis/reset/index.vue"
}
]
},
@ -165,6 +192,12 @@ export const crudResources = [
path: "/crud/component/select",
component: "/crud/component/select/index.vue"
},
{
title: "表格选择(table-select)",
name: "ComponentTableSelect",
path: "/crud/component/table-select",
component: "/crud/component/table-select/index.vue"
},
{
title: "级联(cascader)",
name: "ComponentCascader",
@ -243,6 +276,12 @@ export const crudResources = [
path: "/crud/component/uploader/qiniu",
component: "/crud/component/uploader/qiniu/index.vue"
},
{
title: "s3上传",
name: "ComponentUploaderS3",
path: "/crud/component/uploader/s3",
component: "/crud/component/uploader/s3/index.vue"
},
{
title: "富文本编辑器",
name: "ComponentEditor",
@ -260,6 +299,12 @@ export const crudResources = [
name: "ComponentJson",
path: "/crud/component/json",
component: "/crud/component/json/index.vue"
},
{
title: "组件独立使用",
name: "ComponentIndependent",
path: "/crud/component/independent",
component: "/crud/component/independent/index.vue"
}
]
},
@ -391,6 +436,18 @@ export const crudResources = [
name: "FormNest",
path: "/crud/form/nest",
component: "/crud/form/nest/index.vue"
},
{
title: "字段组件render",
name: "FormRender",
path: "/crud/form/render",
component: "/crud/form/render/index.vue"
},
{
title: "查看表单使用单元格组件",
name: "FormView",
path: "/crud/form/view",
component: "/crud/form/view/index.vue"
}
]
},
@ -444,6 +501,12 @@ export const crudResources = [
path: "/crud/feature/header-group",
component: "/crud/feature/header-group/index.vue"
},
{
title: "自定义表头",
name: "FeatureHeader",
path: "/crud/feature/header",
component: "/crud/feature/header/index.vue"
},
{
title: "合并单元格",
name: "FeatureMerge",
@ -498,6 +561,12 @@ export const crudResources = [
path: "/crud/feature/search-multi",
component: "/crud/feature/search-multi/index.vue"
},
{
title: "Tabs快捷查询",
name: "FeatureTabs",
path: "/crud/feature/tabs",
component: "/crud/feature/tabs/index.vue"
},
{
title: "字段排序",
name: "FeatureColumnSort",
@ -525,9 +594,21 @@ export const crudResources = [
{
title: "v-model",
name: "FeatureVModel",
path: "/crud/feature/v-model",
path: "/crud/feature/local-v-model",
component: "/crud/feature/local-v-model/index.vue"
},
{
title: "导入",
name: "FeatureImport",
path: "/crud/feature/local-import",
component: "/crud/feature/local-import/index.vue"
},
{
title: "导出",
name: "FeatureExport",
path: "/crud/feature/export",
component: "/crud/feature/export/index.vue"
},
{
title: "自定义删除",
name: "FeatureRemove",

View File

@ -0,0 +1,22 @@
export const integrationResources = [
{
title: "集成",
name: "integration",
path: "/integration",
redirect: "/integration/bpmn",
meta: {
icon: "ion:apps-sharp"
},
children: [
{
title: "FsBpmn",
name: "FsBpmn",
path: "/integration/bpmn",
component: "/integration/bpmn/index.vue",
meta: {
icon: "ion:disc-outline"
}
}
]
}
];

View File

@ -0,0 +1,30 @@
export const uiResources = [
{
title: "UI示例",
name: "ui",
path: "/ui",
redirect: "/ui/form",
meta: {
icon: "ion:apps-sharp"
},
children: [
{
title: "表单组件",
name: "UIForm",
path: "/ui/form",
redirect: "/ui/form/input",
meta: {
icon: "ion:disc-outline"
},
children: [
{
title: "input",
name: "UIFormInput",
path: "/ui/form/input",
component: "/ui/form/input/index.vue"
}
]
}
]
}
];

View File

@ -1,7 +1,7 @@
import { createPinia } from "pinia";
const store = createPinia();
export default {
install(app) {
install(app: any) {
app.use(store);
}
};

View File

@ -15,7 +15,7 @@ interface PageState {
// 已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
openedLoaded: boolean;
// 当前页面
current: "";
current: string;
// 需要缓存的页面 name
keepAlive: Array<any>;
inited: boolean;
@ -49,7 +49,7 @@ export const usePageStore = defineStore({
}),
getters: {
// @ts-ignore
getOpened() {
getOpened(): any {
// @ts-ignore
return this.opened;
},
@ -358,14 +358,14 @@ export const usePageStore = defineStore({
*/
keepAliveRefresh() {
this.keepAlive = this.opened.filter((item) => isKeepAlive(item)).map((e) => e.name);
console.log("keep alive:", this.keepAlive);
console.log("keepalive", this.keepAlive);
},
/**
* @description
* @param {Object} state state
* @param {String} name name
*/
keepAliveRemove(name: any) {
keepAliveRemove(name: string) {
const list = cloneDeep(this.keepAlive);
const index = list.findIndex((item) => item === name);
if (index !== -1) {
@ -378,7 +378,7 @@ export const usePageStore = defineStore({
* @param {Object} state state
* @param {String} name name
*/
keepAlivePush(name: any) {
keepAlivePush(name: string) {
const keep = cloneDeep(this.keepAlive);
keep.push(name);
this.keepAlive = uniq(keep);
@ -396,7 +396,7 @@ export const usePageStore = defineStore({
* @param {Object} state state
* @param {String} fullPath new fullPath
*/
currentSet(fullPath: any) {
currentSet(fullPath: string) {
this.current = fullPath;
},
/**
@ -405,7 +405,7 @@ export const usePageStore = defineStore({
* @param {Object} state state
* @param {Array} routes routes
*/
async init(routes: any) {
async init(routes?: any) {
if (this.inited) {
return;
}

View File

@ -45,7 +45,7 @@ export const useResourceStore = defineStore({
// @ts-ignore
return this.frameworkMenus;
}
},
} as any,
actions: {
clear() {
this.inited = false;

View File

@ -48,6 +48,24 @@ h1, h2, h3, h4, h5, h6 {
vertical-align: 0 !important;
}
.flex{
display: flex;
align-items: center;
}
.ml-5{
margin-left:5px;
}
.mt-10{
margin-top:10px;
}
.m-10{
margin:10px;
}
.text-center{
text-align: center;

View File

@ -1,10 +1,4 @@
import type {
ComponentRenderProxy,
VNode,
ComponentPublicInstance,
FunctionalComponent,
PropType as VuePropType,
} from 'vue';
import type { ComponentRenderProxy, VNode, ComponentPublicInstance, FunctionalComponent, PropType as VuePropType } from "vue";
declare global {
const __APP_INFO__: {
@ -64,7 +58,7 @@ declare global {
VITE_GLOB_APP_SHORT_NAME: string;
VITE_USE_CDN: boolean;
VITE_DROP_CONSOLE: boolean;
VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none';
VITE_BUILD_COMPRESS: "gzip" | "brotli" | "none";
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
VITE_LEGACY: boolean;
VITE_USE_IMAGEMIN: boolean;
@ -92,8 +86,6 @@ declare global {
}
}
declare module 'vue' {
export type JSXComponent<Props = any> =
| { new (): ComponentPublicInstance<Props> }
| FunctionalComponent<Props>;
declare module "vue" {
export type JSXComponent<Props = any> = { new (): ComponentPublicInstance<Props> } | FunctionalComponent<Props>;
}

View File

@ -20,7 +20,7 @@ export class EnvConfig {
_.forEach(import.meta.env, (value, key) => {
if (key.startsWith("VITE_APP")) {
key = key.replace("VITE_APP_", "");
//@ts-ignore
// @ts-ignore
this[key] = value;
}
});

View File

@ -1,7 +1,8 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedBigData";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +10,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +18,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +26,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +34,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,25 +1,26 @@
import * as api from "./api";
import { message } from "ant-design-vue";
import { dict } from "@fast-crud/fast-crud";
export default function ({ expose }) {
const pageRequest = async (query) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
output: {},
crudOptions: {
//大量数据的crud配置
request: {
pageRequest,
addRequest,
@ -41,7 +42,6 @@ export default function ({ expose }) {
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 50
@ -58,70 +58,70 @@ export default function ({ expose }) {
title: "字典1",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict1"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict1"
})
},
dict2: {
title: "字典2",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict2"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict2"
})
},
dict3: {
title: "字典3",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict3"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict3"
})
},
dict4: {
title: "字典4",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict4"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict4"
})
},
dict5: {
title: "字典5",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict5"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict5"
})
},
dict6: {
title: "字典6",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict6"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict6"
})
},
dict7: {
title: "字典7",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict7"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict7"
})
},
dict8: {
title: "字典8",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict8"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict8"
})
},
dict9: {
title: "字典9",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict9"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict9"
})
},
dict10: {
title: "字典10",
type: "dict-select",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?from=dict10"
url: "/mock/dicts/ManyOpenStatusEnum?from=dict10"
})
},
text1: {

View File

@ -7,30 +7,18 @@
</fs-page>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud, useExpose } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud.js";
export default defineComponent({
name: "AdvancedBigData",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions, output } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose, output } = useFs({ createCrudOptions });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {

View File

@ -1,7 +1,9 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedBigData",
idGenerator: 0,
//此处copy多次模拟大量数据
copyTimes: 1000
};
const list = [

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedFromBackend";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,5 +1,6 @@
//此处演示从后台获取crudOptions配置字符串
export const crudOptions = `
({expose,dict}) => {
({crudExpose,dict}) => {
return {
columns: {
id: {

View File

@ -1,27 +0,0 @@
import * as api from "./api";
export default function ({ expose }) {
const pageRequest = async (query) => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
}
}
};
}

View File

@ -0,0 +1,49 @@
import * as api from "./api";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, dict } from "@fast-crud/fast-crud";
import { GetCrud } from "./api";
import _ from "lodash-es";
/**
* options
* @param props
*/
export default async function (props: CreateCrudOptionsProps): Promise<CreateCrudOptionsRet> {
const { crudExpose } = props;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const localCrudOptions = {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
}
};
// 上面是本地crudOptions
// 下面从后台获取crudOptions
const ret = await GetCrud();
// 编译
const crudBackend = eval(ret);
// 本示例返回的是一个方法字符串所以要先执行这个方法获取options
const remoteCrudOptions = crudBackend({ crudExpose, dict });
// 与本地options合并
const crudOptions = _.merge(localCrudOptions, remoteCrudOptions);
return {
crudOptions
};
}

View File

@ -1,39 +1,38 @@
<template>
<fs-crud v-if="crudBinding" ref="crudRef" v-bind="crudBinding" />
<fs-page>
<template #header>
<div class="title">CrudOptions从后台加载</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/api/use.html#usefsasync">文档</a>
</div>
</template>
<fs-crud v-if="crudBinding" ref="crudRef" v-bind="crudBinding" />
</fs-page>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud, dict, useExpose } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted, ref, Ref } from "vue";
import { CrudBinding, useFsAsync } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { GetCrud } from "./api";
import _ from "lodash-es";
export default defineComponent({
name: "AdvancedFromBackend",
setup() {
// crudref
const crudRef = ref();
const crudRef: Ref = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions } = createCrudOptions({ expose });
const crudBinding: Ref<CrudBinding> = ref();
const customValue: any = {}; //createCrudOptions
// crud
//
onMounted(async () => {
// crud
const ret = await GetCrud();
//
const crudBackend = eval(ret);
// options
const crudOptionsFromBackend = crudBackend({ expose, dict });
// options
_.merge(crudOptions, crudOptionsFromBackend);
// useCrud
useCrud({ expose, crudOptions });
const customValue = {};
//fscreateCrudOptions
const { crudExpose, context } = await useFsAsync({ crudRef, crudBinding, createCrudOptions, context: customValue });
//
expose.doRefresh();
await crudExpose.doRefresh();
});
return {

View File

@ -1,6 +1,7 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
import { crudOptions } from "./crud-backend";
const options = {
const options: any = {
name: "AdvancedFromBackend",
idGenerator: 0
};
@ -23,7 +24,7 @@ const mock = mockUtil.buildMock(options);
mock.push({
path: "/AdvancedFromBackend/crud",
method: "get",
handle(req) {
handle(req: any) {
return {
code: 0,
msg: "success",

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedInDialog";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,19 +1,22 @@
import * as api from "./api";
export default function ({ expose }) {
const pageRequest = async (query) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes, dict } from "@fast-crud/fast-crud";
import { SearchOutlined } from "@ant-design/icons-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
@ -68,23 +71,16 @@ export default function ({ expose }) {
},
render: {
title: "复杂输入(render)",
type: "text",
form: {
title: "复杂输入",
component: {
render(context) {
render(context: any) {
console.log("context scope", context);
return (
<a-input-group compact>
<a-input
placeholder={"render1 input"}
style="width: 50%"
v-model={[context.form.render, "value"]}
/>
<a-input
placeholder={"render2 input"}
style="width: 50%"
v-model={[context.form.render2, "value"]}
/>
<a-input placeholder={"render1 input"} style="width: 50%" v-model={[context.form.render, "value"]} />
<a-input placeholder={"render2 input"} style="width: 50%" v-model={[context.form.render2, "value"]} />
</a-input-group>
);
}
@ -93,6 +89,7 @@ export default function ({ expose }) {
},
render2: {
title: "我的值是由复杂输入列输入的",
type: "text",
column: {
width: "300px"
},

View File

@ -4,31 +4,19 @@
</fs-page>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { useExpose } from "@fast-crud/fast-crud";
export default defineComponent({
name: "fs-in-dialog",
name: "FsInDialog",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedInDialog",
idGenerator: 0
};

View File

@ -1,32 +1,32 @@
<template>
<fs-page>
<template #header>
<div class="title">
对话框中显示crud
</div>
<div class="title">对话框中显示crud</div>
</template>
<div style="padding:50px">
<div style="padding: 50px">
<a-button type="primary" @click="openDialog"></a-button>
</div>
<a-modal v-model:visible="dialogShow" width="80%" title="fs-crud in dialog">
<div style="height: 400px;position: relative">
<fs-in-dialog ></fs-in-dialog>
<div style="height: 400px; position: relative">
<!-- 在此处显示fs-crud页面 -->
<fs-in-dialog></fs-in-dialog>
</div>
</a-modal>
</fs-page>
</template>
<script>
<script lang="ts">
import { defineComponent, ref } from "vue";
import FsInDialog from './crud/index.vue'
//fs-crud
import FsInDialog from "./crud/index.vue";
export default defineComponent({
name: "InDialog",
components:{FsInDialog},
components: { FsInDialog },
setup() {
const dialogShow = ref(false)
function openDialog(){
dialogShow.value=true
const dialogShow = ref(false);
function openDialog() {
dialogShow.value = true;
}
return {
dialogShow,

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FormLinkage";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,18 +1,18 @@
import * as api from "./api";
import { dict } from "@fast-crud/fast-crud";
export default function ({ expose }) {
const pageRequest = async (query) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, ScopeContext, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
@ -30,7 +30,6 @@ export default function ({ expose }) {
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 50
@ -70,7 +69,7 @@ export default function ({ expose }) {
cache: true,
prototype: true,
// url() 改成构建url返回一个url
url({ form }) {
url({ form }: any) {
if (form && form.province != null) {
// 本数据字典的url是通过前一个select的选项决定的
return `/mock/linkage/city?province=${form.province}`;
@ -81,7 +80,7 @@ export default function ({ expose }) {
}),
form: {
// 注释同上
valueChange({ value, form, getComponentRef }) {
valueChange({ value, form, getComponentRef }: ScopeContext) {
if (value) {
form.county = undefined; // 将county的value置空
const countySelect = getComponentRef("county");
@ -104,7 +103,7 @@ export default function ({ expose }) {
value: "id",
cache: true,
prototype: true,
url({ form }) {
url({ form }: any) {
if (form && form.province != null && form.city != null) {
return `/mock/linkage/county?province=${form.province} &city=${form.city}`;
}

View File

@ -2,31 +2,20 @@
<fs-crud ref="crudRef" v-bind="crudBinding" />
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { useExpose } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud.js";
export default defineComponent({
name: "FormLinkage",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const customValue: any = {}; //createCrudOptions
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions, context: customValue });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {

View File

@ -1,6 +1,7 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
import _ from "lodash-es";
const options = {
const options: any = {
name: "FormLinkage",
idGenerator: 0
};
@ -64,12 +65,12 @@ const tree = [
];
options.list = list;
options.copyTimes = 1000;
options.copyTimes = 100;
const mock = mockUtil.buildMock(options);
function omitChildren(orignalListt) {
const list = [];
orignalListt.forEach((item) => {
function omitChildren(originalList: any) {
const list: any = [];
originalList.forEach((item: any) => {
list.push(_.omit(item, "children"));
});
return list;
@ -90,7 +91,7 @@ mock.push({
mock.push({
path: "/mock/linkage/city",
method: "get",
handle(req) {
handle(req: any) {
const province = parseInt(req.params.province);
const a = tree.filter((item) => {
return item.id === province;
@ -107,7 +108,7 @@ mock.push({
mock.push({
path: "/mock/linkage/county",
method: "get",
handle(req) {
handle(req: any) {
const province = parseInt(req.params.province);
const a = tree.filter((item) => {
return item.id === province;

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedLocalPagination";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,14 +1,17 @@
import * as api from "./api";
import * as api from "./api.js";
import _ from "lodash-es";
import { dict } from "@fast-crud/fast-crud";
export default function ({ expose, localDataRef }) {
const pageRequest = async ({ page, query }) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const localDataRef = context.localDataRef;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
const { page } = query;
//总数据
let data = localDataRef.value;
//获取请求参数
const limit = page.limit;
let offset = page.offset;
data = data.filter((item) => {
const offset = page.offset;
data = data.filter((item: any) => {
// 根据你的业务,编写你的本地查询逻辑
// text改成你的查询字段
if (query.status && item.status !== query.status) {
@ -33,7 +36,7 @@ export default function ({ expose, localDataRef }) {
records
};
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
await api.UpdateObj(form);
//更新本地数据
@ -45,7 +48,7 @@ export default function ({ expose, localDataRef }) {
}
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
const id = await api.AddObj(form);
//本地添加
form.id = id;
@ -53,7 +56,7 @@ export default function ({ expose, localDataRef }) {
return id;
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
await api.DelObj(row.id);
//本地删除那一条记录
const tableData = localDataRef.value;

View File

@ -11,9 +11,9 @@
</fs-page>
</template>
<script>
<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import { useCrud, useExpose } from "@fast-crud/fast-crud";
import { useCrud, useExpose, useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { GetList } from "./api";
@ -36,16 +36,10 @@ export default defineComponent({
const ret = await GetList({ page: { offset: 0, limit: 99999999 }, query: {}, sort: {} });
localDataRef.value = ret.records;
//crud
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions } = createCrudOptions({ expose, localDataRef });
// crud
useCrud({ expose, crudOptions });
const { crudExpose } = useFs({ crudBinding, crudRef, createCrudOptions, context: { localDataRef } });
//
await expose.doRefresh();
await crudExpose.doRefresh();
});
return {

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedLocalPagination",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedNest";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,15 +33,15 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function BatchDelete(ids) {
export function BatchDelete(ids: any[]) {
return request({
url: apiPrefix + "/batchDelete",
method: "post",

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedAside";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,15 +33,15 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function BatchDelete(ids) {
export function BatchDelete(ids: any[]) {
return request({
url: apiPrefix + "/batchDelete",
method: "post",

View File

@ -1,14 +1,19 @@
import * as api from "./api";
import { dict } from "@fast-crud/fast-crud";
export default function ({ expose }) {
const editRequest = async ({ form, row }) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};

View File

@ -6,37 +6,26 @@
</fs-crud>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useExpose, useCrud } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud.js";
import { useFs } from "@fast-crud/fast-crud";
export default defineComponent({
name: "AsideTable",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions, selectedIds } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {
crudBinding,
crudRef,
setSearchFormData: expose.setSearchFormData,
doRefresh: expose.doRefresh
setSearchFormData: crudExpose.setSearchFormData,
doRefresh: crudExpose.doRefresh
};
}
});

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedAside",
idGenerator: 0
};

View File

@ -1,21 +1,27 @@
import * as api from "./api";
import { ref, shallowRef } from "vue";
import SubTable from "./sub-table/index.vue";
import { compute } from "@fast-crud/fast-crud";
export default function ({ expose, asideTableRef }) {
const editRequest = async ({ form, row }) => {
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose, context: { asideTableRef } }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
const currentRow = ref();
const onCurrentRowChange = (id) => {
const onCurrentRowChange = (id: number) => {
currentRow.value = id;
asideTableRef.value.setSearchFormData({ form: { gradeId: id } });
asideTableRef.value.doRefresh();
@ -23,7 +29,7 @@ export default function ({ expose, asideTableRef }) {
return {
crudOptions: {
table: {
customRow(record, index) {
customRow(record: any, index: number) {
const clazz = record.id === currentRow.value ? "fs-current-row" : "";
return {
onClick() {
@ -82,8 +88,7 @@ export default function ({ expose, asideTableRef }) {
// 嵌套表格字段
rules: [{ required: true, message: "请选择用户" }],
component: {
//局部引用子表格要用shallowRef包裹
name: shallowRef(SubTable),
name: SubTable,
vModel: "modelValue",
gradeId: compute(({ form }) => {
return form.id;

View File

@ -13,34 +13,24 @@
</a-row>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useExpose, useCrud } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import createCrudOptions from "./crud.js";
import AsideTable from "./aside-table/index.vue";
import { useFs } from "@fast-crud/fast-crud";
export default defineComponent({
name: "FeatureNest",
// eslint-disable-next-line vue/no-unused-components
components: { AsideTable },
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const asideTableRef = ref();
const { crudOptions } = createCrudOptions({ expose, asideTableRef });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions, context: { asideTableRef } });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedNest",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/AdvancedSubTable";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,15 +33,15 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function BatchDelete(ids) {
export function BatchDelete(ids: any[]) {
return request({
url: apiPrefix + "/batchDelete",
method: "post",

View File

@ -1,20 +1,26 @@
import * as api from "./api";
export default function ({ expose, props, ctx }) {
const editRequest = async ({ form, row }) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ crudExpose, context: { props, ctx } }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
crudOptions: {
table: {
customRow(record, index) {
customRow(record: any, index: number) {
const clazz = record.id === props.modelValue ? "fs-current-row" : "";
return {
onClick() {

View File

@ -7,10 +7,11 @@
</div>
</template>
<script>
import { defineComponent, ref, onMounted, watch } from "vue";
<script lang="ts">
import { defineComponent, onMounted, watch } from "vue";
import createCrudOptions from "./crud";
import { useExpose, useCrud } from "@fast-crud/fast-crud";
import { useFs } from "@fast-crud/fast-crud";
export default defineComponent({
name: "SubTable",
props: {
@ -19,23 +20,11 @@ export default defineComponent({
},
emits: ["update:modelValue"],
setup(props, ctx) {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions } = createCrudOptions({ expose, props, ctx });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { props, ctx } });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
//

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "AdvancedSubTable",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/BasisColumnMergePlugin";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,24 +1,23 @@
import * as api from "./api";
import { dict } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
export default function ({ expose }) {
const pageRequest = async (query) => {
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
output: {},
crudOptions: {
settings: {
viewFormUseCellComponent: true

View File

@ -12,14 +12,15 @@
</fs-page>
</template>
<script>
<script lang="ts">
import { defineComponent, ref, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import { useFs, UseFsProps } from "@fast-crud/fast-crud";
export default defineComponent({
name: "BasisColumnMergePlugin",
setup() {
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
const context: any = {}; //createCrudOptions
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
//
onMounted(() => {
crudExpose.doRefresh();

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "BasisColumnMergePlugin",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/BasisColumnsSet";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,15 +33,15 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}
export function BatchDelete(ids) {
export function BatchDelete(ids: any) {
return request({
url: apiPrefix + "/batchDelete",
method: "post",

View File

@ -1,69 +0,0 @@
import * as api from "./api";
import { dict } from "@fast-crud/fast-crud";
import { ref } from "vue";
export default function ({ expose }) {
const pageRequest = async (query) => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
toolbar: {
columnsFilter: {
mode: "default"
}
},
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 50
},
form: {
show: false
}
},
radio: {
title: "状态",
search: { show: true },
type: "dict-radio",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
},
disabled: {
title: "列设置禁用",
type: "text",
column: {
columnSetDisabled: true
}
},
hidden: {
title: "列设置隐藏",
type: "text",
column: {
columnSetShow: false
}
}
}
}
};
}

View File

@ -0,0 +1,98 @@
import * as api from "./api.js";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { crudBinding } = crudExpose;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
return {
crudOptions: {
request: {
pageRequest,
addRequest,
editRequest,
delRequest
},
toolbar: {
columnsFilter: {
mode: "default"
}
},
actionbar: {
buttons: {
toggleMode: {
text: "切换简单模式",
click() {
crudBinding.value.toolbar.columnsFilter.mode = crudBinding.value.toolbar.columnsFilter.mode === "simple" ? "default" : "simple";
message.info("当前列设置组件的模式为:" + crudBinding.value.toolbar.columnsFilter.mode);
}
},
toggleColumnSetShow: {
text: "切换列设置项显隐",
click() {
crudBinding.value.toolbar.columnsFilter.originalColumns.hidden.columnSetShow = !crudBinding.value.toolbar.columnsFilter.originalColumns.hidden.columnSetShow;
message.info("切换第4列的列设置显隐");
}
},
toggleColumnSetDisabled: {
text: "切换列设置项禁用",
click() {
crudBinding.value.toolbar.columnsFilter.originalColumns.disabled.columnSetDisabled = !crudBinding.value.toolbar.columnsFilter.originalColumns.disabled.columnSetDisabled;
message.info("切换第3列的列设置禁用启用");
}
},
desc: {
text: "点击左侧按钮后,再点最右侧的列设置按钮查看效果"
}
}
},
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 50
},
form: {
show: false
}
},
radio: {
title: "状态",
search: { show: true },
type: "dict-radio",
dict: dict({
url: "/mock/dicts/OpenStatusEnum?single"
})
},
disabled: {
title: "列设置禁用",
type: "text",
column: {
columnSetDisabled: true
}
},
hidden: {
title: "列设置隐藏",
type: "text",
column: {
columnSetShow: false
}
}
}
}
};
}

View File

@ -1,51 +1,47 @@
<template>
<fs-page>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
<a-alert class="ml-1" type="warning" message="列设置可以禁用或者隐藏某字段勾选" />
<a-button @click="columnsSetToggleMode()"> </a-button>
</template>
</fs-crud>
<template #header>
<div class="title">
列设置
<span class="sub">列设置可以禁用或者隐藏某字段勾选 -------> 点击右侧最后一个按钮查看效果</span>
</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/api/crud-options/toolbar.html#columnsfilter-mode">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</fs-page>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, Ref } from "vue";
import createCrudOptions from "./crud.jsx";
import { useExpose, useCrud, CrudBinding } from "@fast-crud/fast-crud";
import { message, Modal, notification } from "ant-design-vue";
import { defineComponent, onMounted } from "vue";
import createCrudOptions from "./crud";
import { useFs } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
export default defineComponent({
name: "BasisColumnsSet",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding: Ref<CrudBinding> = ref({});
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions, selectedRowKeys } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
function columnsSetToggleMode() {
crudBinding.value.toolbar.columnsFilter.mode =
crudBinding.value.toolbar.columnsFilter.mode === "simple" ? "default" : "simple";
message.info("当前列设置组件的模式为:" + crudBinding.value.toolbar.columnsFilter.mode);
crudBinding.value.toolbar.columnsFilter.mode = crudBinding.value.toolbar.columnsFilter.mode === "simple" ? "default" : "simple";
message.info("点击列设置按钮查看效果,当前列设置组件的模式为:" + crudBinding.value.toolbar.columnsFilter.mode);
}
function columnsSetShowToggle() {
crudBinding.value.table.columns.disabled.columnSetShow = !crudBinding.value.table.columns.disabled.columnSetShow;
}
return {
crudBinding,
crudRef,
columnsSetToggleMode
columnsSetToggleMode,
columnsSetShowToggle
};
}
});

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "BasisColumnsSet",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FormComputeMore";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,22 +1,20 @@
import * as api from "./api";
import { requestForMock } from "/src/api/service";
import { useCompute } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
import { ref, computed } from "vue";
const { asyncCompute, compute } = useCompute();
export default function ({ expose }) {
const pageRequest = async (query) => {
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { computed, ref } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
@ -48,7 +46,7 @@ export default function ({ expose }) {
},
rowHandle: {
fixed: "right",
align:'center',
align: "center"
},
columns: {
id: {

View File

@ -2,35 +2,27 @@
<fs-page>
<template #header>
<div class="title">动态计算-更多测试</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/guide/advance/compute.html">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</fs-page>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud, useExpose } from "@fast-crud/fast-crud";
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
export default defineComponent({
name: "BasisComputeMore",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions, output } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
const { crudBinding, crudRef, crudExpose, output } = useFs({ createCrudOptions });
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "FormComputeMore",
idGenerator: 0
};

View File

@ -1,7 +1,7 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/FormCompute";
export function GetList(query) {
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
@ -9,7 +9,7 @@ export function GetList(query) {
});
}
export function AddObj(obj) {
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
@ -17,7 +17,7 @@ export function AddObj(obj) {
});
}
export function UpdateObj(obj) {
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
@ -25,7 +25,7 @@ export function UpdateObj(obj) {
});
}
export function DelObj(id) {
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
@ -33,9 +33,9 @@ export function DelObj(id) {
});
}
export function GetObj(id) {
export function GetObj(id: any) {
return request({
url: apiPrefix + "/info",
url: apiPrefix + "/get",
method: "get",
params: { id }
});

View File

@ -1,43 +1,29 @@
import * as api from "./api";
import { requestForMock } from "/src/api/service";
import { useCompute } from "@fast-crud/fast-crud";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, GetContextFn, ScopeContext, useCompute, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { message } from "ant-design-vue";
import { ref, computed } from "vue";
import { computed } from "vue";
const { asyncCompute, compute } = useCompute();
export default function ({ expose }) {
const pageRequest = async (query) => {
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }) => {
const editRequest = async ({ form, row }: EditReq) => {
form.id = row.id;
return await api.UpdateObj(form);
};
const delRequest = async ({ row }) => {
const delRequest = async ({ row }: DelReq) => {
return await api.DelObj(row.id);
};
const addRequest = async ({ form }) => {
const addRequest = async ({ form }: AddReq) => {
return await api.AddObj(form);
};
//普通的ref引用可以动态切换配置
const showRef = ref(false);
const showTableRef = ref(true);
const showTableComputed = computed(() => {
return showTableRef.value;
});
const columnComponentShowRef = ref(true);
const columnComponentShowComputed = computed(() => {
return columnComponentShowRef.value;
});
const { showRef, showTableComputed, columnComponentShowComputed } = context;
return {
output: {
showRef,
showTableRef,
columnComponentShowRef
},
crudOptions: {
request: {
pageRequest,
@ -58,9 +44,12 @@ export default function ({ expose }) {
},
rowHandle: {
fixed: "right",
show: computed(() => {
return true;
}),
buttons: {
edit: {
show: compute(({ row }) => {
show: compute<boolean>(({ row }) => {
return row.editable;
})
},
@ -153,7 +142,7 @@ export default function ({ expose }) {
vModel: "value",
placeholder: "异步计算远程获取options",
options: asyncCompute({
async asyncFn(watchValue, context) {
async asyncFn(watchValue: any, context: GetContextFn) {
const url = "/mock/dicts/OpenStatusEnum?remote";
return await requestForMock({ url });
}
@ -172,14 +161,12 @@ export default function ({ expose }) {
vModel: "value",
placeholder: "异步计算远程获取options",
options: asyncCompute({
watch({ form }) {
watch({ form }: ScopeContext) {
return form.compute;
},
async asyncFn(watchValue) {
async asyncFn(watchValue: string) {
message.info("监听switch,触发远程获取options");
const url = watchValue
? "/mock/dicts/OpenStatusEnum?remote"
: "/mock/dicts/moreOpenStatusEnum?remote";
const url = watchValue ? "/mock/dicts/OpenStatusEnum?remote" : "/mock/dicts/moreOpenStatusEnum?remote";
return await requestForMock({ url });
}
})

View File

@ -6,7 +6,7 @@
<fs-icon icon="ion:apps-sharp" :spin="true" />
</div>
<div class="more">
<a target="_blank" href="http://fast-crud.docmirror.cn/guide/advance/compute.html">帮助说明</a>
<a target="_blank" href="http://fast-crud.docmirror.cn/guide/advance/compute.html">文档</a>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
@ -15,6 +15,7 @@
<span class="ml-1">表格显隐:<a-switch v-model:checked="showTableRef"></a-switch></span>
</a-tooltip>
<span class="ml-1">列显隐:<a-switch v-model:checked="columnComponentShowRef"></a-switch></span>
<span class="ml-1">列显隐2:<a-button @click="columnsMapSetShow">2</a-button></span>
<a-alert class="ml-1" type="info" message="点击下方右边的编辑按钮查看示例效果-----------> ↓↓↓↓↓" />
</template>
<template #form_refSwitch>
@ -24,36 +25,48 @@
</fs-page>
</template>
<script>
import { defineComponent, ref, onMounted } from "vue";
import { useCrud, useExpose } from "@fast-crud/fast-crud";
<script lang="ts">
import { computed, defineComponent, onMounted, ref } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
export default defineComponent({
name: "BasisCompute",
setup() {
// crudref
const crudRef = ref();
// crud ref
const crudBinding = ref();
//
const { expose } = useExpose({ crudRef, crudBinding });
// crud
const { crudOptions, output } = createCrudOptions({ expose });
// crud
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
const { resetCrudOptions } = useCrud({ expose, crudOptions });
// crud
// resetCrudOptions(options)
//ref
const showRef = ref(false);
const showTableRef = ref(true);
const showTableComputed = computed(() => {
return showTableRef.value;
});
const columnComponentShowRef = ref(true);
const columnComponentShowComputed = computed(() => {
return columnComponentShowRef.value;
});
const context = {
showRef,
showTableRef,
showTableComputed,
columnComponentShowRef,
columnComponentShowComputed
};
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
function columnsMapSetShow() {
crudBinding.value.table.columnsMap["id"].show = !crudBinding.value.table.columnsMap["id"].show;
}
//
onMounted(() => {
expose.doRefresh();
crudExpose.doRefresh();
});
return {
crudBinding,
crudRef,
...output
...context,
columnsMapSetShow
};
}
});

View File

@ -1,5 +1,6 @@
// @ts-ignore
import mockUtil from "/src/mock/base";
const options = {
const options: any = {
name: "FormCompute",
idGenerator: 0
};

View File

@ -0,0 +1,42 @@
import { requestForMock } from "/src/api/service";
const request = requestForMock;
const apiPrefix = "/mock/BasisCustom";
export function GetList(query: any) {
return request({
url: apiPrefix + "/page",
method: "get",
data: query
});
}
export function AddObj(obj: any) {
return request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
}
export function UpdateObj(obj: any) {
return request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
}
export function DelObj(id: any) {
return request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
}
export function GetObj(id: any) {
return request({
url: apiPrefix + "/get",
method: "get",
params: { id }
});
}

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