second commit
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"acceptHMRUpdate": true,
|
||||
"computed": true,
|
||||
"createApp": true,
|
||||
"createPinia": true,
|
||||
"customRef": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"defineStore": true,
|
||||
"effectScope": true,
|
||||
"getActivePinia": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"inject": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"mapActions": true,
|
||||
"mapGetters": true,
|
||||
"mapState": true,
|
||||
"mapStores": true,
|
||||
"mapWritableState": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"provide": true,
|
||||
"reactive": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"resolveComponent": true,
|
||||
"setActivePinia": true,
|
||||
"setMapStoreSuffix": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"storeToRefs": true,
|
||||
"toRaw": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"unref": true,
|
||||
"useAttrs": true,
|
||||
"useCssModule": true,
|
||||
"useCssVars": true,
|
||||
"useLink": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"useSlots": true,
|
||||
"watch": true,
|
||||
"watchEffect": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier',
|
||||
'./.eslintrc-auto-import.json',
|
||||
],
|
||||
rules: {
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off"
|
||||
},
|
||||
env: {
|
||||
"vue/setup-compiler-macros": true
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createPinia: typeof import('pinia')['createPinia']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineStore: typeof import('pinia')['defineStore']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const mapActions: typeof import('pinia')['mapActions']
|
||||
const mapGetters: typeof import('pinia')['mapGetters']
|
||||
const mapState: typeof import('pinia')['mapState']
|
||||
const mapStores: typeof import('pinia')['mapStores']
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
_index: typeof import('./src/core/components/_sample/_index.vue')['default']
|
||||
AAffix: typeof import('ant-design-vue/es')['Affix']
|
||||
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
||||
ABadge: typeof import('ant-design-vue/es')['Badge']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACard: typeof import('ant-design-vue/es')['Card']
|
||||
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
||||
ADivider: typeof import('ant-design-vue/es')['Divider']
|
||||
ADrawer: typeof import('ant-design-vue/es')['Drawer']
|
||||
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
||||
AForm: typeof import('ant-design-vue/es')['Form']
|
||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||
ALayout: typeof import('ant-design-vue/es')['Layout']
|
||||
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
||||
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
|
||||
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
|
||||
AMenu: typeof import('ant-design-vue/es')['Menu']
|
||||
AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider']
|
||||
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
|
||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||
APopover: typeof import('ant-design-vue/es')['Popover']
|
||||
ARadio: typeof import('ant-design-vue/es')['Radio']
|
||||
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
|
||||
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
|
||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||
ATable: typeof import('ant-design-vue/es')['Table']
|
||||
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
||||
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||
BaseButton: typeof import('./src/core/components/BaseButton/index.ts')['default']
|
||||
BaseCard: typeof import('./src/core/components/BaseCard/index.ts')['default']
|
||||
BaseDatePicker: typeof import('./src/core/components/BaseDatePicker/index.ts')['default']
|
||||
BaseIcon: typeof import('./src/core/components/BaseIcon/index.ts')['default']
|
||||
BaseInputNumber: typeof import('./src/core/components/BaseInputNumber/index.ts')['default']
|
||||
BaseModal: typeof import('./src/core/components/BaseModal/index.ts')['default']
|
||||
BaseSwitch: typeof import('./src/core/components/BaseSwitch/index.ts')['default']
|
||||
BaseTable: typeof import('./src/core/components/BaseTable/index.ts')['default']
|
||||
BaseTableOld: typeof import('./src/core/components/BaseTableOld/index.ts')['default']
|
||||
BasicCard: typeof import('./src/components/BasicCard.vue')['default']
|
||||
BasicInfoItem: typeof import('./src/components/BasicInfoItem.vue')['default']
|
||||
BasicInput: typeof import('./src/components/BasicInput.vue')['default']
|
||||
BasicMainCard: typeof import('./src/components/BasicMainCard.vue')['default']
|
||||
BasicMainCardFull: typeof import('./src/components/BasicMainCardFull.vue')['default']
|
||||
BasicMobileHeader: typeof import('./src/components/BasicMobileHeader.vue')['default']
|
||||
BasicModal: typeof import('./src/components/BasicModal.vue')['default']
|
||||
BasicSelect: typeof import('./src/components/BasicSelect.vue')['default']
|
||||
BasicShowContext: typeof import('./src/components/BasicShowContext.vue')['default']
|
||||
BasicTextArea: typeof import('./src/components/BasicTextArea.vue')['default']
|
||||
BudgetSelect: typeof import('./src/components/BudgetSelect.vue')['default']
|
||||
CustomTag: typeof import('./src/components/CustomTag.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import pkg from './package.json'
|
||||
//import colors from './baseColor.json'
|
||||
/** base config **/
|
||||
/** api document http://omde.feep.ir/docu **/
|
||||
|
||||
const baseURL: string = 'http://37.32.26.111/server/'
|
||||
|
||||
const uploadURL = `${baseURL}/site/file`
|
||||
const baseURLStorage = baseURL
|
||||
const prefixCls = 'hr-tamin'
|
||||
const version = pkg.version
|
||||
const tokenName = 'peransa_token'
|
||||
const appName = { fa: 'داشبورد مدیریتی', en: 'Admin Dashboard' }
|
||||
/** Defining the secret key for crypto-js **/
|
||||
const secretKey = 'pwd@1234'
|
||||
|
||||
const baseIconSize = '24'
|
||||
const baseButtonIconSize = '24'
|
||||
const menuIconSize = '20'
|
||||
|
||||
export {
|
||||
baseURL,
|
||||
prefixCls,
|
||||
//colors,
|
||||
version,
|
||||
tokenName,
|
||||
appName,
|
||||
secretKey,
|
||||
uploadURL,
|
||||
baseURLStorage,
|
||||
baseIconSize,
|
||||
baseButtonIconSize,
|
||||
menuIconSize
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/src/assets/img/icon.png">
|
||||
<meta content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<!-- todo -->
|
||||
<title>admin ghatreh gold</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
defineConfig,
|
||||
presetAttributify,
|
||||
presetIcons,
|
||||
presetTypography,
|
||||
presetUno,
|
||||
presetWebFonts,
|
||||
transformerDirectives,
|
||||
transformerVariantGroup
|
||||
} from 'unocss'
|
||||
|
||||
export default defineConfig({
|
||||
shortcuts: [
|
||||
// ...
|
||||
],
|
||||
theme: {
|
||||
colors: {
|
||||
// ...
|
||||
primary: '#0A1B37'
|
||||
}
|
||||
},
|
||||
presets: [
|
||||
presetUno(),
|
||||
presetAttributify(),
|
||||
presetIcons(),
|
||||
presetTypography(),
|
||||
presetWebFonts({
|
||||
fonts: {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
],
|
||||
transformers: [transformerDirectives(), transformerVariantGroup()]
|
||||
})
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "admin-vue3",
|
||||
"version": "0.0.1",
|
||||
"author": {
|
||||
"name": "Ali Ghasami",
|
||||
"email": "alighassami@yahoo.com",
|
||||
"url": "alighasami.ir"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p build-only",
|
||||
"build-type-check": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^10.1.2",
|
||||
"@vueuse/head": "^1.1.26",
|
||||
"ant-design-vue": "^3.2.19",
|
||||
"apexcharts": "^3.45.1",
|
||||
"axios": "^1.3.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjalali": "^1.0.1",
|
||||
"echarts": "^5.4.3",
|
||||
"jalaliday": "^2.3.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"moment-jalaali": "^0.10.0",
|
||||
"pinia": "^2.0.33",
|
||||
"vue": "3.3.13",
|
||||
"vue-content-loader": "^2.0.1",
|
||||
"vue-echarts": "^6.6.8",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue3-apexcharts": "^1.4.4",
|
||||
"vue3-otp-input": "^0.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/lodash": "^4.14.195",
|
||||
"@types/node": "^18.15.13",
|
||||
"@unocss/preset-attributify": "^0.50.8",
|
||||
"@unocss/preset-uno": "^0.50.8",
|
||||
"@unocss/transformer-compile-class": "^0.50.8",
|
||||
"@unocss/transformer-directives": "^0.50.8",
|
||||
"@unocss/transformer-variant-group": "^0.50.8",
|
||||
"@vitejs/plugin-vue": "^4.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.8.8",
|
||||
"typescript": "~4.9.5",
|
||||
"unocss": "^0.50.8",
|
||||
"unplugin-auto-import": "^0.15.3",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vite": "^4.5.5",
|
||||
"vite-plugin-pwa": "^0.14.7",
|
||||
"vue-tsc": "^1.2.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
## Pre Dependency For Panel
|
||||
### html - css
|
||||
### js and type script
|
||||
### vue 3
|
||||
### vue 3 script setup
|
||||
### pinia for store
|
||||
### vite and plugin for vite
|
||||
### less
|
||||
### uno css
|
||||
- https://github.com/unocss/unocss
|
||||
- https://github.com/unocss/unocss/tree/main/packages/preset-attributify/
|
||||
- https://github.com/unocss/unocss/tree/main/packages/transformer-variant-group
|
||||
- https://github.com/unocss/unocss/tree/main/packages/transformer-directives
|
||||
- https://github.com/unocss/unocss/tree/main/packages/transformer-compile-class/
|
||||
- https://github.com/unocss/unocss/tree/main/packages/preset-uno
|
||||
- https://github.com/reslear/unocss-preset-scrollbar-hide
|
||||
### git and git Submodules
|
||||
### vue use
|
||||
### axios
|
||||
### @vueuse/head
|
||||
- https://github.com/vueuse/head
|
||||
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<AConfigProvider direction="rtl">
|
||||
<RouterView />
|
||||
<!-- <button @click="test">this is ssss</button>-->
|
||||
</AConfigProvider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const router = useRouter()
|
||||
|
||||
function test() {
|
||||
console.log('roussss', router)
|
||||
router.push({ name: 'users' })
|
||||
}
|
||||
|
||||
/*const router = useRouter()
|
||||
console.log('this is router', router.currentRoute.value)*/
|
||||
/*import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
useStaticApiListsStore().getWholeData()*/
|
||||
//define store
|
||||
/*import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import { getToken } from '@/utils'*/
|
||||
/*const store = useStaticApiListsStore()
|
||||
const token = getToken()
|
||||
if (token) store.getMyInfo()*/
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import useAxios from "@core/utils/useAxios";
|
||||
import type {Accounting, TotalAccounting} from "@/model/accounting";
|
||||
|
||||
export const getAccountingTable = async (start: string,end: string) =>
|
||||
await useAxios.post<Accounting>('/admin/dashboard/finance', {startDate: start, endDate: end});
|
||||
|
||||
//Accounting Tab
|
||||
export const getTotalAccountingTable = async () =>
|
||||
await useAxios.post<TotalAccounting>('/admin/finance');
|
||||
@@ -0,0 +1,10 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { AddId, Customer } from '@/model/customer'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type { Card, cardSts } from '@/model/card'
|
||||
|
||||
export const changeAccountSts = async (obj: cardSts) =>
|
||||
await useAxios.post<boolean>(`/admin/account/sts`, obj)
|
||||
|
||||
export const getAccountTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Card>>('/admin/account/table', params)
|
||||
@@ -0,0 +1,16 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { City, Province } from '@/model/city'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
|
||||
export const getProvinces = async () => await useAxios.get<Array<Province>>(`/api/city/state`)
|
||||
|
||||
export const getAllCities = async () => await useAxios.get<Array<City>>(`/api/city/all`)
|
||||
|
||||
export const getCitiesList = async (id: number) =>
|
||||
await useAxios.get<Array<Province>>(`/api/city/${id}`)
|
||||
|
||||
export const getCitiesTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Province>>(`/api/city/table`, params)
|
||||
|
||||
export const addCity = async (id?: number, title?: string) =>
|
||||
await useAxios.post<Province>(`/api/city`, { parent_id: id, title: title })
|
||||
@@ -0,0 +1,21 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { Const } from '@/model/const'
|
||||
|
||||
export const getNatureConst = async () => await useAxios.get<Array<Const>>('/api/const/key/nature')
|
||||
|
||||
export const getBudgetConst = async () => await useAxios.get<Array<Const>>('/api/const/key/budget')
|
||||
|
||||
export const getProjectConst = async () => await useAxios.get<Array<Const>>('/api/const/key/type')
|
||||
|
||||
export const getUserTypeConst = async () =>
|
||||
await useAxios.get<Array<Const>>('/api/const/key/user_type')
|
||||
|
||||
export const getSectionConst = async () =>
|
||||
await useAxios.get<Array<Const>>('/api/const/key/section')
|
||||
|
||||
export const updateEditConst = async (obj: Const) =>
|
||||
await useAxios.put<Const>(`/admin/const/1`, obj)
|
||||
|
||||
export const createAddConst = async (obj: Const) => await useAxios.post<Const>(`/admin/const`, obj)
|
||||
|
||||
export const deleteConst = async (id: number) => await useAxios.delete<boolean>(`/api/const/${id}`)
|
||||
@@ -0,0 +1,36 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { AddId, Customer } from '@/model/customer'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
|
||||
export const createCustomer = async (obj: Customer) =>
|
||||
await useAxios.post<AddId>(`/admin/customer`, obj)
|
||||
|
||||
export const deleteCustomer = async (id: number) => await useAxios.delete(`/admin/customer/${id}`)
|
||||
export const updateCustomer = async (id: number, obj: Customer) =>
|
||||
await useAxios.put<AddId>(`/admin/customer/${id}`, obj)
|
||||
|
||||
export const getCustomerTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/customer/table', params)
|
||||
|
||||
export const getCustomersList = async () => await useAxios.get<Customer[]>(`/admin/customer/list`)
|
||||
|
||||
export const changeCustomerActivation = async (id: number) =>
|
||||
await useAxios.get(`/admin/customer/active/${id}`)
|
||||
|
||||
export const changeCustomerOrderActivation = async (id: number) =>
|
||||
await useAxios.get(`/admin/customer/trade/${id}`)
|
||||
|
||||
export const changeCustomerArchive = async (id: number) =>
|
||||
await useAxios.get(`/admin/customer/archive/${id}`)
|
||||
|
||||
export const confirmUser = async (id: number) =>
|
||||
await useAxios.get(`/admin/customer/is_valid/${id}`)
|
||||
|
||||
export const getCustomerArchiveTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/customer/archive/table', params)
|
||||
|
||||
export const getSingleTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/customer/single/table', params)
|
||||
|
||||
export const getSingleArchiveTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/customer/single/archive/table', params)
|
||||
@@ -0,0 +1,13 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { AddId, User } from '@/model/user'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type {Dashboard} from '@/model/dashboard'
|
||||
import type {PriceChart} from "@/model/priceChart";
|
||||
|
||||
export const getDashboard = async () => await useAxios.get<Dashboard>('/admin/dashboard')
|
||||
|
||||
export const updateMyInformation = async (val: User) =>
|
||||
await useAxios.post<User>('/admin/me/update', val)
|
||||
|
||||
//priceChart
|
||||
export const getAllPrices = async () => await useAxios.post('/admin/prices')
|
||||
@@ -0,0 +1,8 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { Token, UserLoginState } from '@/model/login'
|
||||
|
||||
export const Login = async (values: UserLoginState) =>
|
||||
await useAxios.post<Token>('/auth/login', values)
|
||||
|
||||
export const Verify = async (values: UserLoginState) =>
|
||||
await useAxios.post<Token>('/auth/verify', values)
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { TableInput,TableOutput } from '@core/type/baseTable'
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { Order,OrderSts } from '@/model/order'
|
||||
import type { AddId, Customer } from '@/model/customer'
|
||||
|
||||
export const getOrderTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Order>>('/admin/order/table', params)
|
||||
|
||||
export const createOrder = async (obj: Order) =>
|
||||
await useAxios.post<AddId>(`/admin/single/order`, obj)
|
||||
|
||||
export const getSingleOrder = async (id: number) =>
|
||||
await useAxios.get<Order>(`/admin/order/single/${id}`)
|
||||
|
||||
export const getNewOrderTable = async (params: TableInput) =>
|
||||
await useAxios.post<TableOutput<Order>>('/admin/order/table/new', params)
|
||||
|
||||
|
||||
export const getSingleTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/customer/single/table', params)
|
||||
|
||||
export const changeOrderSts = async (params: OrderSts) =>
|
||||
await useAxios.post<OrderSts>('/admin/order/sts', params)
|
||||
@@ -0,0 +1,4 @@
|
||||
import useAxios from "@core/utils/useAxios";
|
||||
import type {OthersPrices} from "@/model/othersPrices";
|
||||
|
||||
export const getOthersPrices = async () => await useAxios.get<OthersPrices>('api/price/last')
|
||||
@@ -0,0 +1,19 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { Permission, UserPermission } from '@/model/permission'
|
||||
|
||||
export const getTreeData = async () => await useAxios.get('/api/permission/show/rid')
|
||||
|
||||
export const updatePermission = async (obj: Permission) =>
|
||||
await useAxios.post('/api/permission', obj)
|
||||
|
||||
export const getSelectedData = async (user_type_id?: number, section_id?: number) =>
|
||||
await useAxios.get(`/api/permission/${user_type_id}/${section_id}`)
|
||||
|
||||
export const updateUserPermission = async (obj: UserPermission) =>
|
||||
await useAxios.post('/api/exclude', obj)
|
||||
|
||||
export const getUserSelectedData = async (id?: number) => await useAxios.get(`/api/exclude/${id}`)
|
||||
|
||||
export async function getUserPermissions(user_id: number) {
|
||||
return await useAxios.get(`/api/exclude/user/permission/${user_id}`)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { AddId } from '@/model/customer'
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { last, Price } from "@/model/price";
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type { MethodePrices } from "@/model/product";
|
||||
|
||||
export const createPrice = async (obj: Price) => await useAxios.post<AddId>(`/admin/price`, obj)
|
||||
|
||||
export const getPriceTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Price>>('/admin/price/table', params)
|
||||
|
||||
export const getLastPrice = async () => await useAxios.get<last>(`/api/price/last`)
|
||||
|
||||
export const methodePrices = async () => await useAxios.get<MethodePrices[]>('/admin/p')
|
||||
@@ -0,0 +1,6 @@
|
||||
import type {TableInput} from "@core/type/baseTable";
|
||||
import useAxios from "@core/utils/useAxios";
|
||||
import type {PriceTriggers} from "@/model/priceTriggers";
|
||||
|
||||
export const getPriceTriggersTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<PriceTriggers>>('/admin/price_triggers/table', params)
|
||||
@@ -0,0 +1,61 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { AddId, Customer } from '@/model/customer'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type { Accounting } from "@/model/accounting"
|
||||
import type { Balance, SetActiveTime } from "@/model/product";
|
||||
|
||||
export const createProduct = async (obj: Customer) =>
|
||||
await useAxios.post<AddId>(`/admin/product`, obj)
|
||||
|
||||
export const deleteCustomer = async (id: number) => await useAxios.delete(`/admin/product/${id}`)
|
||||
export const updateCustomer = async (id: number, obj: Customer) =>
|
||||
await useAxios.put<AddId>(`/admin/product/${id}`, obj)
|
||||
|
||||
export const getCustomerTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/product/table', params)
|
||||
|
||||
export const getCustomersList = async () => await useAxios.get<Customer[]>(`/admin/product/list`)
|
||||
|
||||
export const changeProductActivation = async (id: number) =>
|
||||
await useAxios.get(`/admin/product/active/${id}`)
|
||||
|
||||
export const changeCustomerOrderActivation = async (id: number) =>
|
||||
await useAxios.get(`/admin/product/trade/${id}`)
|
||||
|
||||
export const changeCustomerArchive = async (id: number) =>
|
||||
await useAxios.get(`/admin/product/archive/${id}`)
|
||||
|
||||
export const confirmUser = async (id: number) =>
|
||||
await useAxios.get(`/admin/product/is_valid/${id}`)
|
||||
|
||||
export const getCustomerArchiveTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/product/archive/table', params)
|
||||
|
||||
export const getSingleTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/product/single/table', params)
|
||||
|
||||
export const getSingleArchiveTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Customer>>('/admin/product/single/archive/table', params)
|
||||
|
||||
export const getCustomerById = async (id: number) => {
|
||||
return await useAxios.get(`/admin/product/${id}`)
|
||||
}
|
||||
export const changeBuyActiveProduct = async (id?: number) => {
|
||||
return await useAxios.get(`/admin/product/open_buy/${id}`)
|
||||
}
|
||||
export const changeSellActiveProduct = async (id?: number) => {
|
||||
return await useAxios.get(`/admin/product/open_sell/${id}`)
|
||||
}
|
||||
export const changeActiveProduct = async (id: number) => {
|
||||
return await useAxios.get(`/admin/product/active/${id}`)
|
||||
}
|
||||
export const changeVisibilityProduct = async (id: number) => {
|
||||
return await useAxios.get(`/admin/product/hide/${id}`)
|
||||
}
|
||||
export const setActiveTime = async (open: string, close: string) =>{
|
||||
await useAxios.put<SetActiveTime>(`/admin/products`, {auto_open_at: open, auto_close_at: close})
|
||||
}
|
||||
|
||||
export const getBalance = async (startDate: string, endDate: string) => {
|
||||
return await useAxios.post<Balance>('/admin/getBalance', {startDate, endDate})
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { AddId, Customer } from '@/model/customer'
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { last, Price } from '@/model/price'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type { Order } from '@/model/order'
|
||||
import type { FunctionItem } from '@/model/Item'
|
||||
import sms from '@/router/routes/sms'
|
||||
import type { Sms } from '@/model/sms'
|
||||
|
||||
export const getSMSTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Price>>('/admin/messages/table', params)
|
||||
|
||||
export const getNumbersTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Price>>('/admin/messages/get_customer_list/table', params)
|
||||
|
||||
export const getGroupsList = async () =>
|
||||
await useAxios.get<FunctionItem[]>(`/admin/messages/functions`)
|
||||
|
||||
export const getCustomerList = async (obj: string[]) =>
|
||||
await useAxios.post<{ customers: Customer[] }>(`/admin/messages/get_customer_list`, {
|
||||
functions: obj
|
||||
})
|
||||
|
||||
export const createSMS = async (obj: Sms) =>
|
||||
await useAxios.post<AddId>(`/admin/messages/send_message`, obj)
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
// import { Customer } from '@/model/customer'
|
||||
import type { Wallet } from '@/model/wallet'
|
||||
import type { Transaction } from '@/model/transaction'
|
||||
|
||||
export const getTransactionTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Transaction>>('/admin/wallet/transaction/table', params)
|
||||
@@ -0,0 +1,30 @@
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
import type { AddId, User } from '@/model/user'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import type {Referrals} from '@/model/referrals'
|
||||
import type {Funds} from "@/model/funds";
|
||||
|
||||
//referrals
|
||||
export const getReferralsTable = async (params: TableInput,customer_id: number) => await useAxios.post<Array<Referrals>>(`/admin/customers/${customer_id}/referrals`, params)
|
||||
//funds
|
||||
export const getFundsTable = async (params: TableInput,customer_id: number) => await useAxios.post<Array<Funds>>(`/admin/customers/${customer_id}/funds`, params)
|
||||
|
||||
export const getReferrals = async (val: Referrals) => await useAxios.post<Funds>(`/admin/customers/4/referrals`, val)
|
||||
//me
|
||||
export const getMyInformation = async () => await useAxios.get<User>('/admin/me')
|
||||
|
||||
export const updateMyInformation = async (val: User) => await useAxios.post<User>('/admin/me/update', val)
|
||||
|
||||
//users
|
||||
export const createUser = async (obj: User) => await useAxios.post<AddId>(`/admin/user`, obj)
|
||||
|
||||
export const updateUser = async (id: number, obj: User) =>
|
||||
await useAxios.put<AddId>(`/admin/user/${id}`, obj)
|
||||
|
||||
export const deleteUser = async (id: number) => await useAxios.delete(`/admin/user/${id}`)
|
||||
|
||||
export const getUserTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<User>>('/admin/user/table', params)
|
||||
|
||||
export const changeUserActivation = async (id: number) =>
|
||||
await useAxios.get(`/admin/user/active/${id}`)
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import useAxios from '@core/utils/useAxios'
|
||||
// import { Customer } from '@/model/customer'
|
||||
import type { Charge, Wallet, Withdraw, SendWeight } from '@/model/wallet'
|
||||
|
||||
export const getWalletTable = async (params?: TableInput) =>
|
||||
await useAxios.post<Array<Wallet>>('/admin/wallet/table', params)
|
||||
export const chargeWallet = async (params: Charge, type: 'gold' | 'money') =>
|
||||
type === 'money'
|
||||
? await useAxios.post<boolean>('/admin/wallet/charge', params)
|
||||
: await useAxios.post<boolean>('/admin/wallet/charge_gold', params)
|
||||
|
||||
export const getWithdrawTable = async (params: TableInput) =>
|
||||
await useAxios.post<Array<Withdraw>>('/admin/wallet/withdraw/table', params)
|
||||
|
||||
export const completeWithdraw = async (params: Withdraw) =>
|
||||
await useAxios.post<boolean>('/admin/wallet/withdraw/complete', params)
|
||||
|
||||
export const updateSts = async (id: number, sts: Object) => {
|
||||
return await useAxios.put(`/admin/wallet/withdraw/${id}`, sts)
|
||||
}
|
||||
|
||||
export const getWithdrawById = async (id: number) => {
|
||||
return await useAxios.get(`/admin/wallet/withdraw/${id}`)
|
||||
}
|
||||
|
||||
export const sendWeights = async (params: SendWeight ) => {
|
||||
return await useAxios.put(`/admin/wallet/transaction/reprice`, params)
|
||||
}
|
||||
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 389 B |
@@ -0,0 +1,95 @@
|
||||
|
||||
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
/*::-webkit-scrollbar-track {
|
||||
background-color: #f2f6ff !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 7px !important;
|
||||
background-color: @primary-color !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: @second-color !important;
|
||||
border-radius: @primary-color !important;
|
||||
}*/
|
||||
|
||||
@media (max-width: 376px ) {
|
||||
.ant-card-body {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
display: block;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.ant-select-selector{
|
||||
border-radius: @border-radius-base !important;
|
||||
}
|
||||
.ant-input {
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
|
||||
.ant-picker{
|
||||
border-radius: @border-radius-base;
|
||||
@apply w-full;
|
||||
}
|
||||
.ant-card-body{
|
||||
@apply h-full;
|
||||
}
|
||||
.ant-table-tbody{
|
||||
max-height: 50vh;
|
||||
}
|
||||
.ant-popover-buttons{
|
||||
direction: ltr;
|
||||
}
|
||||
.ant-popover-title{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
//Todo Mohammad(this style change all tbody in project event in datepicker)
|
||||
/*tbody {
|
||||
display: block;
|
||||
overflow: auto;
|
||||
}*/
|
||||
|
||||
//Todo Mohammad(this style change all tbody in project event in datepicker)
|
||||
/*thead, tbody tr {
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: fixed;!* even columns width , fix width of table too*!
|
||||
}*/
|
||||
/*
|
||||
.ant-message-notice{
|
||||
z-index: 1000000000000000;
|
||||
}*/
|
||||
.otp-input {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
padding: 3px;
|
||||
margin: 0 8px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
//@apply bg-gray-50;
|
||||
|
||||
&:focus-visible {
|
||||
background-color: #fff;
|
||||
//display: none;
|
||||
outline: none;
|
||||
border: 1px solid @primary-color !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<a-card class="m-5 rounded-xl h-[91vh]">
|
||||
<slot></slot>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div :class="isLine ? 'flex justify-between items-center' : ''">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="text-gray-400">{{ title }}:</div>
|
||||
<BasicIcon
|
||||
v-if="info"
|
||||
icon="vuesax-linear:info-circle"
|
||||
size="18"
|
||||
color="orange"
|
||||
@click="infoVisible = true"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="value !== undefined" class="font-bold mt-1">{{ value }}</div>
|
||||
<div v-else class="mt-1">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <van-dialog
|
||||
v-model:show="infoVisible"
|
||||
class="updateButton"
|
||||
confirm-button-text="متوجه شدم"
|
||||
show-confirm-button
|
||||
@confirm="update()"
|
||||
>
|
||||
<div class="flex flex-col items-center p-2">
|
||||
<!– <div class="home_appear_fade_in_up delay-100">به روز رسانی</div>–>
|
||||
<div v-if="infoHead" class="font-bold">{{ infoHead }}</div>
|
||||
<div class="home_appear_fade_in_up mt-2 text-sm">{{ info }}</div>
|
||||
</div>
|
||||
</van-dialog>-->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { update } from 'lodash'
|
||||
import { ref } from 'vue'
|
||||
// import anim from '@/assets/lottie/animInfo.json'
|
||||
|
||||
interface Prop {
|
||||
title: string
|
||||
info?: string
|
||||
infoHead?: string
|
||||
isLine?: boolean
|
||||
value?: string | number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
isLine: false
|
||||
})
|
||||
const infoVisible = ref<boolean>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<!-- <BasicModal
|
||||
v-model:visible="props.visible"
|
||||
width="30rem"
|
||||
:title="props.title"
|
||||
@close="emits('close')"
|
||||
>
|
||||
<div :class="[prefixCls]" class="bg-[#F6F6F4] flex justify-between p-3">
|
||||
<div>
|
||||
<div class="font-bold">{{ props.name }}</div>
|
||||
<div class="text-primary-type">{{ props.type }}</div>
|
||||
<!– <div class="text-xl">fggh</div>–>
|
||||
</div>
|
||||
<div>
|
||||
<div>{{ props.date }}</div>
|
||||
<div class="text-left">{{ props.time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
</BasicModal>-->
|
||||
<a-modal
|
||||
v-model:visible="localValue"
|
||||
:title="props.title"
|
||||
centered
|
||||
width="80%"
|
||||
@cancel="emits('close')"
|
||||
@close="emits('close')"
|
||||
footer
|
||||
>
|
||||
<div class="overflow-y-auto max-h-[70vh] mt-10">
|
||||
<div :class="[prefixCls]" class="bg-blue-50 rounded flex justify-between p-3">
|
||||
<div>
|
||||
<div class="font-bold">{{ props.name }}</div>
|
||||
<div class="text-primary-type mt-1">{{ props.type }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>{{ props.date }}</div>
|
||||
<div class="text-left">{{ props.time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-[#CACED8] w-full h-[1px] my-8" />
|
||||
<div class="text-[#949DB0]">{{ props.itemsTitle }}</div>
|
||||
<div class="grid md:grid-cols-4 mt-5 gap-5 p-5">
|
||||
<div v-for="val in props.items">
|
||||
<div class="text-[#949DB0]">{{ val.key }}</div>
|
||||
<div class="font-bold">{{ val.value }}</div>
|
||||
</div>
|
||||
<div class="md:col-span-5" v-if="props.description">
|
||||
<div class="text-[#949DB0]">توضیحات</div>
|
||||
<div class="font-bold">{{ props.description ?? '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
//define emits
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import type { KeyVal } from '@/components/BasicInfoModal/model/Info'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
//props
|
||||
interface Prop {
|
||||
visible?: boolean
|
||||
title?: string
|
||||
name?: string
|
||||
date?: string
|
||||
time?: string
|
||||
type?: string | number
|
||||
itemsTitle?: string
|
||||
description?: string
|
||||
items?: KeyVal[]
|
||||
}
|
||||
|
||||
//emits
|
||||
const emits = defineEmits(['update:visible', 'close'])
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.visible
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emits('update:visible', value)
|
||||
}
|
||||
})
|
||||
|
||||
//set type color
|
||||
const props = defineProps<Prop>()
|
||||
|
||||
//style
|
||||
const { prefixCls } = usePrefix('info-modal')
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-info-modal';
|
||||
|
||||
.@{prefix} {
|
||||
.text-primary-type {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface Info {
|
||||
title?: string
|
||||
date?: string
|
||||
time?: string
|
||||
type?: string | number
|
||||
typeColor?: string
|
||||
mobile?: number
|
||||
name?: string
|
||||
itemsTitle?: string
|
||||
items?: Array<KeyVal>
|
||||
description?: string
|
||||
}
|
||||
export interface KeyVal {
|
||||
key: string
|
||||
value?: string | number
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<a-input-password
|
||||
v-if="isPassword"
|
||||
v-model:value="localValue"
|
||||
:addon-after="props.addonAfter"
|
||||
:addon-before="props.addonBefore"
|
||||
:disabled="props.disabled"
|
||||
:placeHolder="props.placeHolder"
|
||||
:size="props.size"
|
||||
:type="props.type"
|
||||
class=""
|
||||
@change="handlerChange"
|
||||
/>
|
||||
<a-input
|
||||
v-else
|
||||
v-model:value="localValue"
|
||||
:addon-after="props.addonAfter"
|
||||
:addon-before="props.addonBefore"
|
||||
:disabled="props.disabled"
|
||||
:placeHolder="props.placeHolder"
|
||||
:size="props.size"
|
||||
:type="props.type === 'price' ? 'tel' : props.type"
|
||||
class=""
|
||||
@change="handlerChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { computed } from 'vue'
|
||||
import { usePrice } from '@core/utils/usePrice'
|
||||
|
||||
//Props
|
||||
interface Prop {
|
||||
title?: String
|
||||
value?: String | Number
|
||||
size?: String
|
||||
type?: String
|
||||
isPassword?: boolean
|
||||
disabled?: boolean
|
||||
addonAfter?: String
|
||||
addonBefore?: String
|
||||
addonBgColor?: String
|
||||
addonTextColor?: String
|
||||
placeHolder?: String
|
||||
}
|
||||
|
||||
const addonBgColor = computed(() => props.addonBgColor)
|
||||
const addonTextColor = computed(() => props.addonTextColor)
|
||||
//emits
|
||||
const localValue = computed({
|
||||
set(value) {
|
||||
// console.log(value?.toString().replaceAll(',', ''))
|
||||
props.type === 'price'
|
||||
? emits('update:value', value?.toString().replaceAll(',', ''))
|
||||
: emits('update:value', value)
|
||||
},
|
||||
get() {
|
||||
let a =
|
||||
props.type === 'price'
|
||||
? props.value
|
||||
? usePrice(props.value as number, true, '').trim()
|
||||
: ''
|
||||
: props.value
|
||||
// console.log(props.value)
|
||||
return a
|
||||
}
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
isPassword: false
|
||||
})
|
||||
const emits = defineEmits(['update:value', 'onchange'])
|
||||
|
||||
const handlerChange = (e: any) => {
|
||||
// emits('onchange', e.target.value)
|
||||
props.type === 'price'
|
||||
? emits('update:value', e.target.value?.toString().replaceAll(',', ''))
|
||||
: emits('update:value', e.target.value)
|
||||
props.type === 'price'
|
||||
? emits('onchange', e.target.value?.toString().replaceAll(',', ''))
|
||||
: emits('onchange', e.target.value)
|
||||
// console.log(e.target.value)
|
||||
}
|
||||
|
||||
//css style
|
||||
const { prefixCls } = usePrefix('input')
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-input';
|
||||
|
||||
.@{prefix} {
|
||||
/* .ant-input-group-addon:first-child {
|
||||
!* border: #d9d9d9 1px solid;
|
||||
border-radius: 0 6px 6px 0;*!
|
||||
}*/
|
||||
.ant-input-group {
|
||||
direction: ltr;
|
||||
}
|
||||
.ant-input-group > .ant-input:first-child,
|
||||
.ant-input-group-addon:first-child {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: @border-radius-base;
|
||||
border-top-left-radius: @border-radius-base;
|
||||
}
|
||||
/*.ant-input-group > .ant-input-rtl:first-child,
|
||||
.ant-input-group-rtl .ant-input-group-addon:first-child {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: @border-radius-base;
|
||||
border-top-left-radius: @border-radius-base;
|
||||
}*/
|
||||
.ant-input-group > .ant-input:last-child,
|
||||
.ant-input-group-addon:last-child {
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<a-card class="m-5 rounded-xl md:h-[91vh]">
|
||||
<slot></slot>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<a-card class="h-[93vh]">
|
||||
<slot></slot>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<template v-for="item in props.menu" :key="item.name">
|
||||
<AMenuItem :key="item.name" v-if="!item.children" @click="handleClickMenu(item)">
|
||||
<template #icon v-if="item?.meta?.icon">
|
||||
<BaseIcon :icon="item?.meta?.icon" />
|
||||
</template>
|
||||
{{ item?.meta?.title }}
|
||||
</AMenuItem>
|
||||
<ASubMenu :key="item.name" v-else>
|
||||
<template #icon v-if="item?.meta?.icon">
|
||||
<BaseIcon :icon="item.meta.icon" />
|
||||
</template>
|
||||
<template #title>{{ item.meta.title }}</template>
|
||||
<BasicMenuItem v-if="item.children" :menu="item.children" />
|
||||
</ASubMenu>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import BasicMenuItem from './BasicMenuItem'
|
||||
|
||||
import { defineProps } from 'vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
interface Prop {
|
||||
menu: RouteRecordRaw[]
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
function handleClickMenu(item: RouteRecordRaw) {
|
||||
//debugger
|
||||
router.push({ name: item.name })
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- {{ props.menu }}-->
|
||||
<AMenu
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
:style="{ width: props.width }"
|
||||
:mode="props.mode"
|
||||
:theme="props.theme"
|
||||
>
|
||||
<!-- <a-menu-item key="1"> Navigation One </a-menu-item>-->
|
||||
<!-- {{ props.menu }}-->
|
||||
<BasicMenuItem :menu="props.menu" />
|
||||
</AMenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MenuMode, MenuTheme } from 'ant-design-vue'
|
||||
import { defineProps } from 'vue'
|
||||
//import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import BasicMenuItem from '@/components/BasicMenu/components/BasicMenuItem.vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
const selectedKeys = ref<string[]>([])
|
||||
const router = useRouter()
|
||||
/*const state = reactive({
|
||||
selectedKeys: ['1'],
|
||||
openKeys: ['sub1']
|
||||
})*/
|
||||
//define emit
|
||||
//const emits = defineEmits(['onChange'])
|
||||
//selected key
|
||||
//const selectedKeys = ref<Array<string>>(['1'])
|
||||
/*watch(selectedKeys, (val) => {
|
||||
emits('onChange', val[0])
|
||||
})*/
|
||||
|
||||
//prop
|
||||
interface Prop {
|
||||
menu: RouteRecordRaw[]
|
||||
mode?: MenuMode
|
||||
theme?: MenuTheme
|
||||
width?: string
|
||||
}
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
mode: 'inline',
|
||||
theme: 'light',
|
||||
width: '20rem'
|
||||
})
|
||||
onMounted(() => {
|
||||
selectedKeys.value = [router.currentRoute.value.name as string]
|
||||
//emits('onChange', '1')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<div theme="light" :class="[prefixCls]" class="md:hidden">
|
||||
<div class="flex items-center justify-center gap-2 relative">
|
||||
<BaseIcon
|
||||
icon="vuesax-linear:menu"
|
||||
class="p-3 absolute right-2 top-1"
|
||||
@click="showDrawer"
|
||||
/>
|
||||
<img :src="Logo" class="w-4rem mr-2 my-5" />
|
||||
<div class="absolute left-2 top-3">
|
||||
<div class="flex items-center w-full justify-center"></div>
|
||||
<ADropdown placement="bottomLeft">
|
||||
<a class="ant-dropdown-link" @click.prevent>
|
||||
<!-- Hover me-->
|
||||
<div class="flex items-center gap-1 text-gray-400">
|
||||
<AAvatar :src="placeholderM" />
|
||||
<Icon icon="vuesax-linear:arrow-down" size="15" />
|
||||
</div>
|
||||
</a>
|
||||
<template #overlay>
|
||||
<AMenu>
|
||||
<AMenuItem>
|
||||
<div class="flex flex-col">
|
||||
<span class="font-bold">{{ userStore.userInfo?.name }}</span>
|
||||
<span>{{ userStore.userInfo?.post_user }}</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
<AMenuDivider />
|
||||
<AMenuItem @click="myInfoVisible = true">
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon icon="vuesax-linear:profile" size="18" />
|
||||
<span>اطلاعات حساب کاربری</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
<AMenuItem @click="clearLocalStorage">
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon icon="vuesax-linear:logout" size="18" />
|
||||
<span>خروج</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
</AMenu>
|
||||
</template>
|
||||
</ADropdown>
|
||||
<BaseButton
|
||||
iconSize="20"
|
||||
icon="vuesax-linear:setting"
|
||||
type="text"
|
||||
v-if="layoutStore.showSettingsIcon"
|
||||
@click="handleShowSettings"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<BasicModal
|
||||
v-model:visible="myInfoVisible"
|
||||
width="40rem"
|
||||
title="اطلاعات حساب کاربری"
|
||||
@ok="ok"
|
||||
:loading="loading"
|
||||
@close="myInfoVisible = false"
|
||||
>
|
||||
<a-form :model="form" ref="formRef" autocomplete="off">
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<a-form-item label="نام" name="fname" :rules="inputRules()">
|
||||
<BasicInput v-model:value="form.fname" />
|
||||
</a-form-item>
|
||||
<a-form-item label="نام خانوادگی" name="lname" :rules="inputRules()">
|
||||
<BasicInput v-model:value="form.lname" />
|
||||
</a-form-item>
|
||||
<a-form-item label="شماره موبایل" name="mobile" :rules="inputLenRules(11)">
|
||||
<BasicInput v-model:value="form.mobile" type="number" />
|
||||
</a-form-item>
|
||||
<a-form-item label="رمز کاربری" name="password">
|
||||
<BasicInput type="password" v-model:value="form.password" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
</a-form>
|
||||
</BasicModal>
|
||||
</div>
|
||||
</div>
|
||||
<ADrawer height="460px" :placement="placement" v-model:visible="open" :closable="false" @close="onClose">
|
||||
<AMenu v-model:selectedKeys="selectedKeys" mode="vertical">
|
||||
<template v-for="item in menu">
|
||||
<BasicSubMenu
|
||||
v-if="!item.meta?.hideChildren && item.children && item.children.length > 0"
|
||||
:menu-item="item"
|
||||
:key="item.name"
|
||||
:level="1"
|
||||
@click="onClose"
|
||||
/>
|
||||
<BaseMenuItem v-else :item="item" :key="item.name" @click="onClose" />
|
||||
</template>
|
||||
</AMenu>
|
||||
</ADrawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Logo from '@/assets/img/ghatrehLogo.png'
|
||||
import type { DrawerProps } from 'ant-design-vue'
|
||||
import { inputLenRules, inputRules } from '@/utils/inputRules'
|
||||
|
||||
const placement = ref<DrawerProps['placement']>('bottom')
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { useLayoutStore } from '@core/stores/layout'
|
||||
import BasicMenu from '@core/layouts/composnts/BasicMenu.vue'
|
||||
import placeholderM from '@core/assets/img/avatars/placeholder-m.jpg'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import { useSettingsStore } from '@core/stores/settings'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import type { User } from '@/model/user'
|
||||
import { createUser, updateMyInformation, updateUser } from '@/api/user'
|
||||
import { message } from 'ant-design-vue/es'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import type { FormInstance } from 'ant-design-vue'
|
||||
import { cloneDeep, sortBy } from 'lodash'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import { computed } from 'vue'
|
||||
import type { ComputedRef } from 'vue'
|
||||
import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
|
||||
import { useRouterStore } from '@core/stores/router'
|
||||
import BasicSubMenu from '@core/layouts/composnts/BasicSubMenu.vue'
|
||||
import BaseMenuItem from '@core/layouts/composnts/BaseMenuItem.vue'
|
||||
|
||||
const { prefixCls } = usePrefix('basic-header')
|
||||
const layoutStore = useLayoutStore()
|
||||
const store = useStaticApiListsStore()
|
||||
const userStore = useUserStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
const currentRoute = useRoute()
|
||||
const selectedKeys = ref<(RouteRecordName | undefined)[]>([])
|
||||
const routerStore = useRouterStore()
|
||||
|
||||
const { width } = useWindowSize()
|
||||
//my info modal
|
||||
const loading = ref<boolean>(false)
|
||||
const myInfoVisible = ref<boolean>(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const form = ref<User>({
|
||||
fname: '',
|
||||
lname: '',
|
||||
mobile: '',
|
||||
post_user: '',
|
||||
manager_id: '',
|
||||
responsible_id: '',
|
||||
section: '',
|
||||
section_id: undefined,
|
||||
process_id: '',
|
||||
qc_id: undefined,
|
||||
user_type: undefined,
|
||||
permission: []
|
||||
})
|
||||
onMounted(() => {
|
||||
form.value = cloneDeep(userStore?.userInfo) as User
|
||||
if (width.value <= 426) {
|
||||
layoutStore.layout = 'side'
|
||||
layoutStore.sideMenu.mode = 'vertical'
|
||||
layoutStore.sideMenu.collapsed = false
|
||||
console.log(layoutStore.layout + width.value)
|
||||
}
|
||||
const path: (RouteRecordName | undefined)[] = []
|
||||
|
||||
function walkInRoutes(routes: RouteRecordRaw[]) {
|
||||
for (const route of routes) {
|
||||
if (route.name == currentRoute.name) {
|
||||
path.push(route.name)
|
||||
return true
|
||||
}
|
||||
if (route.children && route.children.length > 0) {
|
||||
path.push(route.name)
|
||||
const res = walkInRoutes(route.children)
|
||||
if (!res) {
|
||||
path.pop()
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
walkInRoutes(routerStore.routes)
|
||||
selectedKeys.value = path
|
||||
})
|
||||
const menu: ComputedRef<RouteRecordRaw[]> = computed(() => {
|
||||
return sortBy(routerStore.routes, (item) => {
|
||||
return item.meta?.order
|
||||
}).filter((item) => !item.meta?.hideMenu)
|
||||
})
|
||||
|
||||
//submit user
|
||||
async function ok() {
|
||||
formRef.value?.validateFields().then(async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
await updateMyInformation(form.value)
|
||||
userStore.getMyInfo()
|
||||
message.success('اطلاعات با موفقیت ویرایش شد')
|
||||
myInfoVisible.value = false
|
||||
} catch (e) {
|
||||
// message.error('خطا در بارگذاری اطلاعات')
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//const temp = 12
|
||||
function handleCollapseSideMenu() {
|
||||
layoutStore.sideMenu.collapsed = !layoutStore.sideMenu.collapsed
|
||||
}
|
||||
|
||||
function handleShowSettings() {
|
||||
settingsStore.showSettingsDrawer = !settingsStore.showSettingsDrawer
|
||||
}
|
||||
|
||||
function clearLocalStorage() {
|
||||
localStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
|
||||
const open = ref<boolean>(false)
|
||||
|
||||
const showDrawer = () => {
|
||||
open.value = true
|
||||
}
|
||||
|
||||
const onClose = () => {
|
||||
open.value = false
|
||||
console.log(open.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-modal
|
||||
v-model:visible="localValue"
|
||||
:title="props.title"
|
||||
centered
|
||||
@ok="emits('ok')"
|
||||
@cancel="emits('close')"
|
||||
@close="emits('close')"
|
||||
:confirm-loading="props.confirmLoading"
|
||||
:width="props.width"
|
||||
:ok-text="props.okText"
|
||||
:cancel-text="props.cancelText"
|
||||
:wrapClassName="props.wrapClassName"
|
||||
>
|
||||
<template v-if="props.customFooter" #footer>
|
||||
<slot name="footer" />
|
||||
</template>
|
||||
<a-spin :spinning="props.loading">
|
||||
<div class="overflow-y-auto py-2 px-1 relative max-h-[80vh]" id="body">
|
||||
<slot />
|
||||
</div>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
//define emit
|
||||
const emits = defineEmits(['ok', 'close', 'update:visible'])
|
||||
|
||||
//define props
|
||||
interface Prop {
|
||||
visible: boolean
|
||||
title?: string
|
||||
okText?: string
|
||||
width?: string
|
||||
cancelText?: string
|
||||
customFooter?: boolean
|
||||
confirmLoading?: boolean
|
||||
loading?: boolean
|
||||
wrapClassName?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
visible: false,
|
||||
cancelText: 'انصراف',
|
||||
okText: 'ثبت',
|
||||
customFooter: false,
|
||||
confirmLoading: false,
|
||||
loading: false,
|
||||
wrapClassName: ''
|
||||
})
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.visible
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emits('update:visible', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ant-modal-content {
|
||||
border-radius: 0.6rem;
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<a-select
|
||||
class="w-full"
|
||||
:size="props.size"
|
||||
v-model:value="localValue"
|
||||
:disabled="props.disabled"
|
||||
show-search
|
||||
:mode="props.mode"
|
||||
:style="props.style"
|
||||
:multiple="props.multiple"
|
||||
@change="handleChange"
|
||||
:placeholder="props.placeholder"
|
||||
:allowClear="props.allowClear"
|
||||
:filter-option="filterOption"
|
||||
>
|
||||
<template #notFoundContent v-if="noData">
|
||||
<div class="w-full text-center font-bold">{{ noData }}</div>
|
||||
</template>
|
||||
<a-select-option
|
||||
:label="val[props.valueName]"
|
||||
v-for="val in props.items"
|
||||
:value="val[props.keyName]"
|
||||
>
|
||||
<a-tooltip v-if="props.hasTooltip" placement="left" class="cursor-pointer">
|
||||
<template #title>
|
||||
<span>{{ val[props.valueName] }}</span>
|
||||
</template>
|
||||
<div class="truncate max-w-40">{{ val[props.valueName] }}</div>
|
||||
</a-tooltip>
|
||||
<div v-else>{{ val[props.valueName] }}</div>
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
|
||||
//Props
|
||||
interface Prop {
|
||||
title?: string
|
||||
value?: string | number | boolean
|
||||
style?: string
|
||||
size?: string
|
||||
keyName: string
|
||||
disabled?: boolean
|
||||
mode?: string
|
||||
valueName: string
|
||||
multiple?: boolean
|
||||
items?: any[]
|
||||
placeholder?: string
|
||||
allowClear?: boolean
|
||||
hasTooltip?: boolean
|
||||
noData?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
allowClear: true,
|
||||
hasTooltip: true
|
||||
})
|
||||
|
||||
// console.log('props.items ====>', props.items)
|
||||
//define emits
|
||||
const emit = defineEmits(['update:value', 'change'])
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.value
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emit('update:value', value)
|
||||
}
|
||||
})
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label?.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
|
||||
const handleChange = (e: any) => {
|
||||
// console.log('e ====>', e)
|
||||
emit(
|
||||
'change',
|
||||
props.items?.find((x) => x[props.keyName] === e)
|
||||
)
|
||||
}
|
||||
|
||||
//css style
|
||||
const { prefixCls } = usePrefix('select')
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-select';
|
||||
|
||||
.@{prefix} {
|
||||
//padding: 5px;
|
||||
/* .ant-select {
|
||||
.ant-select-selector {
|
||||
border-color: @primary-color;
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="py-2 pr-3 w-full h-full relative">
|
||||
<div class="text-black font-bold">{{ props.title }}</div>
|
||||
<div class="mt-2 overflow-y-auto p-1 h-[96%]">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface Prop {
|
||||
title: string
|
||||
}
|
||||
const props = defineProps<Prop>()
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div v-if="!props.loading">
|
||||
<div class="gap-2">
|
||||
<a-tag
|
||||
v-for="item in props.items"
|
||||
:color="props.color"
|
||||
:closable="props.closable"
|
||||
@close="emits('delete', item.id)"
|
||||
class="cursor-pointer"
|
||||
@click="emits('edit', item.id)"
|
||||
>{{ item.name }}
|
||||
</a-tag>
|
||||
<a-tag
|
||||
style="background: #fff; border-style: dashed; margin-top: 0.5rem"
|
||||
@click="emits('add')"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<BaseIcon icon="vuesax-linear:add" size="0.7rem" />
|
||||
<div class="mr-1">افزودن</div>
|
||||
</div>
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<ContentLoader
|
||||
width="350"
|
||||
height="100"
|
||||
viewBox="0 0 350 100"
|
||||
backgroundColor="#f5f5f5"
|
||||
foregroundColor="#dbdbdb"
|
||||
>
|
||||
<rect x="0" y="0" rx="3" ry="3" width="80" height="20" />
|
||||
<rect x="90" y="0" rx="3" ry="3" width="80" height="20" />
|
||||
<rect x="180" y="0" rx="3" ry="3" width="80" height="20" />
|
||||
<rect x="270" y="0" rx="3" ry="3" width="80" height="20" />
|
||||
</ContentLoader>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ContentLoader } from 'vue-content-loader'
|
||||
|
||||
//define emits
|
||||
const emits = defineEmits(['add', 'edit', 'delete'])
|
||||
|
||||
//define props
|
||||
interface Prop {
|
||||
items?: Array<string>
|
||||
color: string
|
||||
loading?: boolean
|
||||
closable?: boolean
|
||||
}
|
||||
const props = withDefaults(defineProps<Prop>(), {
|
||||
closable: false
|
||||
})
|
||||
|
||||
/*watch(props, (val) => {
|
||||
console.log('val ====>', val)
|
||||
})*/
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface TagItem {
|
||||
id: number | undefined
|
||||
name: string | undefined
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div>
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<a-textarea
|
||||
v-model:value="localValue"
|
||||
class=""
|
||||
:type="props.type"
|
||||
:show-count="props.showCount"
|
||||
:placeHolder="props.placeHolder"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
|
||||
//Props
|
||||
interface Prop {
|
||||
title?: string
|
||||
value: string | null
|
||||
showCount?: boolean
|
||||
maxlength?: number
|
||||
placeHolder?: string
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
|
||||
const emit = defineEmits(['update:value'])
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.value
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emit('update:value', value)
|
||||
}
|
||||
})
|
||||
|
||||
//css style
|
||||
const { prefixCls } = usePrefix('input-area')
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-input-area';
|
||||
|
||||
.@{prefix} {
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<a-upload-dragger
|
||||
v-model:fileList="fileList"
|
||||
name="file"
|
||||
:multiple="props.multiple"
|
||||
:action="props.url"
|
||||
@change="handleChange"
|
||||
:headers="props.headers"
|
||||
:maxCount="props.maxCount"
|
||||
:showUploadList="true"
|
||||
>
|
||||
<div class="py-10 px-5">
|
||||
<BaseIcon icon="vuesax-linear:document-upload" size="40" color="#4A5568" />
|
||||
<p class="ant-upload-text">برای آپلود، روی فایل کلیک کنید یا فایل را درون این قسمت بکشید</p>
|
||||
</div>
|
||||
</a-upload-dragger>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { InboxOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import type { UploadChangeParam } from 'ant-design-vue'
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
// console.log(info)
|
||||
const status = info.file.status
|
||||
if (status !== 'uploading') {
|
||||
// console.log(info.file, info.fileList)
|
||||
/*emits('ok', info.file.response.id)*/
|
||||
}
|
||||
if (status === 'done') {
|
||||
// message.success(`${info.file.name} file uploaded successfully.`)
|
||||
console.log(fileList)
|
||||
emits('ok', info.file.response.id)
|
||||
} else if (status === 'error') {
|
||||
message.error(`خطا در بارگذاری فایل`)
|
||||
} else if (status === 'removed') {
|
||||
emits('delete', info.file.uid)
|
||||
}
|
||||
}
|
||||
|
||||
//props
|
||||
interface Prop {
|
||||
url: string
|
||||
multiple?: boolean
|
||||
fileList?: Array<FileList>
|
||||
maxCount?: number
|
||||
headers?: any
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
|
||||
//emits
|
||||
const emits = defineEmits(['update:fileList', 'ok', 'delete'])
|
||||
|
||||
// const fileList = ref([])
|
||||
|
||||
const fileList = computed({
|
||||
get() {
|
||||
return props.fileList || ([] as Array<FileList>)
|
||||
},
|
||||
set(value) {
|
||||
emits('update:fileList', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface FileList {
|
||||
uid?: any | null | undefined
|
||||
name?: any | null | undefined
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<BasicSelect :items="budgetItems" valueName="value" keyName="id" />
|
||||
<!-- <div>1111</div>-->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import type { Const } from '@/model/const'
|
||||
const budgetItems = ref<Array<Const> | undefined>([])
|
||||
//define store
|
||||
const store = useStaticApiListsStore()
|
||||
onMounted(async () => {
|
||||
budgetItems.value = store.budgetListData ?? (await store.getBudgetConst())
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
||||
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div
|
||||
:style="{ color: props.textColor, backgroundColor: props.bgColor }"
|
||||
class="w-fit p-1 rounded-lg"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
//props
|
||||
interface Prop {
|
||||
textColor: string
|
||||
bgColor: string
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div
|
||||
class="w-[96px] h-[96px] overflow-hidden border border-solid border-blue-600 bg-gray-50 rounded-md p-2"
|
||||
>
|
||||
<AUpload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
list-type="picture-card"
|
||||
:showUploadList="true"
|
||||
:multiple="false"
|
||||
:action="uploadURL"
|
||||
:headers="fileHeader"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
@preview="handlePreview"
|
||||
>
|
||||
<div v-if="fileList.length === 0">
|
||||
<loading-outlined v-if="loading"></loading-outlined>
|
||||
<BaseIcon v-else icon="vuesax-linear:add" color="#6B7280" />
|
||||
<div class="text-gray-500 text-center text-xs font-normal">تصویر شاخص</div>
|
||||
</div>
|
||||
</AUpload>
|
||||
<AModal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel">
|
||||
<img alt="example" style="width: 100%" :src="previewImage" />
|
||||
</AModal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { LoadingOutlined } from '@ant-design/icons-vue'
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { uploadURL } from '@root/config'
|
||||
import { getToken } from '@/utils'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { prefixCls } = usePrefix('index-image-uploader')
|
||||
const previewVisible = ref(false)
|
||||
const previewImage = ref('')
|
||||
const previewTitle = ref('')
|
||||
|
||||
const loading = ref<boolean>(false)
|
||||
const fileHeader = {
|
||||
Authorization: `Bearer ${getToken()}`
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fileList?: Array<FileList>
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
|
||||
const emits = defineEmits(['update:fileList', 'ok', 'delete'])
|
||||
|
||||
const fileList = computed({
|
||||
get() {
|
||||
return props.fileList || ([] as Array<FileList>)
|
||||
},
|
||||
set(value) {
|
||||
emits('update:fileList', value)
|
||||
}
|
||||
})
|
||||
|
||||
const handlePreview = async (file: UploadProps['fileList'][number]) => {
|
||||
previewImage.value = file.src
|
||||
previewVisible.value = true
|
||||
previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
previewVisible.value = false
|
||||
previewTitle.value = ''
|
||||
}
|
||||
|
||||
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||
const isLt100k = file.size / 1024 / 1024 < 0.2
|
||||
if (!isLt100k) {
|
||||
message.error('حداکثر حجم بارگذاری 200 کیلو بایت میباشد')
|
||||
}
|
||||
return isLt100k
|
||||
}
|
||||
|
||||
function handleChange(info: UploadChangeParam) {
|
||||
if (info.file.status === 'uploading') {
|
||||
loading.value = true
|
||||
return
|
||||
}
|
||||
|
||||
if (info.file.status === 'error') {
|
||||
loading.value = false
|
||||
fileList.value = []
|
||||
message.error('خطا در بارگذاری')
|
||||
}
|
||||
|
||||
if (info.file.status === 'done') {
|
||||
loading.value = false
|
||||
message.success('تصویر شاخص با موفقیت بارگذاری شد')
|
||||
emits('ok', info.file.response.id)
|
||||
}
|
||||
if (info.file.status === 'removed') {
|
||||
emits('delete', info.file.uid)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-index-image-uploader';
|
||||
|
||||
.@{prefix} {
|
||||
.ant-upload-rtl.ant-upload.ant-upload-select-picture-card {
|
||||
margin: 0 !important;
|
||||
border: none;
|
||||
}
|
||||
.ant-upload {
|
||||
width: 78px !important;
|
||||
height: 78px !important;
|
||||
background-color: #eff6ff;
|
||||
border: dashed 1px #93c5fd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.ant-upload-list-picture-card-container {
|
||||
margin: 0;
|
||||
width: 78px !important;
|
||||
height: 78px !important;
|
||||
}
|
||||
.ant-upload-list-picture-card .ant-upload-list-item {
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
.ant-upload-list-picture-card .ant-upload-list-item-info {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div class="border border-solid border-blue-600 bg-gray-50 w-full rounded-md p-2">
|
||||
<div class="flex">
|
||||
<AUpload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
list-type="picture-card"
|
||||
:show-upload-list="false"
|
||||
:action="uploadURL"
|
||||
:headers="fileHeader"
|
||||
:showUploadList="true"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div>
|
||||
<BaseIcon icon="vuesax-linear:add" color="#6B7280" />
|
||||
<div class="text-gray-500 text-center text-xs font-normal">بارگذاری فایل</div>
|
||||
</div>
|
||||
</AUpload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue'
|
||||
import { uploadURL } from '@root/config'
|
||||
import { getToken } from '@/utils'
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const { prefixCls } = usePrefix('product-image-uploader')
|
||||
const loading = ref<boolean>(false)
|
||||
|
||||
const fileHeader = {
|
||||
Authorization: `Bearer ${getToken()}`
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fileList?: Array<FileList>
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
|
||||
const emits = defineEmits(['update:fileList', 'ok', 'delete'])
|
||||
|
||||
const fileList = computed({
|
||||
get() {
|
||||
return props.fileList || ([] as Array<FileList>)
|
||||
},
|
||||
set(value) {
|
||||
emits('update:fileList', value)
|
||||
}
|
||||
})
|
||||
|
||||
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||
const isLt100k = file.size / 1024 / 1024 < 0.24
|
||||
if (!isLt100k) {
|
||||
message.error('حداکثر حجم بارگذاری 240 کیلو بایت میباشد')
|
||||
}
|
||||
return isLt100k
|
||||
}
|
||||
|
||||
function handleChange(info: UploadChangeParam) {
|
||||
if (info.file.status === 'uploading') {
|
||||
loading.value = true
|
||||
return
|
||||
}
|
||||
|
||||
if (info.file.status === 'error') {
|
||||
loading.value = false
|
||||
message.error('خطا در بارگذاری')
|
||||
}
|
||||
|
||||
if (info.file.status === 'done') {
|
||||
loading.value = false
|
||||
message.success('تصویر با موفقیت بارگذاری شد')
|
||||
emits('ok', info.file.response.id)
|
||||
}
|
||||
if (info.file.status === 'removed') {
|
||||
emits('delete', info.file.uid)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-product-image-uploader';
|
||||
|
||||
.@{prefix} {
|
||||
width: 100%;
|
||||
|
||||
.ant-upload-rtl.ant-upload.ant-upload-select-picture-card {
|
||||
margin: 0 !important;
|
||||
border: none;
|
||||
}
|
||||
.ant-upload-picture-card-wrapper {
|
||||
width: fit-content;
|
||||
}
|
||||
.ant-upload {
|
||||
width: 78px !important;
|
||||
height: 78px !important;
|
||||
background-color: #eff6ff;
|
||||
border: dashed 1px #93c5fd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.ant-upload-list-picture-card-container {
|
||||
margin: 0;
|
||||
width: 78px !important;
|
||||
height: 78px !important;
|
||||
}
|
||||
.ant-upload-list-picture-card .ant-upload-list-item {
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
.ant-upload-list-picture-card .ant-upload-list-item-info {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.ant-upload-list {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<div class="w-[78px] h-[78px] flex rounded parent">
|
||||
<img class="w-[78px] h-[78px] rounded" :src="props.src" alt="test" />
|
||||
<div class="child">
|
||||
<div class="flex justify-center gap-2 !z-20">
|
||||
<Icon
|
||||
class="cursor-pointer"
|
||||
icon="vuesax-linear:trash"
|
||||
size="18"
|
||||
color="white"
|
||||
@click="emit('remove')"
|
||||
/>
|
||||
<Icon
|
||||
class="cursor-pointer"
|
||||
icon="vuesax-linear:eye"
|
||||
size="18"
|
||||
color="white"
|
||||
@click="() => setVisible(true)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AImage
|
||||
:src="props.src"
|
||||
style="display: none"
|
||||
:preview="{ visible, onVisibleChange: setVisible }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
|
||||
interface Props {
|
||||
src: string
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
const emit = defineEmits<{
|
||||
(e: 'remove'): void
|
||||
}>()
|
||||
|
||||
const { prefixCls } = usePrefix('upload-image')
|
||||
const visible = ref<boolean>(false)
|
||||
const setVisible = (value: boolean) => {
|
||||
visible.value = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-upload-image';
|
||||
.@{prefix} {
|
||||
.parent:hover {
|
||||
cursor: pointer;
|
||||
.child {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.child {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
position: absolute;
|
||||
width: 78px;
|
||||
height: 78px;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
transition: ease-in-out 1ms;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<!-- <BasicSelect :items="items" v-model:value="localValue" valueName="value" keyName="id" />-->
|
||||
<BasicSelect
|
||||
v-model:value="localValue"
|
||||
:items="items"
|
||||
valueName="title"
|
||||
keyName="title"
|
||||
class="w-[10rem]"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Const } from '@/model/const'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import type { Province } from '@/model/city'
|
||||
|
||||
const store = useStaticApiListsStore()
|
||||
|
||||
const items = ref<Array<Province>>()
|
||||
|
||||
const emits = defineEmits(['update:value', 'loading'])
|
||||
|
||||
interface Prop {
|
||||
value?: string | number
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
|
||||
onMounted(async () => {
|
||||
emits('loading', true)
|
||||
items.value = store.cityListData ?? (await store.getCityList())
|
||||
emits('loading', false)
|
||||
})
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.value
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emits('update:value', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<!-- <BasicSelect :items="items" v-model:value="localValue" valueName="value" keyName="id" />-->
|
||||
<BasicSelect
|
||||
v-model:value="localValue"
|
||||
:items="items"
|
||||
valueName="title"
|
||||
keyName="title"
|
||||
class="w-[10rem]"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Const } from '@/model/const'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import type { Province } from '@/model/city'
|
||||
|
||||
const store = useStaticApiListsStore()
|
||||
|
||||
const items = ref<Array<Province>>()
|
||||
|
||||
const emits = defineEmits(['update:value', 'loading'])
|
||||
|
||||
interface Prop {
|
||||
value?: string | number
|
||||
}
|
||||
|
||||
const props = defineProps<Prop>()
|
||||
|
||||
onMounted(async () => {
|
||||
emits('loading', true)
|
||||
items.value = store.provincesListData ?? (await store.getProvincesList())
|
||||
emits('loading', false)
|
||||
})
|
||||
|
||||
const localValue = computed({
|
||||
get() {
|
||||
return props.value
|
||||
},
|
||||
|
||||
set(value) {
|
||||
emits('update:value', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,22 @@
|
||||
# Admin-Vue3-Core
|
||||
|
||||
This is core admin vue 3 contains
|
||||
- basic components
|
||||
- composable
|
||||
- utils
|
||||
- base
|
||||
- config of project
|
||||
and ...
|
||||
## How use Core
|
||||
load component and other from /core/ folder and use (very easy)
|
||||
## How get update core
|
||||
```git
|
||||
git submodule update --remote --recursive
|
||||
```
|
||||
#### run top command in root of project
|
||||
|
||||
#### The above Link describe about git submodule
|
||||
|
||||
https://www.devroom.io/2020/03/09/the-git-submodule-cheat-sheet/
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
@import (less) "./var.less";
|
||||
|
||||
.ant-input-affix-wrapper,
|
||||
.ant-dropdown-menu,
|
||||
.ant-menu-submenu > .ant-menu,
|
||||
.ant-tag,
|
||||
.ant-card,
|
||||
.ant-btn,
|
||||
.ant-picker,
|
||||
.ant-picker-panel-container,
|
||||
.ant-modal-content
|
||||
{
|
||||
border-radius: var(--border-radius-base);
|
||||
}
|
||||
|
||||
.ant-modal-header{
|
||||
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0;
|
||||
}
|
||||
|
||||
.ant-modal-header{
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ant-modal-header{
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.ant-modal-footer{
|
||||
border-top:none;
|
||||
}
|
||||
|
||||
.ant-modal-close{
|
||||
left: 0 !important;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
.ant-modal-body{
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ant-drawer-header{
|
||||
padding: 12px;
|
||||
}
|
||||
.ant-drawer-body{
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-card-body{
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-pagination-prev .ant-pagination-item-link, .ant-pagination-next .ant-pagination-item-link,.ant-pagination-item{
|
||||
font-family: var(--font-family-base);
|
||||
border-radius: var(--border-radius-base) !important;
|
||||
}
|
||||
|
||||
.ant-input-group > .ant-input-rtl:first-child, .ant-input-group-rtl .ant-input-group-addon:first-child {
|
||||
border-radius: 0 var(--border-radius-base) var(--border-radius-base) 0;
|
||||
}
|
||||
|
||||
.ant-input-search > .ant-input-group > .ant-input-group-addon:last-child .ant-input-search-button {
|
||||
border-radius: var(--border-radius-base) 0 0 var(--border-radius-base);
|
||||
}
|
||||
|
||||
|
||||
.ant-drawer-header{
|
||||
@apply px-1 py-3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
@import (less) './var.less';
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum).woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Light.woff2") format("woff2");
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum)_UltraLight.woff2") format("woff2");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Medium.woff2") format("woff2");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Bold.woff2") format("woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/*@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("/fonts/iranYekan/woff/iranyekanwebextraboldfanum.woff") format("woff");
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}*/
|
||||
|
||||
@font-face {
|
||||
font-family: @prefixCls-font-family;
|
||||
src: url("../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Black.woff2") format("woff");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/*
|
||||
.font-iran-yekan{
|
||||
font-family: 'iran-yekan' !important;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
.font-100{
|
||||
//font-family:'iran-yekan-thin';
|
||||
font-weight:100 ;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//@import (css) 'ant-design-vue/lib/style/
|
||||
//@import '~ant-design-vue/dist/antd.dark.css';
|
||||
@import 'ant-design-vue/dist/antd.variable.css';
|
||||
@import (less) './scroll.less';
|
||||
@import (less) "./fonts.less";
|
||||
@import (less) './var.less';
|
||||
@import (less) './ant-override.less';
|
||||
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: @prefixCls-font-family !important;
|
||||
//background-color: @prefixCls-background-color !important;
|
||||
//color:#555 !important;
|
||||
}
|
||||
|
||||
/*pre{
|
||||
font-family: @prefixCls-font-family !important;
|
||||
}*/
|
||||
|
||||
.en-font {
|
||||
font-family: Arial !important;
|
||||
direction: rtl !important;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
//ok Code
|
||||
/*html {
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
}*/
|
||||
|
||||
.scroll-none{
|
||||
&::-webkit-scrollbar {
|
||||
width: 0; /* Remove scrollbar space */
|
||||
background: transparent; /* Optional: just make scrollbar invisible */
|
||||
}
|
||||
/* Optional: show position indicator in red */
|
||||
&::-webkit-scrollbar-thumb {
|
||||
//background: #FF0000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//scroll style
|
||||
|
||||
::-webkit-scrollbar {
|
||||
background-color: initial;
|
||||
//background-color: red;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0.4rem !important;
|
||||
height: 0.4rem !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
--tw-bg-opacity: 1 !important;
|
||||
background-color: rgb(203 213 225/var(--tw-bg-opacity))!important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 0.25rem !important;
|
||||
}
|
||||
|
||||
.scrollbar-track\:\!bg-slate-100::-webkit-scrollbar-track {
|
||||
--tw-bg-opacity: 1!important;
|
||||
background-color: rgb(241 245 249/var(--tw-bg-opacity))!important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 0.25rem!important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
.beauty-scroll{
|
||||
scrollbar-color: red green;
|
||||
scrollbar-width: thin;
|
||||
-ms-overflow-style:none;
|
||||
position: relative;
|
||||
&::-webkit-scrollbar{
|
||||
width: 3px;
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: burlywood;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 1px rgba(0,0,0,0);
|
||||
border-radius: 3px;
|
||||
background: aqua;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*&::-webkit-scrollbar{
|
||||
width: 3px;
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: burlywood;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 1px rgba(0,0,0,0);
|
||||
border-radius: 3px;
|
||||
background: aqua;
|
||||
}*/
|
||||
|
||||
/* custom scrollbar */
|
||||
/*::-webkit-scrollbar {
|
||||
width: 17px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #d6dee1;
|
||||
border-radius: 20px;
|
||||
border: 6px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #a8bbbf;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
//ok Code
|
||||
/*
|
||||
html {
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 0; !* Remove scrollbar space *!
|
||||
background: transparent; !* Optional: just make scrollbar invisible *!
|
||||
}
|
||||
!* Optional: show position indicator in red *!
|
||||
::-webkit-scrollbar-thumb {
|
||||
//background: #FF0000;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//ok code
|
||||
/*html {
|
||||
overflow: scroll;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
background: transparent; !* make scrollbar transparent *!
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
//old method
|
||||
//override ant less variable
|
||||
//https://github.com/vueComponent/ant-design-vue/blob/main/components/style/themes/default.less
|
||||
// The prefix to use on all css classes from ant.
|
||||
/*@prefixCls: 'adminV3';
|
||||
!* Theme Config *!
|
||||
@header-height:56px;
|
||||
@prefixCls-font-family: 'iran-sans';
|
||||
@ant-prefix: @prefixCls;
|
||||
@primary-color:#0052d9; // #727071; //#abc2f7; //#f4474d;
|
||||
@border-radius-base: 4px;
|
||||
|
||||
html{
|
||||
--ant-primary-color:@primary-color;
|
||||
--ant-primary-1:#f2f3ff;//#f6f6f4;
|
||||
--border-radius-base:@border-radius-base;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
//todo change var
|
||||
//new method
|
||||
|
||||
@prefixCls: 'hr-tamin';
|
||||
/* Theme Config */
|
||||
@header-height:56px;
|
||||
@prefixCls-font-family: 'iran-sans';
|
||||
@ant-prefix: @prefixCls;
|
||||
@primary-color:#2563eb; // #727071; //#abc2f7; //#f4474d;
|
||||
@second-color: #3b82f6; // #727071; //#abc2f7; //#f4474d;
|
||||
@third-color: #B2B2B2; // #727071; //#abc2f7; //#f4474d;
|
||||
|
||||
@bg-color-1: #F9FAFB;
|
||||
@bg-color-2: #F6F6F4;
|
||||
@border-color-1: #B2B2B2;
|
||||
|
||||
@border-radius-base: 4px;
|
||||
|
||||
html{
|
||||
--ant-primary-color:@primary-color;
|
||||
--ant-primary-color-hover:@second-color;
|
||||
--ant-primary-color-active:@third-color;
|
||||
--ant-primary-1:#f2f3ff;//#f6f6f4;
|
||||
--border-radius-base:@border-radius-base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ant-prefix: @prefixCls;
|
||||
@border-radius-base: 8px; // major border radius
|
||||
@primary-color:#2b55e2; //#abc2f7; //#f4474d;
|
||||
// Border color
|
||||
@border-color-base: @gray-100; // base border outline a component
|
||||
// Form
|
||||
@form-item-label-font-size: 14px;
|
||||
//variables
|
||||
@prefixCls-font-family: 'iran-sans';
|
||||
@prefixCls-background-color: #fff;
|
||||
@gray-50: #f6f7f9;
|
||||
@gray-100: #e8eaee;
|
||||
@gray-900: #656f87;
|
||||
@prefixCls-secondary:#abc2f7; // #0072e9;
|
||||
@prefixCls-primary-rgba: #fce6e6;
|
||||
@prefixCls-secondary-rgb: #0072E914;
|
||||
@prefixCls-tertiary: #feb701;
|
||||
@prefixCls-tertiary-rgba: #fec94114;
|
||||
@prefixCls-green: #0f7f36;
|
||||
@prefixCls-green-rgba: #ecf5ef;
|
||||
@prefixCls-red: #f4474d;
|
||||
@prefixCls-red-rgba: #fce6e6;*/
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |