feat: sale_quotation
This commit is contained in:
parent
59e3d00a00
commit
8a4e1791b7
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712886588712" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4546" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M945.493333 839.543467l70.0416 77.141333a13.653333 13.653333 0 0 1 0 18.295467l-70.0416 77.141333a10.376533 10.376533 0 0 1-12.424533 3.003733 13.653333 13.653333 0 0 1-7.645867-12.151466v-154.282667a13.653333 13.653333 0 0 1 7.645867-12.151467 10.376533 10.376533 0 0 1 12.424533 3.003734z m0 0" fill="#0b988f" p-id="4547"></path><path d="M914.773333 133.9392H539.170133V35.498667a26.487467 26.487467 0 0 0-35.2256-27.306667L27.306667 134.485333a30.856533 30.856533 0 0 0-18.158934 30.037334v619.3152A30.856533 30.856533 0 0 0 27.306667 813.8752l477.047466 125.610667a26.487467 26.487467 0 0 0 35.2256-27.306667v-91.7504H914.773333a19.797333 19.797333 0 0 0 19.797334-19.797333V153.736533A19.797333 19.797333 0 0 0 914.773333 133.9392zM400.5888 616.311467l-57.070933 2.730666-69.632-102.673066L204.8 619.042133l-57.070933-2.730666L245.76 474.7264l-98.440533-145.408 55.296 2.594133 71.2704 102.4 71.2704-102.4 55.296-2.594133-98.440534 145.408zM641.706667 709.973333a10.376533 10.376533 0 0 1-10.376534 10.376534h-79.189333a10.376533 10.376533 0 0 1-10.376533-10.376534v-63.351466a10.24 10.24 0 0 1 10.376533-10.24h78.6432a10.376533 10.376533 0 0 1 10.376533 10.24z m0-136.533333a10.376533 10.376533 0 0 1-10.376534 10.376533h-79.189333a10.376533 10.376533 0 0 1-10.376533-10.376533v-62.122667a10.24 10.24 0 0 1 10.376533-10.24h78.6432a10.376533 10.376533 0 0 1 10.376533 10.24z m0-135.304533a10.376533 10.376533 0 0 1-10.376534 10.376533h-79.189333a10.376533 10.376533 0 0 1-10.376533-10.376533v-62.122667a10.24 10.24 0 0 1 10.376533-10.24h78.6432a10.376533 10.376533 0 0 1 10.376533 10.24z m0-135.304534a10.376533 10.376533 0 0 1-10.376534 10.376534h-79.189333a10.376533 10.376533 0 0 1-10.376533-10.376534v-62.122666a10.24 10.24 0 0 1 10.376533-10.24h78.6432a10.376533 10.376533 0 0 1 10.376533 10.24zM826.9824 709.973333a10.376533 10.376533 0 0 1-10.376533 10.376534h-103.082667a10.376533 10.376533 0 0 1-10.376533-10.376534v-63.351466a10.24 10.24 0 0 1 10.376533-10.24h103.2192a10.24 10.24 0 0 1 10.376533 10.24z m0-135.304533a10.376533 10.376533 0 0 1-10.376533 10.376533h-103.082667a10.376533 10.376533 0 0 1-10.376533-11.605333v-62.122667a10.24 10.24 0 0 1 10.376533-10.24h103.2192a10.24 10.24 0 0 1 10.376533 10.24z m0-135.304533a10.376533 10.376533 0 0 1-10.376533 10.376533h-103.082667a10.376533 10.376533 0 0 1-10.376533-10.376533v-63.351467a10.24 10.24 0 0 1 10.376533-10.24h103.2192a10.24 10.24 0 0 1 10.376533 10.24z m0-135.304534a10.376533 10.376533 0 0 1-10.376533 10.376534h-103.082667a10.376533 10.376533 0 0 1-10.376533-10.376534v-63.351466a10.24 10.24 0 0 1 10.376533-10.24h103.2192a10.24 10.24 0 0 1 10.376533 10.24z" fill="#0b988f" p-id="4548"></path><path d="M716.3904 883.5072l226.235733 0 0 80.554667-226.235733 0 0-80.554667Z" fill="#0b988f" p-id="4549"></path></svg>
|
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712818988776" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="38399" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M512 0c282.763636 0 512 229.236364 512 512s-229.236364 512-512 512S0 794.763636 0 512 229.236364 0 512 0zM426.077091 227.84c-20.293818 16.290909-40.634182 40.680727-52.829091 81.361455L352.907636 390.516364H234.961455a8.750545 8.750545 0 0 0-8.09891 8.145454v65.070546c0 4.049455 4.049455 8.098909 8.09891 8.098909h97.605818l-60.974546 243.991272c-12.194909 48.779636-44.730182 40.680727-44.730182 40.680728H186.181818V837.818182h40.680727c32.535273 0 65.024-4.049455 81.31491-24.389818 20.340364-20.340364 32.535273-56.925091 40.634181-97.605819l61.021091-243.991272h93.556364a8.750545 8.750545 0 0 0 8.098909-8.098909V398.661818a8.750545 8.750545 0 0 0-8.145455-8.145454H430.173091l20.340364-77.265455c4.049455-12.194909 24.389818-32.535273 36.584727-40.680727 44.683636-32.488727 105.704727-12.194909 146.385454-4.049455V199.400727c-40.680727-8.145455-130.141091-36.584727-207.406545 28.439273z m222.533818 162.676364h-105.704727a8.750545 8.750545 0 0 0-8.145455 8.145454v65.070546c0 4.049455 4.049455 8.098909 8.145455 8.098909h65.070545c4.049455 0 8.098909 4.096 12.194909 8.145454l24.389819 52.875637v12.194909l-73.216 85.364363c-4.049455 0-8.098909 4.096-12.19491 4.096H502.225455a8.750545 8.750545 0 0 0-8.145455 8.098909v65.070546c0 4.096 4.096 8.145455 8.145455 8.145454h65.070545c4.049455 0 12.194909-4.049455 12.194909-8.145454l93.556364-105.704727c4.049455-4.049455 8.098909-4.049455 8.098909 0l52.875636 105.704727c0 4.096 8.098909 8.145455 12.194909 8.145454h65.070546a8.750545 8.750545 0 0 0 8.098909-8.145454v-65.070546a8.750545 8.750545 0 0 0-8.098909-8.098909h-24.389818c-4.096 0-8.145455-4.096-12.241455-8.145454l-40.634182-81.314909v-12.194909l48.779637-52.875637c4.096-4.049455 8.145455-8.145455 12.194909-8.145454h56.925091a8.750545 8.750545 0 0 0 8.145454-8.098909V398.661818a8.750545 8.750545 0 0 0-8.145454-8.145454h-65.024c-4.096 0-12.241455 4.049455-12.241455 8.145454l-69.12 73.169455c-4.049455 4.096-8.098909 4.096-8.098909 0l-36.631273-73.169455c-4.049455-4.096-8.098909-8.145455-12.194909-8.145454z" fill="#d4237a" p-id="38400"></path></svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712818660922" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10922" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M512 872.838095c-24.380952 0-46.32381-4.87619-68.266667-17.066666l-365.714285-190.171429-51.2 26.819048c-34.133333 17.066667-34.133333 68.266667 0 85.333333l451.047619 236.495238c9.752381 4.87619 21.942857 7.314286 34.133333 7.314286s24.380952-2.438095 34.133333-7.314286l451.047619-236.495238c34.133333-17.066667 34.133333-68.266667 0-85.333333l-51.2-26.819048-365.714285 190.171429c-21.942857 12.190476-43.885714 17.066667-68.266667 17.066666z" fill="#8F65FF" p-id="10923"></path><path d="M997.180952 468.114286l-51.2-26.819048-134.095238 70.704762-80.457143 41.447619-151.161904 80.457143c-21.942857 9.752381-43.885714 17.066667-68.266667 17.066667s-46.32381-4.87619-68.266667-17.066667L292.571429 553.447619 212.114286 512l-134.095238-70.704762-51.2 26.819048c-34.133333 17.066667-34.133333 68.266667 0 85.333333l51.2 26.819048 78.019047 41.447619 319.390476 168.228571c9.752381 4.87619 21.942857 7.314286 34.133334 7.314286s24.380952-2.438095 34.133333-7.314286l319.390476-168.228571 78.019048-41.447619 51.2-26.819048c39.009524-17.066667 39.009524-65.828571 4.87619-85.333333z" fill="#C7B2FF" p-id="10924"></path><path d="M512 799.695238c-12.190476 0-24.380952-2.438095-34.133333-7.314286L158.47619 624.152381l-78.019047 41.447619 365.714286 190.171429c21.942857 9.752381 43.885714 17.066667 68.266666 17.066666s46.32381-4.87619 68.266667-17.066666l365.714286-190.171429-78.019048-41.447619-319.390476 168.228571c-14.628571 4.87619-26.819048 7.314286-39.009524 7.314286z" fill="#FFFFFF" p-id="10925"></path><path d="M997.180952 246.247619L546.133333 9.752381c-4.87619-2.438095-9.752381-4.87619-17.066666-7.314286-4.87619-2.438095-12.190476-2.438095-17.066667-2.438095s-12.190476 0-17.066667 2.438095-12.190476 2.438095-17.066666 7.314286L26.819048 246.247619c-34.133333 17.066667-34.133333 68.266667 0 85.333333l51.2 26.819048 78.019047 41.447619 134.095238 70.704762 78.019048 41.447619 107.27619 56.07619c9.752381 4.87619 21.942857 7.314286 34.133334 7.314286s24.380952-2.438095 34.133333-7.314286l107.276191-56.07619 78.019047-41.447619 134.095238-70.704762 78.019048-41.447619 51.2-26.819048c39.009524-17.066667 39.009524-68.266667 4.87619-85.333333z" fill="#8F65FF" p-id="10926"></path><path d="M529.066667 4.87619c-12.190476-2.438095-24.380952-2.438095-34.133334 0 4.87619-2.438095 12.190476-2.438095 17.066667-2.438095 4.87619 0 12.190476 0 17.066667 2.438095z" fill="#FFFFFF" p-id="10927"></path></svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1712818467557" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5527" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M952.32 122.88v573.44H579.584c-26.624-22.528-63.488-30.72-98.304-22.528l-55.296 12.288c-16.384-36.864-53.248-59.392-94.208-53.248l-98.304 14.336V122.88h718.848z" fill="#4DA9FF" p-id="5528"></path><path d="M968.704 81.92h-757.76c-10.24 0-20.48 10.24-20.48 20.48v552.96c-20.48 6.144-40.96 14.336-59.392 26.624l-77.824 47.104c-18.432 10.24-24.576 32.768-14.336 53.248L122.88 921.6c6.144 12.288 20.48 20.48 34.816 20.48h104.448c40.96 0 81.92-12.288 118.784-32.768l210.944-126.976c16.384-10.24 22.528-28.672 18.432-45.056h358.4c10.24 0 20.48-10.24 20.48-20.48V102.4c0-10.24-8.192-20.48-20.48-20.48zM360.448 872.448c-28.672 18.432-63.488 26.624-96.256 26.624H159.744l-81.92-137.216L153.6 716.8c12.288-8.192 24.576-14.336 38.912-18.432s26.624-8.192 40.96-10.24h4.096l102.4-14.336c20.48-2.048 38.912 8.192 49.152 24.576 0 0 0 2.048 2.048 2.048L272.384 737.28l-30.72 10.24c-10.24 4.096-16.384 16.384-12.288 26.624 4.096 8.192 10.24 14.336 20.48 14.336 2.048 0 4.096 0 6.144-2.048l145.408-49.152 20.48-6.144c2.048 0 4.096-2.048 6.144-2.048l63.488-14.336c26.624-6.144 55.296 4.096 73.728 24.576 2.048 2.048 4.096 6.144 6.144 10.24l-210.944 122.88zM948.224 696.32h-368.64c-26.624-22.528-63.488-30.72-98.304-22.528l-55.296 12.288c-16.384-36.864-53.248-59.392-94.208-53.248l-98.304 14.336V122.88h716.8l-2.048 573.44z" fill="#1C2754" p-id="5529"></path><path d="M354.304 184.32h471.04c12.288 0 20.48 8.192 20.48 20.48v61.44c0 12.288-8.192 20.48-20.48 20.48h-471.04c-12.288 0-20.48-8.192-20.48-20.48v-61.44c0-10.24 10.24-20.48 20.48-20.48z" fill="#334489" p-id="5530"></path><path d="M354.304 368.64h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM559.104 368.64h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM354.304 471.04h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM559.104 471.04h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM354.304 573.44h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM559.104 573.44h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM763.904 368.64h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM763.904 471.04h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48zM763.904 573.44h61.44c12.288 0 20.48 8.192 20.48 20.48s-8.192 20.48-20.48 20.48h-61.44c-12.288 0-20.48-8.192-20.48-20.48 0-10.24 10.24-20.48 20.48-20.48z" fill="#DBECFF" p-id="5531"></path><path d="M573.44 751.616l-215.04 122.88c-28.672 18.432-63.488 26.624-96.256 26.624H157.696l-81.92-137.216L153.6 716.8c12.288-8.192 24.576-14.336 38.912-18.432s26.624-8.192 40.96-10.24h4.096l102.4-14.336c20.48-2.048 43.008 8.192 51.2 26.624L272.384 737.28l-30.72 10.24c-10.24 4.096-16.384 16.384-12.288 26.624 4.096 8.192 10.24 14.336 20.48 14.336 2.048 0 4.096 0 6.144-2.048l145.408-49.152 20.48-6.144c2.048 0 4.096-2.048 6.144-2.048l63.488-14.336c26.624-6.144 55.296 4.096 73.728 24.576 0 2.048 8.192 8.192 8.192 12.288z" fill="#FFD2BF" p-id="5532"></path></svg>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -15,6 +15,33 @@ class Api {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 删除报价模板列表
|
||||||
|
static Future<Response<PaginationData>> deleteSaleQuotationTemplate(int id) {
|
||||||
|
return DioService.dio
|
||||||
|
.delete<PaginationData>('${Urls.saleQuotationTemplate}/$id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取报价模板列表
|
||||||
|
static Future<Response<PaginationData>> getSaleQuotationTemplate(
|
||||||
|
{Map? params}) {
|
||||||
|
return DioService.dio.get<PaginationData>(Urls.saleQuotationTemplate,
|
||||||
|
queryParameters: {'page': 1, 'pageSize': 99, ...(params ?? {})});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取报价配件列表
|
||||||
|
static Future<Response<PaginationData>> getSaleQuotationComponents(
|
||||||
|
{Map? params}) {
|
||||||
|
return DioService.dio.get<PaginationData>(Urls.saleQuotationComponent,
|
||||||
|
queryParameters: {'page': 1, 'pageSize': 99, ...(params ?? {})});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取报价分组列表
|
||||||
|
static Future<Response<PaginationData>> getSaleQuotationGroups(
|
||||||
|
{Map? params}) {
|
||||||
|
return DioService.dio.get<PaginationData>(Urls.saleQuotationGroup,
|
||||||
|
queryParameters: {'page': 1, 'pageSize': 99, ...(params ?? {})});
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取权限资源
|
/// 获取权限资源
|
||||||
static Future<Response> getResources() {
|
static Future<Response> getResources() {
|
||||||
return DioService.dio.get(Urls.accountResources);
|
return DioService.dio.get(Urls.accountResources);
|
||||||
|
@ -61,48 +88,59 @@ class Api {
|
||||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页获取产品列表
|
/// 分页获取产品列表
|
||||||
static Future<Response<PaginationData>> getProducts(Map params) {
|
static Future<Response<PaginationData>> getProducts(Map params) {
|
||||||
return DioService.dio.get<PaginationData>(Urls.products,
|
return DioService.dio.get<PaginationData>(Urls.products,
|
||||||
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
queryParameters: {'page': 1, 'pageSize': 10, ...params});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页获取原材料出入库列表
|
/// 分页获取原材料出入库列表
|
||||||
static Future<Response<PaginationData>> getInventoryInout(Map params) {
|
static Future<Response<PaginationData>> getInventoryInout(Map params) {
|
||||||
return DioService.dio.get<PaginationData>(Urls.inventoryInout,
|
return DioService.dio.get<PaginationData>(Urls.inventoryInout,
|
||||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取原材料出入库详情
|
/// 获取原材料出入库详情
|
||||||
static Future<Response> getInventoryInOutInfo(int id) {
|
static Future<Response> getInventoryInOutInfo(int id) {
|
||||||
return DioService.dio.get(
|
return DioService.dio.get(
|
||||||
'${Urls.inventoryInout}/$id',
|
'${Urls.inventoryInout}/$id',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建出入库记录
|
/// 创建出入库记录
|
||||||
static Future<Response> createInventoryInout(Map params) {
|
static Future<Response> createInventoryInout(Map params) {
|
||||||
return DioService.dio.post(Urls.inventoryInout, data: params);
|
return DioService.dio.post(Urls.inventoryInout, data: params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新出入库记录
|
/// 创建报价计算模板
|
||||||
|
static Future<Response> createSaleQuotationTemplate(Map params) {
|
||||||
|
return DioService.dio.post(Urls.saleQuotationTemplate, data: params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新报价计算模板
|
||||||
|
static Future<Response> updateSaleQuotationTemplate(int id, Map params) {
|
||||||
|
return DioService.dio
|
||||||
|
.put('${Urls.saleQuotationTemplate}/$id', data: params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新出入库记录
|
||||||
static Future<Response> updateInventoryInout(int id, Map params) {
|
static Future<Response> updateInventoryInout(int id, Map params) {
|
||||||
return DioService.dio.put('${Urls.inventoryInout}/$id', data: params);
|
return DioService.dio.put('${Urls.inventoryInout}/$id', data: params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页获取库存列表
|
/// 分页获取库存列表
|
||||||
static Future<Response<PaginationData>> getInventory(Map params) {
|
static Future<Response<PaginationData>> getInventory(Map params) {
|
||||||
return DioService.dio.get<PaginationData>(Urls.inventory,
|
return DioService.dio.get<PaginationData>(Urls.inventory,
|
||||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页获取用户
|
/// 分页获取用户
|
||||||
static Future<Response<PaginationData>> getUsers(Map params) {
|
static Future<Response<PaginationData>> getUsers(Map params) {
|
||||||
return DioService.dio.get<PaginationData>(Urls.sysUser,
|
return DioService.dio.get<PaginationData>(Urls.sysUser,
|
||||||
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
queryParameters: {'page': 1, 'pageSize': 10, ...(params)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一次性获取所有的字典类型(不分页)
|
/// 一次性获取所有的字典类型(不分页)
|
||||||
static Future<Response> getDictTypeAll(Map params) {
|
static Future<Response> getDictTypeAll(Map params) {
|
||||||
return DioService.dio.post(Urls.getDictType, data: params);
|
return DioService.dio.post(Urls.getDictType, data: params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
class AppTheme {
|
class AppTheme {
|
||||||
AppTheme._();
|
AppTheme._();
|
||||||
static const Color primaryColor = Color(0xFFC89607);
|
static const Color primaryColor = Color(0xFFC89607);
|
||||||
|
static const Color onPrimaryColor = Color(0xFFFEFEFE);
|
||||||
static const Color primaryColorLight = Color.fromARGB(255, 255, 206, 70);
|
static const Color primaryColorLight = Color.fromARGB(255, 255, 206, 70);
|
||||||
static const Color primaryColorDark = Color.fromARGB(255, 163, 120, 0);
|
static const Color primaryColorDark = Color.fromARGB(255, 163, 120, 0);
|
||||||
static const Color primaryTextColorWithBg = Color(0x00000000);
|
static const Color primaryTextColorWithBg = Color(0x00000000);
|
||||||
|
@ -27,7 +28,7 @@ class AppTheme {
|
||||||
static const Color dividerColor = Color.fromARGB(255, 224, 224, 224);
|
static const Color dividerColor = Color.fromARGB(255, 224, 224, 224);
|
||||||
static const Color appbarBgColor = AppTheme.primaryColor;
|
static const Color appbarBgColor = AppTheme.primaryColor;
|
||||||
static const Color scaffoldBackgroundColor = Color(0XFFe9f0fd);
|
static const Color scaffoldBackgroundColor = Color(0XFFe9f0fd);
|
||||||
static const Color inputFillColor = Color(0xfffefefe);
|
static const Color inputFillColor = Color(0xFFf5f8ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
final theme = ThemeData(
|
final theme = ThemeData(
|
||||||
|
@ -63,7 +64,7 @@ final theme = ThemeData(
|
||||||
),
|
),
|
||||||
dialogBackgroundColor: AppTheme.nearlyWhite,
|
dialogBackgroundColor: AppTheme.nearlyWhite,
|
||||||
colorScheme: ColorScheme.fromSeed(
|
colorScheme: ColorScheme.fromSeed(
|
||||||
onPrimary: AppTheme.nearlyWhite,
|
onPrimary: AppTheme.onPrimaryColor,
|
||||||
seedColor: AppTheme.primaryColor,
|
seedColor: AppTheme.primaryColor,
|
||||||
primary: AppTheme.primaryColor),
|
primary: AppTheme.primaryColor),
|
||||||
datePickerTheme: DatePickerThemeData(
|
datePickerTheme: DatePickerThemeData(
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
// Global config
|
// Global config
|
||||||
class GloablConfig {
|
class GloablConfig {
|
||||||
static const BASE_URL = "http://10.0.2.2:8001/api/";
|
// static const BASE_URL = "http://10.0.2.2:8001/api/";
|
||||||
static const OSS_URL = "http://10.0.2.2:8001";
|
// static const OSS_URL = "http://10.0.2.2:8001";
|
||||||
|
|
||||||
// static const BASE_URL = "http://144.123.43.138:3001/api/";
|
static const BASE_URL = "http://144.123.43.138:3001/api/";
|
||||||
// static const OSS_URL = "http://144.123.43.138:3001";
|
static const OSS_URL = "http://144.123.43.138:3001";
|
||||||
// static const BASE_URL = "http://192.168.60.220:8001/api/";
|
// static const BASE_URL = "http://192.168.60.220:8001/api/";
|
||||||
// static const OSS_URL = "http://192.168.60.220:8001";
|
// static const OSS_URL = "http://192.168.60.220:8001";
|
||||||
static const DOMAIN_NAME = "山矿通";
|
static const DOMAIN_NAME = "山矿通";
|
||||||
|
|
|
@ -17,4 +17,9 @@ class Urls {
|
||||||
static String accountResources = 'account/menus';
|
static String accountResources = 'account/menus';
|
||||||
static String depts = 'system/depts';
|
static String depts = 'system/depts';
|
||||||
static String roles = 'system/roles';
|
static String roles = 'system/roles';
|
||||||
|
static String saleQuotationGroup = 'sale_quotation/sale_quotation_group';
|
||||||
|
static String saleQuotationComponent =
|
||||||
|
'sale_quotation/sale_quotation_component';
|
||||||
|
static String saleQuotationTemplate =
|
||||||
|
'sale_quotation/sale_quotation_template';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,38 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
||||||
|
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
|
||||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||||
import 'package:sk_base_mobile/models/base_search_more.model.dart';
|
import 'package:sk_base_mobile/models/base_search_more.model.dart';
|
||||||
|
|
||||||
mixin BaseSearchMoreController<T extends BaseSearchMoreModel> {
|
class BaseSearchMoreController<T extends BaseSearchMoreModel>
|
||||||
|
extends GetxController {
|
||||||
RxList<T> list = RxList([]);
|
RxList<T> list = RxList([]);
|
||||||
RxString searchKey = ''.obs;
|
RxString searchKey = ''.obs;
|
||||||
final searchBarTextConroller = TextEditingController();
|
final searchBarTextConroller = TextEditingController();
|
||||||
RefreshController refreshController = RefreshController(initialRefresh: true);
|
RefreshController refreshController =
|
||||||
|
RefreshController(initialRefresh: false);
|
||||||
int page = 1;
|
int page = 1;
|
||||||
int limit = 15;
|
int limit = 15;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
RxList<int> selectedIndex = RxList([]);
|
RxList<int> selectedIndex = RxList([]);
|
||||||
|
final loading = false.obs;
|
||||||
getData({bool isRefresh = false}) {}
|
getData({bool isRefresh = false}) {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
onReady() {
|
||||||
|
super.onReady();
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
|
||||||
|
initData() async {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
await getData(isRefresh: true);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> onRefresh() async {
|
Future<void> onRefresh() async {
|
||||||
await getData(isRefresh: true).then((_) {
|
await getData(isRefresh: true).then((_) {
|
||||||
refreshController.refreshCompleted(resetFooterState: true);
|
refreshController.refreshCompleted(resetFooterState: true);
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
class SaleQuotationComponentModel {
|
||||||
|
SaleQuotationComponentModel({
|
||||||
|
required this.id,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
required this.name,
|
||||||
|
required this.componentSpecification,
|
||||||
|
required this.unitId,
|
||||||
|
required this.unitPrice,
|
||||||
|
required this.remark,
|
||||||
|
required this.isDelete,
|
||||||
|
required this.unit,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int? id;
|
||||||
|
final DateTime? createdAt;
|
||||||
|
final DateTime? updatedAt;
|
||||||
|
final String? name;
|
||||||
|
final String? componentSpecification;
|
||||||
|
final int? unitId;
|
||||||
|
final double? unitPrice;
|
||||||
|
final String? remark;
|
||||||
|
final int? isDelete;
|
||||||
|
final Unit? unit;
|
||||||
|
|
||||||
|
factory SaleQuotationComponentModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return SaleQuotationComponentModel(
|
||||||
|
id: json["id"],
|
||||||
|
createdAt: DateTime.tryParse(json["createdAt"] ?? ""),
|
||||||
|
updatedAt: DateTime.tryParse(json["updatedAt"] ?? ""),
|
||||||
|
name: json["name"],
|
||||||
|
componentSpecification: json["componentSpecification"],
|
||||||
|
unitId: json["unitId"],
|
||||||
|
unitPrice: double.parse(json["unitPrice"]),
|
||||||
|
remark: json["remark"],
|
||||||
|
isDelete: json["isDelete"],
|
||||||
|
unit: json["unit"] == null ? null : Unit.fromJson(json["unit"]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"id": id,
|
||||||
|
"createdAt": createdAt?.toIso8601String(),
|
||||||
|
"updatedAt": updatedAt?.toIso8601String(),
|
||||||
|
"name": name,
|
||||||
|
"componentSpecification": componentSpecification,
|
||||||
|
"unitId": unitId,
|
||||||
|
"unitPrice": unitPrice,
|
||||||
|
"remark": remark,
|
||||||
|
"isDelete": isDelete,
|
||||||
|
"unit": unit?.toJson(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Unit {
|
||||||
|
Unit({
|
||||||
|
required this.id,
|
||||||
|
required this.label,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int? id;
|
||||||
|
final String? label;
|
||||||
|
|
||||||
|
factory Unit.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Unit(
|
||||||
|
id: json["id"],
|
||||||
|
label: json["label"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"id": id,
|
||||||
|
"label": label,
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
class SaleQuotationGroupModel {
|
||||||
|
SaleQuotationGroupModel({
|
||||||
|
required this.id,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
required this.name,
|
||||||
|
required this.isDelete,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int? id;
|
||||||
|
final DateTime? createdAt;
|
||||||
|
final DateTime? updatedAt;
|
||||||
|
final String? name;
|
||||||
|
final int? isDelete;
|
||||||
|
|
||||||
|
factory SaleQuotationGroupModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return SaleQuotationGroupModel(
|
||||||
|
id: json["id"],
|
||||||
|
createdAt: DateTime.tryParse(json["createdAt"] ?? ""),
|
||||||
|
updatedAt: DateTime.tryParse(json["updatedAt"] ?? ""),
|
||||||
|
name: json["name"],
|
||||||
|
isDelete: json["isDelete"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"id": id,
|
||||||
|
"createdAt": createdAt?.toIso8601String(),
|
||||||
|
"updatedAt": updatedAt?.toIso8601String(),
|
||||||
|
"name": name,
|
||||||
|
"isDelete": isDelete,
|
||||||
|
};
|
||||||
|
}
|
|
@ -26,9 +26,9 @@ class SaleQuotationItemModel extends BaseSearchMoreModel {
|
||||||
final String? unit;
|
final String? unit;
|
||||||
final String? remark;
|
final String? remark;
|
||||||
// 成本
|
// 成本
|
||||||
int cost;
|
num cost;
|
||||||
int quantity;
|
int quantity;
|
||||||
int amount;
|
num amount;
|
||||||
|
|
||||||
SaleQuotationItemModel(
|
SaleQuotationItemModel(
|
||||||
{required this.name,
|
{required this.name,
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
||||||
|
|
||||||
|
class SaleQuotationTemplateModel {
|
||||||
|
SaleQuotationTemplateModel({
|
||||||
|
this.id,
|
||||||
|
this.name,
|
||||||
|
required this.template,
|
||||||
|
this.isDelete,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int? id;
|
||||||
|
final String? name;
|
||||||
|
final Template template;
|
||||||
|
final int? isDelete;
|
||||||
|
|
||||||
|
factory SaleQuotationTemplateModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return SaleQuotationTemplateModel(
|
||||||
|
id: json["id"],
|
||||||
|
name: json["name"],
|
||||||
|
template: Template.fromJson(json["template"]),
|
||||||
|
isDelete: json["isDelete"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"template": template.toJson(),
|
||||||
|
"isDelete": isDelete,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Template {
|
||||||
|
Template({
|
||||||
|
required this.data,
|
||||||
|
required this.formula,
|
||||||
|
required this.totalCost,
|
||||||
|
required this.totalPrice,
|
||||||
|
});
|
||||||
|
|
||||||
|
List<SaleQuotationModel> data;
|
||||||
|
String formula;
|
||||||
|
num? totalCost;
|
||||||
|
num? totalPrice;
|
||||||
|
|
||||||
|
factory Template.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Template(
|
||||||
|
data: json["data"] == null
|
||||||
|
? []
|
||||||
|
: List<SaleQuotationModel>.from(
|
||||||
|
json["data"]!.map((x) => SaleQuotationModel.fromJson(x))),
|
||||||
|
formula: json["formula"],
|
||||||
|
totalCost: json["totalCost"],
|
||||||
|
totalPrice: json["totalPrice"],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"data": data.map((x) => x.toJson()).toList(),
|
||||||
|
"formula": formula,
|
||||||
|
"totalCost": totalCost,
|
||||||
|
"totalPrice": totalPrice,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
class WorkBenchModel {
|
class WorkBenchModel {
|
||||||
final String title;
|
final String title;
|
||||||
final String icon;
|
final String icon;
|
||||||
final String route;
|
final String? route;
|
||||||
|
final VoidCallback? onTap;
|
||||||
WorkBenchModel(
|
WorkBenchModel(
|
||||||
{required this.title, required this.route, required this.icon});
|
{required this.title, required this.icon, this.route, this.onTap});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:sk_base_mobile/constants/constants.dart';
|
||||||
import 'package:sk_base_mobile/store/resource.store.dart';
|
import 'package:sk_base_mobile/store/resource.store.dart';
|
||||||
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
||||||
|
|
||||||
class RouterUtil {
|
class RouterUtil {
|
||||||
|
static List<String> hasPermissionRoute = [
|
||||||
|
RouteConfig.hrManage,
|
||||||
|
RouteConfig.inventory,
|
||||||
|
RouteConfig.saleQuotation,
|
||||||
|
];
|
||||||
static Future<T?> toNamed<T>(String routeName, {arguments}) async {
|
static Future<T?> toNamed<T>(String routeName, {arguments}) async {
|
||||||
//关闭键盘
|
//关闭键盘
|
||||||
if (Get.context != null) {
|
if (Get.context != null) {
|
||||||
|
@ -12,12 +18,21 @@ class RouterUtil {
|
||||||
bool isExsited = ResourceService.to.resources
|
bool isExsited = ResourceService.to.resources
|
||||||
.firstWhereOrNull((element) => element.path == routeName) !=
|
.firstWhereOrNull((element) => element.path == routeName) !=
|
||||||
null;
|
null;
|
||||||
|
bool hasPermission = isExsited || !hasPermissionRoute.contains(routeName);
|
||||||
if (!isExsited) {
|
if (!hasPermission) {
|
||||||
SnackBarUtil().info('您没有权限,请联系管理员分配权限,后期将隐藏无权限的菜单');
|
SnackBarUtil().info('您没有权限,请联系管理员分配权限,后期将隐藏无权限的菜单');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await Get.toNamed<T?>(routeName, arguments: arguments);
|
return Get.toNamed<T?>(routeName, arguments: arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 返回
|
||||||
|
static Future<void> back<T>({T? result}) async {
|
||||||
|
//关闭键盘
|
||||||
|
if (Get.context != null) {
|
||||||
|
FocusScope.of(Get.context!).requestFocus(FocusNode());
|
||||||
|
}
|
||||||
|
Get.key.currentState?.pop(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||||
import 'package:sk_base_mobile/constants/enum.dart';
|
import 'package:sk_base_mobile/constants/enum.dart';
|
||||||
import 'package:sk_base_mobile/models/role.model.dart';
|
import 'package:sk_base_mobile/models/role.model.dart';
|
||||||
import 'package:sk_base_mobile/models/user_info.model.dart';
|
import 'package:sk_base_mobile/models/user_info.model.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/screens/hr_manage/components/dept_picker.dart';
|
import 'package:sk_base_mobile/screens/hr_manage/components/dept_picker.dart';
|
||||||
import 'package:sk_base_mobile/util/loading_util.dart';
|
import 'package:sk_base_mobile/util/loading_util.dart';
|
||||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||||
|
@ -323,12 +324,13 @@ class EditUserInfoController extends GetxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Api.updateUserInfo(userInfo.value!.id!, data);
|
await Api.updateUserInfo(userInfo.value.id!, data);
|
||||||
final resUser = await Api.getUserInfo(userInfo.value!.id!);
|
await LoadingUtil.to.dismiss();
|
||||||
|
final resUser = await Api.getUserInfo(userInfo.value.id!);
|
||||||
if (resUser.data != null) {
|
if (resUser.data != null) {
|
||||||
userInfo.value = UserInfoModel.fromJson(resUser.data);
|
userInfo.value = UserInfoModel.fromJson(resUser.data);
|
||||||
}
|
}
|
||||||
Get.back(result: userInfo.value);
|
await RouterUtil.back<UserInfoModel>(result: userInfo.value);
|
||||||
SnackBarUtil().success(
|
SnackBarUtil().success(
|
||||||
'保存成功',
|
'保存成功',
|
||||||
);
|
);
|
||||||
|
|
|
@ -150,6 +150,7 @@ class HrManagePage extends StatelessWidget {
|
||||||
|
|
||||||
Widget buildUserCard(int index) {
|
Widget buildUserCard(int index) {
|
||||||
return SkInk(
|
return SkInk(
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
RouterUtil.toNamed(RouteConfig.employeeDetail,
|
RouterUtil.toNamed(RouteConfig.employeeDetail,
|
||||||
arguments: controller.list[index]);
|
arguments: controller.list[index]);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:sk_base_mobile/apis/api.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/constants/enum.dart';
|
import 'package:sk_base_mobile/constants/enum.dart';
|
||||||
import 'package:sk_base_mobile/db_helper/db_help.dart';
|
import 'package:sk_base_mobile/db_helper/db_help.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_info.dart';
|
import 'package:sk_base_mobile/screens/inventory_inout/components/inventory_inout_info.dart';
|
||||||
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart';
|
import 'package:sk_base_mobile/screens/new_inventory_inout/new_inventory_inout.dart';
|
||||||
import 'package:sk_base_mobile/util/date.util.dart';
|
import 'package:sk_base_mobile/util/date.util.dart';
|
||||||
|
@ -76,7 +77,7 @@ class InventoryInoutController extends GetxController {
|
||||||
),
|
),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
showInventoryInoutCreateDialog(
|
showInventoryInoutCreateDialog(
|
||||||
InventoryInOrOutEnum.In);
|
InventoryInOrOutEnum.In);
|
||||||
},
|
},
|
||||||
|
@ -145,7 +146,7 @@ class InventoryInoutController extends GetxController {
|
||||||
),
|
),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
showInventoryInoutCreateDialog(
|
showInventoryInoutCreateDialog(
|
||||||
InventoryInOrOutEnum.Out);
|
InventoryInOrOutEnum.Out);
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:sk_base_mobile/constants/dict_enum.dart';
|
||||||
import 'package:sk_base_mobile/models/index.dart';
|
import 'package:sk_base_mobile/models/index.dart';
|
||||||
import 'package:sk_base_mobile/models/inventory.model.dart';
|
import 'package:sk_base_mobile/models/inventory.model.dart';
|
||||||
import 'package:sk_base_mobile/models/user_info.model.dart';
|
import 'package:sk_base_mobile/models/user_info.model.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/agent_search.dart';
|
import 'package:sk_base_mobile/screens/new_inventory_inout/components/agent_search.dart';
|
||||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/inventory_search.dart';
|
import 'package:sk_base_mobile/screens/new_inventory_inout/components/inventory_search.dart';
|
||||||
import 'package:sk_base_mobile/screens/new_inventory_inout/components/product_search.dart';
|
import 'package:sk_base_mobile/screens/new_inventory_inout/components/product_search.dart';
|
||||||
|
@ -242,7 +243,7 @@ class NewInventoryInout extends StatelessWidget {
|
||||||
if (inOrOut == InventoryInOrOutEnum.In) {
|
if (inOrOut == InventoryInOrOutEnum.In) {
|
||||||
ModalUtil.showGeneralDialog(content: ProductSearch(
|
ModalUtil.showGeneralDialog(content: ProductSearch(
|
||||||
onProductSelected: (ProductModel product) {
|
onProductSelected: (ProductModel product) {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
String productName =
|
String productName =
|
||||||
'${product.productNumber} ${product.name!}';
|
'${product.productNumber} ${product.name!}';
|
||||||
controller.payload['productId'] = product.id;
|
controller.payload['productId'] = product.id;
|
||||||
|
@ -263,7 +264,7 @@ class NewInventoryInout extends StatelessWidget {
|
||||||
return (itemData.quantity ?? 0) > 0;
|
return (itemData.quantity ?? 0) > 0;
|
||||||
},
|
},
|
||||||
onInventorySelected: (InventoryModel inventory) {
|
onInventorySelected: (InventoryModel inventory) {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
controller.payload['inventoryId'] = inventory.id;
|
controller.payload['inventoryId'] = inventory.id;
|
||||||
String productName =
|
String productName =
|
||||||
'${inventory.product!.name!}(¥${double.parse('${inventory.unitPrice}')})(${inventory.product?.company?.name})';
|
'${inventory.product!.name!}(¥${double.parse('${inventory.unitPrice}')})(${inventory.product?.company?.name})';
|
||||||
|
@ -364,7 +365,7 @@ class NewInventoryInout extends StatelessWidget {
|
||||||
ModalUtil.showGeneralDialog(
|
ModalUtil.showGeneralDialog(
|
||||||
content: AgentSearch(
|
content: AgentSearch(
|
||||||
onSelected: (UserInfoModel userInfo) {
|
onSelected: (UserInfoModel userInfo) {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
controller.payload['agent'] = userInfo.nickname;
|
controller.payload['agent'] = userInfo.nickname;
|
||||||
controller.agentTextController.text = userInfo.nickname!;
|
controller.agentTextController.text = userInfo.nickname!;
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:sk_base_mobile/apis/api.dart';
|
||||||
import 'package:sk_base_mobile/constants/enum.dart';
|
import 'package:sk_base_mobile/constants/enum.dart';
|
||||||
import 'package:sk_base_mobile/db_helper/db_help.dart';
|
import 'package:sk_base_mobile/db_helper/db_help.dart';
|
||||||
import 'package:sk_base_mobile/models/index.dart';
|
import 'package:sk_base_mobile/models/index.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout_controller.dart';
|
import 'package:sk_base_mobile/screens/inventory_inout/inventory_inout_controller.dart';
|
||||||
import 'package:sk_base_mobile/util/date.util.dart';
|
import 'package:sk_base_mobile/util/date.util.dart';
|
||||||
import 'package:sk_base_mobile/util/loading_util.dart';
|
import 'package:sk_base_mobile/util/loading_util.dart';
|
||||||
|
@ -190,7 +191,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
await Api.updateInventoryInout(
|
await Api.updateInventoryInout(
|
||||||
response.data, {'fileIds': uploadRes.map((e) => e!.id).toList()});
|
response.data, {'fileIds': uploadRes.map((e) => e!.id).toList()});
|
||||||
}
|
}
|
||||||
Get.back(result: true);
|
await RouterUtil.back<bool>(result: true);
|
||||||
SnackBarUtil().success(
|
SnackBarUtil().success(
|
||||||
'提交成功',
|
'提交成功',
|
||||||
);
|
);
|
||||||
|
@ -238,7 +239,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// // uploadImgFilePath(pickedFile.path);
|
// // uploadImgFilePath(pickedFile.path);
|
||||||
// Get.back();
|
// await RouterUtil.back();
|
||||||
// } catch (e) {
|
// } catch (e) {
|
||||||
// SnackBarUtil().error('上传失败,请重试');
|
// SnackBarUtil().error('上传失败,请重试');
|
||||||
// } finally {
|
// } finally {
|
||||||
|
@ -354,7 +355,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
// inventoryInoutlist[dif.inDays].add(value);
|
// inventoryInoutlist[dif.inDays].add(value);
|
||||||
// Timer(const Duration(seconds: 1), () {
|
// Timer(const Duration(seconds: 1), () {
|
||||||
// loading.value = false;
|
// loading.value = false;
|
||||||
// Get.back();
|
// await RouterUtil.back();
|
||||||
// SnackBarUtil().success(
|
// SnackBarUtil().success(
|
||||||
// 'Successful',
|
// 'Successful',
|
||||||
// message: 'Task is created',
|
// message: 'Task is created',
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/models/sale_quotation_template.model.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
|
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.controller.dart';
|
||||||
|
import 'package:sk_base_mobile/util/modal.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/core/sk_flat_button.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/core/sk_ink.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart';
|
||||||
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
|
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
|
||||||
|
|
||||||
class SaleQuotationEndDrawer extends StatelessWidget {
|
class SaleQuotationEndDrawer extends StatelessWidget {
|
||||||
const SaleQuotationEndDrawer({super.key});
|
final controller = Get.find<SaleQuotationController>();
|
||||||
|
SaleQuotationEndDrawer({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: SkAppbar(title: '工具栏', hideLeading: true),
|
appBar: const SkAppbar(title: '', hideLeading: true),
|
||||||
body: buildBody(),
|
body: buildBody(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,24 +29,280 @@ class SaleQuotationEndDrawer extends StatelessWidget {
|
||||||
Widget buildBody() {
|
Widget buildBody() {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
buildToolbar(),
|
||||||
title: Text('选择报价模板'),
|
Expanded(
|
||||||
onTap: () {},
|
child: buildTemplatePicker(),
|
||||||
),
|
),
|
||||||
Divider(
|
buildAction()
|
||||||
color: AppTheme.dividerColor,
|
],
|
||||||
height: 1,
|
);
|
||||||
),
|
}
|
||||||
Spacer(),
|
|
||||||
GradientButton(
|
Widget buildAction() {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SkFlatButton(
|
||||||
|
color: AppTheme.dangerColor,
|
||||||
|
onPressed: () {
|
||||||
|
controller.clearWorkbench();
|
||||||
|
RouterUtil.back();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
|
size: ScreenAdaper.height(40),
|
||||||
|
),
|
||||||
|
buttonText: '清空工作区',
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: SkFlatButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (controller.templateName.value != '默认') {
|
||||||
|
await RouterUtil.back();
|
||||||
|
await controller.saveToDatabase();
|
||||||
|
} else {
|
||||||
|
templateNameDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
// final isSuccessed = await controller.saveToDatabase();
|
||||||
|
// if (isSuccessed) await RouterUtil.back();
|
||||||
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.save,
|
Icons.save,
|
||||||
color: AppTheme.nearlyWhite,
|
color: AppTheme.nearlyWhite,
|
||||||
size: ScreenAdaper.height(40),
|
size: ScreenAdaper.height(40),
|
||||||
),
|
),
|
||||||
buttonText: '保存为模板',
|
buttonText: '保存模板',
|
||||||
)
|
))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildToolbar() {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(20))),
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: ScreenAdaper.height(20),
|
||||||
|
vertical: ScreenAdaper.height(20)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
buildGroupHeader('工具栏'),
|
||||||
|
Row(
|
||||||
|
children: controller.menus
|
||||||
|
.mapIndexed(
|
||||||
|
(index, item) => Expanded(child: buildItem(index)))
|
||||||
|
.toList())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildGroupHeader(String text) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
right: ScreenAdaper.width(20),
|
||||||
|
left: ScreenAdaper.width(20),
|
||||||
|
top: ScreenAdaper.height(20)),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: ScreenAdaper.height(25), color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildItem(int index) {
|
||||||
|
return SkInk(
|
||||||
|
onTap: () {
|
||||||
|
// final route = RouteConfig.getPages
|
||||||
|
// .map((e) => e.name)
|
||||||
|
// .firstWhereOrNull((name) => name == controller.menus[index].route);
|
||||||
|
// if (route != null) {
|
||||||
|
// } else {
|
||||||
|
// SnackBarUtil().info('您没有权限,请联系管理员。后期会隐藏没有权限的功能');
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: ScreenAdaper.height(20), bottom: ScreenAdaper.height(20)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
'assets/icons/${controller.menus[index].icon}',
|
||||||
|
width: ScreenAdaper.width(75),
|
||||||
|
height: ScreenAdaper.width(75),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: ScreenAdaper.height(10),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
controller.menus[index].title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: ScreenAdaper.height(22),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildTemplatePicker() {
|
||||||
|
return Obx(() => Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(20))),
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: ScreenAdaper.height(20),
|
||||||
|
right: ScreenAdaper.height(20),
|
||||||
|
bottom: ScreenAdaper.height(20)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
buildGroupHeader('请选择模板'),
|
||||||
|
SizedBox(
|
||||||
|
height: ScreenAdaper.height(10),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: ScreenAdaper.height(20)),
|
||||||
|
children: controller.templates
|
||||||
|
.mapIndexed((int index, element) =>
|
||||||
|
buildTemplateItem(element, index))
|
||||||
|
.toList(),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildTemplateItem(SaleQuotationTemplateModel element, int index) {
|
||||||
|
return SkInk(
|
||||||
|
onTap: () async {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 150));
|
||||||
|
controller.changeTemplate(element);
|
||||||
|
await RouterUtil.back();
|
||||||
|
},
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: ScreenAdaper.width(10),
|
||||||
|
vertical: ScreenAdaper.height(10)),
|
||||||
|
border: Border.all(color: AppTheme.dividerColor),
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: ScreenAdaper.height(20),
|
||||||
|
horizontal: ScreenAdaper.width(20)),
|
||||||
|
child: Row(children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${element.name}',
|
||||||
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
||||||
|
)),
|
||||||
|
SkInk(
|
||||||
|
onTap: () {
|
||||||
|
templateNameDialog(title: element.name);
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.edit,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
size: ScreenAdaper.height(40),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: ScreenAdaper.width(10),
|
||||||
|
),
|
||||||
|
SkInk(
|
||||||
|
color: Colors.transparent,
|
||||||
|
onTap: () {
|
||||||
|
ModalUtil.alert(
|
||||||
|
title: '删除模板',
|
||||||
|
content: Text(
|
||||||
|
'确定删除模板${element.name}吗?',
|
||||||
|
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
||||||
|
),
|
||||||
|
onConfirm: () async {
|
||||||
|
await controller.deleteTemplate(element.id!);
|
||||||
|
controller.templates.removeAt(index);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
size: ScreenAdaper.height(40),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void templateNameDialog({String? title = ''}) {
|
||||||
|
final textController = TextEditingController(text: title);
|
||||||
|
Get.dialog(AlertDialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(20)),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
top: ScreenAdaper.height(10),
|
||||||
|
right: ScreenAdaper.height(20),
|
||||||
|
left: ScreenAdaper.height(20)),
|
||||||
|
content: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
SkInk(
|
||||||
|
onTap: () {
|
||||||
|
RouterUtil.back();
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.close))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SkTextInput(
|
||||||
|
height: ScreenAdaper.height(100),
|
||||||
|
textController: textController,
|
||||||
|
customLabel: true,
|
||||||
|
labelText: '模板名称',
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
RouterUtil.back();
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
'取消',
|
||||||
|
style: TextStyle(color: AppTheme.nearlyBlack),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (textController.text.isEmpty) {
|
||||||
|
SnackBarUtil().error('模板名不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
controller.templateName.value = textController.text;
|
||||||
|
await RouterUtil.back();
|
||||||
|
await controller.saveToLocal();
|
||||||
|
await controller.saveToDatabase();
|
||||||
|
await controller.getTemplates();
|
||||||
|
},
|
||||||
|
child: const Text('确定'),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class SaleQuotationDrawerController extends GetxController{
|
||||||
|
|
||||||
|
// }
|
|
@ -111,34 +111,10 @@ class SaleQuotationGroupSearch extends StatelessWidget {
|
||||||
vertical: ScreenAdaper.height(10)),
|
vertical: ScreenAdaper.height(10)),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
// ClipRRect(
|
|
||||||
// borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
|
|
||||||
// child: FadeInCacheImage(
|
|
||||||
// url: controller.list[index].avatar ?? '',
|
|
||||||
// width: ScreenAdaper.width(60),
|
|
||||||
// height: ScreenAdaper.width(60),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// SizedBox(
|
|
||||||
// width: ScreenAdaper.width(20),
|
|
||||||
// ),
|
|
||||||
Text(
|
Text(
|
||||||
'${controller.list[index].name}',
|
controller.list[index].name,
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
||||||
),
|
),
|
||||||
// if (controller.list[index].dept != null) ...[
|
|
||||||
// SizedBox(
|
|
||||||
// width: ScreenAdaper.width(20),
|
|
||||||
// ),
|
|
||||||
// Container(
|
|
||||||
// padding: EdgeInsets.symmetric(
|
|
||||||
// horizontal: ScreenAdaper.width(10),
|
|
||||||
// vertical: ScreenAdaper.height(5)),
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// color: Colors.grey[300],
|
|
||||||
// borderRadius: BorderRadius.circular(ScreenAdaper.sp(10))),
|
|
||||||
// child: Text('${controller.list[index].dept?.name}'),
|
|
||||||
// )
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -4,10 +4,16 @@ import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:math_expressions/math_expressions.dart';
|
import 'package:math_expressions/math_expressions.dart';
|
||||||
|
import 'package:sk_base_mobile/apis/api.dart';
|
||||||
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
||||||
|
import 'package:sk_base_mobile/models/sale_quotaion_component.model.dart';
|
||||||
|
import 'package:sk_base_mobile/models/sale_quotaion_group.model.dart';
|
||||||
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
||||||
|
import 'package:sk_base_mobile/models/sale_quotation_template.model.dart';
|
||||||
|
import 'package:sk_base_mobile/models/workbench.model.dart';
|
||||||
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart';
|
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_group_search.dart';
|
||||||
import 'package:sk_base_mobile/services/storage.service.dart';
|
import 'package:sk_base_mobile/services/storage.service.dart';
|
||||||
|
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/form_item/sk_multi_search_more.dart';
|
import 'package:sk_base_mobile/widgets/form_item/sk_multi_search_more.dart';
|
||||||
import 'package:sk_base_mobile/util/modal.util.dart';
|
import 'package:sk_base_mobile/util/modal.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
@ -17,39 +23,21 @@ class SaleQuotationController extends GetxController {
|
||||||
static SaleQuotationController get to => Get.find();
|
static SaleQuotationController get to => Get.find();
|
||||||
final RxList editingcell = RxList([null, null, null]);
|
final RxList editingcell = RxList([null, null, null]);
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
RxList<SaleQuotationItemModel> products = RxList([
|
|
||||||
SaleQuotationItemModel(
|
|
||||||
name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z', cost: 4700),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
|
||||||
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200),
|
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600),
|
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400),
|
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500),
|
|
||||||
SaleQuotationItemModel(
|
|
||||||
name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
|
||||||
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
|
||||||
SaleQuotationItemModel(
|
|
||||||
name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200),
|
|
||||||
SaleQuotationItemModel(
|
|
||||||
name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500),
|
|
||||||
SaleQuotationItemModel(
|
|
||||||
name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000),
|
|
||||||
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型位移传感器'),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型压力传感器'),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型红外发射器'),
|
|
||||||
SaleQuotationItemModel(name: '矿用本安型LED信号灯'),
|
|
||||||
SaleQuotationItemModel(name: '倾角传感器'),
|
|
||||||
SaleQuotationItemModel(name: '各类安装附件'),
|
|
||||||
]);
|
|
||||||
RxList<SaleQuotationModel> groups = RxList<SaleQuotationModel>([]);
|
RxList<SaleQuotationModel> groups = RxList<SaleQuotationModel>([]);
|
||||||
RxInt totalCost = RxInt(0);
|
RxDouble totalCost = RxDouble(0.0);
|
||||||
RxDouble totalPrice = RxDouble(0.0);
|
RxDouble totalPrice = RxDouble(0.0);
|
||||||
RxBool isFormulaEditing = false.obs;
|
RxBool isFormulaEditing = false.obs;
|
||||||
RxString formula = '成本 * 1.3 / 0.864'.obs;
|
RxString formula = '成本 * 1.3 / 0.864'.obs;
|
||||||
|
RxList<SaleQuotationTemplateModel> templates = RxList([]);
|
||||||
|
final List<WorkBenchModel> menus = [
|
||||||
|
WorkBenchModel(title: '导出明细', icon: 'export.svg'),
|
||||||
|
// WorkBenchModel(title: '模板', icon: 'sale_quotation_template.svg'),
|
||||||
|
WorkBenchModel(title: '配件管理', icon: 'product.svg'),
|
||||||
|
WorkBenchModel(title: '分组管理', icon: 'sale_quotation_group.svg'),
|
||||||
|
WorkBenchModel(title: '计算公式', icon: 'sale_quotation_formula.svg'),
|
||||||
|
];
|
||||||
|
RxString templateName = '默认'.obs;
|
||||||
|
int? templateId;
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
init();
|
init();
|
||||||
|
@ -59,18 +47,43 @@ class SaleQuotationController extends GetxController {
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
String? salesQuotation = StorageService.to.getString('salesQuotation');
|
String? salesQuotation = StorageService.to.getString('salesQuotation');
|
||||||
if (salesQuotation != null) {
|
if (salesQuotation != null) {
|
||||||
groups.assignAll((jsonDecode(salesQuotation) as List)
|
SaleQuotationTemplateModel editTemplate =
|
||||||
.map((e) => SaleQuotationModel.fromJson(e))
|
SaleQuotationTemplateModel.fromJson(jsonDecode(salesQuotation));
|
||||||
.toList());
|
parseTemplateModel(editTemplate);
|
||||||
calculateTotal();
|
|
||||||
}
|
}
|
||||||
|
await getTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseTemplateModel(SaleQuotationTemplateModel editTemplate) {
|
||||||
|
groups.assignAll(editTemplate.template.data);
|
||||||
|
templateName.value = editTemplate.name ?? '';
|
||||||
|
formula.value = editTemplate.template.formula;
|
||||||
|
totalPrice.value = editTemplate.template.totalPrice?.toDouble() ?? 0.0;
|
||||||
|
totalCost.value = editTemplate.template.totalCost?.toDouble() ?? 0.0;
|
||||||
|
templateId = editTemplate.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 切换报价模板
|
||||||
|
void changeTemplate(SaleQuotationTemplateModel templateModel) {
|
||||||
|
parseTemplateModel(templateModel);
|
||||||
|
saveToLocal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取报价模板
|
||||||
|
Future<void> getTemplates() async {
|
||||||
|
final res = await Api.getSaleQuotationTemplate();
|
||||||
|
List<SaleQuotationTemplateModel> newList = res.data!.items
|
||||||
|
.map((e) => SaleQuotationTemplateModel.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
templates.assignAll(newList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 实时计算总数
|
||||||
void calculateTotal({String? newFormula}) {
|
void calculateTotal({String? newFormula}) {
|
||||||
//计算groups中所有items中的amout总和
|
//计算groups中所有items中的amout总和
|
||||||
totalCost.value = groups.fold<int>(0, (previousValue, element) {
|
totalCost.value = groups.fold<double>(0, (previousValue, element) {
|
||||||
return previousValue +
|
return previousValue +
|
||||||
element.items.fold<int>(0, (previousValue, element) {
|
element.items.fold<double>(0, (previousValue, element) {
|
||||||
return previousValue + element.amount;
|
return previousValue + element.amount;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -100,39 +113,87 @@ class SaleQuotationController extends GetxController {
|
||||||
// 入库一般是先输入单价和数量,然后计算单价
|
// 入库一般是先输入单价和数量,然后计算单价
|
||||||
if (changedField != 'amount') {
|
if (changedField != 'amount') {
|
||||||
Decimal result = cost * quantity;
|
Decimal result = cost * quantity;
|
||||||
data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
data.amount = result != Decimal.zero ? result.toDouble() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedField == 'amount' && quantity != Decimal.zero) {
|
if (changedField == 'amount' && quantity != Decimal.zero) {
|
||||||
Decimal result =
|
Decimal result =
|
||||||
(amount / quantity).toDecimal(scaleOnInfinitePrecision: 10);
|
(amount / quantity).toDecimal(scaleOnInfinitePrecision: 10);
|
||||||
data.cost = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
data.cost = result != Decimal.zero ? result.toDouble() : 0.0;
|
||||||
} else if (changedField != 'amount') {
|
} else if (changedField != 'amount') {
|
||||||
Decimal result = (cost * quantity);
|
Decimal result = (cost * quantity);
|
||||||
data.amount = result != Decimal.zero ? result.toBigInt().toInt() : 0;
|
data.amount = result != Decimal.zero ? result.toDouble() : 0;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveChanges(int groupIndex, int rowIndex, SaleQuotationItemModel data,
|
/// 处理行数据变化
|
||||||
String changedField) {
|
void afterRowChanges(int groupIndex, int rowIndex,
|
||||||
|
SaleQuotationItemModel data, String changedField) {
|
||||||
data = calculateRow(data, changedField);
|
data = calculateRow(data, changedField);
|
||||||
groups[groupIndex].items[rowIndex] = data;
|
groups[groupIndex].items[rowIndex] = data;
|
||||||
calculateTotal();
|
calculateTotal();
|
||||||
stopEditing();
|
stopEditing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 停止编辑
|
||||||
void stopEditing() {
|
void stopEditing() {
|
||||||
editingcell.assignAll([null, null, null]);
|
editingcell.assignAll([null, null, null]);
|
||||||
save();
|
saveToLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> save() async {
|
/// 保存到本地持久化
|
||||||
await StorageService.to
|
Future<void> saveToLocal() async {
|
||||||
.setString('salesQuotation', jsonEncode(groups.toJson()));
|
Map<String, dynamic> data = {
|
||||||
// SnackBarUtil().success('已保存到本地');
|
'name': templateName.value,
|
||||||
|
'template': {
|
||||||
|
'data': groups.map((e) => e.toJson()).toList(),
|
||||||
|
'totalCost': totalCost.value,
|
||||||
|
'totalPrice': totalPrice.value,
|
||||||
|
'formula': formula.value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (templateId != null) {
|
||||||
|
data['id'] = templateId;
|
||||||
|
}
|
||||||
|
await StorageService.to.setString('salesQuotation', jsonEncode(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 保存到数据库
|
||||||
|
Future<bool> saveToDatabase() async {
|
||||||
|
if (templateId == null) {
|
||||||
|
await Api.createSaleQuotationTemplate({
|
||||||
|
'name': templateName.value,
|
||||||
|
'template': {
|
||||||
|
'data': groups.toJson(),
|
||||||
|
'totalCost': totalCost.value,
|
||||||
|
'totalPrice': totalPrice.value,
|
||||||
|
'formula': formula.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await Api.updateSaleQuotationTemplate(templateId!, {
|
||||||
|
'name': templateName.value,
|
||||||
|
'template': {
|
||||||
|
'data': groups.toJson(),
|
||||||
|
'totalCost': totalCost.value,
|
||||||
|
'totalPrice': totalPrice.value,
|
||||||
|
'formula': formula.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await getTemplates();
|
||||||
|
await SnackBarUtil().success('已保存');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除模板
|
||||||
|
Future<void> deleteTemplate(int templateId) async {
|
||||||
|
await Api.deleteSaleQuotationTemplate(templateId);
|
||||||
|
SnackBarUtil().success('已删除');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 添加分组
|
||||||
void addGroup() async {
|
void addGroup() async {
|
||||||
final controller = Get.put(GroupSearchMoreController());
|
final controller = Get.put(GroupSearchMoreController());
|
||||||
// 选择组件 选择分组
|
// 选择组件 选择分组
|
||||||
|
@ -145,7 +206,7 @@ class SaleQuotationController extends GetxController {
|
||||||
groups.addAll(controller.list.where((element) {
|
groups.addAll(controller.list.where((element) {
|
||||||
return indexes.contains(controller.list.indexOf(element));
|
return indexes.contains(controller.list.indexOf(element));
|
||||||
}));
|
}));
|
||||||
save();
|
saveToLocal();
|
||||||
},
|
},
|
||||||
leadingBuilder: (index) {
|
leadingBuilder: (index) {
|
||||||
return Container(
|
return Container(
|
||||||
|
@ -168,15 +229,16 @@ class SaleQuotationController extends GetxController {
|
||||||
calculateTotal();
|
calculateTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 移除分组
|
||||||
void removeGroup(int index) {
|
void removeGroup(int index) {
|
||||||
groups.removeAt(index);
|
groups.removeAt(index);
|
||||||
calculateTotal();
|
calculateTotal();
|
||||||
save();
|
saveToLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addItems(int groupIndex) async {
|
void addItems(int groupIndex) async {
|
||||||
final controller = Get.put(ItemSearchMoreController());
|
final controller = Get.put(ItemSearchMoreController());
|
||||||
// 选择产品
|
// 选择配件
|
||||||
ModalUtil.showGeneralDialog(
|
ModalUtil.showGeneralDialog(
|
||||||
content: SkMutilSearchMore<SaleQuotationItemModel>(
|
content: SkMutilSearchMore<SaleQuotationItemModel>(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
@ -184,10 +246,12 @@ class SaleQuotationController extends GetxController {
|
||||||
enablePullDown: true,
|
enablePullDown: true,
|
||||||
isDialog: true,
|
isDialog: true,
|
||||||
onOk: (List<int> indexes) {
|
onOk: (List<int> indexes) {
|
||||||
groups[groupIndex].items.addAll(products.where((element) {
|
groups[groupIndex]
|
||||||
return indexes.contains(products.indexOf(element));
|
.items
|
||||||
|
.addAll(controller.list.where((element) {
|
||||||
|
return indexes.contains(controller.list.indexOf(element));
|
||||||
}));
|
}));
|
||||||
save();
|
saveToLocal();
|
||||||
},
|
},
|
||||||
leadingBuilder: (index) {
|
leadingBuilder: (index) {
|
||||||
return Container(
|
return Container(
|
||||||
|
@ -250,22 +314,41 @@ class SaleQuotationController extends GetxController {
|
||||||
groups[groupIndex].items.removeAt(rowIndex);
|
groups[groupIndex].items.removeAt(rowIndex);
|
||||||
calculateTotal();
|
calculateTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearWorkbench() {
|
||||||
|
groups.value = [];
|
||||||
|
totalCost.value = 0.0;
|
||||||
|
totalPrice.value = 0.0;
|
||||||
|
formula.value = '成本 * 1.3 / 0.864';
|
||||||
|
templateName.value = '默认';
|
||||||
|
templateId = null;
|
||||||
|
saveToLocal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupSearchMoreController extends GetxController
|
class GroupSearchMoreController
|
||||||
with BaseSearchMoreController<SaleQuotationModel> {
|
extends BaseSearchMoreController<SaleQuotationModel> {
|
||||||
@override
|
@override
|
||||||
Future<List<SaleQuotationModel>> getData({bool isRefresh = false}) async {
|
Future<List<SaleQuotationModel>> getData({bool isRefresh = false}) async {
|
||||||
List<SaleQuotationModel> newList = [
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])),
|
final res = await Api.getSaleQuotationGroups();
|
||||||
SaleQuotationModel(name: '端头架电控部分', items: RxList([])),
|
List<SaleQuotationGroupModel> groups = res.data!.items
|
||||||
SaleQuotationModel(name: '主阀部分', items: RxList([])),
|
.map((e) => SaleQuotationGroupModel.fromJson(e))
|
||||||
SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])),
|
.toList();
|
||||||
SaleQuotationModel(name: '位移测量部分', items: RxList([])),
|
|
||||||
SaleQuotationModel(name: '压力检测部分', items: RxList([])),
|
List<SaleQuotationModel> newList = groups
|
||||||
SaleQuotationModel(name: '煤机定位部分', items: RxList([])),
|
.map((e) => SaleQuotationModel(name: e.name!, items: RxList([])))
|
||||||
SaleQuotationModel(name: '姿态检测部分', items: RxList([])),
|
.toList();
|
||||||
];
|
// List<SaleQuotationModel> newList = [
|
||||||
|
// SaleQuotationModel(name: '中间过渡架电控部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '端头架电控部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '主阀部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '自动反冲洗过滤器部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '位移测量部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '压力检测部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '煤机定位部分', items: RxList([])),
|
||||||
|
// SaleQuotationModel(name: '姿态检测部分', items: RxList([])),
|
||||||
|
// ];
|
||||||
list.assignAll(newList
|
list.assignAll(newList
|
||||||
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
|
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
|
||||||
.contains(searchKey.value))
|
.contains(searchKey.value))
|
||||||
|
@ -274,42 +357,58 @@ class GroupSearchMoreController extends GetxController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemSearchMoreController extends GetxController
|
class ItemSearchMoreController
|
||||||
with BaseSearchMoreController<SaleQuotationItemModel> {
|
extends BaseSearchMoreController<SaleQuotationItemModel> {
|
||||||
@override
|
@override
|
||||||
Future<List<SaleQuotationItemModel>> getData({bool isRefresh = false}) async {
|
Future<List<SaleQuotationItemModel>> getData({bool isRefresh = false}) async {
|
||||||
List<SaleQuotationItemModel> newList = [
|
try {
|
||||||
SaleQuotationItemModel(
|
final res = await Api.getSaleQuotationComponents();
|
||||||
name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z', cost: 4700),
|
List<SaleQuotationComponentModel> componets = res.data!.items
|
||||||
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
.map((e) => SaleQuotationComponentModel.fromJson(e))
|
||||||
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
.toList();
|
||||||
SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200),
|
List<SaleQuotationItemModel> newList = componets
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600),
|
.map((e) => SaleQuotationItemModel(
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400),
|
name: e.name!,
|
||||||
SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500),
|
cost: e.unitPrice ?? 0.0,
|
||||||
SaleQuotationItemModel(
|
unit: e.unit?.label ?? '',
|
||||||
name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000),
|
remark: e.remark))
|
||||||
SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700),
|
.toList();
|
||||||
SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
// List<SaleQuotationItemModel> newList = [
|
||||||
SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
// SaleQuotationItemModel(
|
||||||
SaleQuotationItemModel(
|
// name: '矿用本安型支架控制器', unit: '台', spec: 'ZDYZ-Z', cost: 4700),
|
||||||
name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200),
|
// SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
||||||
SaleQuotationItemModel(
|
// SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
||||||
name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500),
|
// SaleQuotationItemModel(name: '矿用本安型隔离耦合器', cost: 1200),
|
||||||
SaleQuotationItemModel(
|
// SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', cost: 600),
|
||||||
name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000),
|
// SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-控制器', cost: 400),
|
||||||
SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
|
// SaleQuotationItemModel(name: '钢丝编织橡胶护套连接器', remark: '控制器-驱动器', cost: 500),
|
||||||
SaleQuotationItemModel(name: '矿用本安型位移传感器'),
|
// SaleQuotationItemModel(
|
||||||
SaleQuotationItemModel(name: '矿用本安型压力传感器'),
|
// name: '钢丝编织橡胶护套连接器', remark: '控制器-隔离耦合器', cost: 2000),
|
||||||
SaleQuotationItemModel(name: '矿用本安型红外发射器'),
|
// SaleQuotationItemModel(name: '矿用本安型支架控制器', cost: 4700),
|
||||||
SaleQuotationItemModel(name: '矿用本安型LED信号灯'),
|
// SaleQuotationItemModel(name: '矿用本安型电磁阀驱动器', cost: 1200),
|
||||||
SaleQuotationItemModel(name: '倾角传感器'),
|
// SaleQuotationItemModel(name: '矿用隔爆兼本安型电源', cost: 5700),
|
||||||
SaleQuotationItemModel(name: '各类安装附件'),
|
// SaleQuotationItemModel(
|
||||||
];
|
// name: '电液换向阀(10功能10接口)', remark: '中间过渡架主阀组', cost: 13200),
|
||||||
list.assignAll(newList
|
// SaleQuotationItemModel(
|
||||||
.where((element) => PinyinHelper.getPinyin(element.name, separator: '')
|
// name: '电液换向阀(20功能20接口)', remark: '端头架主阀组', cost: 26500),
|
||||||
.contains(searchKey.value))
|
// SaleQuotationItemModel(
|
||||||
.toList());
|
// name: '自动反冲洗过滤装置', remark: '流量:900L/min,过滤精度25μm', cost: 2000),
|
||||||
return newList;
|
// SaleQuotationItemModel(name: '全自动反冲洗过滤器电缆', remark: '控制器-自动反冲洗'),
|
||||||
|
// SaleQuotationItemModel(name: '矿用本安型位移传感器'),
|
||||||
|
// SaleQuotationItemModel(name: '矿用本安型压力传感器'),
|
||||||
|
// SaleQuotationItemModel(name: '矿用本安型红外发射器'),
|
||||||
|
// SaleQuotationItemModel(name: '矿用本安型LED信号灯'),
|
||||||
|
// SaleQuotationItemModel(name: '倾角传感器'),
|
||||||
|
// SaleQuotationItemModel(name: '各类安装附件'),
|
||||||
|
// ];
|
||||||
|
list.assignAll(newList
|
||||||
|
.where((element) =>
|
||||||
|
PinyinHelper.getPinyin(element.name, separator: '')
|
||||||
|
.contains(searchKey.value))
|
||||||
|
.toList());
|
||||||
|
return newList;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,11 @@ import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
import 'package:sk_base_mobile/models/sale_quotation.model.dart';
|
||||||
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_drawer.dart';
|
import 'package:sk_base_mobile/screens/sale_quotation/components/sale_quotation_drawer.dart';
|
||||||
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.controller.dart';
|
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.controller.dart';
|
||||||
|
import 'package:sk_base_mobile/util/common.util.dart';
|
||||||
import 'package:sk_base_mobile/util/modal.util.dart';
|
import 'package:sk_base_mobile/util/modal.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/util/snack_bar.util.dart';
|
|
||||||
import 'package:sk_base_mobile/widgets/form_item/sk_number_input.dart';
|
import 'package:sk_base_mobile/widgets/form_item/sk_number_input.dart';
|
||||||
import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart';
|
import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart';
|
||||||
import 'package:sk_base_mobile/widgets/empty.dart';
|
|
||||||
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
|
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
|
||||||
import 'package:flutter_sticky_header/flutter_sticky_header.dart';
|
import 'package:flutter_sticky_header/flutter_sticky_header.dart';
|
||||||
import 'package:math_expressions/math_expressions.dart';
|
import 'package:math_expressions/math_expressions.dart';
|
||||||
|
@ -22,93 +21,75 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
final quantityWidth = 140.0;
|
final quantityWidth = 140.0;
|
||||||
final unitPriceWidth = 140.0;
|
final unitPriceWidth = 140.0;
|
||||||
final amountWidth = 140.0;
|
final amountWidth = 140.0;
|
||||||
final headerTitleStyle = TextStyle(
|
final TextStyle? headerTitleStyle = TextStyle(
|
||||||
fontSize: ScreenAdaper.height(30),
|
fontSize: ScreenAdaper.height(30),
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: AppTheme.nearlyBlack);
|
color: Theme.of(Get.context!).colorScheme.onPrimary);
|
||||||
final headerBgcolor = const Color.fromARGB(255, 238, 238, 238);
|
final headerBgcolor = AppTheme.appbarBgColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Obx(() => Scaffold(
|
||||||
key: controller.scaffoldKey,
|
key: controller.scaffoldKey,
|
||||||
endDrawer: const Drawer(
|
backgroundColor: AppTheme.nearlyWhite,
|
||||||
// 从右到左出现
|
endDrawer: Drawer(
|
||||||
child: SaleQuotationEndDrawer(),
|
// 从右到左出现
|
||||||
),
|
child: SaleQuotationEndDrawer(),
|
||||||
appBar: SkAppbar(
|
|
||||||
title: '报价计算',
|
|
||||||
action: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
controller.scaffoldKey.currentState?.openEndDrawer();
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.more_horiz_outlined, color: AppTheme.white),
|
|
||||||
),
|
),
|
||||||
Container(
|
appBar: SkAppbar(
|
||||||
padding: EdgeInsets.symmetric(
|
title: '报价计算-${controller.templateName}',
|
||||||
vertical: ScreenAdaper.height(10),
|
action: [
|
||||||
horizontal: ScreenAdaper.width(20)),
|
IconButton(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
onPressed: () {
|
||||||
GestureDetector(
|
controller.scaffoldKey.currentState?.openEndDrawer();
|
||||||
onTap: () {
|
|
||||||
controller.addGroup();
|
|
||||||
},
|
},
|
||||||
child: Icon(
|
icon: const Icon(Icons.more_horiz_outlined,
|
||||||
Icons.add,
|
color: AppTheme.white),
|
||||||
size: ScreenAdaper.height(40),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
bottom: ScreenAdaper.isLandspace() ? false : true,
|
|
||||||
child: Stack(children: [
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
builderHeader(),
|
|
||||||
Expanded(
|
|
||||||
child: Obx(() => controller.groups.isEmpty
|
|
||||||
? Empty(text: '请先添加分组')
|
|
||||||
: CustomScrollView(
|
|
||||||
slivers: controller.groups
|
|
||||||
.mapIndexed<Widget>(
|
|
||||||
(index, e) => buildBody(index))
|
|
||||||
.toList(),
|
|
||||||
))),
|
|
||||||
// 当键盘弹起时,不显示
|
|
||||||
|
|
||||||
SizedBox(
|
|
||||||
height: ScreenAdaper.height(100),
|
|
||||||
child: buildTotalCostRow(),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
|
||||||
height: ScreenAdaper.height(100),
|
|
||||||
child: buildTotalSalesPriceRow(),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// Positioned(
|
body: SafeArea(
|
||||||
// bottom: ScreenAdaper.height(220),
|
bottom: ScreenAdaper.isLandspace() ? false : true,
|
||||||
// right: ScreenAdaper.height(10),
|
child: Stack(children: [
|
||||||
// child: IconButton(
|
Column(
|
||||||
// padding: EdgeInsets.all(ScreenAdaper.height(20)),
|
children: [
|
||||||
// style: ButtonStyle(
|
builderHeader(),
|
||||||
// backgroundColor: MaterialStateProperty.all<Color>(
|
Expanded(
|
||||||
// AppTheme.primaryColorLight)),
|
child: Obx(() => controller.groups.isEmpty
|
||||||
// onPressed: () {
|
? Column(
|
||||||
// controller.addGroup();
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
// },
|
children: [
|
||||||
// icon: Icon(
|
Text(
|
||||||
// Icons.add,
|
'请右上角选择模板',
|
||||||
// size: ScreenAdaper.height(40),
|
style: TextStyle(
|
||||||
// ),
|
fontSize: ScreenAdaper.height(30)),
|
||||||
// ))
|
),
|
||||||
]),
|
Text('或者左上角加号添加分组',
|
||||||
),
|
style: TextStyle(
|
||||||
);
|
fontSize: ScreenAdaper.height(30)))
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: CustomScrollView(
|
||||||
|
slivers: controller.groups
|
||||||
|
.mapIndexed<Widget>(
|
||||||
|
(index, e) => buildBody(index))
|
||||||
|
.toList(),
|
||||||
|
))),
|
||||||
|
// 当键盘弹起时,不显示
|
||||||
|
|
||||||
|
SizedBox(
|
||||||
|
height: ScreenAdaper.height(100),
|
||||||
|
child: buildTotalCostRow(),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: ScreenAdaper.height(100),
|
||||||
|
child: buildTotalSalesPriceRow(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildTotalSalesPriceRow() {
|
Widget buildTotalSalesPriceRow() {
|
||||||
|
@ -254,6 +235,19 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
bottom: ScreenAdaper.height(10)),
|
bottom: ScreenAdaper.height(10)),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
controller.addGroup();
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.add_circle_outline_outlined,
|
||||||
|
size: ScreenAdaper.height(40),
|
||||||
|
color: Theme.of(Get.context!).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: ScreenAdaper.width(5),
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
'名称',
|
'名称',
|
||||||
style: headerTitleStyle,
|
style: headerTitleStyle,
|
||||||
|
@ -315,8 +309,13 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
color: AppTheme.nearlyBlack,
|
color: AppTheme.nearlyBlack,
|
||||||
fontWeight: FontWeight.w600);
|
fontWeight: FontWeight.w600);
|
||||||
return Container(
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromARGB(255, 235, 235, 235)
|
||||||
|
.withOpacity(1.0 - state.scrollPercentage),
|
||||||
|
border: const Border(
|
||||||
|
top: BorderSide(width: 1, color: AppTheme.dividerColor),
|
||||||
|
bottom: BorderSide(width: 1, color: AppTheme.dividerColor))),
|
||||||
height: ScreenAdaper.height(80),
|
height: ScreenAdaper.height(80),
|
||||||
color: headerBgcolor.withOpacity(1.0 - state.scrollPercentage),
|
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@ -469,7 +468,9 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'${controller.groups[groupIndex].items[rowIndex].remark ?? ''}${controller.groups[groupIndex].items[rowIndex].remark ?? ''}${controller.products[rowIndex].remark ?? ''}',
|
controller.groups[groupIndex].items[rowIndex]
|
||||||
|
.remark ??
|
||||||
|
'',
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: subTextStyle,
|
style: subTextStyle,
|
||||||
),
|
),
|
||||||
|
@ -496,18 +497,19 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
value: controller.groups[groupIndex].items[rowIndex].quantity,
|
value: controller.groups[groupIndex].items[rowIndex].quantity,
|
||||||
func: (value) {
|
func: (value) {
|
||||||
// 取消失去焦点,并且弹窗警告
|
// 取消失去焦点,并且弹窗警告
|
||||||
bool isValid = value > 0;
|
// bool isValid = (value ?? 0) > 0;
|
||||||
if (!isValid) {
|
// if (!isValid) {
|
||||||
SnackBarUtil().error('数量必须>0,若想删除产品0,请左滑');
|
// SnackBarUtil().error('数量必须>0,若想删除产品0,请左滑');
|
||||||
}
|
// }
|
||||||
return isValid;
|
return true;
|
||||||
}),
|
}),
|
||||||
buildEditCell<int>(
|
buildEditCell<double>(
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
width: ScreenAdaper.width(unitPriceWidth),
|
width: ScreenAdaper.width(unitPriceWidth),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${controller.groups[groupIndex].items[rowIndex].cost}',
|
CommonUtil.toNumberWithout0(
|
||||||
|
controller.groups[groupIndex].items[rowIndex].cost),
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -516,12 +518,13 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
field: 'cost',
|
field: 'cost',
|
||||||
inputWidth: ScreenAdaper.width(unitPriceWidth),
|
inputWidth: ScreenAdaper.width(unitPriceWidth),
|
||||||
value: controller.groups[groupIndex].items[rowIndex].cost),
|
value: controller.groups[groupIndex].items[rowIndex].cost),
|
||||||
buildEditCell<int>(
|
buildEditCell<double>(
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
width: ScreenAdaper.width(amountWidth),
|
width: ScreenAdaper.width(amountWidth),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${controller.groups[groupIndex].items[rowIndex].amount}',
|
CommonUtil.toNumberWithout0(
|
||||||
|
controller.groups[groupIndex].items[rowIndex].amount),
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
style: TextStyle(fontSize: ScreenAdaper.height(25)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -558,22 +561,24 @@ class SaleQuotationPage extends StatelessWidget {
|
||||||
onFieldSubmitted: (value) {
|
onFieldSubmitted: (value) {
|
||||||
final editingData =
|
final editingData =
|
||||||
controller.groups[groupIndex].items[rowIndex].toJson();
|
controller.groups[groupIndex].items[rowIndex].toJson();
|
||||||
editingData[field] = value as T;
|
editingData[field] = value;
|
||||||
controller.saveChanges(groupIndex, rowIndex,
|
controller.afterRowChanges(groupIndex, rowIndex,
|
||||||
SaleQuotationItemModel.fromJson(editingData), field);
|
SaleQuotationItemModel.fromJson(editingData), field);
|
||||||
},
|
},
|
||||||
onTapOutside: (dynamic value) {
|
onTapOutside: (dynamic value) {
|
||||||
|
value = value ?? 0;
|
||||||
final editingData =
|
final editingData =
|
||||||
controller.groups[groupIndex].items[rowIndex].toJson();
|
controller.groups[groupIndex].items[rowIndex].toJson();
|
||||||
editingData[field] = value as T;
|
editingData[field] = value as T;
|
||||||
controller.saveChanges(groupIndex, rowIndex,
|
controller.afterRowChanges(groupIndex, rowIndex,
|
||||||
SaleQuotationItemModel.fromJson(editingData), field);
|
SaleQuotationItemModel.fromJson(editingData), field);
|
||||||
},
|
},
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: ScreenAdaper.width(20),
|
horizontal: ScreenAdaper.width(20),
|
||||||
vertical: ScreenAdaper.height(10)),
|
vertical: ScreenAdaper.height(10)),
|
||||||
textController:
|
textController: TextEditingController(
|
||||||
TextEditingController(text: '${value == 0 ? '' : value}')),
|
text:
|
||||||
|
value == 0 ? '' : CommonUtil.toNumberWithout0(value))),
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|
|
@ -43,7 +43,7 @@ class WorkBenchPage extends StatelessWidget {
|
||||||
.map((e) => e.name)
|
.map((e) => e.name)
|
||||||
.firstWhereOrNull((name) => name == controller.menus[index].route);
|
.firstWhereOrNull((name) => name == controller.menus[index].route);
|
||||||
if (route != null) {
|
if (route != null) {
|
||||||
RouterUtil.toNamed(controller.menus[index].route);
|
RouterUtil.toNamed(controller.menus[index].route!);
|
||||||
} else {
|
} else {
|
||||||
SnackBarUtil().info('您没有权限,请联系管理员。后期会隐藏没有权限的功能');
|
SnackBarUtil().info('您没有权限,请联系管理员。后期会隐藏没有权限的功能');
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'package:sk_base_mobile/apis/api.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/config.dart';
|
import 'package:sk_base_mobile/config.dart';
|
||||||
import 'package:sk_base_mobile/models/app_config.dart';
|
import 'package:sk_base_mobile/models/app_config.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/services/service.dart';
|
import 'package:sk_base_mobile/services/service.dart';
|
||||||
import 'package:sk_base_mobile/util/device.util.dart';
|
import 'package:sk_base_mobile/util/device.util.dart';
|
||||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||||
|
@ -125,6 +126,7 @@ class AppInfoService extends GetxService {
|
||||||
ModalUtil.alert(
|
ModalUtil.alert(
|
||||||
// title: '有新版本',
|
// title: '有新版本',
|
||||||
builder: (_) => UpgradeConfirm(
|
builder: (_) => UpgradeConfirm(
|
||||||
|
version: newVersion,
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
upgradeApp(newVersion);
|
upgradeApp(newVersion);
|
||||||
},
|
},
|
||||||
|
@ -156,8 +158,7 @@ class AppInfoService extends GetxService {
|
||||||
try {
|
try {
|
||||||
/// 下载
|
/// 下载
|
||||||
downloadProgress.value = 0;
|
downloadProgress.value = 0;
|
||||||
Get.back();
|
await RouterUtil.back();
|
||||||
|
|
||||||
ModalUtil.alert(
|
ModalUtil.alert(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 0),
|
contentPadding: EdgeInsets.symmetric(vertical: 0),
|
||||||
|
@ -167,7 +168,7 @@ class AppInfoService extends GetxService {
|
||||||
Obx(
|
Obx(
|
||||||
() => Stack(
|
() => Stack(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SizedBox(
|
||||||
height: ScreenAdaper.height(40),
|
height: ScreenAdaper.height(40),
|
||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: downloadProgress.value,
|
value: downloadProgress.value,
|
||||||
|
@ -191,7 +192,7 @@ class AppInfoService extends GetxService {
|
||||||
responseType: ResponseType.bytes,
|
responseType: ResponseType.bytes,
|
||||||
followRedirects: false,
|
followRedirects: false,
|
||||||
));
|
));
|
||||||
Get.back();
|
await RouterUtil.back();
|
||||||
InstallPlugin.install(
|
InstallPlugin.install(
|
||||||
file.path,
|
file.path,
|
||||||
).then((result) {}).catchError((error) {});
|
).then((result) {}).catchError((error) {});
|
||||||
|
|
|
@ -135,7 +135,7 @@ class DioService extends get_package.GetxService {
|
||||||
}
|
}
|
||||||
if (response.data != null && response.data is Map) {
|
if (response.data != null && response.data is Map) {
|
||||||
if (response.data['code'] == 200) {
|
if (response.data['code'] == 200) {
|
||||||
if (GloablConfig.DEBUG) LoggerUtil().info(response.data['data']);
|
// if (GloablConfig.DEBUG) LoggerUtil().info(response.data['data']);
|
||||||
response.data = response.data['data'];
|
response.data = response.data['data'];
|
||||||
// 分页数据处理
|
// 分页数据处理
|
||||||
if (response.data != null &&
|
if (response.data != null &&
|
||||||
|
|
|
@ -36,6 +36,10 @@ class CommonUtil {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String toNumberWithout0(num num) {
|
||||||
|
return num.toStringAsFixed(num.truncateToDouble() == num ? 0 : 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TreeNode<T> {
|
class TreeNode<T> {
|
||||||
|
|
|
@ -33,12 +33,12 @@ class ModalUtil {
|
||||||
titlePadding: EdgeInsets.zero,
|
titlePadding: EdgeInsets.zero,
|
||||||
contentPadding: contentPadding ??
|
contentPadding: contentPadding ??
|
||||||
EdgeInsets.symmetric(
|
EdgeInsets.symmetric(
|
||||||
vertical: ScreenAdaper.height(10),
|
vertical: ScreenAdaper.height(15),
|
||||||
),
|
horizontal: ScreenAdaper.width(25)),
|
||||||
title: title != null
|
title: title != null
|
||||||
? Container(
|
? Container(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
vertical: ScreenAdaper.height(20),
|
vertical: ScreenAdaper.height(10),
|
||||||
),
|
),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
|
@ -59,7 +59,7 @@ class ModalUtil {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: ScreenAdaper.height(30),
|
fontSize: ScreenAdaper.height(25),
|
||||||
color: AppTheme.black,
|
color: AppTheme.black,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/media_util.dart';
|
import 'package:sk_base_mobile/util/media_util.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ class PhotoPickerUtil {
|
||||||
title: Text(title),
|
title: Text(title),
|
||||||
cancelButton: CupertinoActionSheetAction(
|
cancelButton: CupertinoActionSheetAction(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'取消',
|
'取消',
|
||||||
|
@ -22,7 +23,7 @@ class PhotoPickerUtil {
|
||||||
actions: ['拍照', '相册']
|
actions: ['拍照', '相册']
|
||||||
.map((item) => CupertinoActionSheetAction(
|
.map((item) => CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Get.back();
|
await RouterUtil.back();
|
||||||
XFile? pickedFile = item == '拍照'
|
XFile? pickedFile = item == '拍照'
|
||||||
? await MediaUtil().getImageFromCamera()
|
? await MediaUtil().getImageFromCamera()
|
||||||
: await MediaUtil().getImageFromGallery();
|
: await MediaUtil().getImageFromGallery();
|
||||||
|
|
|
@ -23,7 +23,7 @@ class SnackBarUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Get.isSnackbarOpen) {
|
if (Get.isSnackbarOpen) {
|
||||||
await Get.closeCurrentSnackbar();
|
Get.back();
|
||||||
}
|
}
|
||||||
Get.rawSnackbar(
|
Get.rawSnackbar(
|
||||||
snackPosition: SnackPosition.TOP,
|
snackPosition: SnackPosition.TOP,
|
||||||
|
@ -46,7 +46,7 @@ class SnackBarUtil {
|
||||||
Future<void> success(String title, {String? message}) async {
|
Future<void> success(String title, {String? message}) async {
|
||||||
if (checkIsSnackBarInit()) {
|
if (checkIsSnackBarInit()) {
|
||||||
if (Get.isSnackbarOpen) {
|
if (Get.isSnackbarOpen) {
|
||||||
await Get.closeCurrentSnackbar();
|
Get.back();
|
||||||
}
|
}
|
||||||
Get.rawSnackbar(
|
Get.rawSnackbar(
|
||||||
message: title,
|
message: title,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/logger_util.dart';
|
import 'package:sk_base_mobile/util/logger_util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class SkBaseDatePicker extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'取消',
|
'取消',
|
||||||
|
@ -41,7 +41,7 @@ class SkBaseDatePicker extends StatelessWidget {
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
final year = 2000 + yearController.selectedItem;
|
final year = 2000 + yearController.selectedItem;
|
||||||
String month = '${monthController.selectedItem + 1}';
|
String month = '${monthController.selectedItem + 1}';
|
||||||
if (int.parse(month) < 10) {
|
if (int.parse(month) < 10) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
|
||||||
class SkBottomSheetPicker extends StatelessWidget {
|
class SkBottomSheetPicker extends StatelessWidget {
|
||||||
|
@ -39,7 +39,7 @@ class SkBottomSheetPicker extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'取消',
|
'取消',
|
||||||
|
@ -57,7 +57,7 @@ class SkBottomSheetPicker extends StatelessWidget {
|
||||||
)),
|
)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
onChanged!(
|
onChanged!(
|
||||||
firstLevelControlller.selectedItem,
|
firstLevelControlller.selectedItem,
|
||||||
(secondLevel ?? []).isNotEmpty
|
(secondLevel ?? []).isNotEmpty
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/core/sk_ink.dart';
|
import 'package:sk_base_mobile/widgets/core/sk_ink.dart';
|
||||||
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||||
|
@ -65,7 +66,7 @@ class SkCascadePicker<T, Z> extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
SkInk(
|
SkInk(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'取消',
|
'取消',
|
||||||
|
@ -74,7 +75,7 @@ class SkCascadePicker<T, Z> extends StatelessWidget {
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
SkInk(
|
SkInk(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
if (onConfirm != null) {
|
if (onConfirm != null) {
|
||||||
onConfirm!(cascadeController.selectedTabs
|
onConfirm!(cascadeController.selectedTabs
|
||||||
.where((e) =>
|
.where((e) =>
|
||||||
|
@ -98,7 +99,7 @@ class SkCascadePicker<T, Z> extends StatelessWidget {
|
||||||
// GradientButton(
|
// GradientButton(
|
||||||
// buttonText: '确定',
|
// buttonText: '确定',
|
||||||
// onPressed: () {
|
// onPressed: () {
|
||||||
// Get.back();
|
// await RouterUtil.back();
|
||||||
// if (onConfirm != null) {
|
// if (onConfirm != null) {
|
||||||
// onConfirm!(cascadeController.selectedTabs
|
// onConfirm!(cascadeController.selectedTabs
|
||||||
// .where((e) =>
|
// .where((e) =>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
|
||||||
class SkDialogHeader extends StatelessWidget {
|
class SkDialogHeader extends StatelessWidget {
|
||||||
|
@ -39,11 +39,11 @@ class SkDialogHeader extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
trailing ??
|
trailing ??
|
||||||
Container(
|
SizedBox(
|
||||||
width: ScreenAdaper.width(100),
|
width: ScreenAdaper.width(100),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/constants/constants.dart';
|
||||||
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/core/sk_ink.dart';
|
||||||
|
|
||||||
|
class SkFlatButton extends StatelessWidget {
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final bool isLoading;
|
||||||
|
final String buttonText;
|
||||||
|
final Icon? icon;
|
||||||
|
final Color? color;
|
||||||
|
final BorderRadiusGeometry? borderRadius;
|
||||||
|
const SkFlatButton(
|
||||||
|
{super.key,
|
||||||
|
this.buttonText = TextEnum.createInventoryInOutBtnText,
|
||||||
|
this.onPressed,
|
||||||
|
this.icon,
|
||||||
|
this.color,
|
||||||
|
this.borderRadius,
|
||||||
|
this.isLoading = false});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SkInk(
|
||||||
|
onTap: onPressed ?? () {},
|
||||||
|
color: color ?? AppTheme.primaryColor,
|
||||||
|
child: SizedBox(
|
||||||
|
height: ScreenAdaper.height(80),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (icon != null) ...[
|
||||||
|
icon!,
|
||||||
|
SizedBox(
|
||||||
|
width: ScreenAdaper.width(10),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
isLoading
|
||||||
|
? LoadingAnimationWidget.fourRotatingDots(
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
|
size: ScreenAdaper.height(40),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
buttonText,
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppTheme.nearlyWhite,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: ScreenAdaper.height(25),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,11 +29,11 @@ class SkInk extends StatelessWidget {
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: borderRadius ?? BorderRadius.zero,
|
borderRadius: borderRadius ?? BorderRadius.zero,
|
||||||
child: Material(
|
child: Material(
|
||||||
|
color: color ?? Colors.transparent,
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: padding,
|
padding: padding,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: border,
|
border: border,
|
||||||
color: color ?? AppTheme.nearlyWhite,
|
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
|
||||||
class Empty extends StatelessWidget {
|
class Empty extends StatelessWidget {
|
||||||
final String? text;
|
final String? text;
|
||||||
const Empty({super.key, this.text});
|
final Widget? icon;
|
||||||
|
final void Function()? onTap;
|
||||||
|
const Empty({super.key, this.text, this.icon, this.onTap});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return GestureDetector(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
onTap: onTap,
|
||||||
Center(
|
child: Center(
|
||||||
child: Icon(Icons.error_outline,
|
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
size: ScreenAdaper.height(40), color: Colors.red)),
|
Center(
|
||||||
SizedBox(
|
child: icon ??
|
||||||
width: ScreenAdaper.width(10),
|
Icon(Icons.error_outline,
|
||||||
),
|
size: ScreenAdaper.height(40),
|
||||||
Text(
|
color: AppTheme.dangerColor)),
|
||||||
text ?? '',
|
SizedBox(
|
||||||
textAlign: TextAlign.center,
|
width: ScreenAdaper.width(10),
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(35)),
|
),
|
||||||
),
|
Text(
|
||||||
]),
|
text ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: ScreenAdaper.height(35)),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,12 @@ import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/constants/bg_color.dart';
|
import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||||
import 'package:sk_base_mobile/models/base_search_more.model.dart';
|
import 'package:sk_base_mobile/models/base_search_more.model.dart';
|
||||||
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/debouncer.dart';
|
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/empty.dart';
|
import 'package:sk_base_mobile/widgets/empty.dart';
|
||||||
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
|
||||||
|
|
||||||
class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
final Function(List<int>)? onOk;
|
final Function(List<int>)? onOk;
|
||||||
|
@ -18,7 +20,6 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
final bool enablePullUp;
|
final bool enablePullUp;
|
||||||
final bool enablePullDown;
|
final bool enablePullDown;
|
||||||
final bool isDialog;
|
final bool isDialog;
|
||||||
|
|
||||||
final Function(int)? leadingBuilder;
|
final Function(int)? leadingBuilder;
|
||||||
SkMutilSearchMore(
|
SkMutilSearchMore(
|
||||||
{super.key,
|
{super.key,
|
||||||
|
@ -33,42 +34,45 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
TextStyle(fontSize: ScreenAdaper.height(20), fontWeight: FontWeight.w600);
|
TextStyle(fontSize: ScreenAdaper.height(20), fontWeight: FontWeight.w600);
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Column(
|
||||||
padding: EdgeInsets.symmetric(
|
children: [
|
||||||
horizontal: ScreenAdaper.width(20),
|
Expanded(
|
||||||
vertical: ScreenAdaper.height(20)),
|
child: Container(
|
||||||
child: Column(
|
padding: EdgeInsets.symmetric(
|
||||||
children: [
|
horizontal: ScreenAdaper.width(20),
|
||||||
buildDialogHeader(),
|
vertical: ScreenAdaper.height(20)),
|
||||||
SizedBox(
|
child: Column(
|
||||||
height: ScreenAdaper.height(defaultPadding) / 2,
|
children: [
|
||||||
),
|
buildDialogHeader(),
|
||||||
buildSearchBar(),
|
SizedBox(
|
||||||
SizedBox(
|
height: ScreenAdaper.height(defaultPadding) / 2,
|
||||||
height: ScreenAdaper.height(defaultPadding) / 2,
|
),
|
||||||
),
|
buildSearchBar(),
|
||||||
Expanded(child: buildList()),
|
SizedBox(
|
||||||
SizedBox(
|
height: ScreenAdaper.height(defaultPadding) / 2,
|
||||||
height: ScreenAdaper.height(defaultPadding) / 2,
|
),
|
||||||
),
|
Expanded(child: buildList()),
|
||||||
GradientButton(
|
],
|
||||||
onPressed: () {
|
)),
|
||||||
if (onOk != null) {
|
),
|
||||||
onOk!(controller.selectedIndex);
|
GradientButton(
|
||||||
}
|
onPressed: () {
|
||||||
if (isDialog) {
|
if (onOk != null) {
|
||||||
Get.back();
|
onOk!(controller.selectedIndex);
|
||||||
}
|
}
|
||||||
controller.selectedIndex.clear();
|
if (isDialog) {
|
||||||
},
|
RouterUtil.back();
|
||||||
buttonText: '确定',
|
}
|
||||||
)
|
controller.selectedIndex.clear();
|
||||||
],
|
},
|
||||||
));
|
buttonText: '确定',
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildDialogHeader() {
|
Widget buildDialogHeader() {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: ScreenAdaper.height(60),
|
height: ScreenAdaper.height(60),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@ -84,7 +88,7 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
right: 0,
|
right: 0,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
|
@ -135,23 +139,25 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildList() {
|
Widget buildList() {
|
||||||
return Obx(() => SmartRefresher(
|
return Obx(() => controller.loading.value
|
||||||
enablePullDown: enablePullDown,
|
? const LoadingIndicator(common: true)
|
||||||
enablePullUp: enablePullUp,
|
: SmartRefresher(
|
||||||
controller: controller.refreshController,
|
enablePullDown: enablePullDown,
|
||||||
onLoading: controller.onLoading,
|
enablePullUp: enablePullUp,
|
||||||
onRefresh: controller.onRefresh,
|
controller: controller.refreshController,
|
||||||
child: controller.list.isEmpty
|
onLoading: controller.onLoading,
|
||||||
? const Center(
|
onRefresh: controller.onRefresh,
|
||||||
child: Empty(text: '暂无数据'),
|
child: controller.list.isEmpty
|
||||||
)
|
? const Center(
|
||||||
: ListView.separated(
|
child: Empty(text: '暂无数据'),
|
||||||
separatorBuilder: (context, index) => const Divider(
|
)
|
||||||
color: AppTheme.dividerColor,
|
: ListView.separated(
|
||||||
height: 1,
|
separatorBuilder: (context, index) => const Divider(
|
||||||
),
|
color: AppTheme.dividerColor,
|
||||||
itemCount: controller.list.length,
|
height: 1,
|
||||||
itemBuilder: (_, index) => buildItem(index))));
|
),
|
||||||
|
itemCount: controller.list.length,
|
||||||
|
itemBuilder: (_, index) => buildItem(index))));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildItem(int index) {
|
Widget buildItem(int index) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ class SkNumberInput<T> extends StatefulWidget {
|
||||||
final TextEditingController textController;
|
final TextEditingController textController;
|
||||||
final Function(FocusNode)? onTap;
|
final Function(FocusNode)? onTap;
|
||||||
final Function(String)? onChanged;
|
final Function(String)? onChanged;
|
||||||
final Function(dynamic)? onTapOutside;
|
final void Function(dynamic)? onTapOutside;
|
||||||
final Function(dynamic)? validator;
|
final Function(dynamic)? validator;
|
||||||
|
|
||||||
final bool isDense;
|
final bool isDense;
|
||||||
|
@ -16,7 +16,7 @@ class SkNumberInput<T> extends StatefulWidget {
|
||||||
final bool isRequired;
|
final bool isRequired;
|
||||||
final String labelText;
|
final String labelText;
|
||||||
final String? hint;
|
final String? hint;
|
||||||
final ValueChanged<int>? onFieldSubmitted;
|
final ValueChanged<T>? onFieldSubmitted;
|
||||||
const SkNumberInput(
|
const SkNumberInput(
|
||||||
{super.key,
|
{super.key,
|
||||||
required this.textController,
|
required this.textController,
|
||||||
|
@ -76,13 +76,13 @@ class _SkNumberInputState<T> extends State<SkNumberInput> {
|
||||||
},
|
},
|
||||||
onTapOutside: (event) {
|
onTapOutside: (event) {
|
||||||
if (widget.onTapOutside != null) {
|
if (widget.onTapOutside != null) {
|
||||||
dynamic value;
|
dynamic value = widget.textController.text;
|
||||||
if (T == double) {
|
if (T == double) {
|
||||||
value = double.tryParse(widget.textController.text);
|
value = double.tryParse(widget.textController.text) ?? 0.0;
|
||||||
|
|
||||||
widget.onTapOutside!(value as T);
|
widget.onTapOutside!(value as T);
|
||||||
} else {
|
} else {
|
||||||
value = int.tryParse(widget.textController.text);
|
value = int.tryParse(widget.textController.text) ?? 0;
|
||||||
}
|
}
|
||||||
if (widget.validator != null && !widget.validator!(value)) {
|
if (widget.validator != null && !widget.validator!(value)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/constants/bg_color.dart';
|
import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||||
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
import 'package:sk_base_mobile/models/base_search_more_controller.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/debouncer.dart';
|
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/empty.dart';
|
import 'package:sk_base_mobile/widgets/empty.dart';
|
||||||
|
@ -52,7 +53,7 @@ class SkSingleSearchMore<T> extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildDialogHeader() {
|
Widget buildDialogHeader() {
|
||||||
return Container(
|
return SizedBox(
|
||||||
height: ScreenAdaper.height(60),
|
height: ScreenAdaper.height(60),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@ -68,7 +69,7 @@ class SkSingleSearchMore<T> extends StatelessWidget {
|
||||||
right: 0,
|
right: 0,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SkTextInput extends SkBaseFieldWidget {
|
||||||
final InputBorder? border;
|
final InputBorder? border;
|
||||||
final FloatingLabelBehavior? floatingLabelBehavior;
|
final FloatingLabelBehavior? floatingLabelBehavior;
|
||||||
final TextInputType? keyboardType;
|
final TextInputType? keyboardType;
|
||||||
|
final double? height;
|
||||||
SkTextInput(
|
SkTextInput(
|
||||||
{super.key,
|
{super.key,
|
||||||
super.customLabel = false,
|
super.customLabel = false,
|
||||||
|
@ -40,6 +40,7 @@ class SkTextInput extends SkBaseFieldWidget {
|
||||||
this.suffixIcon,
|
this.suffixIcon,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.border,
|
this.border,
|
||||||
|
this.height,
|
||||||
this.floatingLabelBehavior = FloatingLabelBehavior.always,
|
this.floatingLabelBehavior = FloatingLabelBehavior.always,
|
||||||
this.isTextArea = false,
|
this.isTextArea = false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
|
@ -48,69 +49,76 @@ class SkTextInput extends SkBaseFieldWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget field = TextFormField(
|
Widget field = SizedBox(
|
||||||
focusNode: focusNode,
|
height: height,
|
||||||
controller: textController,
|
child: TextFormField(
|
||||||
onChanged: (String value) {
|
focusNode: focusNode,
|
||||||
if (onChanged != null) {
|
controller: textController,
|
||||||
onChanged!(value);
|
onChanged: (String value) {
|
||||||
}
|
if (onChanged != null) {
|
||||||
},
|
onChanged!(value);
|
||||||
onTapOutside: (event) {
|
}
|
||||||
if (onTapOutside != null) {
|
},
|
||||||
onTapOutside!(textController.text);
|
onTapOutside: (event) {
|
||||||
FocusScope.of(context).unfocus();
|
if (onTapOutside != null) {
|
||||||
}
|
onTapOutside!(textController.text);
|
||||||
},
|
FocusScope.of(context).unfocus();
|
||||||
maxLines: isTextArea ? 2 : 1, // 添加这行代码
|
}
|
||||||
onTap: () {
|
},
|
||||||
if (onTap != null) {
|
maxLines: isTextArea ? 2 : 1, // 添加这行代码
|
||||||
onTap!(focusNode);
|
onTap: () {
|
||||||
}
|
if (onTap != null) {
|
||||||
},
|
onTap!(focusNode);
|
||||||
keyboardType: keyboardType,
|
}
|
||||||
onFieldSubmitted: onFieldSubmitted,
|
},
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
keyboardType: keyboardType,
|
||||||
validator: validator,
|
onFieldSubmitted: onFieldSubmitted,
|
||||||
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
|
validator: validator,
|
||||||
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefixIcon: prefix,
|
prefixIcon: prefix,
|
||||||
suffixIcon: suffixIcon,
|
suffixIcon: suffixIcon,
|
||||||
fillColor: fillColor,
|
fillColor: fillColor,
|
||||||
filled: true,
|
filled: true,
|
||||||
errorStyle: const TextStyle(fontSize: 0, height: 0.01),
|
errorStyle: const TextStyle(fontSize: 0, height: 0.01),
|
||||||
contentPadding: contentPadding,
|
contentPadding: contentPadding,
|
||||||
isDense: isDense,
|
isDense: isDense,
|
||||||
border: border,
|
border: border,
|
||||||
floatingLabelBehavior: floatingLabelBehavior,
|
floatingLabelBehavior: floatingLabelBehavior,
|
||||||
label: labelText != null && !customLabel
|
label: labelText != null && !customLabel
|
||||||
? Row(
|
? Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (isRequired)
|
if (isRequired)
|
||||||
|
Text(
|
||||||
|
"*",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.red,
|
||||||
|
fontSize: ScreenAdaper.height(30)),
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
"*",
|
labelText!,
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
||||||
color: Colors.red,
|
|
||||||
fontSize: ScreenAdaper.height(30)),
|
|
||||||
),
|
),
|
||||||
Text(
|
])
|
||||||
labelText!,
|
: null,
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
hintText: hint ?? '请输入',
|
||||||
),
|
),
|
||||||
])
|
|
||||||
: null,
|
|
||||||
hintText: hint ?? '请输入',
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return SkFormItem(
|
if (customLabel) {
|
||||||
controller: baseFieldController,
|
return SkFormItem(
|
||||||
customLabel: customLabel,
|
controller: baseFieldController,
|
||||||
labelText: labelText,
|
customLabel: customLabel,
|
||||||
isRequired: isRequired,
|
labelText: labelText,
|
||||||
child: field,
|
isRequired: isRequired,
|
||||||
);
|
child: field,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ class GradientButton extends StatelessWidget {
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
final String buttonText;
|
final String buttonText;
|
||||||
final Icon? icon;
|
final Icon? icon;
|
||||||
final BorderRadiusGeometry? borderRadius;
|
final BorderRadius? borderRadius;
|
||||||
const GradientButton(
|
const GradientButton(
|
||||||
{super.key,
|
{super.key,
|
||||||
this.buttonText = TextEnum.createInventoryInOutBtnText,
|
this.buttonText = TextEnum.createInventoryInOutBtnText,
|
||||||
|
@ -21,6 +21,7 @@ class GradientButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SkInk(
|
return SkInk(
|
||||||
|
borderRadius: borderRadius,
|
||||||
onTap: onPressed ?? () {},
|
onTap: onPressed ?? () {},
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: [AppTheme.primaryColorLight, AppTheme.primaryColor]),
|
colors: [AppTheme.primaryColorLight, AppTheme.primaryColor]),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:photo_view/photo_view.dart';
|
import 'package:photo_view/photo_view.dart';
|
||||||
import 'package:photo_view/photo_view_gallery.dart';
|
import 'package:photo_view/photo_view_gallery.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/config.dart';
|
import 'package:sk_base_mobile/config.dart';
|
||||||
import 'package:sk_base_mobile/models/file.model.dart';
|
import 'package:sk_base_mobile/models/file.model.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/loading_util.dart';
|
import 'package:sk_base_mobile/util/loading_util.dart';
|
||||||
import 'package:sk_base_mobile/util/media_util.dart';
|
import 'package:sk_base_mobile/util/media_util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
@ -96,7 +96,7 @@ class _ImagePreivewState extends State<ImagePreivew> {
|
||||||
final FileModel item = widget.galleryItems[index];
|
final FileModel item = widget.galleryItems[index];
|
||||||
return PhotoViewGalleryPageOptions(
|
return PhotoViewGalleryPageOptions(
|
||||||
onTapUp: (_, tapUpDetails, value) {
|
onTapUp: (_, tapUpDetails, value) {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
imageProvider: Image.network('${GloablConfig.OSS_URL}${item.path}').image,
|
imageProvider: Image.network('${GloablConfig.OSS_URL}${item.path}').image,
|
||||||
initialScale: PhotoViewComputedScale.contained,
|
initialScale: PhotoViewComputedScale.contained,
|
||||||
|
|
|
@ -80,7 +80,7 @@ class MyAvatarController extends GetxController {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// uploadImgFilePath(pickedFile.path);
|
// uploadImgFilePath(pickedFile.path);
|
||||||
// Get.back();
|
// await RouterUtil.back();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
SnackBarUtil().error('Update avatar failed.');
|
SnackBarUtil().error('Update avatar failed.');
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:sk_base_mobile/app_theme.dart';
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/router/router.util.dart';
|
||||||
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
import 'package:sk_base_mobile/widgets/gradient_button.dart';
|
||||||
|
|
||||||
class UpgradeConfirm extends StatelessWidget {
|
class UpgradeConfirm extends StatelessWidget {
|
||||||
final void Function()? onConfirm;
|
final void Function()? onConfirm;
|
||||||
final bool forceUpgrade;
|
final bool forceUpgrade;
|
||||||
const UpgradeConfirm({super.key, this.onConfirm, this.forceUpgrade = true});
|
final String version;
|
||||||
|
const UpgradeConfirm(
|
||||||
|
{super.key,
|
||||||
|
this.onConfirm,
|
||||||
|
this.forceUpgrade = true,
|
||||||
|
required this.version});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -33,7 +39,7 @@ class UpgradeConfirm extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'有新的版本更新啦',
|
'有新的版本v_${version}更新啦',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
fontSize: ScreenAdaper.height(35),
|
fontSize: ScreenAdaper.height(35),
|
||||||
|
@ -83,7 +89,7 @@ class UpgradeConfirm extends StatelessWidget {
|
||||||
child: // 更新内容
|
child: // 更新内容
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
RouterUtil.back();
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.close)),
|
icon: const Icon(Icons.close)),
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.devz
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.0+1
|
version: 1.0.2+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.2.6 <4.0.0'
|
sdk: '>=3.2.6 <4.0.0'
|
||||||
|
|
Loading…
Reference in New Issue